ast: Merge Ty into Pat, merge Mod and Fn into Bind

This commit is contained in:
2025-10-20 04:24:21 -04:00
parent 22094f4862
commit b80a3a55c3
4 changed files with 188 additions and 338 deletions

View File

@@ -271,18 +271,13 @@ impl<'t> Parse<'t> for Literal {
Ok(match tok.kind {
TKind::True => p.consume().then(Literal::Bool(true)),
TKind::False => p.consume().then(Literal::Bool(false)),
TKind::Character => Literal::Char({
let Token { lexeme, .. } = p.take().expect("should have Token");
lexeme.char().expect("char token should have char")
}),
TKind::Integer => Literal::Int({
let Token { lexeme, .. } = p.take().expect("should have Token");
lexeme.int().expect("integer token should have int")
}),
TKind::String => Literal::Str({
let Token { lexeme, .. } = p.take().expect("should have Token");
lexeme.string().expect("string token should have string")
}),
TKind::Character | TKind::Integer | TKind::String => {
match p.take().expect("should have Token").lexeme {
Lexeme::String(str) => Literal::Str(str),
Lexeme::Integer(int, base) => Literal::Int(int, base),
Lexeme::Char(chr) => Literal::Char(chr),
}
}
other => Err(ParseError::NotLiteral(other, tok.span))?,
})
}
@@ -295,6 +290,7 @@ pub enum PPrec {
Tuple,
Typed,
Range,
Fn,
Max,
}
@@ -305,14 +301,14 @@ impl PPrec {
Self::Alt => Self::Tuple,
Self::Tuple => Self::Typed,
Self::Typed => Self::Range,
Self::Range => Self::Max,
Self::Range => Self::Fn,
Self::Fn => Self::Max,
Self::Max => Self::Max,
}
}
}
enum PatPs {
Typed,
Op(PatOp),
}
@@ -320,8 +316,9 @@ fn pat_from_infix(token: &Token) -> Option<(PatPs, PPrec)> {
Some(match token.kind {
TKind::DotDot => (PatPs::Op(PatOp::RangeEx), PPrec::Range),
TKind::DotDotEq => (PatPs::Op(PatOp::RangeIn), PPrec::Range),
TKind::Colon => (PatPs::Typed, PPrec::Typed),
TKind::Colon => (PatPs::Op(PatOp::Typed), PPrec::Typed),
TKind::Comma => (PatPs::Op(PatOp::Tuple), PPrec::Tuple),
TKind::Arrow => (PatPs::Op(PatOp::Fn), PPrec::Fn),
TKind::Bar => (PatPs::Op(PatOp::Alt), PPrec::Alt),
_ => None?,
})
@@ -335,6 +332,7 @@ impl<'t> Parse<'t> for Pat {
// Prefix
let mut head = match tok.kind {
TKind::Fn => return p.consume().parse(PPrec::Fn),
TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
Pat::Lit(p.parse(())?)
}
@@ -350,8 +348,8 @@ impl<'t> Parse<'t> for Pat {
let mut path: FqPath = p.parse(())?;
// TODO: make these postfix.
match p.peek().map(|t| t.kind) {
Ok(TKind::LParen) => Pat::TupStruct(path, p.parse(PPrec::Typed)?),
Ok(TKind::LCurly) => Pat::Struct(
Ok(TKind::LParen) => Pat::NamedTuple(path, p.parse(PPrec::Typed)?),
Ok(TKind::LCurly) if level <= PPrec::Tuple => Pat::NamedStruct(
path,
p.consume()
.opt(PPrec::Alt, TKind::RCurly)?
@@ -406,7 +404,12 @@ impl<'t> Parse<'t> for Pat {
{
let kind = tok.kind;
head = match op {
PatPs::Typed => Pat::Typed(head.into(), p.consume().parse(())?),
PatPs::Op(PatOp::Typed) => {
Pat::Op(PatOp::Typed, vec![head, p.consume().parse(PPrec::Max)?])
}
PatPs::Op(PatOp::Fn) => {
Pat::Op(PatOp::Fn, vec![head, p.consume().parse(PPrec::Fn.next())?])
}
PatPs::Op(op @ (PatOp::RangeEx | PatOp::RangeIn)) => Pat::Op(
op,
match p.consume().peek().map(|t| t.kind) {
@@ -423,59 +426,59 @@ impl<'t> Parse<'t> for Pat {
}
}
impl<'t> Parse<'t> for Ty {
type Prec = ();
// impl<'t> Parse<'t> for Ty {
// type Prec = ();
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self>
where Self: Sized {
let &Token { kind, span, .. } = p.peek()?;
// fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self>
// where Self: Sized {
// let &Token { kind, span, .. } = p.peek()?;
// TODO: this is a kinda jank way of error reporting
let head = match kind {
TKind::Identifier => match p.peek()?.lexeme.str() {
Some("_") => p.consume().then(Ty::Infer),
_ => Ty::Named(p.parse(())?),
},
TKind::Amp => Ty::Ref(p.consume().parse(())?),
TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))),
TKind::LBrack => {
let ty = p.consume().parse(level)?;
match p.next()? {
Token { kind: TKind::Semi, .. } => {
let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?);
p.expect(TKind::RBrack)?;
ty
}
Token { kind: TKind::RBrack, .. } => Ty::Slice(ty),
tok => Err(ParseError::NotType(tok.kind, tok.span))?,
}
}
TKind::Fn => {
p.consume();
match p.parse(())? {
Ty::Fn(args) => Ty::Fn(args),
other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
other => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
}
}
TKind::LParen => {
Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?)
}
_ => Err(ParseError::NotType(kind, span))?,
};
// // TODO: this is a kinda jank way of error reporting
// let head = match kind {
// TKind::Identifier => match p.peek()?.lexeme.str() {
// Some("_") => p.consume().then(Ty::Infer),
// _ => Ty::Named(p.parse(())?),
// },
// TKind::Amp => Ty::Ref(p.consume().parse(())?),
// TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))),
// TKind::LBrack => {
// let ty = p.consume().parse(level)?;
// match p.next()? {
// Token { kind: TKind::Semi, .. } => {
// let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?);
// p.expect(TKind::RBrack)?;
// ty
// }
// Token { kind: TKind::RBrack, .. } => Ty::Slice(ty),
// tok => Err(ParseError::NotType(tok.kind, tok.span))?,
// }
// }
// TKind::Fn => {
// p.consume();
// match p.parse(())? {
// Ty::Fn(args) => Ty::Fn(args),
// other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
// other => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
// }
// }
// TKind::LParen => {
// Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?)
// }
// _ => Err(ParseError::NotType(kind, span))?,
// };
Ok(match p.next_if(TKind::Arrow).allow_eof()? {
Some(Ok(_)) => Ty::Fn(vec![
match head {
args @ Ty::Tuple(_) => args,
arg => Ty::Tuple(vec![arg]),
},
p.parse(())?,
]),
_ => head,
})
}
}
// Ok(match p.next_if(TKind::Arrow).allow_eof()? {
// Some(Ok(_)) => Ty::Fn(vec![
// match head {
// args @ Ty::Tuple(_) => args,
// arg => Ty::Tuple(vec![arg]),
// },
// p.parse(())?,
// ]),
// _ => head,
// })
// }
// }
/// Organizes the precedence hierarchy for syntactic elements
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
@@ -669,73 +672,57 @@ impl<'t> Parse<'t> for Typedef {
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
let tok = p.next()?;
match tok.kind {
TKind::Enum => Ok(Self(TypedefKind::Enum, p.parse(PPrec::Alt)?)),
TKind::Enum => Ok(Self(TypedefKind::Enum, p.parse(PPrec::Tuple)?)),
TKind::Struct => Ok(Self(TypedefKind::Struct, p.parse(PPrec::Tuple)?)),
_ => Err(ParseError::NotType(tok.kind, tok.span)),
}
}
}
impl<'t> Parse<'t> for Fn {
type Prec = ();
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
match p.consume().next_if(TKind::Identifier)? {
Ok(Token { lexeme, .. }) => Ok(Self(
lexeme.string(),
p.parse(PPrec::Tuple)?,
p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Tuple(vec![])),
p.parse(Prec::Body.next())?,
)),
_ => Ok(Self(
None,
Pat::Op(
PatOp::Tuple,
p.expect(TKind::LParen)?.list(
vec![],
PPrec::Tuple,
TKind::Comma,
TKind::RParen,
)?,
),
p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Tuple(vec![])),
p.parse(Prec::Body.next())?,
)),
}
}
}
impl<'t> Parse<'t> for Bind {
type Prec = BindKind;
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self> {
if let BindKind::Match = level {
// |? Pat => Expr
p.next_if(TKind::Bar)?.ok(); // and discard
return Ok(Self(
match level {
BindKind::Match => {
// |? Pat => Expr
p.next_if(TKind::Bar)?.ok(); // and discard
Ok(Self(
level,
p.parse(PPrec::Alt)?,
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
))
}
BindKind::Mod => Ok(Self(
level,
p.parse(PPrec::Min)?,
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
));
}
p.consume().parse(PPrec::Max)?,
vec![p.parse(Prec::Body.next())?],
)),
BindKind::Fn => Ok(Self(
level,
p.consume().parse(PPrec::Fn)?,
vec![p.parse(Prec::Body.next())?],
)),
_ => {
// let Pat
let pat = p.consume().parse(PPrec::Tuple)?;
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
return Ok(Self(level, pat, vec![]));
}
// let Pat
let pat = p.consume().parse(PPrec::Tuple)?;
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
return Ok(Self(level, pat, vec![]));
}
// = Expr
let body = p.parse(Prec::Tuple.value())?;
if p.next_if(TKind::Else)
.allow_eof()?
.is_none_or(|v| v.is_err())
{
return Ok(Self(level, pat, vec![body]));
}
// = Expr
let body = p.parse(Prec::Tuple.value())?;
if p.next_if(TKind::Else)
.allow_eof()?
.is_none_or(|v| v.is_err())
{
return Ok(Self(level, pat, vec![body]));
// else Expr
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
}
}
// else Expr
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
}
}
@@ -753,16 +740,6 @@ impl<'t> Parse<'t> for MakeArm {
}
}
impl<'t> Parse<'t> for Mod {
type Prec = ();
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
let ty = p.consume().parse(())?;
let body = p.parse(Prec::Body.value())?;
Ok(Mod(ty, body))
}
}
fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
// for Pat
let pat = p.consume().parse(PPrec::Tuple)?;
@@ -830,7 +807,7 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
.anno(fspan),
Expr::Bind(Box::new(Bind(
BindKind::Match,
Pat::TupStruct(
Pat::NamedTuple(
"Some".into(),
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
),
@@ -876,12 +853,31 @@ impl<'t> Parse<'t> for Expr {
Ps::Id => Expr::Id(p.parse(())?),
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()),
Ps::Lit => Expr::Lit(p.parse(())?),
Ps::Typedef => Expr::Struct(p.parse(())?),
Ps::Let => Expr::Bind(p.parse(BindKind::Let)?),
Ps::Const => Expr::Bind(p.parse(BindKind::Const)?),
Ps::Static => Expr::Bind(p.parse(BindKind::Static)?),
Ps::Mod => Expr::Bind(p.parse(BindKind::Mod)?),
Ps::Fn => Expr::Bind(p.parse(BindKind::Fn)?),
Ps::Lambda | Ps::Lambda0 => {
p.consume();
let args = if op == Ps::Lambda {
p.opt(PPrec::Tuple, TKind::Bar)?
.unwrap_or(Pat::Op(PatOp::Tuple, vec![]))
} else {
Pat::Op(PatOp::Tuple, vec![])
};
let rety = p.opt_if(PPrec::Max, TKind::Arrow)?.unwrap_or(Pat::Ignore);
Expr::Bind(Box::new(Bind(
BindKind::Fn,
Pat::Op(PatOp::Fn, vec![args, rety]),
vec![p.parse(Prec::Body.next())?],
)))
}
Ps::For => parse_for(p, ())?,
Ps::Typedef => Expr::Struct(p.parse(())?),
Ps::Mod => Expr::Mod(p.parse(())?),
Ps::Op(Op::Match) => parse_match(p)?,
Ps::Op(Op::Meta) => Expr::Op(
Op::Meta,
@@ -917,21 +913,6 @@ impl<'t> Parse<'t> for Expr {
];
Expr::Op(op, exprs)
}
Ps::Fn => Expr::Fn(p.parse(())?),
Ps::Lambda => Expr::Fn(Box::new(Fn(
None,
p.consume()
.opt(PPrec::Tuple, TKind::Bar)?
.unwrap_or(Pat::Op(PatOp::Tuple, vec![])),
p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Infer),
p.parse(Prec::Body.next())?,
))),
Ps::Lambda0 => Expr::Fn(Box::new(Fn(
None,
Pat::Op(PatOp::Tuple, vec![]),
p.consume().opt_if((), TKind::Arrow)?.unwrap_or(Ty::Infer),
p.parse(Prec::Body.next())?,
))),
Ps::DoubleRef => p.consume().parse(prec.next()).map(|Anno(expr, span)| {
Expr::Op(
Op::Refer,