📄 actiontranslator.g
字号:
/* [The "BSD licence"] Copyright (c) 2005-2006 Terence Parr 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.*/lexer grammar ActionTranslator;options { filter=true; // try all non-fragment rules in order specified // output=template; TODO: can we make tokens return templates somehow?}@header {package org.antlr.codegen;import org.antlr.stringtemplate.StringTemplate;import org.antlr.runtime.*;import org.antlr.tool.*;}@members {public List chunks = new ArrayList();Rule enclosingRule;int outerAltNum;Grammar grammar;CodeGenerator generator;antlr.Token actionToken; public ActionTranslatorLexer(CodeGenerator generator, String ruleName, GrammarAST actionAST) { this(new ANTLRStringStream(actionAST.token.getText())); this.generator = generator; this.grammar = generator.grammar; this.enclosingRule = grammar.getRule(ruleName); this.actionToken = actionAST.token; this.outerAltNum = actionAST.outerAltNum; } public ActionTranslatorLexer(CodeGenerator generator, String ruleName, antlr.Token actionToken, int outerAltNum) { this(new ANTLRStringStream(actionToken.getText())); this.generator = generator; grammar = generator.grammar; this.enclosingRule = grammar.getRule(ruleName); this.actionToken = actionToken; this.outerAltNum = outerAltNum; } // BACKWARD COMPATIBILITY UNTIL REGENERATING WITH 3.0b7 public Token emit(int tokenType, int line, int charPosition, int channel, int start, int stop) { Token t = new CommonToken(input, tokenType, channel, start, stop); t.setLine(line); t.setText(text); t.setCharPositionInLine(charPosition); emit(t); return t; }/*public ActionTranslatorLexer(CharStream input, CodeGenerator generator, Grammar grammar, Rule enclosingRule, antlr.Token actionToken, int outerAltNum){ this(input); this.grammar = grammar; this.generator = generator; this.enclosingRule = enclosingRule; this.actionToken = actionToken; this.outerAltNum = outerAltNum;}*//** Return a list of strings and StringTemplate objects that * represent the translated action. */public List translateToChunks() { // System.out.println("###\naction="+action); Token t; do { t = nextToken(); } while ( t.getType()!= Token.EOF ); return chunks;}public String translate() { List theChunks = translateToChunks(); //System.out.println("chunks="+a.chunks); StringBuffer buf = new StringBuffer(); for (int i = 0; i < theChunks.size(); i++) { Object o = (Object) theChunks.get(i); buf.append(o); } //System.out.println("translated: "+buf.toString()); return buf.toString();}public List translateAction(String action) { ActionTranslatorLexer translator = new ActionTranslatorLexer(generator, enclosingRule.name, new antlr.CommonToken(ANTLRParser.ACTION,action),outerAltNum); return translator.translateToChunks();}public boolean isTokenRefInAlt(String id) { return enclosingRule.getTokenRefsInAlt(id, outerAltNum)!=null;}public boolean isRuleRefInAlt(String id) { return enclosingRule.getRuleRefsInAlt(id, outerAltNum)!=null;}public Grammar.LabelElementPair getElementLabel(String id) { return enclosingRule.getLabel(id);}public void checkElementRefUniqueness(String ref, boolean isToken) { List refs = null; if ( isToken ) { refs = enclosingRule.getTokenRefsInAlt(ref, outerAltNum); } else { refs = enclosingRule.getRuleRefsInAlt(ref, outerAltNum); } if ( refs!=null && refs.size()>1 ) { ErrorManager.grammarError(ErrorManager.MSG_NONUNIQUE_REF, grammar, actionToken, ref); }}/** For \$rulelabel.name, return the Attribute found for name. It * will be a predefined property or a return value. */public Attribute getRuleLabelAttribute(String ruleName, String attrName) { Rule r = grammar.getRule(ruleName); AttributeScope scope = r.getLocalAttributeScope(attrName); if ( scope!=null && !scope.isParameterScope ) { return scope.getAttribute(attrName); } return null;}AttributeScope resolveDynamicScope(String scopeName) { if ( grammar.getGlobalScope(scopeName)!=null ) { return grammar.getGlobalScope(scopeName); } Rule scopeRule = grammar.getRule(scopeName); if ( scopeRule!=null ) { return scopeRule.ruleScope; } return null; // not a valid dynamic scope}protected StringTemplate template(String name) { StringTemplate st = generator.getTemplates().getInstanceOf(name); chunks.add(st); return st;}}/** $x.y x is enclosing rule, y is a return value, parameter, or * predefined property. * * r[int i] returns [int j] * : {$r.i, $r.j, $r.start, $r.stop, $r.st, $r.tree} * ; */SET_ENCLOSING_RULE_SCOPE_ATTR : '$' x=ID '.' y=ID WS? '=' expr=ATTR_VALUE_EXPR ';' {enclosingRule!=null && $x.text.equals(enclosingRule.name) && enclosingRule.getLocalAttributeScope($y.text)!=null}? //{System.out.println("found \$rule.attr");} { StringTemplate st = null; AttributeScope scope = enclosingRule.getLocalAttributeScope($y.text); if ( scope.isPredefinedRuleScope ) { if ( $y.text.equals("st") || $y.text.equals("tree") ) { st = template("ruleSetPropertyRef_"+$y.text); grammar.referenceRuleLabelPredefinedAttribute($x.text); st.setAttribute("scope", $x.text); st.setAttribute("attr", $y.text); st.setAttribute("expr", translateAction($expr.text)); } else { ErrorManager.grammarError(ErrorManager.MSG_WRITE_TO_READONLY_ATTR, grammar, actionToken, $x.text, $y.text); } } else if ( scope.isPredefinedLexerRuleScope ) { // this is a better message to emit than the previous one... ErrorManager.grammarError(ErrorManager.MSG_WRITE_TO_READONLY_ATTR, grammar, actionToken, $x.text, $y.text); } else if ( scope.isParameterScope ) { st = template("parameterSetAttributeRef"); st.setAttribute("attr", scope.getAttribute($y.text)); st.setAttribute("expr", translateAction($expr.text)); } else { // must be return value st = template("returnSetAttributeRef"); st.setAttribute("ruleDescriptor", enclosingRule); st.setAttribute("attr", scope.getAttribute($y.text)); st.setAttribute("expr", translateAction($expr.text)); } } ;ENCLOSING_RULE_SCOPE_ATTR : '$' x=ID '.' y=ID {enclosingRule!=null && $x.text.equals(enclosingRule.name) && enclosingRule.getLocalAttributeScope($y.text)!=null}? //{System.out.println("found \$rule.attr");} { StringTemplate st = null; AttributeScope scope = enclosingRule.getLocalAttributeScope($y.text); if ( scope.isPredefinedRuleScope ) { st = template("rulePropertyRef_"+$y.text); grammar.referenceRuleLabelPredefinedAttribute($x.text); st.setAttribute("scope", $x.text); st.setAttribute("attr", $y.text); } else if ( scope.isPredefinedLexerRuleScope ) { // perhaps not the most precise error message to use, but... ErrorManager.grammarError(ErrorManager.MSG_RULE_HAS_NO_ARGS, grammar, actionToken, $x.text); } else if ( scope.isParameterScope ) { st = template("parameterAttributeRef"); st.setAttribute("attr", scope.getAttribute($y.text)); } else { // must be return value st = template("returnAttributeRef"); st.setAttribute("ruleDescriptor", enclosingRule); st.setAttribute("attr", scope.getAttribute($y.text)); } } ;/** Setting $tokenlabel.attr or $tokenref.attr where attr is predefined property of a token is an error. */SET_TOKEN_SCOPE_ATTR : '$' x=ID '.' y=ID WS? '=' {enclosingRule!=null && input.LA(1)!='=' && (enclosingRule.getTokenLabel($x.text)!=null|| isTokenRefInAlt($x.text)) && AttributeScope.tokenScope.getAttribute($y.text)!=null}? //{System.out.println("found \$tokenlabel.attr or \$tokenref.attr");} { ErrorManager.grammarError(ErrorManager.MSG_WRITE_TO_READONLY_ATTR, grammar, actionToken, $x.text, $y.text); } ;/** $tokenlabel.attr or $tokenref.attr where attr is predefined property of a token. * If in lexer grammar, only translate for strings and tokens (rule refs) */TOKEN_SCOPE_ATTR : '$' x=ID '.' y=ID {enclosingRule!=null && (enclosingRule.getTokenLabel($x.text)!=null|| isTokenRefInAlt($x.text)) && AttributeScope.tokenScope.getAttribute($y.text)!=null && (grammar.type!=Grammar.LEXER || getElementLabel($x.text).elementRef.token.getType()==ANTLRParser.TOKEN_REF || getElementLabel($x.text).elementRef.token.getType()==ANTLRParser.STRING_LITERAL)}? // {System.out.println("found \$tokenlabel.attr or \$tokenref.attr");} { String label = $x.text; if ( enclosingRule.getTokenLabel($x.text)==null ) { // \$tokenref.attr gotta get old label or compute new one checkElementRefUniqueness($x.text, true); label = enclosingRule.getElementLabel($x.text, outerAltNum, generator); if ( label==null ) { ErrorManager.grammarError(ErrorManager.MSG_FORWARD_ELEMENT_REF, grammar, actionToken, "\$"+$x.text+"."+$y.text); label = $x.text; } } StringTemplate st = template("tokenLabelPropertyRef_"+$y.text); st.setAttribute("scope", label); st.setAttribute("attr", AttributeScope.tokenScope.getAttribute($y.text)); } ;/** Setting $rulelabel.attr or $ruleref.attr where attr is a predefined property is an error * This must also fail, if we try to access a local attribute's field, like $tree.scope = localObject * That must be handled by LOCAL_ATTR below. ANTLR only concerns itself with the top-level scope * attributes declared in scope {} or parameters, return values and the like. */SET_RULE_SCOPE_ATTR@init {Grammar.LabelElementPair pair=null;String refdRuleName=null;} : '$' x=ID '.' y=ID WS? '=' {enclosingRule!=null && input.LA(1)!='='}? { pair = enclosingRule.getRuleLabel($x.text); refdRuleName = $x.text; if ( pair!=null ) { refdRuleName = pair.referencedRuleName; } } // supercomplicated because I can't exec the above action. // This asserts that if it's a label or a ref to a rule proceed but only if the attribute // is valid for that rule's scope {(enclosingRule.getRuleLabel($x.text)!=null || isRuleRefInAlt($x.text)) && getRuleLabelAttribute(enclosingRule.getRuleLabel($x.text)!=null?enclosingRule.getRuleLabel($x.text).referencedRuleName:$x.text,$y.text)!=null}? //{System.out.println("found set \$rulelabel.attr or \$ruleref.attr: "+$x.text+"."+$y.text);} { ErrorManager.grammarError(ErrorManager.MSG_WRITE_TO_READONLY_ATTR, grammar, actionToken, $x.text, $y.text); } ;/** $rulelabel.attr or $ruleref.attr where attr is a predefined property*/RULE_SCOPE_ATTR@init {Grammar.LabelElementPair pair=null;String refdRuleName=null;} : '$' x=ID '.' y=ID {enclosingRule!=null}? { pair = enclosingRule.getRuleLabel($x.text); refdRuleName = $x.text; if ( pair!=null ) { refdRuleName = pair.referencedRuleName; } } // supercomplicated because I can't exec the above action. // This asserts that if it's a label or a ref to a rule proceed but only if the attribute // is valid for that rule's scope {(enclosingRule.getRuleLabel($x.text)!=null || isRuleRefInAlt($x.text)) && getRuleLabelAttribute(enclosingRule.getRuleLabel($x.text)!=null?enclosingRule.getRuleLabel($x.text).referencedRuleName:$x.text,$y.text)!=null}? //{System.out.println("found \$rulelabel.attr or \$ruleref.attr: "+$x.text+"."+$y.text);} { String label = $x.text; if ( pair==null ) { // \$ruleref.attr gotta get old label or compute new one checkElementRefUniqueness($x.text, false); label = enclosingRule.getElementLabel($x.text, outerAltNum, generator); if ( label==null ) { ErrorManager.grammarError(ErrorManager.MSG_FORWARD_ELEMENT_REF, grammar, actionToken, "\$"+$x.text+"."+$y.text); label = $x.text; } } StringTemplate st; Rule refdRule = grammar.getRule(refdRuleName); AttributeScope scope = refdRule.getLocalAttributeScope($y.text); if ( scope.isPredefinedRuleScope ) { st = template("ruleLabelPropertyRef_"+$y.text); grammar.referenceRuleLabelPredefinedAttribute(refdRuleName); st.setAttribute("scope", label); st.setAttribute("attr", $y.text); } else if ( scope.isPredefinedLexerRuleScope ) { st = template("lexerRuleLabelPropertyRef_"+$y.text); grammar.referenceRuleLabelPredefinedAttribute(refdRuleName); st.setAttribute("scope", label); st.setAttribute("attr", $y.text); } else if ( scope.isParameterScope ) { // TODO: error! }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -