diff --git a/forge-script-lang/src/parser/ast.rs b/forge-script-lang/src/parser/ast.rs index 24690c24670dfede9be8289f83412cf38dcc74f0..5913f3fec256e3f02f457af845154afff7b32333 100644 --- a/forge-script-lang/src/parser/ast.rs +++ b/forge-script-lang/src/parser/ast.rs @@ -193,6 +193,107 @@ pub enum ValueExpression { Typeof(TypeofValue), } +impl ValueExpression { + pub fn add(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Add, + } + } + pub fn sub(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Subtract, + } + } + pub fn mul(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Multiply, + } + } + pub fn div(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Divide, + } + } + pub fn modulo(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Modulo, + } + } + pub fn equals(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::Equals, + } + } + + pub fn bool_and(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::BoolAnd, + } + } + + pub fn bool_or(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::BoolOr, + } + } + + pub fn not_equals(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::NotEquals, + } + } + + pub fn less_than(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::LessThan, + } + } + + pub fn greater_than(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::GreaterThan, + } + } + + pub fn less_than_equal(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::LessThanEqual, + } + } + + pub fn greater_than_equal(lhs: ValueExpression, rhs: ValueExpression) -> Self { + ValueExpression::Binary { + lhs: Box::new(lhs), + rhs: Box::new(rhs), + operator: BinaryOp::GreaterThanEqual, + } + } +} + #[derive(Clone)] #[cfg_attr(any(feature = "debug-ast", test), derive(Debug))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/forge-script-lang/src/parser/forge_grammar.lalrpop b/forge-script-lang/src/parser/forge_grammar.lalrpop index 68a5d3d813cc29cda32d20015361276866abe19e..82e6ff301cd07a22bd8c83d0497ab8a22635ea53 100644 --- a/forge-script-lang/src/parser/forge_grammar.lalrpop +++ b/forge-script-lang/src/parser/forge_grammar.lalrpop @@ -5,158 +5,74 @@ use crate::runtime::numbers::Number; grammar<'a>; pub Program: Program = { - ExpressionList => Program(<>) -}; - -Block: Option<ExpressionList> = { - "{" <ExpressionList?> "}" => <>, -}; - -ExpressionList: ExpressionList = { - <e:Expression> <b:";"?> => { - ExpressionList { - expressions: vec![e], - is_void: b.is_some(), - } - }, - <e:Expression> ";" <mut ls:ExpressionList> => { - let mut new = vec![e]; - new.append(&mut ls.expressions); - - ExpressionList { - expressions: new, - is_void: ls.is_void, - } - } -}; + <Expression> => Program(ExpressionList { expressions: vec![<>], is_void: false }) +} pub Expression: Expression = { - ValueExpression => Expression::Value(<>), - VoidExpression => Expression::Void(<>), -}; - -VoidExpression: VoidExpression = { - AsVoid<PrintStmt> => <>, - AsVoid<ImportStmt> => <>, - AsVoid<ExportStmt> => <>, -}; - -ValueExpression: ValueExpression = { - AsValue<Literal> => <>, - AsValue<Identifier> => <>, - AsValue<IfStatement> => <>, - "(" <lhs:ValueExpression> "+" <rhs:ValueExpression> ")" => ValueExpression::Binary { lhs: Box::new(lhs), rhs: Box::new(rhs), operator: BinaryOp::Add }, - "typeof" <expr:ValueExpression> => TypeofValue(Box::new(expr)).into(), - "-" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Negate }, - "!" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Not }, - "(" <expr:ValueExpression> ")" => GroupedExpression { inner: Box::new(expr) }.into(), + <TopExpression> => Expression::Value(<>), } -//ValueExpression: ValueExpression = { -// #[precedence(level="100")] -// "(" <expr:ValueExpression> ")" => GroupedExpression { inner: Box::new(expr) }.into(), -// #[precedence(level="0")] -// Literal => ValueExpression::Literal(<>), -// #[precedence(level="0")] -// Identifier => <>.into(), -// -// #[precedence(level="2")] -// "typeof" <expr:ValueExpression> => TypeofValue(Box::new(expr)).into(), -// #[precedence(level="2")] -// "-" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Negate }, -// #[precedence(level="2")] -// "!" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Not }, -// -// #[precedence(level = "3")] -// IfStatement => <>.into(), -// -// #[precedence(level="4")] #[assoc(side="left")] -// <lhs:ValueExpression> "*" <rhs:ValueExpression> => { -// ValueExpression::Binary { -// lhs: Box::new(lhs), -// rhs: Box::new(rhs), -// operator: BinaryOp::Multiply, -// } -// }, -// #[precedence(level="4")] #[assoc(side="left")] -// <lhs:ValueExpression> "/" <rhs:ValueExpression> => { -// ValueExpression::Binary { -// lhs: Box::new(lhs), -// rhs: Box::new(rhs), -// operator: BinaryOp::Divide, -// } -// }, -// #[precedence(level="6")] #[assoc(side="left")] -// <lhs:ValueExpression> "+" <rhs:ValueExpression> => { -// ValueExpression::Binary { -// lhs: Box::new(lhs), -// rhs: Box::new(rhs), -// operator: BinaryOp::Add, -// } -// }, -// #[precedence(level="6")] #[assoc(side="left")] -// <lhs:ValueExpression> "-" <rhs:ValueExpression> => { -// ValueExpression::Binary { -// lhs: Box::new(lhs), -// rhs: Box::new(rhs), -// operator: BinaryOp::Subtract, -// } -// }, -//}; - -AsVoid<R>: VoidExpression = { - R => <>.into() +TopExpression: ValueExpression = { + <BoolOrExpression> => <>, } -AsValue<R>: ValueExpression = { - R => <>.into() + +BoolOrExpression: ValueExpression = { + <BoolAndExpression> => <>, + <lhs:BoolOrExpression> "||" <rhs:BoolAndExpression> => ValueExpression::bool_or(lhs, rhs), } -TypeofStmt: TypeofValue = { - "typeof" <ValueExpression> => TypeofValue(Box::new(<>)) +BoolAndExpression: ValueExpression = { + <EqualityExpression> => <>, + <lhs:BoolAndExpression> "&&" <rhs:EqualityExpression> => ValueExpression::bool_and(lhs, rhs), } -PrintStmt: Print = { - "print" <expr:ValueExpression> => Print { expr: Box::new(expr) }, +EqualityExpression: ValueExpression = { + <ComparisonExpression> => <>, + <lhs:EqualityExpression> "==" <rhs:ComparisonExpression> => ValueExpression::equals(lhs, rhs), + <lhs:EqualityExpression> "!=" <rhs:ComparisonExpression> => ValueExpression::not_equals(lhs, rhs), } -ImportStmt: Import = { - "import" "{" <items:IdentifierList> "}" "from" <source:StringValue> => Import { source, items }, + +ComparisonExpression: ValueExpression = { + <AdditiveExpression> => <>, + <lhs:ComparisonExpression> "<" <rhs:AdditiveExpression> => ValueExpression::less_than(lhs, rhs), + <lhs:ComparisonExpression> ">" <rhs:AdditiveExpression> => ValueExpression::greater_than(lhs, rhs), + <lhs:ComparisonExpression> "<=" <rhs:AdditiveExpression> => ValueExpression::greater_than_equal(lhs, rhs), + <lhs:ComparisonExpression> ">=" <rhs:AdditiveExpression> => ValueExpression::greater_than_equal(lhs, rhs), } -ExportStmt: Export = { - "export" "{" <items:IdentifierList> "}" => Export { items }, + +AdditiveExpression: ValueExpression = { + <MultiplicativeExpression> => <>, + <lhs:AdditiveExpression> "+" <rhs:MultiplicativeExpression> => ValueExpression::add(lhs, rhs), + <lhs:AdditiveExpression> "-" <rhs:MultiplicativeExpression> => ValueExpression::sub(lhs, rhs), } -IfStatement: Conditional = { - BareIfStatement => Conditional { blocks: vec![<>], fallback: None }, - <fi:BareIfStatement> "else" <bl:Block> => Conditional { blocks: vec![fi], fallback: bl }, - <fi:BareIfStatement> "else" <ls:IfStatement> => { - let mut ls = ls; - let mut new = vec![fi]; - new.append(&mut ls.blocks); - Conditional { - blocks: new, - fallback: ls.fallback, - } - } -}; +MultiplicativeExpression: ValueExpression = { + <UnaryExpression> => <>, + <lhs:MultiplicativeExpression> "*" <rhs:UnaryExpression> => ValueExpression::mul(lhs, rhs), + <lhs:MultiplicativeExpression> "/" <rhs:UnaryExpression> => ValueExpression::div(lhs, rhs), + <lhs:MultiplicativeExpression> "%" <rhs:UnaryExpression> => ValueExpression::modulo(lhs, rhs), +} -BareIfStatement: GuardedBlock = { - "if" <guard:ValueExpression> <bl:Block> => { - GuardedBlock { - block: bl.unwrap_or_default(), - guard: Box::new(guard), - } - } -}; +UnaryExpression: ValueExpression = { + <IndexedExpression> => <>, + "typeof" <UnaryExpression> => TypeofValue(Box::new(<>)).into(), + "!" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Not }, + "-" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Negate }, +} -ParameterList = ListOf<ValueExpression>; -IdentifierList = ListOf<IdentifierNode>; +IndexedExpression: ValueExpression = { + // Include indexing expression here + // <idx:IndexedExpression> "." <id:Identifier> => Indexed access + <BaseExpression> => <>, +} -IdentifierNode: IdentifierNode = { - IdentifierAlias => IdentifierNode::Alias(<>), - Identifier => IdentifierNode::Direct(<>), -}; +BaseExpression: ValueExpression = { + <Literal> => <>.into(), + <Identifier> => <>.into(), + "(" <TopExpression> ")" => GroupedExpression { inner: Box::new(<>) }.into(), +} -IdentifierAlias: IdentifierAlias = { +IdentifierAsAlias: IdentifierAlias = { <base:Identifier> "as" <alias:Identifier> => IdentifierAlias(base.0, alias.0), }; @@ -178,16 +94,6 @@ StringValue: String = { "owned_string" => <>, }; -ListOf<T>: Vec<T> = { - <mut v:(<T> ",")+> <e:T?> => match e { - None => v, - Some(e) => { - v.push(e); - v - } - } -}; - extern { type Location = usize; type Error = String; diff --git a/forge-script-lang/src/parser/forge_script.rs b/forge-script-lang/src/parser/forge_script.rs index 78b7df73129e786c33449a3b2371fb7f9a95cdb6..a554eb220045e0c5586acd2c1cd535c3224a325a 100644 --- a/forge-script-lang/src/parser/forge_script.rs +++ b/forge-script-lang/src/parser/forge_script.rs @@ -48,7 +48,11 @@ mod grammar_test { #[test_case("null" => matches Ok(_) ; "Parse literal null")] #[test_case("if foo {}" => matches Ok(_) ; "Parse conditional")] #[test_case("2 * 4 - 3" => matches Ok(_) ; "Parse arithmetic")] + #[test_case("10 - 2 * 4 + 3" => matches Ok(_) ; "Parse arithmetic reverse")] fn expression_parsing(prog: &str) -> Result<Expression, String> { - parse_expression(prog) + parse_expression(prog).map(|foo| { + dbg!(&foo); + foo + }) } } diff --git a/forge-script-lang/src/runtime/vm/compile.rs b/forge-script-lang/src/runtime/vm/compile.rs index f985cd1e2d6890b6d1f3084d06dcfde3276ae69a..e1fb05078179bafbb5bfe2398d9e9484eaa66706 100644 --- a/forge-script-lang/src/runtime/vm/compile.rs +++ b/forge-script-lang/src/runtime/vm/compile.rs @@ -65,15 +65,6 @@ impl<'a> Compiler<'a> { Ok(cmp) } - pub fn as_parsing_table(&mut self) -> ParsingRules { - rule_table!(( - ParsingRuleType::LeftParen, - Some(Box::new(compile_expression)), - None, - RulePrecedence::None, - ),) - } - pub fn chunk(&self) -> &Chunk { &self.chunk }