95 lines
2.2 KiB
Text
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],
|
|
}
|
|
},
|
|
};
|