org.antlr.v4.codegen.ActionTranslator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of antlr4 Show documentation
Show all versions of antlr4 Show documentation
The ANTLR 4 grammar compiler.
/*
* Copyright (c) 2012 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD-3-Clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.codegen;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.Token;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.chunk.ActionChunk;
import org.antlr.v4.codegen.model.chunk.ActionText;
import org.antlr.v4.codegen.model.chunk.ArgRef;
import org.antlr.v4.codegen.model.chunk.LabelRef;
import org.antlr.v4.codegen.model.chunk.ListLabelRef;
import org.antlr.v4.codegen.model.chunk.LocalRef;
import org.antlr.v4.codegen.model.chunk.NonLocalAttrRef;
import org.antlr.v4.codegen.model.chunk.QRetValueRef;
import org.antlr.v4.codegen.model.chunk.RetValueRef;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef_ctx;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef_parser;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef_start;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef_stop;
import org.antlr.v4.codegen.model.chunk.RulePropertyRef_text;
import org.antlr.v4.codegen.model.chunk.SetAttr;
import org.antlr.v4.codegen.model.chunk.SetNonLocalAttr;
import org.antlr.v4.codegen.model.chunk.ThisRulePropertyRef_ctx;
import org.antlr.v4.codegen.model.chunk.ThisRulePropertyRef_parser;
import org.antlr.v4.codegen.model.chunk.ThisRulePropertyRef_start;
import org.antlr.v4.codegen.model.chunk.ThisRulePropertyRef_stop;
import org.antlr.v4.codegen.model.chunk.ThisRulePropertyRef_text;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_channel;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_index;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_int;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_line;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_pos;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_text;
import org.antlr.v4.codegen.model.chunk.TokenPropertyRef_type;
import org.antlr.v4.codegen.model.chunk.TokenRef;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.antlr.v4.parse.ActionSplitter;
import org.antlr.v4.parse.ActionSplitterListener;
import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** */
public class ActionTranslator implements ActionSplitterListener {
public static final Map> thisRulePropToModelMap =
new HashMap>();
static {
thisRulePropToModelMap.put("start", ThisRulePropertyRef_start.class);
thisRulePropToModelMap.put("stop", ThisRulePropertyRef_stop.class);
thisRulePropToModelMap.put("text", ThisRulePropertyRef_text.class);
thisRulePropToModelMap.put("ctx", ThisRulePropertyRef_ctx.class);
thisRulePropToModelMap.put("parser", ThisRulePropertyRef_parser.class);
}
public static final Map> rulePropToModelMap =
new HashMap>();
static {
rulePropToModelMap.put("start", RulePropertyRef_start.class);
rulePropToModelMap.put("stop", RulePropertyRef_stop.class);
rulePropToModelMap.put("text", RulePropertyRef_text.class);
rulePropToModelMap.put("ctx", RulePropertyRef_ctx.class);
rulePropToModelMap.put("parser", RulePropertyRef_parser.class);
}
public static final Map> tokenPropToModelMap =
new HashMap>();
static {
tokenPropToModelMap.put("text", TokenPropertyRef_text.class);
tokenPropToModelMap.put("type", TokenPropertyRef_type.class);
tokenPropToModelMap.put("line", TokenPropertyRef_line.class);
tokenPropToModelMap.put("index", TokenPropertyRef_index.class);
tokenPropToModelMap.put("pos", TokenPropertyRef_pos.class);
tokenPropToModelMap.put("channel", TokenPropertyRef_channel.class);
tokenPropToModelMap.put("int", TokenPropertyRef_int.class);
}
CodeGenerator gen;
ActionAST node;
RuleFunction rf;
List chunks = new ArrayList();
OutputModelFactory factory;
StructDecl nodeContext;
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
this.factory = factory;
this.node = node;
this.gen = factory.getGenerator();
}
public static String toString(List chunks) {
StringBuilder buf = new StringBuilder();
for (ActionChunk c : chunks) buf.append(c.toString());
return buf.toString();
}
public static List translateAction(OutputModelFactory factory,
RuleFunction rf,
Token tokenWithinAction,
ActionAST node)
{
String action = tokenWithinAction.getText();
if ( action!=null && action.length()>0 && action.charAt(0)=='{' ) {
int firstCurly = action.indexOf('{');
int lastCurly = action.lastIndexOf('}');
if ( firstCurly>=0 && lastCurly>=0 ) {
action = action.substring(firstCurly+1, lastCurly); // trim {...}
}
}
return translateActionChunk(factory, rf, action, node);
}
public static List translateActionChunk(OutputModelFactory factory,
RuleFunction rf,
String action,
ActionAST node)
{
Token tokenWithinAction = node.token;
ActionTranslator translator = new ActionTranslator(factory, node);
translator.rf = rf;
factory.getGrammar().tool.log("action-translator", "translate " + action);
String altLabel = node.getAltLabel();
if ( rf!=null ) {
translator.nodeContext = rf.getEffectiveRuleContext(factory.getController());
if ( altLabel!=null ) translator.nodeContext = rf.getEffectiveAltLabelContexts(factory.getController()).get(altLabel);
}
ANTLRStringStream in = new ANTLRStringStream(action);
in.setLine(tokenWithinAction.getLine());
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
ActionSplitter trigger = new ActionSplitter(in, translator);
// forces eval, triggers listener methods
trigger.getActionTokens();
return translator.chunks;
}
@Override
public void attr(String expr, Token x) {
gen.g.tool.log("action-translator", "attr "+x);
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
if ( a!=null ) {
switch ( a.dict.type ) {
case ARG: chunks.add(new ArgRef(nodeContext,x.getText())); break;
case RET: chunks.add(new RetValueRef(rf.getEffectiveRuleContext(factory.getController()), x.getText())); break;
case LOCAL: chunks.add(new LocalRef(nodeContext,x.getText())); break;
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x)); break;
}
}
if ( node.resolver.resolvesToToken(x.getText(), node) ) {
chunks.add(new TokenRef(nodeContext,getTokenLabel(x.getText()))); // $label
return;
}
if ( node.resolver.resolvesToLabel(x.getText(), node) ) {
chunks.add(new LabelRef(nodeContext,getTokenLabel(x.getText()))); // $x for x=ID etc...
return;
}
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
chunks.add(new ListLabelRef(nodeContext,x.getText())); // $ids for ids+=ID etc...
return;
}
Rule r = factory.getGrammar().getRule(x.getText());
if ( r!=null ) {
chunks.add(new LabelRef(nodeContext,getRuleLabel(x.getText()))); // $r for r rule ref
}
}
@Override
public void qualifiedAttr(String expr, Token x, Token y) {
gen.g.tool.log("action-translator", "qattr "+x+"."+y);
if ( node.resolver.resolveToAttribute(x.getText(), node)!=null ) {
// must be a member access to a predefined attribute like $ctx.foo
attr(expr, x);
chunks.add(new ActionText(nodeContext, "."+y.getText()));
return;
}
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
if ( a==null ) {
// Added in response to https://github.com/antlr/antlr4/issues/1211
gen.g.tool.errMgr.grammarError(ErrorType.UNKNOWN_SIMPLE_ATTRIBUTE,
gen.g.fileName, x,
x.getText(),
"rule");
return;
}
switch ( a.dict.type ) {
case ARG: chunks.add(new ArgRef(nodeContext,y.getText())); break; // has to be current rule
case RET:
chunks.add(new QRetValueRef(nodeContext, getRuleLabel(x.getText()), y.getText()));
break;
case PREDEFINED_RULE:
chunks.add(getRulePropertyRef(x, y));
break;
case TOKEN:
chunks.add(getTokenPropertyRef(x, y));
break;
}
}
@Override
public void setAttr(String expr, Token x, Token rhs) {
gen.g.tool.log("action-translator", "setAttr "+x+" "+rhs);
List rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
SetAttr s = new SetAttr(nodeContext, x.getText(), rhsChunks);
chunks.add(s);
}
@Override
public void nonLocalAttr(String expr, Token x, Token y) {
gen.g.tool.log("action-translator", "nonLocalAttr "+x+"::"+y);
Rule r = factory.getGrammar().getRule(x.getText());
chunks.add(new NonLocalAttrRef(nodeContext, x.getText(), y.getText(), r.index));
}
@Override
public void setNonLocalAttr(String expr, Token x, Token y, Token rhs) {
gen.g.tool.log("action-translator", "setNonLocalAttr "+x+"::"+y+"="+rhs);
Rule r = factory.getGrammar().getRule(x.getText());
List rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
SetNonLocalAttr s = new SetNonLocalAttr(nodeContext, x.getText(), y.getText(), r.index, rhsChunks);
chunks.add(s);
}
@Override
public void text(String text) {
chunks.add(new ActionText(nodeContext,text));
}
TokenPropertyRef getTokenPropertyRef(Token x, Token y) {
try {
Class extends TokenPropertyRef> c = tokenPropToModelMap.get(y.getText());
Constructor extends TokenPropertyRef> ctor = c.getConstructor(StructDecl.class, String.class);
TokenPropertyRef ref =
ctor.newInstance(nodeContext, getTokenLabel(x.getText()));
return ref;
}
catch (Exception e) {
factory.getGrammar().tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, e);
}
return null;
}
// $text
RulePropertyRef getRulePropertyRef(Token prop) {
try {
Class extends RulePropertyRef> c = thisRulePropToModelMap.get(prop.getText());
Constructor extends RulePropertyRef> ctor = c.getConstructor(StructDecl.class, String.class);
RulePropertyRef ref =
ctor.newInstance(nodeContext, getRuleLabel(prop.getText()));
return ref;
}
catch (Exception e) {
factory.getGrammar().tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, e);
}
return null;
}
RulePropertyRef getRulePropertyRef(Token x, Token prop) {
Grammar g = factory.getGrammar();
try {
Class extends RulePropertyRef> c = rulePropToModelMap.get(prop.getText());
Constructor extends RulePropertyRef> ctor = c.getConstructor(StructDecl.class, String.class);
RulePropertyRef ref =
ctor.newInstance(nodeContext, getRuleLabel(x.getText()));
return ref;
}
catch (Exception e) {
g.tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, e, prop.getText());
}
return null;
}
public String getTokenLabel(String x) {
if ( node.resolver.resolvesToLabel(x, node) ) return x;
return factory.getTarget().getImplicitTokenLabel(x);
}
public String getRuleLabel(String x) {
if ( node.resolver.resolvesToLabel(x, node) ) return x;
return factory.getTarget().getImplicitRuleLabel(x);
}
}