0
votes

I write (own lang -> JS) transpiler, using ANTLR (javascript target using visitor).
Focus is on variations, in target code generation.

An earlier SO post, described solution to a simpler situation. This one being different, primarily due to recursion being involved.

Grammar:

grammar Alang;
...

variableDeclaration : DECL (varDecBl1 | varDecBl2) EOS;
varDecBl1 : ID AS TYP;
varDecBl2 : CMP ID US (SGST varDecBl1+ SGFN);
...


DECL  : 'var-declare' ;
EOS   : ';' ;
SGST  : 'segment-start:' ;
SGFN  : 'segment-finish' ;
AS    : 'as';
CMP   : 'cmp';
US    : 'using';
TYP
: 'str'
| 'int'
| 'bool'
;
ID    : [a-zA-Z0-9_]+ ;

Two different cases of source code needs to be handled differently.

Source code 1:

var-declare fooString as str;

target of which needs to come out as: var fooString;

Source code 2:

var-declare cmp barComplex using 
segment-start:
 barF1 as int
 barF2 as bool
 barF3 as str 
segment-finish;

target of this one has to be: var barComplex = new Map();
(as simple var declaration can't handle value type)

code generation done using:

  visitVarDecBl1 = function(ctx) {    
    this.targetCode += `var ${ctx.getChild(0).getText()};`;
    return this.visitChildren(ctx);
  };

....

  visitVarDecBl2 = function(ctx) {
    this.targetCode += `var ${ctx.getChild(1).getText()} = new Map();`;
    return this.visitChildren(ctx);
  };

(targetCode consolidates the target code)

Above works for case 1.
For case 2, it ends up going beyond var barComplex = new Map(), due to recursive use of rule varDecBl1, which invokes visitVarDecBl1 code gen implement again.

Wrong outcome:

var barComplex = new Map();
var barF1;   // <---- wrong one coming from visitVarDecBl1
var barF2;   // <---- wrong
var barF3;   // <---- wrong

To deal with this, one approach that I want to try, is to make visitVarDecBl1 conditional to parent ctx.
If parent = variableDeclaration, target code = var ${ctx.getChild(0).getText()};.
If parent = varDecBl2, skip generation of code.

But I can't find invoking rule within ctx payload, that I can string compare.
Using something like ctx.parentCtx gives me [378 371 204 196 178 168] (hashes?).

Inputs welcome. (including proposal of a better approach, if any)

1

1 Answers

0
votes

In case anyone comes looking with similar situation at hand, I post the answer myself.
I dealt with it by extracting parent rule myself.

util = require("util");

...

//  parentCtx object -> string
const parentCtxStr = util.inspect(ctx.parentCtx);   

// snip out parent rule from payload, e.g.: 'varDecBl2 {…, ruleIndex: 16, …}'
const snip = parentCtxStr.slice(0,parentCtxStr.indexOf("{")-1); // extracts varDecBl2 for you
}

Now use value of snip to deal with as described above.

Of course, this way establishes a coupling to how payload is structured. And risk breaking in future if that is changed. I'd rather use same stuff through the API, though I couldn't find it.