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.
The newest version!
/*
* Copyright (c) 2012-2017 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);
}
final CodeGenerator gen;
final Target target;
final ActionAST node;
RuleFunction rf;
final List chunks = new ArrayList();
final OutputModelFactory factory;
StructDecl nodeContext;
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
this.factory = factory;
this.node = node;
this.gen = factory.getGenerator();
this.target = gen.getTarget();
}
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.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);
// 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);
String name = x.getText();
String escapedName = target.escapeIfNeeded(name);
if ( a!=null ) {
switch ( a.dict.type ) {
case ARG:
chunks.add(new ArgRef(nodeContext, name, escapedName));
break;
case RET:
chunks.add(new RetValueRef(rf.ruleCtx, name, escapedName));
break;
case LOCAL:
chunks.add(new LocalRef(nodeContext, name, escapedName));
break;
case PREDEFINED_RULE:
chunks.add(getRulePropertyRef(null, x));
break;
default:
break;
}
}
if ( node.resolver.resolvesToToken(name, node) ) {
String tokenLabel = getTokenLabel(name);
chunks.add(new TokenRef(nodeContext, tokenLabel, target.escapeIfNeeded(tokenLabel))); // $label
return;
}
if ( node.resolver.resolvesToLabel(name, node) ) {
String tokenLabel = getTokenLabel(name);
chunks.add(new LabelRef(nodeContext, tokenLabel, target.escapeIfNeeded(tokenLabel))); // $x for x=ID etc...
return;
}
if ( node.resolver.resolvesToListLabel(name, node) ) {
chunks.add(new ListLabelRef(nodeContext, name, escapedName)); // $ids for ids+=ID etc...
return;
}
Rule r = factory.getGrammar().getRule(name);
if ( r!=null ) {
String ruleLabel = getRuleLabel(name);
chunks.add(new LabelRef(nodeContext, ruleLabel, target.escapeIfNeeded(ruleLabel))); // $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(), target.escapeIfNeeded(y.getText()))); break; // has to be current rule
case RET:
chunks.add(new QRetValueRef(nodeContext, getRuleLabel(x.getText()), y.getText(), target.escapeIfNeeded(y.getText())));
break;
case PREDEFINED_RULE:
chunks.add(getRulePropertyRef(x, y));
break;
case TOKEN:
chunks.add(getTokenPropertyRef(x, y));
break;
default:
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);
String name = x.getText();
SetAttr s = new SetAttr(nodeContext, name, target.escapeIfNeeded(name), 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());
String name = y.getText();
chunks.add(new NonLocalAttrRef(nodeContext, x.getText(), name, target.escapeIfNeeded(name), 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);
String name = y.getText();
SetNonLocalAttr s = new SetNonLocalAttr(nodeContext, x.getText(), name, target.escapeIfNeeded(name), 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);
return ctor.newInstance(nodeContext, getTokenLabel(x.getText()));
}
catch (Exception e) {
factory.getGrammar().tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, e);
}
return null;
}
RulePropertyRef getRulePropertyRef(Token x, Token prop) {
try {
Class extends RulePropertyRef> c = (x != null ? rulePropToModelMap : thisRulePropToModelMap).get(prop.getText());
Constructor extends RulePropertyRef> ctor = c.getConstructor(StructDecl.class, String.class);
return ctor.newInstance(nodeContext, getRuleLabel((x != null ? x : prop).getText()));
}
catch (Exception e) {
factory.getGrammar().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 target.getImplicitTokenLabel(x);
}
public String getRuleLabel(String x) {
if ( node.resolver.resolvesToLabel(x, node) ) return x;
return target.getImplicitRuleLabel(x);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy