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<String, Class<? extends RulePropertyRef>> thisRulePropToModelMap =
new HashMap<String, Class<? extends RulePropertyRef>>();
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<String, Class<? extends RulePropertyRef>> rulePropToModelMap =
new HashMap<String, Class<? extends RulePropertyRef>>();
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<String, Class<? extends TokenPropertyRef>> tokenPropToModelMap =
new HashMap<String, Class<? extends TokenPropertyRef>>();
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<ActionChunk> chunks = new ArrayList<ActionChunk>();
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<ActionChunk> chunks) {
StringBuilder buf = new StringBuilder();
for (ActionChunk c : chunks) buf.append(c.toString());
return buf.toString();
}
public static List<ActionChunk> 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);
}
}
return translateActionChunk(factory, rf, action, node);
}
public static List<ActionChunk> 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.ruleCtx;
if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(altLabel);
}
ANTLRStringStream in = new ANTLRStringStream(action);
in.setLine(tokenWithinAction.getLine());
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
ActionSplitter trigger = new ActionSplitter(in, translator);
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.ruleCtx, 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())));
return;
}
if ( node.resolver.resolvesToLabel(x.getText(), node) ) {
chunks.add(new LabelRef(nodeContext,getTokenLabel(x.getText())));
return;
}
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
chunks.add(new ListLabelRef(nodeContext,x.getText()));
return;
}
Rule r = factory.getGrammar().getRule(x.getText());
if ( r!=null ) {
chunks.add(new LabelRef(nodeContext,getRuleLabel(x.getText())));
}
}
@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 ) {
attr(expr, x);
chunks.add(new ActionText(nodeContext, "."+y.getText()));
return;
}
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
if ( a==null ) {
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;
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<ActionChunk> 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<ActionChunk> 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;
}
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.getGenerator().getTarget().getImplicitTokenLabel(x);
}
public String getRuleLabel(String x) {
if ( node.resolver.resolvesToLabel(x, node) ) return x;
return factory.getGenerator().getTarget().getImplicitRuleLabel(x);
}
}