diff --git a/forge-script-lang/src/parser/ast.rs b/forge-script-lang/src/parser/ast.rs index 4485d55fbc0ab898298bfafe51997386003077b6..feab3203bacc7bc0b4a65da38d576fac9d0a87ee 100644 --- a/forge-script-lang/src/parser/ast.rs +++ b/forge-script-lang/src/parser/ast.rs @@ -388,3 +388,28 @@ pub struct FunctionCall { pub name: Identifier, pub params: ParameterList, } + +macro_rules! impl_into_ast { + ($($type: ty => $variant: expr),+) => { + $( + impl From<$type> for ValueExpression { + fn from(other: $type) -> Self { + $variant(other) + } + } + )+ + }; +} + +impl_into_ast!( + GroupedExpression => ValueExpression::Grouped, + ExpressionList => ValueExpression::Block, + LiteralNode => ValueExpression::Literal, + DeclareIdent => ValueExpression::DeclareIdentifier, + Assignment => ValueExpression::Assignment, + Conditional => ValueExpression::ConditionalBlock, + Identifier => ValueExpression::Identifier, + FunctionCall => ValueExpression::FunctionCall, + DeclareFunction => ValueExpression::DeclareFunction, + TypeofValue => ValueExpression::Typeof +); diff --git a/forge-script-lang/src/parser/grammar.rs b/forge-script-lang/src/parser/grammar.rs index 6cf95b30b34002fa815892970be78551c48922b3..82bbd341019b717d13f41b9c0630720d61b14e8f 100644 --- a/forge-script-lang/src/parser/grammar.rs +++ b/forge-script-lang/src/parser/grammar.rs @@ -10,7 +10,7 @@ peg::parser! { = ex:expression_list() eof() { Program(ex) } pub rule expression() -> Expression - = ex:precedence_expression() { Expression::Value(ex) } + = ex:value_expression() { Expression::Value(ex) } / ex:void_expression() { Expression::Void(ex) } rule void_expression() -> VoidExpression @@ -24,15 +24,15 @@ peg::parser! { = co:conditional_statement() { ValueExpression::ConditionalBlock(co) } / t:type_of() { ValueExpression::Typeof(t) } - / precedence_expression() + // / binary_expression() / decl:declare_variable() { ValueExpression::DeclareIdentifier(decl) } / decl:declare_function() { ValueExpression::DeclareFunction(decl) } / name:simple_identifier() "(" params:param_list()? ")" { ValueExpression::FunctionCall(FunctionCall { name, params: params.unwrap_or_default() }) } - // / left:value_expression() op:binary_operator() right:value_expression() - // { ValueExpression::Binary { lhs: Box::new(left), rhs: Box::new(right), operator: op } } / op:unary_operator() operand:value_expression() { ValueExpression::Unary { operator: op, operand: Box::new(operand) } } + / left:value_expression() op:binary_operator() right:value_expression() + { ValueExpression::Binary { lhs: Box::new(left), rhs: Box::new(right), operator: op } } / grouped() / ident:simple_identifier() !"(" { ValueExpression::Identifier(ident) } / li:literal() { ValueExpression::Literal(li) } @@ -84,37 +84,37 @@ peg::parser! { rule expression_list() -> ExpressionList = ex:(expression() ** ";") term:";"? { ExpressionList { expressions: ex, is_void: term.is_some() } } - #[cache_left_rec] - rule precedence_expression() -> ValueExpression - = precedence! { - "-" z:(@) { ValueExpression::Unary { operator: UnaryOp::Negate, operand: Box::new(z) } } - -- - x:(@) "+" y:@ { ValueExpression::Binary { operator: BinaryOp::Add, lhs: Box::new(x), rhs: Box::new(y) } } - x:(@) "-" y:@ { ValueExpression::Binary { operator: BinaryOp::Subtract, lhs: Box::new(x), rhs: Box::new(y) } } - -- - x:(@) "*" y:@ { ValueExpression::Binary { operator: BinaryOp::Multiply, lhs: Box::new(x), rhs: Box::new(y) } } - x:(@) "/" y:@ { ValueExpression::Binary { operator: BinaryOp::Divide, lhs: Box::new(x), rhs: Box::new(y) } } - x:(@) "%" y:@ { ValueExpression::Binary { operator: BinaryOp::Modulo, lhs: Box::new(x), rhs: Box::new(y) } } - -- - x:(@) "==" y:@ { ValueExpression::Binary { operator: BinaryOp::Equals, lhs: Box::new(x), rhs: Box::new(y) } } - x:(@) "&&" y:@ { ValueExpression::Binary { operator: BinaryOp::BoolAnd, lhs: Box::new(x), rhs: Box::new(y) } } - x:(@) "||" y:@ { ValueExpression::Binary { operator: BinaryOp::BoolOr, lhs: Box::new(x), rhs: Box::new(y) } } - -- - "!" z:(@) { ValueExpression::Unary { operator: UnaryOp::Not, operand: Box::new(z) } } - -- - "(" ex:precedence_expression() ")" { ValueExpression::Grouped(GroupedExpression { inner: Box::new(ex) }) } - val:value_expression() { val } - } - - // rule binary_operator() -> BinaryOp - // = "+" { BinaryOp::Add } - // / "-" { BinaryOp::Subtract } - // / "*" { BinaryOp::Multiply } - // / "/" { BinaryOp::Divide } - // / "%" { BinaryOp::Modulo } - // / "==" { BinaryOp::Equals } - // / "&&" { BinaryOp::BoolAnd } - // / "||" { BinaryOp::BoolOr } + // #[cache_left_rec] + // rule precedence_expression() -> ValueExpression + // = precedence! { + // val:value_expression() { val } + // "-" z:(@) { ValueExpression::Unary { operator: UnaryOp::Negate, operand: Box::new(z) } } + // -- + // x:(@) "+" y:@ { ValueExpression::Binary { operator: BinaryOp::Add, lhs: Box::new(x), rhs: Box::new(y) } } + // x:(@) "-" y:@ { ValueExpression::Binary { operator: BinaryOp::Subtract, lhs: Box::new(x), rhs: Box::new(y) } } + // -- + // x:(@) "*" y:@ { ValueExpression::Binary { operator: BinaryOp::Multiply, lhs: Box::new(x), rhs: Box::new(y) } } + // x:(@) "/" y:@ { ValueExpression::Binary { operator: BinaryOp::Divide, lhs: Box::new(x), rhs: Box::new(y) } } + // x:(@) "%" y:@ { ValueExpression::Binary { operator: BinaryOp::Modulo, lhs: Box::new(x), rhs: Box::new(y) } } + // -- + // x:(@) "==" y:@ { ValueExpression::Binary { operator: BinaryOp::Equals, lhs: Box::new(x), rhs: Box::new(y) } } + // x:(@) "&&" y:@ { ValueExpression::Binary { operator: BinaryOp::BoolAnd, lhs: Box::new(x), rhs: Box::new(y) } } + // x:(@) "||" y:@ { ValueExpression::Binary { operator: BinaryOp::BoolOr, lhs: Box::new(x), rhs: Box::new(y) } } + // -- + // "!" z:(@) { ValueExpression::Unary { operator: UnaryOp::Not, operand: Box::new(z) } } + // -- + // "(" ex:precedence_expression() ")" { ValueExpression::Grouped(GroupedExpression { inner: Box::new(ex) }) } + // } + + rule binary_operator() -> BinaryOp + = "+" { BinaryOp::Add } + / "-" { BinaryOp::Subtract } + / "*" { BinaryOp::Multiply } + / "/" { BinaryOp::Divide } + / "%" { BinaryOp::Modulo } + / "==" { BinaryOp::Equals } + / "&&" { BinaryOp::BoolAnd } + / "||" { BinaryOp::BoolOr } rule unary_operator() -> UnaryOp = "!" { UnaryOp::Not }