Community
Participate
Working Groups
Currently, the ConcreteSyntaxValidation can not handle grammar rule containing assigned actions. As mentioned by Sebastian, it should be possible to derive an action-free grammar from any grammar. Example: (In reply to comment https://bugs.eclipse.org/bugs/show_bug.cgi?id=267583#c4) > Btw: Did you consider to transform the grammar for use cases such as the > IConcreteSyntaxValidator to remove the complicated parts, e.g. > > Foo: > Bar ({Zonk.baz=current} op=.. foo=Bar)*; > > can be seen by the CSV (but not by the parser) as > > Foo: > Zonk | Bar; > > Zonk: > baz=Foo op=.. foo=Bar; We should investigate this further... if this works for all cases, this could allow the ConcreteSyntaxValidatior to be handle Actions as well. Furthermore, this could be one building block for a Serializer based on a declarative approach (rather than the current one, which is based on a backtracking approach). Both the ConcreteSyntaxValidator and a Declarative Serializer are not afraid of grammatical left/right recursion :D (due to their declarative approach)
I sketched some examples, please review. The numbering of the identifiers is a result of avoiding validation errors in the xtext editor. /******* Example 1: Binary Tree **************/ Expression11: Prim11 ({Add11.left=current} "+" right=Prim11)*; Prim11: {Val} name=ID; /*-------- 1. remove assigned actions. -------*/ Expression12: Prim12 | Add12; Add12: left=(Prim12|Add12) "+" right=Prim12; Prim12: {Val} name=ID; /*-------- 2. remove unassigned rule calls. ------*/ Expression13: {Val} name=ID | {Add13} left=(Prim13|Add13) "+" right=Prim13; Add13: left=(Prim13|Add13) "+" right=Prim13; Prim13: {Val} name=ID; /*-------- 3. simplification. ------*/ Expression14: // this equals Prim14Add14 {Val} name=ID | {Add14} left=Expression14 "+" right=Prim14; Prim14: {Val} name=ID; /******* Example 2: No Tree at all, just a tuple **************/ Expression21: Prim21 ({Add21.left=current} "+" right=Prim21)?; Prim21: {Val} name=ID; /*-------- 1. remove assigned actions. -------*/ Expression22: Prim22 | Add22; Add22: left=Prim22 "+" right=Prim22; Prim22: {Val} name=ID; /******* Example 3: N-ary Tree **************/ Expression31: Prim31 ({Add31.children+=current} ("+" children+=Prim31)+)?; Prim31: {Val} name=ID; /*-------- 1. remove assigned actions. -------*/ Expression32: Prim32 | Add32; Add32: children+=Prim32 ("+" children+=Prim32)*; Prim32: {Val} name=ID; /***** Example 4: A path (which is actually a binary tree) **********/ Path41: {Root41} name=ID ({Segment41.parent=current} "." name=ID)*; /*-------- 1. remove assigned actions. -------*/ Path42: Root42 | Segment42; Segment42: parent=(Root42|Segment42) "." name=ID; Root42: name=ID; /************ Example 5: Expressions with Add, Mult, Parenthesis **/ Addition51 returns Expr51: Multiplication51 ({Add51.left=current} "+" right=Multiplication51)*; Multiplication51 returns Expr51: Prim51 ({Mult51.left=current} "*" right=Prim51)*; Prim51 returns Expr51: {Val} name=ID | "(" Addition51 ")"; /*-------- 1. remove assigned actions. -------*/ Addition52 returns Expr52: Multiplication52 | Add52; Add52: left=(Multiplication52 | Add52) "+" right=Multiplication52; Multiplication52 returns Expr52: Prim52 | Mult52; Mult52: left=(Prim52 | Mult52) "*" right=Prim52; Prim52 returns Expr52: {Val} name=ID | "(" Addition52 ")"; /*---------- 2a. inlining unassigend rule calls -----------*/ // this is not suitable for serialization since it contains // recursion via unassigned rule calls. // Addition -> Add -> Mult -> Prim -> Addition ... Addition53 returns Expr53: Prim53 | Mult53 | Add53; Add53: left=(Prim53 | Mult53 | Add53) "+" right=(Prim53 | Mult53); Mult53: left=(Prim53 | Mult53) "*" right=Prim53; Prim53 returns Expr53: {Val} name=ID | "(" Addition53 ")"; /*---------- 2b. inlining unassigend rule calls -----------*/ Addition54 returns Expr54: {Val} name=ID /* | "(" Addition54 ")" */ | {Mult54} left=(Prim54 | Mult54) "*" right=Prim54 | {Add54} left=(Prim54 | Mult54 | Add54) "+" right=(Prim54 | Mult54); Add54: left=(Prim54 | Mult54 | Add54) "+" right=(Prim54 | Mult54); Mult54: left=(Prim54 | Mult54) "*" right=Prim54; Prim54 returns Expr54: {Val} name=ID | "(" Addition54 ")"; /*---------- 2c. inlining unassigend rule calls -----------*/ Addition55 returns Expr55: // this equals Prim55Mult55Add55 {Val} name=ID | {Mult55} left=Prim55Mult55 "*" right=Prim55 | {Add55} left=Addition55 "+" right=Prim55Mult55; Prim55Mult55 returns Expr55: {Val} name=ID | {Add55} "(" left=Addition55 "+" right=Prim55Mult55 ")" | {Mult55} left=Prim55Mult55 "*" right=Prim55; Prim55 returns Expr55: {Val} name=ID | {Add55} "(" left=Addition55 "+" right=Prim55Mult55 ")" | {Mult55} "(" left=Prim55Mult55 "*" right=Prim55 ")";
depends on bug 333976: The proposed GrammarConstraintProvider implements this algorithm.
Since the new serializer architecture is based on such a grammar, I consider this one to be done. Please reopen if I missed something.
Closing all bugs that were set to RESOLVED before Neon.0