Skip to content
Snippets Groups Projects
Verified Commit 23dfab80 authored by Louis's avatar Louis :fire:
Browse files

Restructure lalrpop grammar with manual climbing

parent 9bf10abe
No related branches found
No related tags found
No related merge requests found
...@@ -193,6 +193,107 @@ pub enum ValueExpression { ...@@ -193,6 +193,107 @@ pub enum ValueExpression {
Typeof(TypeofValue), 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)] #[derive(Clone)]
#[cfg_attr(any(feature = "debug-ast", test), derive(Debug))] #[cfg_attr(any(feature = "debug-ast", test), derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
......
...@@ -5,158 +5,74 @@ use crate::runtime::numbers::Number; ...@@ -5,158 +5,74 @@ use crate::runtime::numbers::Number;
grammar<'a>; grammar<'a>;
pub Program: Program = { pub Program: Program = {
ExpressionList => Program(<>) <Expression> => Program(ExpressionList { expressions: vec![<>], is_void: false })
}; }
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,
}
}
};
pub Expression: Expression = { pub Expression: Expression = {
ValueExpression => Expression::Value(<>), <TopExpression> => 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(),
} }
//ValueExpression: ValueExpression = { TopExpression: ValueExpression = {
// #[precedence(level="100")] <BoolOrExpression> => <>,
// "(" <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()
} }
AsValue<R>: ValueExpression = {
R => <>.into() BoolOrExpression: ValueExpression = {
<BoolAndExpression> => <>,
<lhs:BoolOrExpression> "||" <rhs:BoolAndExpression> => ValueExpression::bool_or(lhs, rhs),
} }
TypeofStmt: TypeofValue = { BoolAndExpression: ValueExpression = {
"typeof" <ValueExpression> => TypeofValue(Box::new(<>)) <EqualityExpression> => <>,
<lhs:BoolAndExpression> "&&" <rhs:EqualityExpression> => ValueExpression::bool_and(lhs, rhs),
} }
PrintStmt: Print = { EqualityExpression: ValueExpression = {
"print" <expr:ValueExpression> => Print { expr: Box::new(expr) }, <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 = { MultiplicativeExpression: ValueExpression = {
BareIfStatement => Conditional { blocks: vec![<>], fallback: None }, <UnaryExpression> => <>,
<fi:BareIfStatement> "else" <bl:Block> => Conditional { blocks: vec![fi], fallback: bl }, <lhs:MultiplicativeExpression> "*" <rhs:UnaryExpression> => ValueExpression::mul(lhs, rhs),
<fi:BareIfStatement> "else" <ls:IfStatement> => { <lhs:MultiplicativeExpression> "/" <rhs:UnaryExpression> => ValueExpression::div(lhs, rhs),
let mut ls = ls; <lhs:MultiplicativeExpression> "%" <rhs:UnaryExpression> => ValueExpression::modulo(lhs, rhs),
let mut new = vec![fi]; }
new.append(&mut ls.blocks);
Conditional {
blocks: new,
fallback: ls.fallback,
}
}
};
BareIfStatement: GuardedBlock = { UnaryExpression: ValueExpression = {
"if" <guard:ValueExpression> <bl:Block> => { <IndexedExpression> => <>,
GuardedBlock { "typeof" <UnaryExpression> => TypeofValue(Box::new(<>)).into(),
block: bl.unwrap_or_default(), "!" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Not },
guard: Box::new(guard), "-" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Negate },
} }
}
};
ParameterList = ListOf<ValueExpression>; IndexedExpression: ValueExpression = {
IdentifierList = ListOf<IdentifierNode>; // Include indexing expression here
// <idx:IndexedExpression> "." <id:Identifier> => Indexed access
<BaseExpression> => <>,
}
IdentifierNode: IdentifierNode = { BaseExpression: ValueExpression = {
IdentifierAlias => IdentifierNode::Alias(<>), <Literal> => <>.into(),
Identifier => IdentifierNode::Direct(<>), <Identifier> => <>.into(),
}; "(" <TopExpression> ")" => GroupedExpression { inner: Box::new(<>) }.into(),
}
IdentifierAlias: IdentifierAlias = { IdentifierAsAlias: IdentifierAlias = {
<base:Identifier> "as" <alias:Identifier> => IdentifierAlias(base.0, alias.0), <base:Identifier> "as" <alias:Identifier> => IdentifierAlias(base.0, alias.0),
}; };
...@@ -178,16 +94,6 @@ StringValue: String = { ...@@ -178,16 +94,6 @@ StringValue: String = {
"owned_string" => <>, "owned_string" => <>,
}; };
ListOf<T>: Vec<T> = {
<mut v:(<T> ",")+> <e:T?> => match e {
None => v,
Some(e) => {
v.push(e);
v
}
}
};
extern { extern {
type Location = usize; type Location = usize;
type Error = String; type Error = String;
......
...@@ -48,7 +48,11 @@ mod grammar_test { ...@@ -48,7 +48,11 @@ mod grammar_test {
#[test_case("null" => matches Ok(_) ; "Parse literal null")] #[test_case("null" => matches Ok(_) ; "Parse literal null")]
#[test_case("if foo {}" => matches Ok(_) ; "Parse conditional")] #[test_case("if foo {}" => matches Ok(_) ; "Parse conditional")]
#[test_case("2 * 4 - 3" => matches Ok(_) ; "Parse arithmetic")] #[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> { fn expression_parsing(prog: &str) -> Result<Expression, String> {
parse_expression(prog) parse_expression(prog).map(|foo| {
dbg!(&foo);
foo
})
} }
} }
...@@ -65,15 +65,6 @@ impl<'a> Compiler<'a> { ...@@ -65,15 +65,6 @@ impl<'a> Compiler<'a> {
Ok(cmp) 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 { pub fn chunk(&self) -> &Chunk {
&self.chunk &self.chunk
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment