ThomasH
ThomasH

Reputation: 23506

Rascal: TrafoFields Syntax error: concrete syntax fragment

I'm trying to re-create Tijs' CurryOn16 example "TrafoFields" scraping the code from the video, but using the Java18.rsc grammar instead of his Java15.rsc. I've parsed the Example.java successfully in the repl, like he did in the video, yielding a var pt. I then try to do the transformation with trafoFields(pt). The response I get is:

|project://Rascal-Test/src/TrafoFields.rsc|(235,142,<12,9>,<16,11>): Syntax error: concrete syntax fragment

My TrafoFields.rsc looks like this:

module TrafoFields

import lang::java::\syntax::Java18;

/**
 * - Make public fields private
 * - add getters and setters
 */

 start[CompilationUnit] trafoFields(start[CompilationUnit] cu) {
    return innermost visit (cu) {
        case  (ClassBody)`{
                         '  <ClassBodyDeclaration* cs1>
                         '  public <Type t> <ID f>;
                         '  <ClassBodyDeclaration* cs2>
                         '}`
         =>  (ClassBody)`{
                         '  <ClassBodyDeclaration* cs1>
                         '  private <Type t> <ID f>;
                         '  public void <ID setter>(<Type t> x) {
                         '    this.<ID f> = x;
                         '  }
                         '  public <Type t> <ID getter>() {
                         '      return this.<ID f>;
                         '  }
                         '  <ClassBodyDeclaration* cs2>
                         '}`
         when
            ID setter := [ID]"set<f>",
            ID getter := [ID]"get<f>"
    }
 }

The only deviation from Tijs' code is that I've changed ClassBodyDec* to ClassBodyDeclaration*, as the grammar has this as a non-terminal. Any hint what else could be wrong?

UPDATE

More non-terminal re-writing adapting to Java18 grammar:

Upvotes: 1

Views: 210

Answers (1)

Jurgen Vinju
Jurgen Vinju

Reputation: 6696

Ah yes, that is the Achilles-heal of concrete syntax usability; parse errors.

Note that a generalized parser (such as GLL which Rascal uses), simulates "unlimited lookahead" and so a parse error may be reported a few characters or even a few lines after the actual cause (but never before!). So shortening the example (delta debugging) will help localize the cause.

My way-of-life in this is:

  1. First replace all pattern holes by concrete Java snippets. I know Java, so I should be able to write a correct fragment that would have matched the holes.
  2. If there is still a parse error, now you check the top-non-terminal. Is it the one you needed? also make sure there is no extra whitespace before the start and after the end of the fragment inside the backquotes. Still a parse error? Write a shorter fragment first for a sub-nonterminal first.
  3. Parse error solved? this means one of the pattern holes was not syntactically correct. The type of the hole is leading here, it should be one of the non-terminals used the grammar literally, and of course at the right spot in the fragment. Add the holes back in one-by-one until you hit the error again. Then you know the cause and probably also the fix.

Upvotes: 1

Related Questions