generate es6 classes

This commit is contained in:
Eric Vergnaud 2020-10-03 14:09:46 +08:00
parent bec37fc0e5
commit 71cdf89eb3
1 changed files with 100 additions and 111 deletions

View File

@ -48,12 +48,12 @@ javascriptTypeInitMap ::= [
ParserFile(file, parser, namedActions, contextSuperClass) ::= << ParserFile(file, parser, namedActions, contextSuperClass) ::= <<
<fileHeader(file.grammarFileName, file.ANTLRVersion)> <fileHeader(file.grammarFileName, file.ANTLRVersion)>
var antlr4 = require('antlr4/index'); const antlr4 = require('antlr4');
<if(file.genListener)> <if(file.genListener)>
var <file.grammarName>Listener = require('./<file.grammarName>Listener').<file.grammarName>Listener; const <file.grammarName>Listener = require('./<file.grammarName>Listener').default;
<endif> <endif>
<if(file.genVisitor)> <if(file.genVisitor)>
var <file.grammarName>Visitor = require('./<file.grammarName>Visitor').<file.grammarName>Visitor; const <file.grammarName>Visitor = require('./<file.grammarName>Visitor').default;
<endif> <endif>
<namedActions.header> <namedActions.header>
@ -62,54 +62,43 @@ var <file.grammarName>Visitor = require('./<file.grammarName>Visitor').<file.gra
ListenerFile(file, header, namedActions) ::= << ListenerFile(file, header, namedActions) ::= <<
<fileHeader(file.grammarFileName, file.ANTLRVersion)> <fileHeader(file.grammarFileName, file.ANTLRVersion)>
var antlr4 = require('antlr4/index'); const antlr4 = require('antlr4');
// This class defines a complete listener for a parse tree produced by <file.parserName>. // This class defines a complete listener for a parse tree produced by <file.parserName>.
function <file.grammarName>Listener() { export default class <file.grammarName>Listener extends antlr4.tree.ParseTreeListener {
return this;
}
<file.grammarName>Listener.prototype = Object.create(antlr4.tree.ParseTreeListener.prototype);
<file.grammarName>Listener.prototype.constructor = <file.grammarName>Listener;
<file.listenerNames:{lname | <file.listenerNames:{lname |
// Enter a parse tree produced by <file.parserName>#<lname>. // Enter a parse tree produced by <file.parserName>#<lname>.
<file.grammarName>Listener.prototype.enter<lname; format="cap"> = function(ctx) { enter<lname; format="cap">(ctx) {
\}; \}
// Exit a parse tree produced by <file.parserName>#<lname>. // Exit a parse tree produced by <file.parserName>#<lname>.
<file.grammarName>Listener.prototype.exit<lname; format="cap"> = function(ctx) { exit<lname; format="cap">(ctx) {
\}; \}
}; separator="\n"> }; separator="\n">
exports.<file.grammarName>Listener = <file.grammarName>Listener; }
>> >>
VisitorFile(file, header, namedActions) ::= << VisitorFile(file, header, namedActions) ::= <<
<fileHeader(file.grammarFileName, file.ANTLRVersion)> <fileHeader(file.grammarFileName, file.ANTLRVersion)>
var antlr4 = require('antlr4/index'); const antlr4 = require('antlr4');
// This class defines a complete generic visitor for a parse tree produced by <file.parserName>. // This class defines a complete generic visitor for a parse tree produced by <file.parserName>.
function <file.grammarName>Visitor() { export default class <file.grammarName>Visitor extends antlr4.tree.ParseTreeVisitor {
antlr4.tree.ParseTreeVisitor.call(this);
return this;
}
<file.grammarName>Visitor.prototype = Object.create(antlr4.tree.ParseTreeVisitor.prototype);
<file.grammarName>Visitor.prototype.constructor = <file.grammarName>Visitor;
<file.visitorNames:{lname | <file.visitorNames:{lname |
// Visit a parse tree produced by <file.parserName>#<lname>. // Visit a parse tree produced by <file.parserName>#<lname>.
<file.grammarName>Visitor.prototype.visit<lname; format="cap"> = function(ctx) { visit<lname; format="cap"> = function(ctx) {
return this.visitChildren(ctx); return this.visitChildren(ctx);
\}; \}
}; separator="\n"> }; separator="\n">
exports.<file.grammarName>Visitor = <file.grammarName>Visitor; }
>> >>
@ -120,26 +109,27 @@ fileHeader(grammarFileName, ANTLRVersion) ::= <<
Parser(parser, funcs, atn, sempredFuncs, superClass) ::= << Parser(parser, funcs, atn, sempredFuncs, superClass) ::= <<
<if(superClass)> <if(superClass)>
var <superClass> = require('./<superClass>').<superClass>; const <superClass> = require('./<superClass>.js').default;
<endif> <endif>
var grammarFileName = "<parser.grammarFileName; format="java-escape">";
<atn> <atn>
var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN); const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); }); const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
var sharedContextCache = new antlr4.PredictionContextCache(); const sharedContextCache = new antlr4.PredictionContextCache();
var literalNames = [ <parser.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; const literalNames = [ <parser.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
var symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; const symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
var ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ]; const ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
export default class <parser.name> extends <superClass; null="antlr4.Parser"> {
static grammarFileName = "<parser.grammarFileName; format="java-escape">";
class <parser.name> extends <superClass; null="antlr4.Parser"> {
constructor(input) { constructor(input) {
super(input); super(input);
this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache); this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache);
@ -161,10 +151,13 @@ class <parser.name> extends <superClass; null="antlr4.Parser"> {
default: default:
throw "No predicate with index:" + ruleIndex; throw "No predicate with index:" + ruleIndex;
} }
}; }
<sempredFuncs.values; separator="\n"> <sempredFuncs.values; separator="\n">
<endif> <endif>
<funcs; separator="\n">
} }
<parser.name>.EOF = antlr4.Token.EOF; <parser.name>.EOF = antlr4.Token.EOF;
@ -174,12 +167,19 @@ class <parser.name> extends <superClass; null="antlr4.Parser"> {
<parser.rules:{r | <parser.name>.RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor> <parser.rules:{r | <parser.name>.RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>
<funcs; separator="\n"> <funcs:{f | <ruleContexts(f)>}; separator="\n">
module.exports.<parser.name> = <parser.name>; <! Define fields of this parser to export the context classes !>
<parser.funcs:{f | <parser.name>.<f.ctxType> = <f.ctxType>; }; separator="\n">
>> >>
ruleContexts(currentRule) ::= <<
<currentRule.ruleCtx>
<currentRule.altLabelCtxs:{l | <currentRule.altLabelCtxs.(l)>}; separator="\n">
>>
dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= << dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= <<
<if(actionFuncs)> <if(actionFuncs)>
<lexer.name>.prototype.action = function(localctx, ruleIndex, actionIndex) { <lexer.name>.prototype.action = function(localctx, ruleIndex, actionIndex) {
@ -244,16 +244,9 @@ RuleSempredFunction(r, actions) ::= <<
RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble,exceptions) ::= << RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble,exceptions) ::= <<
<ruleCtx>
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n"> <currentRule.name>(<currentRule.args:{a | <a.name>}; separator=", ">) {
let localctx = new <currentRule.ctxType>(this, this._ctx, this.state<currentRule.args:{a | , <a.name>}>);
<! Define fields of this parser to export the context classes !>
<parser.name>.<currentRule.ctxType> = <currentRule.ctxType>;
<parser.name>.prototype.<currentRule.name> = function(<currentRule.args:{a | <a.name>}; separator=", ">) {
var localctx = new <currentRule.ctxType>(this, this._ctx, this.state<currentRule.args:{a | , <a.name>}>);
this.enterRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>); this.enterRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>);
<namedActions.init> <namedActions.init>
<locals; separator="\n"> <locals; separator="\n">
@ -277,7 +270,7 @@ RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,fina
this.exitRule(); this.exitRule();
} }
return localctx; return localctx;
}; }
>> >>
@ -285,18 +278,15 @@ LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,
namedActions,finallyAction,postamble) ::= namedActions,finallyAction,postamble) ::=
<< <<
<ruleCtx> <currentRule.name>(_p<if(currentRule.args)>, <args:{a | , <a>}><endif>) {
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
<parser.name>.prototype.<currentRule.name> = function(_p<if(currentRule.args)>, <args:{a | , <a>}><endif>) {
if(_p===undefined) { if(_p===undefined) {
_p = 0; _p = 0;
} }
var _parentctx = this._ctx; const _parentctx = this._ctx;
var _parentState = this.state; const _parentState = this.state;
var localctx = new <currentRule.ctxType>(this, this._ctx, _parentState<args:{a | , <a.name>}>); let localctx = new <currentRule.ctxType>(this, this._ctx, _parentState<args:{a | , <a.name>}>);
var _prevctx = localctx; let _prevctx = localctx;
var _startState = <currentRule.startState>; const _startState = <currentRule.startState>;
this.enterRecursionRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>, _p); this.enterRecursionRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>, _p);
<namedActions.init> <namedActions.init>
<locals; separator="\n"> <locals; separator="\n">
@ -317,7 +307,7 @@ LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,
this.unrollRecursionContexts(_parentctx) this.unrollRecursionContexts(_parentctx)
} }
return localctx; return localctx;
}; }
>> >>
@ -424,7 +414,7 @@ if(la_===<i><if(!choice.ast.greedy)>+1<endif>) {
StarBlock(choice, alts, sync, iteration) ::= << StarBlock(choice, alts, sync, iteration) ::= <<
this.state = <choice.stateNumber>; this.state = <choice.stateNumber>;
this._errHandler.sync(this); this._errHandler.sync(this);
var _alt = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx) let _alt = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx)
while(_alt!=<choice.exitAlt> && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) { while(_alt!=<choice.exitAlt> && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
if(_alt===1<if(!choice.ast.greedy)>+1<endif>) { if(_alt===1<if(!choice.ast.greedy)>+1<endif>) {
<iteration> <iteration>
@ -440,7 +430,7 @@ while(_alt!=<choice.exitAlt> && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
PlusBlock(choice, alts, error) ::= << PlusBlock(choice, alts, error) ::= <<
this.state = <choice.blockStartStateNumber>; <! alt block decision !> this.state = <choice.blockStartStateNumber>; <! alt block decision !>
this._errHandler.sync(this); this._errHandler.sync(this);
var _alt = 1<if(!choice.ast.greedy)>+1<endif>; let _alt = 1<if(!choice.ast.greedy)>+1<endif>;
do { do {
switch (_alt) { switch (_alt) {
<alts:{alt| <alts:{alt|
@ -604,15 +594,16 @@ RuleContextDecl(r) ::= "this.<r.name> = null; // <r.ctxName>"
RuleContextListDecl(rdecl) ::= "this.<rdecl.name> = []; // of <rdecl.ctxName>s" RuleContextListDecl(rdecl) ::= "this.<rdecl.name> = []; // of <rdecl.ctxName>s"
ContextTokenGetterDecl(t) ::= << ContextTokenGetterDecl(t) ::= <<
<t.name> = function() { <t.name>() {
return this.getToken(<parser.name>.<t.name>, 0); return this.getToken(<parser.name>.<t.name>, 0);
}; };
>> >>
// should never be called // should never be called
ContextTokenListGetterDecl(t) ::= << ContextTokenListGetterDecl(t) ::= <<
def <t.name>_list(self): <t.name>_list() {
return self.getTokens(<parser.name>.<t.name>) return this.getTokens(<parser.name>.<t.name>);
}
>> >>
ContextTokenListIndexedGetterDecl(t) ::= << ContextTokenListIndexedGetterDecl(t) ::= <<
@ -630,16 +621,16 @@ ContextTokenListIndexedGetterDecl(t) ::= <<
>> >>
ContextRuleGetterDecl(r) ::= << ContextRuleGetterDecl(r) ::= <<
<r.name> = function() { <r.name>() {
return this.getTypedRuleContext(<r.ctxName>,0); return this.getTypedRuleContext(<r.ctxName>,0);
}; };
>> >>
// should never be called // should never be called
ContextRuleListGetterDecl(r) ::= << ContextRuleListGetterDecl(r) ::= <<
def <r.name>_list(self): <r.name>_list() {
return self.getTypedRuleContexts(<parser.name>.<r.ctxName>) return this.getTypedRuleContexts(<parser.name>.<r.ctxName>);
}
>> >>
ContextRuleListIndexedGetterDecl(r) ::= << ContextRuleListIndexedGetterDecl(r) ::= <<
@ -672,6 +663,7 @@ CaptureNextTokenType(d) ::= "<d.varName> = this._input.LA(1);"
StructDecl(struct,ctorAttrs,attrs,getters,dispatchMethods,interfaces,extensionMembers) ::= << StructDecl(struct,ctorAttrs,attrs,getters,dispatchMethods,interfaces,extensionMembers) ::= <<
class <struct.name> extends <if(contextSuperClass)><contextSuperClass><else>antlr4.ParserRuleContext<endif> { class <struct.name> extends <if(contextSuperClass)><contextSuperClass><else>antlr4.ParserRuleContext<endif> {
constructor(parser, parent, invokingState<struct.ctorAttrs:{a | , <a.name>}>) { constructor(parser, parent, invokingState<struct.ctorAttrs:{a | , <a.name>}>) {
if(parent===undefined) { if(parent===undefined) {
parent = null; parent = null;
@ -685,47 +677,48 @@ class <struct.name> extends <if(contextSuperClass)><contextSuperClass><else>antl
<attrs:{a | <a>}; separator="\n"> <attrs:{a | <a>}; separator="\n">
<struct.ctorAttrs:{a | this.<a.name> = <a.name> || null;}; separator="\n"> <struct.ctorAttrs:{a | this.<a.name> = <a.name> || null;}; separator="\n">
} }
<getters:{g | <g>}; separator="\n\n">
<if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !>
copyFrom(ctx) {
super.copyFrom(ctx);
<struct.attrs:{a | this.<a.name> = ctx.<a.name>;}; separator="\n">
}
<endif>
<dispatchMethods; separator="\n">
<extensionMembers; separator="\n">
} }
<getters:{g | <struct.name>.prototype.<g>}; separator="\n\n">
<if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !>
<struct.name>.prototype.copyFrom = function(ctx) {
<if(contextSuperClass)><contextSuperClass><else>antlr4.ParserRuleContext<endif>.prototype.copyFrom.call(this, ctx);
<struct.attrs:{a | this.<a.name> = ctx.<a.name>;}; separator="\n">
};
<endif>
<dispatchMethods; separator="\n">
<extensionMembers; separator="\n">
>> >>
AltLabelStructDecl(struct,attrs,getters,dispatchMethods) ::= << AltLabelStructDecl(struct,attrs,getters,dispatchMethods) ::= <<
class <struct.name> extends <currentRule.name; format="cap">Context { class <struct.name> extends <struct.parentRule; format="cap">Context {
constructor(parser, ctx) { constructor(parser, ctx) {
super(parser); super(parser);
<attrs:{a | <a>;}; separator="\n"> <attrs:{a | <a>;}; separator="\n">
<currentRule.name; format="cap">Context.prototype.copyFrom.call(this, ctx); super.copyFrom(ctx);
} }
}
<struct.name>.prototype = Object.create(<currentRule.name; format="cap">Context.prototype); <getters:{g | <g>}; separator="\n\n">
<struct.name>.prototype.constructor = <struct.name>;
<dispatchMethods; separator="\n">
}
<! Define fields of this parser to export this struct/context class !> <! Define fields of this parser to export this struct/context class !>
<parser.name>.<struct.name> = <struct.name>; <parser.name>.<struct.name> = <struct.name>;
<getters:{g | <struct.name>.prototype.<g>}; separator="\n\n">
<dispatchMethods; separator="\n">
>> >>
ListenerDispatchMethod(method) ::= << ListenerDispatchMethod(method) ::= <<
<struct.name>.prototype.<if(method.isEnter)>enter<else>exit<endif>Rule = function(listener) { <if(method.isEnter)>enter<else>exit<endif>Rule(listener) {
if(listener instanceof <parser.grammarName>Listener ) { if(listener instanceof <parser.grammarName>Listener ) {
listener.<if(method.isEnter)>enter<else>exit<endif><struct.derivedFromName; format="cap">(this); listener.<if(method.isEnter)>enter<else>exit<endif><struct.derivedFromName; format="cap">(this);
} }
}; }
>> >>
@ -787,7 +780,7 @@ _prevctx = localctx;
LexerFile(lexerFile, lexer, namedActions) ::= << LexerFile(lexerFile, lexer, namedActions) ::= <<
<fileHeader(lexerFile.grammarFileName, lexerFile.ANTLRVersion)> <fileHeader(lexerFile.grammarFileName, lexerFile.ANTLRVersion)>
var antlr4 = require('antlr4/index'); const antlr4 = require('antlr4');
<namedActions.header> <namedActions.header>
@ -797,32 +790,28 @@ var antlr4 = require('antlr4/index');
Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass) ::= << Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass) ::= <<
<if(superClass)> <if(superClass)>
var <superClass> = require('./<superClass>').<superClass>; const <superClass> = require('./<superClass>.js').default;
<endif> <endif>
<atn> <atn>
var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN); const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); }); const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
export default class <lexer.name> extends <if(superClass)><superClass><else>antlr4.Lexer<endif> {
static grammarFileName = "<lexer.grammarFileName>";
static channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"<if (lexer.channels)>, <lexer.channels:{c| "<c>"}; separator=", ", wrap, anchor><endif> ];
static modeNames = [ <lexer.modes:{m| "<m>"}; separator=", ", wrap, anchor> ];
static literalNames = [ <lexer.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
static symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
static ruleNames = [ <lexer.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
class <lexer.name> extends <if(superClass)><superClass><else>antlr4.Lexer<endif> {
constructor(input) { constructor(input) {
super(input) super(input)
this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache()); this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache());
<namedActions.members> <namedActions.members>
this.channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"<if (lexer.channels)>, <lexer.channels:{c| "<c>"}; separator=", ", wrap, anchor><endif> ];
this.modeNames = [ <lexer.modes:{m| "<m>"}; separator=", ", wrap, anchor> ];
this.literalNames = [ <lexer.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
this.symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
this.ruleNames = [ <lexer.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
this.grammarFileName = "<lexer.grammarFileName>";
} }
get atn() { get atn() {
@ -851,7 +840,7 @@ module.exports.<lexer.name> = <lexer.name>;
SerializedATN(model) ::= << SerializedATN(model) ::= <<
<! only one segment, can be inlined !> <! only one segment, can be inlined !>
var serializedATN = ["<model.serialized; wrap={",<\n> "}>"].join(""); const serializedATN = ["<model.serialized; wrap={",<\n> "}>"].join("");
>> >>