Created
January 11, 2020 09:21
-
-
Save cronokirby/ac6f9d6545aeee784c383b0d2133a621 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use crate::ast::*; | |
| use crate::lexer; | |
| grammar; | |
| Comma<T>: Vec<T> = { | |
| <v:(<T> ",")*> <e: T?> => match e { | |
| None => v, | |
| Some(e) => { | |
| let mut v = v; | |
| v.push(e); | |
| v | |
| } | |
| } | |
| } | |
| pub AST: AST = { | |
| <functions:(<Function> ";"?)*> => AST {<>}, | |
| }; | |
| Function: Function = { | |
| "func" <name:name> "(" <args:Comma<name>>")" <body:Block> => Function { name, args, body }, | |
| }; | |
| Block: Vec<Expr> = { | |
| "{" <v:(<Expr> ";")*> <e: Expr?> "}" => match e { | |
| None => v, | |
| Some(e) => { | |
| let mut v = v; | |
| v.push(e); | |
| v | |
| } | |
| } | |
| }; | |
| Expr: Expr = { | |
| <value:name> ":=" <e:Expr> => Expr::Declare(value, Box::new(e)), | |
| <value:name> "=" <e:Expr> => Expr::Assign(value, Box::new(e)), | |
| Expr1 | |
| } | |
| Expr1: Expr = { | |
| <left:Expr2> "&&" <right:Expr1> => Expr::ConditionalOp(BoolOp::And, Box::new(left), Box::new(right)), | |
| Expr2, | |
| }; | |
| Expr2: Expr = { | |
| <left:Expr3> "==" <right:Expr3> => Expr::BinOp(Op::Equal, Box::new(left), Box::new(right)), | |
| <left:Expr3> "!=" <right:Expr3> => Expr::BinOp(Op::NotEqual, Box::new(left), Box::new(right)), | |
| Expr3, | |
| }; | |
| Expr3: Expr = { | |
| <left:Expr4> "<=" <right:Expr4> => Expr::BinOp(Op::Leq, Box::new(left), Box::new(right)), | |
| <left:Expr4> "<" <right:Expr4> => Expr::BinOp(Op::Less, Box::new(left), Box::new(right)), | |
| <left:Expr4> ">=" <right:Expr4> => Expr::BinOp(Op::Geq, Box::new(left), Box::new(right)), | |
| <left:Expr4> ">" <right:Expr4> => Expr::BinOp(Op::Greater, Box::new(left), Box::new(right)), | |
| Expr4 | |
| }; | |
| Expr4: Expr = { | |
| <left:Expr4> "+" <right:Expr5> => Expr::BinOp(Op::Add, Box::new(left), Box::new(right)), | |
| <left:Expr4> "-" <right:Expr5> => Expr::BinOp(Op::Sub, Box::new(left), Box::new(right)), | |
| Expr5, | |
| }; | |
| Expr5: Expr = { | |
| <left:Expr5> "*" <right:Expr6> => Expr::BinOp(Op::Mul, Box::new(left), Box::new(right)), | |
| <left:Expr5> "/" <right:Expr6> => Expr::BinOp(Op::Div, Box::new(left), Box::new(right)), | |
| <left:Expr5> "%" <right:Expr6> => Expr::BinOp(Op::Mod, Box::new(left), Box::new(right)), | |
| Expr6, | |
| }; | |
| Expr6: Expr = { | |
| <value:name> "(" <args:Comma<Expr>> ")" => Expr::Call(value, args), | |
| <l:Litteral> => Expr::Litt(l), | |
| <value:name> => Expr::Name(value), | |
| <Block> => Expr::Block(<>), | |
| <ExprIfElse>, | |
| "(" <Expr> ")", | |
| }; | |
| ExprIfElse: Expr = { | |
| "if" <cond:Expr> <left:Block> <right:("else" <ExprAfterElse>)?> => { | |
| let right = match right { | |
| None => Vec::new(), | |
| Some(v) => v, | |
| }; | |
| Expr::IfElse(Box::new(cond), left, right) | |
| } | |
| } | |
| ExprAfterElse: Vec<Expr> = { | |
| <ExprIfElse> => vec![<>], | |
| <Block>, | |
| } | |
| Litteral: Litteral = { | |
| <value:int> => Litteral::I64(value), | |
| <value:string> => Litteral::Str(value), | |
| <value:bool> => Litteral::Bool(value), | |
| }; | |
| extern { | |
| type Location = lexer::Location; | |
| type Error = lexer::LexError; | |
| enum lexer::Token { | |
| "{" => lexer::Token::OpenBrace, | |
| "}" => lexer::Token::CloseBrace, | |
| "(" => lexer::Token::OpenParens, | |
| ")" => lexer::Token::CloseParens, | |
| ";" => lexer::Token::Semicolon, | |
| ":=" => lexer::Token::Define, | |
| "==" => lexer::Token::DoubleEquals, | |
| "!=" => lexer::Token::NotEquals, | |
| "=" => lexer::Token::Equals, | |
| "<=" => lexer::Token::LessEquals, | |
| "<" => lexer::Token::Less, | |
| ">" => lexer::Token::Greater, | |
| ">=" => lexer::Token::GreaterEquals, | |
| "," => lexer::Token::Comma, | |
| "+" => lexer::Token::Plus, | |
| "-" => lexer::Token::Minus, | |
| "*" => lexer::Token::Asterisk, | |
| "/" => lexer::Token::Slash, | |
| "%" => lexer::Token::Percent, | |
| "&&" => lexer::Token::DoubleAmpersand, | |
| "func" => lexer::Token::Func, | |
| "if" => lexer::Token::If, | |
| "else" => lexer::Token::Else, | |
| name => lexer::Token::Name { value: <String> }, | |
| int => lexer::Token::IntLitteral { value: <i64> }, | |
| string => lexer::Token::StringLitteral { value: <String> }, | |
| bool => lexer::Token::BoolLitteral { value: <bool> }, | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use crate::ast::*; | |
| use crate::lexer; | |
| grammar; | |
| Comma<T>: Vec<T> = { | |
| <v:(<T> ",")*> <e: T?> => match e { | |
| None => v, | |
| Some(e) => { | |
| let mut v = v; | |
| v.push(e); | |
| v | |
| } | |
| } | |
| } | |
| pub AST: AST = { | |
| <functions:(<Function> ";"?)*> => AST {<>}, | |
| }; | |
| Function: Function = { | |
| "func" <name:name> "(" <args:Comma<name>>")" <body:Block> => Function { name, args, body }, | |
| }; | |
| Block: Vec<Expr> = { | |
| "{" <v:(<Expr> ";")*> <e: Expr?> "}" => match e { | |
| None => v, | |
| Some(e) => { | |
| let mut v = v; | |
| v.push(e); | |
| v | |
| } | |
| } | |
| }; | |
| Expr: Expr = { | |
| <value:name> ":=" <e:Expr> => Expr::Declare(value, Box::new(e)), | |
| <value:name> "=" <e:Expr> => Expr::Assign(value, Box::new(e)), | |
| Expr1 | |
| }; | |
| Expr1: Expr = { | |
| <left:Expr2> "||" <right:Expr1> => Expr::ConditionalOp(BoolOp::Or, Box::new(left), Box::new(right)), | |
| Expr2, | |
| }; | |
| Expr2: Expr = { | |
| <left:Expr3> "&&" <right:Expr2> => Expr::ConditionalOp(BoolOp::And, Box::new(left), Box::new(right)), | |
| Expr2, | |
| }; | |
| Expr3: Expr = { | |
| <left:Expr4> "==" <right:Expr4> => Expr::BinOp(Op::Equal, Box::new(left), Box::new(right)), | |
| <left:Expr4> "!=" <right:Expr4> => Expr::BinOp(Op::NotEqual, Box::new(left), Box::new(right)), | |
| Expr4, | |
| }; | |
| Expr4: Expr = { | |
| <left:Expr5> "<=" <right:Expr5> => Expr::BinOp(Op::Leq, Box::new(left), Box::new(right)), | |
| <left:Expr5> "<" <right:Expr5> => Expr::BinOp(Op::Less, Box::new(left), Box::new(right)), | |
| <left:Expr5> ">=" <right:Expr5> => Expr::BinOp(Op::Geq, Box::new(left), Box::new(right)), | |
| <left:Expr5> ">" <right:Expr5> => Expr::BinOp(Op::Greater, Box::new(left), Box::new(right)), | |
| Expr5, | |
| }; | |
| Expr5: Expr = { | |
| <left:Expr5> "+" <right:Expr6> => Expr::BinOp(Op::Add, Box::new(left), Box::new(right)), | |
| <left:Expr5> "-" <right:Expr6> => Expr::BinOp(Op::Sub, Box::new(left), Box::new(right)), | |
| Expr6, | |
| }; | |
| Expr6: Expr = { | |
| <left:Expr6> "*" <right:Expr7> => Expr::BinOp(Op::Mul, Box::new(left), Box::new(right)), | |
| <left:Expr6> "/" <right:Expr7> => Expr::BinOp(Op::Div, Box::new(left), Box::new(right)), | |
| <left:Expr6> "%" <right:Expr7> => Expr::BinOp(Op::Mod, Box::new(left), Box::new(right)), | |
| Expr7, | |
| }; | |
| Expr7: Expr = { | |
| <value:name> "(" <args:Comma<Expr>> ")" => Expr::Call(value, args), | |
| <l:Litteral> => Expr::Litt(l), | |
| <value:name> => Expr::Name(value), | |
| <Block> => Expr::Block(<>), | |
| <ExprIfElse>, | |
| "(" <Expr> ")", | |
| }; | |
| ExprIfElse: Expr = { | |
| "if" <cond:Expr> <left:Block> <right:("else" <ExprAfterElse>)?> => { | |
| let right = match right { | |
| None => Vec::new(), | |
| Some(v) => v, | |
| }; | |
| Expr::IfElse(Box::new(cond), left, right) | |
| } | |
| } | |
| ExprAfterElse: Vec<Expr> = { | |
| <ExprIfElse> => vec![<>], | |
| <Block>, | |
| } | |
| Litteral: Litteral = { | |
| <value:int> => Litteral::I64(value), | |
| <value:string> => Litteral::Str(value), | |
| <value:bool> => Litteral::Bool(value), | |
| }; | |
| extern { | |
| type Location = lexer::Location; | |
| type Error = lexer::LexError; | |
| enum lexer::Token { | |
| "{" => lexer::Token::OpenBrace, | |
| "}" => lexer::Token::CloseBrace, | |
| "(" => lexer::Token::OpenParens, | |
| ")" => lexer::Token::CloseParens, | |
| ";" => lexer::Token::Semicolon, | |
| ":=" => lexer::Token::Define, | |
| "==" => lexer::Token::DoubleEquals, | |
| "!=" => lexer::Token::NotEquals, | |
| "=" => lexer::Token::Equals, | |
| "<=" => lexer::Token::LessEquals, | |
| "<" => lexer::Token::Less, | |
| ">" => lexer::Token::Greater, | |
| ">=" => lexer::Token::GreaterEquals, | |
| "," => lexer::Token::Comma, | |
| "+" => lexer::Token::Plus, | |
| "-" => lexer::Token::Minus, | |
| "*" => lexer::Token::Asterisk, | |
| "/" => lexer::Token::Slash, | |
| "%" => lexer::Token::Percent, | |
| "&&" => lexer::Token::DoubleAmpersand, | |
| "||" => lexer::Token::DoublePipe, | |
| "func" => lexer::Token::Func, | |
| "if" => lexer::Token::If, | |
| "else" => lexer::Token::Else, | |
| name => lexer::Token::Name { value: <String> }, | |
| int => lexer::Token::IntLitteral { value: <i64> }, | |
| string => lexer::Token::StringLitteral { value: <String> }, | |
| bool => lexer::Token::BoolLitteral { value: <bool> }, | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment