diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index a0c9f53..c8e886f 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -6,7 +6,7 @@ mod declaration; mod expression; mod function; mod include; -mod list_identity; +mod list; mod main_component; mod pragma; mod statement; diff --git a/crates/parser/src/grammar/declaration.rs b/crates/parser/src/grammar/declaration.rs index 7238bac..c23223d 100644 --- a/crates/parser/src/grammar/declaration.rs +++ b/crates/parser/src/grammar/declaration.rs @@ -1,4 +1,4 @@ -use super::expression::{expression, identifier_list, parameter_list}; +use super::{expression::expression, list::{expression_tuple, identifier_tuple}}; use crate::{parser::Parser, token_kind::TokenKind::*}; // [N][M-1] @@ -6,9 +6,11 @@ fn array(p: &mut Parser) -> bool { let is_array = p.at(LBracket); while p.at(LBracket) { + let array_marker = p.open(); p.expect(LBracket); expression(p); p.expect(RBracket); + p.close(array_marker, ArrayQuery); } is_array @@ -89,7 +91,7 @@ pub(super) fn var_declaration(p: &mut Parser) { // tuple of variables // eg: var (in1, in2, in3) = (1, 2, 3); if p.at(LParen) { - identifier_list(p); + identifier_tuple(p); if p.at_var_assign() { p.advance(); expression(p); @@ -127,7 +129,7 @@ pub(super) fn signal_declaration(p: &mut Parser) { // tuple of signal // eg: signal (in1, in2, in3) <== tuple_value; if p.at(LParen) { - identifier_list(p); + identifier_tuple(p); // can not assign for input signal if assign_able && p.at_inline_assign_signal() { p.advance(); @@ -181,7 +183,9 @@ pub(super) fn component_declaration(p: &mut Parser) { p.close(m_c, TemplateName); // template params - parameter_list(p); + let parameter_marker = p.open(); + expression_tuple(p); + p.close(parameter_marker, Call); } p.close(m, ComponentDecl); diff --git a/crates/parser/src/grammar/expression.rs b/crates/parser/src/grammar/expression.rs index 6ff7886..2d34bef 100644 --- a/crates/parser/src/grammar/expression.rs +++ b/crates/parser/src/grammar/expression.rs @@ -1,90 +1,59 @@ +use list::expression_tuple; + use crate::parser::Marker; use super::*; pub(super) fn expression(p: &mut Parser) { - let m = p.open(); + let open_marker = p.open(); circom_expression(p); - p.close(m, Expression); + p.close(open_marker, Expression); } /** - * grammar: "(param1, param2,..., paramn)" - * can be an empty () + * TODO: why parse a stament inside expression module??? + * manage 2 cases: normal expression (a++, a-b,...), tenary_conditional_statement (a ? b : c) + * circom_expression = expr ? expr: expr | + * expr */ -pub(super) fn parameter_list(p: &mut Parser) { - let m = p.open(); - p.expect(LParen); - - while !p.at(RParen) && !p.eof() { - // each parameter can be an expression - expression(p); +fn circom_expression(p: &mut Parser) { + if let Some(lhs) = expression_rec(p, 0) { + let current_kind = p.current(); - // there are no parameters remaining - if p.eat(Comma) == false { - break; + if matches!(current_kind, MarkQuestion) { + tenary_conditional_statement(p, lhs); } } - - p.expect(RParen); - - p.close(m, ParameterList); } /** - * grammar: "(iden1, iden2,..., idenn)" - * can be an empty () - */ -pub(super) fn identifier_list(p: &mut Parser) { - let m = p.open(); - p.expect(LParen); - - // iden1, iden2, iden3 - list_identity::parse(p); + * grammar: ? : +* is also an expression, +* whose open and close events are already in the Parser event list +* lhs is that open event +*/ +pub fn tenary_conditional_statement(p: &mut Parser, lhs: Marker) { + // + let open_marker = p.open_before(lhs); + p.close(open_marker, Condition); + + // ? + p.expect(MarkQuestion); + + // ? + let first_expression = p.open(); + expression_rec(p, 0); + p.close(first_expression, Expression); + + // ? : + p.expect(Colon); + + // ? : + let last_expression = p.open(); + expression_rec(p, 0); + p.close(last_expression, Expression); - p.expect(RParen); - p.close(m, IdentifierList); -} - -/** - * grammar: - * "= | <== | <--" expression - */ -// pub(super) fn tuple_init(p: &mut Parser) { -// let m = p.open(); -// p.expect_any(&[Assign, RAssignSignal, RAssignConstraintSignal]); -// expression(p); -// p.close(m, TupleInit); -// } - -fn expression_atom(p: &mut Parser) -> Option { - let m_close: Marker; - match p.current() { - Number => { - let m = p.open(); - p.advance(); - m_close = p.close(m, Number); - Some(m_close) - } - Identifier => { - let m = p.open(); - p.advance(); - m_close = p.close(m, Identifier); - Some(m_close) - } - LParen => { - let m = p.open(); - p.expect(LParen); - expression_rec(p, 0); - p.expect(RParen); - m_close = p.close(m, Tuple); - Some(m_close) - } - _ => { - p.advance_with_error("Invalid Token"); - None - } - } + p.close(open_marker, TenaryConditional); } /** @@ -95,14 +64,13 @@ pub fn expression_rec(p: &mut Parser, pb: u16) -> Option { // next, consume first atom (identifier/number/tuple) let parse_able: Option = { if let Some(pp) = p.current().prefix() { - println!("Prefix..."); let kind = p.current(); - let m = p.open(); + let open_marker = p.open(); // consume prefix token (++, --, -, +, !) p.advance(); // continue with the next tokens expression_rec(p, pp); - Some(p.close(m, kind)) + Some(p.close(open_marker, kind)) } else { expression_atom(p) } @@ -113,61 +81,66 @@ pub fn expression_rec(p: &mut Parser, pb: u16) -> Option { let mut lhs = parse_able.unwrap(); while !p.eof() { - let current_kind = p.current(); + let kind = p.current(); + + if let Some((lp, rp)) = kind.infix() { + // infix case: + + // is already consume in parse_able - if let Some((lp, rp)) = current_kind.infix() { // TODO: what does it mean??? if rp <= pb { return None; } - let m = p.open_before(lhs); + // open event that wrap the first parameter () + let open_marker = p.open_before(lhs); + // consume the infix token p.advance(); // extract the second parameter - // eg: + --> extract expression_rec(p, lp); - lhs = p.close(m, current_kind); - } else if let Some(pp) = current_kind.postfix() { - println!("Postfix..."); + lhs = p.close(open_marker, kind); + + } else if let Some(pp) = kind.postfix() { if pp <= pb { return None; } - match current_kind { + match kind { LParen => { // function call - let m = p.open_before(lhs); - parameter_list(p); - lhs = p.close(m, Call); + let open_marker = p.open_before(lhs); + expression_tuple(p); + lhs = p.close(open_marker, Call); } LBracket => { // array subscript: abc[N - 1] - let m = p.open_before(lhs); + let open_marker = p.open_before(lhs); p.expect(LBracket); expression(p); p.expect(RBracket); - p.close(m, ArrayQuery); + p.close(open_marker, ArrayQuery); } Dot => { // attribute access // abc[N - 1].def OR abc.def --> component call - let m = p.open_before(lhs); + let open_marker = p.open_before(lhs); p.expect(Dot); p.expect(Identifier); - p.close(m, ComponentCall); + p.close(open_marker, ComponentCall); } UnitDec | UnitInc => { - let m = p.open_before(lhs); - // consume token and do nothing + let open_marker = p.open_before(lhs); + // consume token ++/-- and do nothing p.advance(); - p.close(m, Expression); + p.close(open_marker, Expression); } _ => { // not a postfix token - p.advance_with_error(&format!("Expect a postfix token, but found {:?}", current_kind)); + p.advance_with_error(&format!("Expect a postfix token, but found {:?}", kind)); + break; } }; } @@ -176,34 +149,37 @@ pub fn expression_rec(p: &mut Parser, pb: u16) -> Option { } } + // return the outer open marker Some(lhs) } /** - * circom_expression = expr ? expr: expr | - * expr + * the unit element in expression + * eg: a, b, 5, 100, () */ -fn circom_expression(p: &mut Parser) { - if let Some(mut lhs) = expression_rec(p, 0) { - let current_kind = p.current(); - if matches!(current_kind, MarkQuestion) { - let m = p.open_before(lhs); - lhs = p.close(m, Condition); - - let m = p.open_before(lhs); +fn expression_atom(p: &mut Parser) -> Option { + let kind = p.current(); + + match kind { + Number | Identifier => { + let open_marker = p.open(); p.advance(); - - let first_expression = p.open(); - expression_rec(p, 0); - p.close(first_expression, Expression); - - p.expect(Colon); - - let last_expression = p.open(); + let m_close = p.close(open_marker, kind); + Some(m_close) + }, + LParen => { + // () + let open_marker = p.open(); + p.expect(LParen); expression_rec(p, 0); - p.close(last_expression, Expression); - - p.close(m, TenaryConditional); + p.expect(RParen); + let m_close = p.close(open_marker, Expression); + Some(m_close) + }, + _ => { + p.advance_with_error("Invalid Token"); + None } } } + diff --git a/crates/parser/src/grammar/function.rs b/crates/parser/src/grammar/function.rs index 4da6276..283f622 100644 --- a/crates/parser/src/grammar/function.rs +++ b/crates/parser/src/grammar/function.rs @@ -1,3 +1,5 @@ +use list::identifier_tuple; + use crate::grammar::*; // fucntion name() @@ -10,12 +12,10 @@ pub fn function_parse(p: &mut Parser) { p.expect(Identifier); p.close(fn_name_marker, FunctionName); - p.expect(LParen); - let arg_marker = p.open(); - list_identity::parse(p); - p.close(arg_marker, ParameterList); - p.expect(RParen); - + let parameter_marker = p.open(); + identifier_tuple(p); + p.close(parameter_marker, ParameterList); + block::block(p); p.close(m, FunctionDef); diff --git a/crates/parser/src/grammar/list.rs b/crates/parser/src/grammar/list.rs new file mode 100644 index 0000000..83e58d4 --- /dev/null +++ b/crates/parser/src/grammar/list.rs @@ -0,0 +1,69 @@ +use crate::grammar::{ + *, + expression::expression +}; + +/** + * grammar: "(expression-1, expression-2,..., expression-n)" + * can be an empty () + */ +pub(super) fn expression_tuple(p: &mut Parser) { + // let m = p.open(); + p.expect(LParen); + + // expression-1, expression-2,..., expression-n) + while !p.at(RParen) && !p.eof() { + expression(p); + + // there are no expressions remaining + if p.eat(Comma) == false { + break; + } + } + + p.expect(RParen); + + // p.close(m, ExpressionList); +} + +/** + * grammar: "(iden1, iden2,..., idenn)" + * can be an empty () + */ +pub(super) fn identifier_tuple(p: &mut Parser) { + // let m = p.open(); + p.expect(LParen); + + // iden1, iden2, iden3 + while p.at(Identifier) && !p.eof() { + p.expect(Identifier); + + if p.eat(Comma) == false { + break; + } + } + + p.expect(RParen); + // p.close(m, IdentifierList); +} + +/** + * grammar: "[iden1, iden2,..., idenn]" + * can be an empty () + */ +pub(super) fn identifier_list(p: &mut Parser) { + // let m = p.open(); + p.expect(LBracket); + + // iden1, iden2, iden3 + while p.at(Identifier) && !p.eof() { + p.expect(Identifier); + + if p.eat(Comma) == false { + break; + } + } + + p.expect(RBracket); + // p.close(m, IdentifierList); +} \ No newline at end of file diff --git a/crates/parser/src/grammar/list_identity.rs b/crates/parser/src/grammar/list_identity.rs deleted file mode 100644 index 26cfda1..0000000 --- a/crates/parser/src/grammar/list_identity.rs +++ /dev/null @@ -1,12 +0,0 @@ -use super::*; - -// a, b, c, d -pub fn parse(p: &mut Parser) { - while p.at(Identifier) && !p.eof() { - p.expect(Identifier); - - if p.eat(Comma) == false { - break; - } - } -} diff --git a/crates/parser/src/grammar/main_component.rs b/crates/parser/src/grammar/main_component.rs index 5129310..7efdea8 100644 --- a/crates/parser/src/grammar/main_component.rs +++ b/crates/parser/src/grammar/main_component.rs @@ -1,3 +1,5 @@ +use list::identifier_list; + use super::*; /* @@ -13,7 +15,7 @@ pub fn main_component(p: &mut Parser) { p.expect(LCurly); p.expect(PublicKw); p.expect(LBracket); - list_identity::parse(p); + identifier_list(p); p.expect(RBracket); } diff --git a/crates/parser/src/grammar/template.rs b/crates/parser/src/grammar/template.rs index a502365..1c70156 100644 --- a/crates/parser/src/grammar/template.rs +++ b/crates/parser/src/grammar/template.rs @@ -1,3 +1,5 @@ +use list::identifier_tuple; + use crate::grammar::*; /** * template Identifier() {content} @@ -13,11 +15,9 @@ pub fn template(p: &mut Parser) { p.expect(Identifier); p.close(name_marker, TemplateName); - p.expect(LParen); - let arg_marker = p.open(); - list_identity::parse(p); - p.close(arg_marker, ParameterList); - p.expect(RParen); + let parameter_marker = p.open(); + identifier_tuple(p); + p.close(parameter_marker, ParameterList); block::block(p); diff --git a/crates/syntax/src/abstract_syntax_tree/ast.rs b/crates/syntax/src/abstract_syntax_tree/ast.rs index e105b64..3508dd2 100644 --- a/crates/syntax/src/abstract_syntax_tree/ast.rs +++ b/crates/syntax/src/abstract_syntax_tree/ast.rs @@ -91,6 +91,15 @@ impl AstPragma { } ast_node!(AstParameterList, TokenKind::ParameterList); +impl AstParameterList { + pub fn parameters(&self) -> Vec { + self.syntax() + .children() + .filter_map(AstIdentifier::cast) + .collect() + } +} + ast_node!(AstIdentifier, Identifier); impl AstIdentifier { diff --git a/crates/syntax/src/syntax.rs b/crates/syntax/src/syntax.rs index 46db801..036473d 100644 --- a/crates/syntax/src/syntax.rs +++ b/crates/syntax/src/syntax.rs @@ -316,22 +316,23 @@ mod grammar_tests { insta::assert_yaml_snapshot!(name, @"MultiplierN"); // parameter list - let first_param = template + let paramater_list = template .parameter_list() .expect("Can not detect parameter list") + .parameters(); + + let first_param = paramater_list + .get(0) + .expect("Can not detect first parameter") .syntax() - .first_child() - .unwrap() .text() .to_string(); insta::assert_yaml_snapshot!(first_param, @"N"); - let last_param = template - .parameter_list() - .expect("Can not detect parameter list") + let last_param = paramater_list + .last() + .expect("Can not detect last parameter") .syntax() - .last_child() - .unwrap() .text() .to_string(); insta::assert_yaml_snapshot!(last_param, @"QQ");