Package org.antlr.v4.codegen

Source Code of org.antlr.v4.codegen.ActionTranslator

/*
* [The "BSD license"]
*  Copyright (c) 2012 Terence Parr
*  Copyright (c) 2012 Sam Harwell
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*  1. Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*  2. Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*  3. The name of the author may not be used to endorse or promote products
*     derived from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
*  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
*  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
*  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

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_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_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);
  }

  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);
  }

  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.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<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);
    // 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.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()))); // $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);
    switch ( a.dict.type ) {
      case ARG: chunks.add(new ArgRef(nodeContext,y.getText())); break; // has to be current rule
      case RET:
        if ( factory.getCurrentRuleFunction()!=null &&
          factory.getCurrentRuleFunction().name.equals(x.getText()) )
        {
          chunks.add(new RetValueRef(rf.ruleCtx, y.getText())); break;
        }
        else {
          chunks.add(new QRetValueRef(nodeContext, getRuleLabel(x.getText()), y.getText())); break;
        }
      case PREDEFINED_RULE:
        if ( factory.getCurrentRuleFunction()!=null &&
          factory.getCurrentRuleFunction().name.equals(x.getText()) )
        {
          chunks.add(getRulePropertyRef(y));
        }
        else {
          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;
  }

  // $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.getGenerator().getTarget().getImplicitTokenLabel(x);
  }

  public String getRuleLabel(String x) {
    if ( node.resolver.resolvesToLabel(x, node) ) return x;
    return factory.getGenerator().getTarget().getImplicitRuleLabel(x);
  }

}
TOP

Related Classes of org.antlr.v4.codegen.ActionTranslator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.