The Java-based SGLR imploder (used in JSGLRv1) does not build the correct AST for list variables (where the variable name ends with an asterisk) in mixed syntax (such as in Stratego-Java-15).

Reproduce

Parsing:

module foo

rules

  bar:
    _ -> |[ x_name.bar(e_bla*) ]|
    with
      x_name := "a"
    ; e_bla* := [1]

produces the AST:

ToMetaExpr(
  Invoke(
    Method(MethodName(AmbName(Id(meta-var("x_name"))), Id("bar")))
  , []
  )
)

whereas the expected output is:

ToMetaExpr(
  Invoke(
    Method(MethodName(AmbName(Id(meta-var("x_name"))), Id("bar")))
  , meta-listvar("e_bla*")
  )
)

Note that the AST contains an empty list at line 4 instead of the meta-listvar term. This problem occurs when you parse the file from within Spoofax (Spoofax > Show Abstract Syntax) or when you parse programmatically (using Spoofax Core API). The strj compiler does not suffer from this problem; it looks like strj uses a different (Stratego-based) imploder. This also means that for the following example the Spoofax editor will show an “unresolved variable” error on the use of e_arg* but the project will build without a problem:

  java-to-gm-statement:
    java |[ x_method(e_arg*); ]| -> gm |[ x_method(e_arg'*); ]|
    with
      e_arg'* := <map(java-to-gm-expression)> e_arg*

Similarly, the following program contains unresolved variables, but no error shows up:

  java-to-gm-statement:
    java |[ x_method(e_arg*); ]| -> gm |[ x_method(e_arg'*); ]|

Analysis

In this specific example the mixed parse table contains two productions:

  1. {Expr[JavaObject] ","}* = varsym({Expr[JavaObject] ","})
  2. varsym({Expr[JavaObject] ","}) = [lit("e_"),lex(iter-star(char-class([39,range(48,57),range(65,90),range(97,122)]))),lit("*")]

After parsing the example the parse tree contains a parent parse node (corresponding to production 1) and a child parse node (corresponding to production 2). When the TreeBuilder encounters the first parse node it tries to create a list (because {Expr[_] ","}* indicates that a list will follow). Since a list does not follow this fails and the TreeBuilder defaults to an empty list.

Solution

I created a solution, albeit a bit hacky, here (https://github.com/MartijnDwars/jsglr/commit/088366d0210f2aa28e8780b26ea895586584f478). This solution checks if the parent node is a list node and has as child a meta-listvar node, and in that case it takes a different path.

Submitted by Martijn on 14 February 2018 at 14:00

Log in to post comments