e0/src/parser.lalrpop
2022-04-28 11:33:26 -05:00

95 lines
2.2 KiB
Text

use crate::ast::*;
grammar;
pub Program: Vec<Decl<()>> = Decl* => <>;
Decl: Decl<()> = {
Func => Decl::Func(<>),
};
Func: Func<()> = {
"fn" <name:Ident> "(" <args:Args> ")" "->" <return_ty:Type> "{" <stmts:Stmt*> "}" =>
Func { name, args, return_ty, stmts, ty: (), },
};
Args: Vec<Arg> = Punct<",", Arg>? => <>.unwrap_or_else(|| Vec::new());
Arg: Arg = <name:Ident> ":" <ty:Type> => Arg { name, ty };
Stmt: Stmt<()> = {
"let" <name:Ident> <ty:ColonType?> "=" <expr:Expr> ";" =>
Stmt::Let(name, ty, expr),
"return" <expr:Expr?> ";" => Stmt::Return(expr),
IfElse => Stmt::IfElse(<>),
};
ColonType: Type = ":" <ty:Type> => ty;
IfElse: IfElse<()> =
"if" <cond:Expr> "{" <body:Stmt*> "}" <else_clause:Else?> =>
IfElse { cond, body, else_clause };
Else: ElseClause<()> = "else" <else_clause:Else_> => else_clause;
Else_: ElseClause<()> = {
IfElse => ElseClause::If(Box::new(<>)),
"{" <body:Stmt*> "}" => ElseClause::Body(body),
};
Expr: Expr<()> = {
#[precedence(level = "0")]
"(" <expr:Expr> ")" => expr,
#[precedence(level = "0")]
r"[0-9]+" => Expr { kind: ExprKind::Int(<>.parse::<i64>().unwrap()), ty: () },
#[precedence(level = "0")]
Ident => Expr { kind: ExprKind::Var(<>), ty: () },
#[precedence(level = "2")]
<func:Ident> "(" <args:Punct<",", Expr>?> ")" =>
Expr { kind: ExprKind::Call(func, args.unwrap_or_else(|| vec![])), ty: () },
#[precedence(level = "8")]
#[assoc(side = "left")]
<left:Expr> <op:AddOp> <right:Expr> => Expr {
kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)),
ty: (),
},
#[precedence(level = "13")]
#[assoc(side = "none")]
<left:Expr> <op:CompareOp> <right:Expr> => Expr {
kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)),
ty: (),
},
};
AddOp: Op = {
"+" => Op::Plus,
};
CompareOp: Op = {
"<" => Op::LessThan,
">" => Op::GreaterThan,
};
Type: Type = {
"int" => Type::Int,
};
Ident: String = r"([A-Za-z][A-Za-z0-9_]*)|(_[A-Za-z0-9_]+)" => <>.to_string();
Punct<P, T>: Vec<T> = {
P => vec![],
<first:T> <rest:(P Punct<P, T>)?> => {
match rest {
Some(rest) => {
let (_, mut vec) = rest;
vec.insert(0, first);
vec
}
None => vec![first],
}
},
};