antlr-ng
Version:
Next generation ANTLR Tool
844 lines (843 loc) • 33.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import {
CommonToken,
ParserRuleContext,
Token
} from "antlr4ng";
import {
ANTLRv4Parser,
ElementContext
} from "../generated/ANTLRv4Parser.js";
import { ANTLRv4Lexer } from "../generated/ANTLRv4Lexer.js";
import { Grammar } from "../tool/Grammar.js";
import { ActionAST } from "../tool/ast/ActionAST.js";
import { AltAST } from "../tool/ast/AltAST.js";
import { BlockAST } from "../tool/ast/BlockAST.js";
import { GrammarAST } from "../tool/ast/GrammarAST.js";
import { GrammarRootAST } from "../tool/ast/GrammarRootAST.js";
import { NotAST } from "../tool/ast/NotAST.js";
import { OptionalBlockAST } from "../tool/ast/OptionalBlockAST.js";
import { PlusBlockAST } from "../tool/ast/PlusBlockAST.js";
import { PredAST } from "../tool/ast/PredAST.js";
import { RangeAST } from "../tool/ast/RangeAST.js";
import { RuleAST } from "../tool/ast/RuleAST.js";
import { RuleRefAST } from "../tool/ast/RuleRefAST.js";
import { SetAST } from "../tool/ast/SetAST.js";
import { StarBlockAST } from "../tool/ast/StarBlockAST.js";
import { TerminalAST } from "../tool/ast/TerminalAST.js";
import { GrammarType } from "./GrammarType.js";
class ParseTreeToASTConverter {
static {
__name(this, "ParseTreeToASTConverter");
}
/**
* Converts the grammar parse tree to an abstract syntax tree (AST).
* We generate here the same tree structure as produced by the old ANTlR 3.x parser.
*
* @param grammarSpec The root context of the grammar parse tree.
* @param tokens The token stream to use for the AST nodes.
*
* @returns The generated AST.
*/
static convertGrammarSpecToAST(grammarSpec, tokens) {
let name = "";
let type;
if (grammarSpec.grammarDecl().grammarType().LEXER() !== null) {
name = "LEXER_GRAMMAR";
type = GrammarType.Lexer;
} else if (grammarSpec.grammarDecl().grammarType().PARSER() !== null) {
name = "PARSER_GRAMMAR";
type = GrammarType.Parser;
} else {
name = "COMBINED_GRAMMAR";
type = GrammarType.Combined;
}
const token = this.createToken(ANTLRv4Parser.GRAMMAR, grammarSpec);
const root = new GrammarRootAST(ANTLRv4Parser.GRAMMAR, token, name, tokens);
root.grammarType = type;
const grammarName = grammarSpec.grammarDecl().identifier();
root.addChild(this.createASTNode(ANTLRv4Parser.ID, grammarName));
this.convertPrequelConstructToAST(grammarSpec.prequelConstruct(), root);
this.convertRulesToAST(grammarSpec.rules(), root);
grammarSpec.modeSpec().forEach((modeSpec) => {
this.convertModeSpecToAST(modeSpec, root);
});
const options = root.getFirstChildWithType(ANTLRv4Parser.OPTIONS);
if (options) {
Grammar.setNodeOptions(root, options);
}
return root;
}
static convertRuleSpecToAST(rule, ast) {
if (rule.parserRuleSpec()) {
const parserRule = rule.parserRuleSpec();
const ruleAST = this.createVirtualASTNode(RuleAST, ANTLRv4Lexer.RULE, rule, "RULE");
ast.addChild(ruleAST);
ruleAST.addChild(new TerminalAST(this.createToken(ANTLRv4Parser.RULE_REF, parserRule.RULE_REF())));
if (parserRule.argActionBlock()) {
this.convertArgActionBlockToAST(ANTLRv4Lexer.ARG_ACTION, parserRule.argActionBlock(), ruleAST);
}
if (parserRule.ruleReturns()) {
const returnsAST = this.createASTNode(ANTLRv4Parser.RETURNS, parserRule.ruleReturns().RETURNS());
this.convertArgActionBlockToAST(
ANTLRv4Lexer.ARG_ACTION,
parserRule.ruleReturns().argActionBlock(),
returnsAST
);
ruleAST.addChild(returnsAST);
}
if (parserRule.throwsSpec()) {
const throwsAST = this.createASTNode(ANTLRv4Parser.THROWS, parserRule.throwsSpec().THROWS());
parserRule.throwsSpec().qualifiedIdentifier().forEach((id) => {
throwsAST.addChild(this.createASTNode(ANTLRv4Parser.ID, id));
});
ruleAST.addChild(throwsAST);
}
if (parserRule.localsSpec()) {
const localsAST = this.createASTNode(ANTLRv4Parser.LOCALS, parserRule.localsSpec().LOCALS());
this.convertArgActionBlockToAST(
ANTLRv4Lexer.ARG_ACTION,
parserRule.localsSpec().argActionBlock(),
localsAST
);
ruleAST.addChild(localsAST);
}
parserRule.rulePrequel().forEach((prequel) => {
if (prequel.optionsSpec()) {
this.convertOptionsSpecToAST(prequel.optionsSpec(), ruleAST);
} else if (prequel.ruleAction()) {
this.convertRuleActionToAST(prequel.ruleAction(), ruleAST);
}
});
this.convertRuleBlockToAST(parserRule.ruleBlock(), ruleAST);
parserRule.exceptionGroup().exceptionHandler().forEach((exceptionHandler) => {
const exception = this.createASTNode(exceptionHandler.CATCH().symbol.type, exceptionHandler.CATCH());
ruleAST.addChild(exception);
this.convertArgActionBlockToAST(ANTLRv4Lexer.ARG_ACTION, exceptionHandler.argActionBlock(), exception);
this.convertActionBlockToAST(ANTLRv4Lexer.ARG_ACTION, exceptionHandler.actionBlock(), exception);
});
if (parserRule.exceptionGroup().finallyClause()) {
const finallyAST = new BlockAST(this.createToken(
ANTLRv4Lexer.FINALLY,
parserRule.exceptionGroup().finallyClause()
));
ruleAST.addChild(finallyAST);
this.convertActionBlockToAST(
ANTLRv4Lexer.ACTION,
parserRule.exceptionGroup().finallyClause().actionBlock(),
finallyAST
);
}
const options = ruleAST.getFirstChildWithType(ANTLRv4Parser.OPTIONS);
if (options) {
Grammar.setNodeOptions(ruleAST, options);
}
return ruleAST;
} else if (rule.lexerRuleSpec()) {
return this.convertLexerRuleSpecToAST(rule.lexerRuleSpec(), ast);
}
return void 0;
}
static convertRuleBlockToAST(ruleBlock, ast) {
const colon = ruleBlock.parent.COLON();
const blockAST = this.createVirtualASTNode(BlockAST, ANTLRv4Lexer.BLOCK, colon, "BLOCK");
ast.addChild(blockAST);
ruleBlock.ruleAltList().labeledAlt().forEach((labeledAlt) => {
const altAST = this.convertAlternativeToAST(labeledAlt.alternative(), blockAST);
if (altAST && labeledAlt.POUND()) {
const id = this.createASTNode(ANTLRv4Parser.ID, labeledAlt.identifier());
altAST.altLabel = id;
}
});
return blockAST;
}
static convertRulerefToAST(ruleref, ast) {
const ruleRefAST = this.createVirtualASTNode(RuleRefAST, ANTLRv4Parser.RULE_REF, ruleref.RULE_REF());
ast.addChild(ruleRefAST);
if (ruleref.argActionBlock()) {
this.convertArgActionBlockToAST(ANTLRv4Lexer.ARG_ACTION, ruleref.argActionBlock(), ruleRefAST);
}
if (ruleref.elementOptions()) {
this.convertElementOptionsToAST(ruleref.elementOptions(), ruleRefAST);
}
const options = ruleRefAST.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options) {
Grammar.setNodeOptions(ruleRefAST, options);
}
return ruleRefAST;
}
static convertPrequelConstructToAST(prequelConstruct, ast) {
prequelConstruct.forEach((prequel) => {
if (prequel.optionsSpec()) {
this.convertOptionsSpecToAST(prequel.optionsSpec(), ast);
} else if (prequel.delegateGrammars()) {
this.convertDelegateGrammarsToAST(prequel.delegateGrammars(), ast);
} else if (prequel.tokensSpec()) {
this.convertTokensSpec(prequel.tokensSpec(), ast);
} else if (prequel.channelsSpec()) {
this.convertChannelsSpecToAST(prequel.channelsSpec(), ast);
} else if (prequel.action_()) {
this.convertActionRuleToAST(prequel.action_(), ast);
}
});
}
static convertRulesToAST(rules, ast) {
const rulesRoot = this.createVirtualASTNode(GrammarAST, ANTLRv4Lexer.RULES, rules, "RULES");
ast.addChild(rulesRoot);
rules.ruleSpec().forEach((rule) => {
this.convertRuleSpecToAST(rule, rulesRoot);
});
}
static convertModeSpecToAST(modeSpec, ast) {
const mode = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.MODE, modeSpec.MODE(), "MODE");
ast.addChild(mode);
mode.addChild(this.createASTNode(ANTLRv4Parser.ID, modeSpec.identifier()));
modeSpec.lexerRuleSpec().forEach((lexerRule) => {
this.convertLexerRuleSpecToAST(lexerRule, mode);
});
}
static convertOptionsSpecToAST(optionsSpec, ast) {
const options = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.OPTIONS, optionsSpec.OPTIONS(), "OPTIONS");
ast.addChild(options);
optionsSpec.option().forEach((option) => {
const assign = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.ASSIGN, option, "=");
options.addChild(assign);
const id = this.createASTNode(ANTLRv4Parser.ID, option.identifier());
assign.addChild(id);
const value = this.createASTNode(ANTLRv4Parser.STRING_LITERAL, option.optionValue());
assign.addChild(value);
});
}
static convertDelegateGrammarsToAST(delegateGrammars, ast) {
const delegate = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.IMPORT, delegateGrammars, "import");
ast.addChild(delegate);
delegateGrammars.delegateGrammar().forEach((dg) => {
if (dg.ASSIGN()) {
const assign = this.createASTNode(ANTLRv4Parser.ASSIGN, dg.ASSIGN());
delegate.addChild(assign);
assign.addChild(this.createASTNode(ANTLRv4Parser.ID, dg.identifier()[0]));
assign.addChild(this.createASTNode(ANTLRv4Parser.ID, dg.identifier()[1]));
} else {
const id = this.createASTNode(ANTLRv4Parser.ID, dg.identifier()[0]);
delegate.addChild(id);
}
});
return delegate;
}
static convertTokensSpec(tokensSpec, ast) {
if (tokensSpec.idList()) {
const tokens = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.TOKENS, tokensSpec);
ast.addChild(tokens);
tokensSpec.idList().identifier().forEach((id) => {
tokens.addChild(this.createASTNode(ANTLRv4Parser.ID, id));
});
}
}
static convertChannelsSpecToAST(channelsSpec, ast) {
if (channelsSpec.idList()) {
const channels = this.createASTNode(ANTLRv4Parser.CHANNELS, channelsSpec);
ast.addChild(channels);
channelsSpec.idList().identifier().forEach((id) => {
channels.addChild(this.createASTNode(ANTLRv4Parser.ID, id));
});
}
}
static convertActionRuleToAST(actionRule, ast) {
const action = this.createVirtualASTNode(GrammarAST, ANTLRv4Parser.AT, actionRule, "@");
ast.addChild(action);
if (actionRule.actionScopeName()) {
action.addChild(this.createASTNode(ANTLRv4Parser.ID, actionRule.actionScopeName()));
}
action.addChild(this.createASTNode(ANTLRv4Parser.ID, actionRule.identifier()));
this.convertActionBlockToAST(ANTLRv4Lexer.ACTION, actionRule.actionBlock(), action);
}
static convertAtomToAST(atom, ast) {
if (atom.terminalDef()) {
return this.convertTerminalDefToAST(atom.terminalDef(), ast);
} else if (atom.ruleref()) {
return this.convertRulerefToAST(atom.ruleref(), ast);
} else if (atom.notSet()) {
return this.convertNotSetToAST(atom.notSet(), ast);
} else if (atom.wildcard()) {
return this.convertWildcardToAST(atom.wildcard(), ast);
}
return void 0;
}
static convertBlockToAST(block, ast) {
const blockAST = new BlockAST(ANTLRv4Parser.BLOCK, block.LPAREN().symbol, "BLOCK");
ast.addChild(blockAST);
if (block.optionsSpec()) {
this.convertOptionsSpecToAST(block.optionsSpec(), blockAST);
}
block.ruleAction().forEach((ruleAction) => {
this.convertRuleActionToAST(ruleAction, blockAST);
});
this.convertAltListToAST(block.altList(), blockAST);
const options = blockAST.getFirstChildWithType(ANTLRv4Parser.OPTIONS);
if (options) {
Grammar.setNodeOptions(blockAST, options);
}
return blockAST;
}
static convertEbnfSuffixToAST(ebnfSuffix, ast) {
let blockAST;
const first = ebnfSuffix.getChild(0);
switch (first.symbol.type) {
case ANTLRv4Parser.QUESTION: {
blockAST = new OptionalBlockAST(ANTLRv4Lexer.OPTIONAL, this.createToken(
ANTLRv4Lexer.OPTIONAL,
ebnfSuffix
), ebnfSuffix.QUESTION().length === 1);
break;
}
case ANTLRv4Parser.STAR: {
blockAST = new StarBlockAST(
ANTLRv4Lexer.CLOSURE,
this.createToken(ANTLRv4Lexer.CLOSURE, ebnfSuffix),
ebnfSuffix.QUESTION().length === 0
);
break;
}
case ANTLRv4Parser.PLUS: {
blockAST = new PlusBlockAST(
ANTLRv4Lexer.POSITIVE_CLOSURE,
this.createToken(ANTLRv4Lexer.POSITIVE_CLOSURE, ebnfSuffix),
ebnfSuffix.QUESTION().length === 0
);
break;
}
default:
}
ast.addChild(blockAST);
return blockAST;
}
static convertEbnfToAST(ebnf, ast) {
if (ebnf.blockSuffix()) {
const root = this.convertEbnfSuffixToAST(ebnf.blockSuffix().ebnfSuffix(), ast);
if (root) {
const blockAST = this.convertBlockToAST(ebnf.block(), root);
root.startIndex = blockAST.startIndex;
}
return root;
} else {
return this.convertBlockToAST(ebnf.block(), ast);
}
}
static convertActionElementToAST(actionElement, ast) {
const actionBlock = actionElement.actionBlock();
if (!actionBlock) {
return void 0;
}
const isPredicate = actionElement.QUESTION() !== null;
const predicateOptions = actionElement instanceof ElementContext ? actionElement.predicateOptions() : null;
if (isPredicate) {
const predicate = this.createVirtualASTNode(
PredAST,
ANTLRv4Parser.SEMPRED,
actionBlock,
actionBlock.getText() + "?"
);
ast.addChild(predicate);
if (predicateOptions) {
this.convertPredicateOptionsToAST(predicateOptions, predicate);
const options2 = predicate.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options2) {
Grammar.setNodeOptions(predicate, options2);
}
}
return predicate;
}
const actionAST = this.convertActionBlockToAST(ANTLRv4Lexer.ACTION, actionBlock, ast);
if (predicateOptions) {
this.convertPredicateOptionsToAST(predicateOptions, actionAST);
}
const options = actionAST.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options) {
Grammar.setNodeOptions(actionAST, options);
}
return actionAST;
}
static convertActionBlockToAST(astType, actionBlock, ast) {
const text = actionBlock.getText();
const token = this.createToken(astType, actionBlock, text);
token.type = ANTLRv4Parser.ACTION;
const actionAST = new ActionAST(token);
ast.addChild(actionAST);
return actionAST;
}
static convertArgActionBlockToAST(astType, actionBlock, ast) {
const text = actionBlock.getText();
const token = this.createToken(astType, actionBlock, text.substring(1, text.length - 1));
const actionAST = new ActionAST(token);
ast.addChild(actionAST);
return actionAST;
}
static convertPredicateOptionsToAST(options, ast) {
const predicateOptions = this.createVirtualASTNode(
GrammarAST,
ANTLRv4Lexer.ELEMENT_OPTIONS,
options,
"ELEMENT_OPTIONS"
);
ast.addChild(predicateOptions);
options.predicateOption().forEach((option) => {
if (option.elementOption()) {
this.convertElementOptionToAST(option.elementOption(), predicateOptions);
} else if (option.ASSIGN()) {
const assign = this.createASTNode(ANTLRv4Parser.ASSIGN, option.ASSIGN());
predicateOptions.addChild(assign);
const id = this.createASTNode(ANTLRv4Parser.ID, option.identifier());
assign.addChild(id);
if (option.actionBlock()) {
this.convertActionBlockToAST(ANTLRv4Lexer.ACTION, option.actionBlock(), assign);
} else if (option.INT()) {
const int = this.createASTNode(ANTLRv4Parser.INT, option.INT());
assign.addChild(int);
} else if (option.STRING_LITERAL()) {
const string = this.createASTNode(ANTLRv4Parser.STRING_LITERAL, option.STRING_LITERAL());
assign.addChild(string);
}
} else {
const id = this.createASTNode(ANTLRv4Parser.ID, option.identifier());
predicateOptions.addChild(id);
}
});
}
static convertLexerRuleSpecToAST(lexerRule, ast) {
const ruleAST = this.createVirtualASTNode(RuleAST, ANTLRv4Lexer.RULE, lexerRule, "RULE");
ast.addChild(ruleAST);
ruleAST.addChild(this.createASTNode(ANTLRv4Parser.TOKEN_REF, lexerRule.TOKEN_REF()));
if (lexerRule.FRAGMENT()) {
const ruleModifiers = this.createASTNode(ANTLRv4Lexer.RULEMODIFIERS, lexerRule.FRAGMENT());
ruleAST.addChild(ruleModifiers);
ruleModifiers.addChild(this.createASTNode(ANTLRv4Parser.FRAGMENT, lexerRule.FRAGMENT()));
}
if (lexerRule.optionsSpec()) {
this.convertOptionsSpecToAST(lexerRule.optionsSpec(), ruleAST);
}
this.convertLexerRuleBlockToAST(lexerRule.lexerRuleBlock(), ruleAST);
return ruleAST;
}
static convertLexerRuleBlockToAST(lexerRuleBlock, ast) {
const colon = lexerRuleBlock.parent.COLON();
const blockAST = this.createVirtualASTNode(BlockAST, ANTLRv4Lexer.BLOCK, colon, "BLOCK");
ast.addChild(blockAST);
lexerRuleBlock.lexerAltList().lexerAlt().forEach((lexerAlt) => {
this.convertLexerAltToAST(lexerAlt, blockAST);
});
const options = blockAST.getFirstChildWithType(ANTLRv4Parser.OPTIONS);
if (options) {
Grammar.setNodeOptions(blockAST, options);
}
}
static convertLexerAltToAST(lexerAlt, ast) {
if (lexerAlt.lexerElements()) {
if (lexerAlt.lexerCommands()) {
const altAST = this.createVirtualASTNode(
AltAST,
ANTLRv4Lexer.LEXER_ALT_ACTION,
lexerAlt.lexerCommands(),
"LEXER_ALT_ACTION"
);
ast.addChild(altAST);
this.convertLexerElementsToAST(lexerAlt.lexerElements(), altAST);
this.convertLexerCommandsToAST(lexerAlt.lexerCommands(), altAST);
} else {
this.convertLexerElementsToAST(lexerAlt.lexerElements(), ast);
}
}
}
static convertLexerElementsToAST(lexerElements, ast) {
const altAST = this.createVirtualASTNode(AltAST, ANTLRv4Lexer.ALT, lexerElements, "ALT");
ast.addChild(altAST);
if (lexerElements.lexerElement().length === 0) {
altAST.addChild(this.createASTNode(ANTLRv4Lexer.EPSILON, lexerElements));
} else {
lexerElements.lexerElement().forEach((lexerElement) => {
this.convertLexerElementToAST(lexerElement, altAST);
});
}
}
static convertLexerElementToAST(lexerElement, ast) {
if (lexerElement.lexerAtom()) {
if (lexerElement.ebnfSuffix()) {
const ebnfSuffixAST = this.convertEbnfSuffixToAST(lexerElement.ebnfSuffix(), ast);
if (ebnfSuffixAST) {
const blockAST = this.createVirtualASTNode(
BlockAST,
ANTLRv4Parser.BLOCK,
lexerElement.lexerAtom(),
"BLOCK"
);
ebnfSuffixAST.startIndex = blockAST.startIndex;
ebnfSuffixAST.addChild(blockAST);
const altAST = this.createVirtualASTNode(
AltAST,
ANTLRv4Lexer.ALT,
lexerElement.lexerAtom(),
"ALT"
);
blockAST.addChild(altAST);
this.convertLexerAtomToAST(lexerElement.lexerAtom(), altAST);
}
return ebnfSuffixAST;
} else {
return this.convertLexerAtomToAST(lexerElement.lexerAtom(), ast);
}
} else if (lexerElement.lexerBlock()) {
if (lexerElement.ebnfSuffix()) {
const ebnfSuffixAST = this.convertEbnfSuffixToAST(lexerElement.ebnfSuffix(), ast);
if (ebnfSuffixAST) {
const blockAST = this.convertLexerBlockToAST(lexerElement.lexerBlock(), ebnfSuffixAST);
ebnfSuffixAST.startIndex = blockAST.startIndex;
}
return ebnfSuffixAST;
} else {
return this.convertLexerBlockToAST(lexerElement.lexerBlock(), ast);
}
} else if (lexerElement.actionBlock()) {
return this.convertActionElementToAST(lexerElement, ast);
}
return void 0;
}
static convertElementOptionsToAST(elementOptions, ast) {
const options = this.createVirtualASTNode(
GrammarAST,
ANTLRv4Lexer.ELEMENT_OPTIONS,
elementOptions,
"ELEMENT_OPTIONS"
);
elementOptions.elementOption().forEach((elementOption) => {
this.convertElementOptionToAST(elementOption, options);
});
ast.addChild(options);
}
static convertElementOptionToAST(elementOption, ast) {
if (elementOption.ASSIGN()) {
const assign = this.createASTNode(ANTLRv4Parser.ASSIGN, elementOption.ASSIGN());
ast.addChild(assign);
const id = this.createASTNode(ANTLRv4Parser.ID, elementOption.identifier());
assign.addChild(id);
if (elementOption.STRING_LITERAL()) {
const value = this.createASTNode(ANTLRv4Parser.STRING_LITERAL, elementOption.STRING_LITERAL());
assign.addChild(value);
} else if (elementOption.INT()) {
const value = this.createASTNode(ANTLRv4Parser.INT, elementOption.INT());
assign.addChild(value);
} else {
const id2 = this.createASTNode(ANTLRv4Parser.ID, elementOption.qualifiedIdentifier());
assign.addChild(id2);
}
} else {
ast.addChild(this.createASTNode(ANTLRv4Parser.ID, elementOption));
}
}
static convertLexerCommandsToAST(lexerCommands, ast) {
lexerCommands.lexerCommand().forEach((lexerCommand) => {
this.convertLexerCommandToAST(lexerCommand, ast);
});
}
static convertLexerCommandToAST(lexerCommand, ast) {
if (lexerCommand.lexerCommandExpr()) {
const callAST = this.createASTNode(ANTLRv4Lexer.LEXER_ACTION_CALL, lexerCommand);
ast.addChild(callAST);
callAST.addChild(this.createASTNode(ANTLRv4Parser.ID, lexerCommand.lexerCommandName()));
if (lexerCommand.lexerCommandExpr()?.identifier()) {
callAST.addChild(this.createASTNode(
ANTLRv4Parser.ID,
lexerCommand.lexerCommandExpr().identifier()
));
} else {
callAST.addChild(this.createASTNode(ANTLRv4Parser.INT, lexerCommand.lexerCommandExpr().INT()));
}
} else {
if (lexerCommand.lexerCommandName().identifier()) {
ast.addChild(this.createASTNode(ANTLRv4Parser.ID, lexerCommand.lexerCommandName().identifier()));
} else {
ast.addChild(this.createASTNode(ANTLRv4Parser.ID, lexerCommand.lexerCommandName().MODE()));
}
}
}
static convertTerminalDefToAST(terminalDef, ast) {
let terminalAST;
if (terminalDef.TOKEN_REF()) {
const token = this.createToken(ANTLRv4Parser.TOKEN_REF, terminalDef.TOKEN_REF());
terminalAST = new TerminalAST(token);
} else if (terminalDef.STRING_LITERAL()) {
const token = this.createToken(ANTLRv4Parser.STRING_LITERAL, terminalDef.STRING_LITERAL());
terminalAST = new TerminalAST(token);
}
if (terminalAST) {
ast.addChild(terminalAST);
if (terminalDef.elementOptions()) {
this.convertElementOptionsToAST(terminalDef.elementOptions(), terminalAST);
}
const options = terminalAST.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options) {
Grammar.setNodeOptions(terminalAST, options);
}
}
return terminalAST;
}
static convertNotSetToAST(notSet, ast) {
const notAST = new NotAST(ANTLRv4Parser.NOT);
notAST.setText("~");
ast.addChild(notAST);
if (notSet.setElement()) {
const setAST = new SetAST(ANTLRv4Lexer.SET, notSet.start, "SET");
notAST.addChild(setAST);
this.convertSetElementToAST(notSet.setElement(), setAST);
} else if (notSet.blockSet()) {
this.convertBlockSetToAST(notSet.blockSet(), notAST);
}
return notAST;
}
static convertSetElementToAST(setElement, ast) {
if (setElement.TOKEN_REF()) {
const terminalAST = new TerminalAST(this.createToken(ANTLRv4Parser.TOKEN_REF, setElement.TOKEN_REF()));
ast.addChild(terminalAST);
if (setElement.elementOptions()) {
this.convertElementOptionsToAST(setElement.elementOptions(), terminalAST);
}
return terminalAST;
} else if (setElement.STRING_LITERAL()) {
const literalAST = new TerminalAST(this.createToken(
ANTLRv4Parser.STRING_LITERAL,
setElement.STRING_LITERAL()
));
ast.addChild(literalAST);
if (setElement.elementOptions()) {
this.convertElementOptionsToAST(setElement.elementOptions(), literalAST);
}
return literalAST;
} else if (setElement.characterRange()) {
return this.convertCharacterRangeToAST(setElement.characterRange(), ast);
} else if (setElement.LEXER_CHAR_SET()) {
const set = this.createASTNode(ANTLRv4Parser.LEXER_CHAR_SET, setElement.LEXER_CHAR_SET());
ast.addChild(set);
return set;
}
return void 0;
}
static convertBlockSetToAST(blockSet, ast) {
const setAST = new SetAST(ANTLRv4Lexer.SET, blockSet.start, "SET");
ast.addChild(setAST);
blockSet.setElement().forEach((setElement) => {
this.convertSetElementToAST(setElement, setAST);
});
return setAST;
}
static convertLexerAtomToAST(lexerAtom, ast) {
if (lexerAtom.characterRange()) {
return this.convertCharacterRangeToAST(lexerAtom.characterRange(), ast);
} else if (lexerAtom.terminalDef()) {
return this.convertTerminalDefToAST(lexerAtom.terminalDef(), ast);
} else if (lexerAtom.notSet()) {
return this.convertNotSetToAST(lexerAtom.notSet(), ast);
} else if (lexerAtom.LEXER_CHAR_SET()) {
const set = this.createASTNode(ANTLRv4Parser.LEXER_CHAR_SET, lexerAtom.LEXER_CHAR_SET());
ast.addChild(set);
return set;
} else if (lexerAtom.wildcard()) {
return this.convertWildcardToAST(lexerAtom.wildcard(), ast);
}
return void 0;
}
static convertCharacterRangeToAST(characterRange, ast) {
const range = this.createVirtualASTNode(RangeAST, ANTLRv4Parser.RANGE, characterRange, "..");
ast.addChild(range);
characterRange.STRING_LITERAL().forEach((string) => {
const literalAST = new TerminalAST(this.createToken(ANTLRv4Parser.STRING_LITERAL, string));
range.addChild(literalAST);
});
return range;
}
static convertWildcardToAST(wildcard, ast) {
const dotAST = this.createVirtualASTNode(TerminalAST, ANTLRv4Parser.WILDCARD, wildcard.DOT());
ast.addChild(dotAST);
if (wildcard.elementOptions()) {
this.convertElementOptionsToAST(wildcard.elementOptions(), dotAST);
}
const options = dotAST.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options) {
Grammar.setNodeOptions(dotAST, options);
}
return dotAST;
}
static convertRuleActionToAST(ruleAction, ast) {
const action = this.createASTNode(ANTLRv4Parser.AT, ruleAction.AT());
ast.addChild(action);
action.addChild(this.createASTNode(ANTLRv4Parser.ID, ruleAction.identifier()));
this.convertActionBlockToAST(ANTLRv4Lexer.ACTION, ruleAction.actionBlock(), action);
return action;
}
static convertAltListToAST(altList, ast) {
altList.alternative().forEach((alternative) => {
this.convertAlternativeToAST(alternative, ast);
});
return ast;
}
static convertAlternativeToAST(alternative, ast) {
const altAST = this.createVirtualASTNode(AltAST, ANTLRv4Lexer.ALT, alternative, "ALT");
ast.addChild(altAST);
if (alternative.elementOptions()) {
this.convertElementOptionsToAST(alternative.elementOptions(), altAST);
}
if (alternative.element().length === 0) {
altAST.addChild(this.createASTNode(ANTLRv4Lexer.EPSILON, alternative));
} else {
alternative.element().forEach((element) => {
this.convertElementToAST(element, altAST);
});
}
const options = altAST.getFirstChildWithType(ANTLRv4Parser.ELEMENT_OPTIONS);
if (options) {
Grammar.setNodeOptions(altAST, options);
}
return altAST;
}
static convertElementToAST(element, ast) {
if (element.labeledElement()) {
if (element.ebnfSuffix()) {
const ebnfAST = this.convertEbnfSuffixToAST(element.ebnfSuffix(), ast);
if (ebnfAST) {
const blockAST = this.createVirtualASTNode(
BlockAST,
ANTLRv4Lexer.BLOCK,
element.labeledElement(),
"BLOCK"
);
ebnfAST.startIndex = blockAST.startIndex;
ebnfAST.addChild(blockAST);
const altAST = this.createVirtualASTNode(
AltAST,
ANTLRv4Lexer.ALT,
element.labeledElement(),
"ALT"
);
blockAST.addChild(altAST);
this.convertLabeledElementToAST(element.labeledElement(), altAST);
return ebnfAST;
}
} else {
return this.convertLabeledElementToAST(element.labeledElement(), ast);
}
} else if (element.atom()) {
if (element.ebnfSuffix()) {
const ebnfAST = this.convertEbnfSuffixToAST(element.ebnfSuffix(), ast);
if (ebnfAST) {
const blockAST = this.createVirtualASTNode(BlockAST, ANTLRv4Lexer.BLOCK, element.atom(), "BLOCK");
ebnfAST.startIndex = blockAST.startIndex;
ebnfAST.addChild(blockAST);
const altAST = this.createVirtualASTNode(AltAST, ANTLRv4Lexer.ALT, element.atom(), "ALT");
blockAST.addChild(altAST);
this.convertAtomToAST(element.atom(), altAST);
ebnfAST.startIndex = element.start.tokenIndex;
ebnfAST.stopIndex = element.stop.tokenIndex;
}
return ebnfAST;
} else {
return this.convertAtomToAST(element.atom(), ast);
}
} else if (element.ebnf()) {
return this.convertEbnfToAST(element.ebnf(), ast);
} else if (element.actionBlock()) {
return this.convertActionElementToAST(element, ast);
}
return void 0;
}
static convertLabeledElementToAST(labeledElement, ast) {
let root;
if (labeledElement.ASSIGN()) {
root = this.createASTNode(ANTLRv4Parser.ASSIGN, labeledElement.ASSIGN());
} else {
root = this.createASTNode(ANTLRv4Parser.PLUS_ASSIGN, labeledElement.PLUS_ASSIGN());
}
ast.addChild(root);
const id = this.createASTNode(ANTLRv4Parser.ID, labeledElement.identifier());
root.addChild(id);
root.startIndex = id.startIndex;
if (labeledElement.atom()) {
this.convertAtomToAST(labeledElement.atom(), root);
} else if (labeledElement.block()) {
this.convertBlockToAST(labeledElement.block(), root);
}
return root;
}
static convertLexerBlockToAST(lexerBlock, ast) {
const blockAST = this.createVirtualASTNode(BlockAST, ANTLRv4Lexer.BLOCK, lexerBlock.LPAREN(), "BLOCK");
ast.addChild(blockAST);
lexerBlock.lexerAltList().lexerAlt().forEach((lexerAlt) => {
if (lexerAlt.lexerElements()) {
let targetAST;
if (lexerAlt.lexerCommands()) {
const altAST = this.createVirtualASTNode(
AltAST,
ANTLRv4Lexer.LEXER_ALT_ACTION,
lexerAlt.lexerCommands(),
"ALT"
);
blockAST.addChild(altAST);
targetAST = altAST;
} else {
targetAST = blockAST;
}
this.convertLexerElementsToAST(lexerAlt.lexerElements(), targetAST);
}
});
return blockAST;
}
static createToken(type, context, text, column) {
let token;
if (context instanceof ParserRuleContext) {
token = CommonToken.fromSource(
[context.start.tokenSource, context.start.inputStream],
type,
Token.DEFAULT_CHANNEL,
context.start.start,
context.start.stop
);
token.tokenIndex = context.start.tokenIndex;
token.line = context.start.line;
token.column = context.start.column;
} else {
token = CommonToken.fromToken(context.symbol);
token.type = type;
token.tokenIndex = context.symbol.tokenIndex;
token.line = context.symbol.line;
token.column = context.symbol.column;
}
if (text) {
token.text = text;
}
if (column) {
token.column = column;
}
return token;
}
static createASTNode(astType, context) {
const token = this.createToken(astType, context, context.getText());
const ast = new GrammarAST(token);
if (context instanceof ParserRuleContext) {
ast.stopIndex = context.stop.tokenIndex;
}
return ast;
}
static createVirtualASTNode(c, astType, ref, text) {
const sourceToken = ref instanceof ParserRuleContext ? ref.start : ref.symbol;
const token = this.createToken(astType, ref, text);
if (text) {
token.text = text;
}
token.tokenIndex = sourceToken.tokenIndex;
const ast = new c(token);
if (ref instanceof ParserRuleContext) {
ast.stopIndex = ref.stop.tokenIndex;
}
return ast;
}
}
export {
ParseTreeToASTConverter
};