got more symbol resolution in

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6687]
This commit is contained in:
parrt 2010-02-11 13:57:38 -08:00
parent e825a77466
commit b3f7c8e3cc
18 changed files with 627 additions and 313 deletions

View File

@ -0,0 +1,196 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.
*/
package org.antlr.v4.runtime;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.Token;
import java.io.Serializable;
public class CommonToken implements Token, Serializable {
protected int type;
protected int line;
protected int charPositionInLine = -1; // set to invalid position
protected int channel=DEFAULT_CHANNEL;
protected transient CharStream input;
/** We need to be able to change the text once in a while. If
* this is non-null, then getText should return this. Note that
* start/stop are not affected by changing this.
*/
protected String text;
/** What token number is this from 0..n-1 tokens; < 0 implies invalid index */
protected int index = -1;
/** The char position into the input buffer where this token starts */
protected int start;
/** The char position into the input buffer where this token stops */
protected int stop;
public CommonToken(int type) {
this.type = type;
}
public CommonToken(CharStream input, int type, int channel, int start, int stop) {
this.input = input;
this.type = type;
this.channel = channel;
this.start = start;
this.stop = stop;
this.line = input.getLine();
this.charPositionInLine = input.getCharPositionInLine();
}
public CommonToken(int type, String text) {
this.type = type;
this.channel = DEFAULT_CHANNEL;
this.text = text;
}
public CommonToken(Token oldToken) {
text = oldToken.getText();
type = oldToken.getType();
line = oldToken.getLine();
index = oldToken.getTokenIndex();
charPositionInLine = oldToken.getCharPositionInLine();
channel = oldToken.getChannel();
input = oldToken.getInputStream();
if ( oldToken instanceof CommonToken ) {
start = ((CommonToken)oldToken).start;
stop = ((CommonToken)oldToken).stop;
}
}
public int getType() {
return type;
}
public void setLine(int line) {
this.line = line;
}
public String getText() {
if ( text!=null ) {
return text;
}
if ( input==null ) {
return null;
}
if ( start<input.size() && stop<input.size() ) {
text = input.substring(start,stop);
}
else {
text = "<EOF>";
}
return text;
}
/** Override the text for this token. getText() will return this text
* rather than pulling from the buffer. Note that this does not mean
* that start/stop indexes are not valid. It means that that input
* was converted to a new string in the token object.
*/
public void setText(String text) {
this.text = text;
}
public int getLine() {
return line;
}
public int getCharPositionInLine() {
return charPositionInLine;
}
public void setCharPositionInLine(int charPositionInLine) {
this.charPositionInLine = charPositionInLine;
}
public int getChannel() {
return channel;
}
public void setChannel(int channel) {
this.channel = channel;
}
public void setType(int type) {
this.type = type;
}
public int getStartIndex() {
return start;
}
public void setStartIndex(int start) {
this.start = start;
}
public int getStopIndex() {
return stop;
}
public void setStopIndex(int stop) {
this.stop = stop;
}
public int getTokenIndex() {
return index;
}
public void setTokenIndex(int index) {
this.index = index;
}
public CharStream getInputStream() {
return input;
}
public void setInputStream(CharStream input) {
this.input = input;
}
public String toString() {
String channelStr = "";
if ( channel>0 ) {
channelStr=",channel="+channel;
}
String txt = getText();
if ( txt!=null ) {
txt = txt.replaceAll("\n","\\\\n");
txt = txt.replaceAll("\r","\\\\r");
txt = txt.replaceAll("\t","\\\\t");
}
else {
txt = "<no text>";
}
return "[@"+getTokenIndex()+","+start+":"+stop+"='"+txt+"',<"+type+">"+channelStr+","+line+":"+getCharPositionInLine()+"]";
}
}

View File

@ -4,29 +4,11 @@ options { filter=true; }
@header {
package org.antlr.v4.parse;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.tool.*;
}
@members {
/*
public void setQualifiedAttr(Token x, Token y, Token expr) { }
public void qualifiedAttr(Token x, Token y) { }
public void setDynamicScopeAttr(Token x, Token y, Token expr) { }
public void dynamicScopeAttr(Token x, Token y) { }
public void setDynamicNegativeIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicNegativeIndexedScopeAttr(Token x, Token y, Token index) { }
public void setDynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index) { }
public void setAttr(Token x, Token expr) { }
public void attr(Token x) { }
public void templateInstance() { }
public void indirectTemplateInstance() { }
public void setExprAttribute() { }
public void setAttribute() { }
public void templateExpr() { }
public void unknownSyntax(String text) { }
public void text(String text) { }
*/
ActionSplitterListener delegate;
public ActionSplitter(CharStream input, ActionSplitterListener delegate) {
@ -34,6 +16,11 @@ public ActionSplitter(CharStream input, ActionSplitterListener delegate) {
this.delegate = delegate;
}
public void emit(Token token) {
super.emit(token);
}
/** force filtering (and return tokens). triggers all above actions. */
public List<Token> getActionChunks() {
List<Token> chunks = new ArrayList<Token>();

File diff suppressed because it is too large Load Diff

View File

@ -5,36 +5,23 @@ import org.antlr.runtime.Token;
/** */
public interface ActionSplitterListener {
void setQualifiedAttr(Token x, Token y, Token expr);
void qualifiedAttr(Token x, Token y);
void setAttr(Token x, Token expr);
void attr(Token x);
void setDynamicScopeAttr(Token x, Token y, Token expr);
void dynamicScopeAttr(Token x, Token y);
void setDynamicNegativeIndexedScopeAttr(Token x, Token y, Token index, Token expr);
void dynamicNegativeIndexedScopeAttr(Token x, Token y, Token index);
void setDynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index, Token expr);
void dynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index);
void setAttr(Token x, Token expr);
void attr(Token x);
void templateInstance();
void indirectTemplateInstance();
void setExprAttribute();
void setAttribute();
void templateExpr();
void unknownSyntax(String text);
void text(String text);
}

View File

@ -4,51 +4,76 @@ import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.Token;
import org.antlr.v4.parse.ActionSplitter;
import org.antlr.v4.parse.ActionSplitterListener;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarAST;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.*;
import java.util.List;
/** Trigger checks for various kinds of attribute expressions. no side-effects */
public class AttributeChecks implements ActionSplitterListener {
public Grammar g;
public Rule r;
public Rule r; // null if action outside of rule
public Alternative alt; // null if action outside of rule
public GrammarAST node;
String action;
public String action;
public AttributeChecks(Grammar g, Rule r, GrammarAST node, String action) {
public AttributeChecks(Grammar g, Rule r, Alternative alt, GrammarAST node, String action) {
this.g = g;
this.r = r;
this.alt = alt;
this.node = node;
this.action = action;
}
public void examine() {
ActionSplitter splitter =
new ActionSplitter(new ANTLRStringStream(action), this);
ANTLRStringStream in = new ANTLRStringStream(action);
in.setLine(node.getLine());
in.setCharPositionInLine(node.getCharPositionInLine());
ActionSplitter splitter = new ActionSplitter(in, this);
splitter.getActionChunks(); // forces eval, fills extractor
}
// LISTENER METHODS
public void setQualifiedAttr(Token x, Token y, Token expr) {
System.out.println(x+"."+y+"="+expr);
new AttributeChecks(g, r, node, expr.getText()).examine();
new AttributeChecks(g, r, alt, node, expr.getText()).examine();
}
public void qualifiedAttr(Token x, Token y) {
System.out.println(x+"."+y);
AttributeScope s = r.resolveScope(x.getText(), alt);
if ( s==null ) {
System.err.println("not found: "+x);
}
}
public void setDynamicScopeAttr(Token x, Token y, Token expr) { }
public void dynamicScopeAttr(Token x, Token y) { }
public void setDynamicNegativeIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicNegativeIndexedScopeAttr(Token x, Token y, Token index) { }
public void setDynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index) { }
public void setAttr(Token x, Token expr) {
System.out.println(x+"="+expr);
new AttributeChecks(g, r, node, expr.getText()).examine();
System.out.println(x+"="+expr);
if ( !r.resolves(x.getText(), alt) ) System.err.println("not found: "+x);
new AttributeChecks(g, r, alt, node, expr.getText()).examine();
}
public void attr(Token x) {
public void attr(Token x) { // arg, retval, predefined, token ref, rule ref, current rule
System.out.println(x);
if ( !r.resolves(x.getText(), alt) ) System.err.println("not found: "+x);
}
public void setDynamicScopeAttr(Token x, Token y, Token expr) { }
public void dynamicScopeAttr(Token x, Token y) { }
public void setDynamicNegativeIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicNegativeIndexedScopeAttr(Token x, Token y, Token index) { }
public void setDynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index, Token expr) { }
public void dynamicAbsoluteIndexedScopeAttr(Token x, Token y, Token index) { }
public void unknownSyntax(String text) { }
public void text(String text) { }
// don't care

View File

@ -1,10 +1,10 @@
package org.antlr.v4.semantics;
import org.antlr.misc.MultiMap;
import org.antlr.runtime.Token;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.*;
import org.stringtemplate.v4.misc.MultiMap;
import java.io.File;
import java.util.*;
@ -114,8 +114,6 @@ public class BasicSemanticChecks {
}
};
// TODO: track errors?
protected static void checkGrammarName(Grammar g, Token nameToken) {
if ( g.implicitLexer==null ) return;
String fullyQualifiedName = nameToken.getInputStream().getSourceName();

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-11 11:14:49
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-11 12:59:15
/*
[The "BSD license"]
@ -26,14 +26,15 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.semantics;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.TreeNodeStream;
import org.antlr.runtime.tree.TreeRuleReturnScope;
import org.antlr.v4.tool.*;
import java.util.ArrayList;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
/** Triggers for the basic semantics of the input. Side-effects:
* Set token, block, rule options in the tree. Load field option
* with grammar options. Only legal options are set.

View File

@ -135,7 +135,7 @@ tokensSection
rule: ^( RULE name=ID .+)
{
int numAlts = $RULE.getFirstChildWithType(BLOCK).getChildCount();
Rule r = new Rule($name.text, (GrammarASTWithOptions)$RULE, numAlts);
Rule r = new Rule(g, $name.text, (GrammarASTWithOptions)$RULE, numAlts);
rules.add(r);
currentRule = r;
currentAlt = 1;
@ -157,15 +157,15 @@ rulelNamedAction
;
ruleAction
: {inContext("RULE ...")}? ACTION {currentRule.inlineActions.add($ACTION);}
: {inContext("RULE ...")}? ACTION {currentRule.alt[currentAlt].actions.add($ACTION);}
;
exceptionHandler
: ^(CATCH ARG_ACTION ACTION) {currentRule.inlineActions.add($ACTION);}
: ^(CATCH ARG_ACTION ACTION) {currentRule.exceptionActions.add($ACTION);}
;
finallyClause
: ^(FINALLY ACTION) {currentRule.inlineActions.add($ACTION);}
: ^(FINALLY ACTION) {currentRule.exceptionActions.add($ACTION);}
;
ruleArg
@ -206,7 +206,7 @@ labeledElement
@after {
LabelElementPair lp = new LabelElementPair(g, $id, $e, $start.getType());
currentRule.labelDefs.map($id.text, lp);
currentRule.alt[currentAlt].labelRefs.map($id.text, $id);
currentRule.alt[currentAlt].labelDefs.map($id.text, $id);
}
: {inContext("RULE ...")}?
( ^(ASSIGN id=ID e=.)

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 CollectSymbols.g 2010-02-11 11:14:49
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 CollectSymbols.g 2010-02-11 12:59:15
/*
[The "BSD license"]
@ -26,15 +26,19 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.semantics;
import org.antlr.v4.tool.*;
import org.antlr.v4.parse.*;
import java.util.Set;
import java.util.HashSet;
import org.stringtemplate.v4.misc.MultiMap;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.TreeNodeStream;
import org.antlr.runtime.tree.TreeRuleReturnScope;
import org.antlr.v4.parse.ScopeParser;
import org.antlr.v4.tool.*;
import java.util.ArrayList;
import org.antlr.runtime.tree.*;import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
/** Collects rules, terminals, strings, actions, scopes etc... from AST
* Side-effects: None
*/
@ -620,7 +624,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
if ( state.backtracking==1 ) {
int numAlts = RULE5.getFirstChildWithType(BLOCK).getChildCount();
Rule r = new Rule((name!=null?name.getText():null), (GrammarASTWithOptions)RULE5, numAlts);
Rule r = new Rule(g, (name!=null?name.getText():null), (GrammarASTWithOptions)RULE5, numAlts);
rules.add(r);
currentRule = r;
currentAlt = 1;
@ -765,7 +769,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
}
ACTION8=(GrammarAST)match(input,ACTION,FOLLOW_ACTION_in_ruleAction430); if (state.failed) return ;
if ( state.backtracking==1 ) {
currentRule.inlineActions.add(ACTION8);
currentRule.alt[currentAlt].actions.add(ACTION8);
}
}
@ -799,7 +803,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
match(input, Token.UP, null); if (state.failed) return ;
if ( state.backtracking==1 ) {
currentRule.inlineActions.add(ACTION9);
currentRule.exceptionActions.add(ACTION9);
}
}
@ -832,7 +836,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
match(input, Token.UP, null); if (state.failed) return ;
if ( state.backtracking==1 ) {
currentRule.inlineActions.add(ACTION10);
currentRule.exceptionActions.add(ACTION10);
}
}
@ -1178,7 +1182,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
LabelElementPair lp = new LabelElementPair(g, id, e, ((GrammarAST)retval.start).getType());
currentRule.labelDefs.map((id!=null?id.getText():null), lp);
currentRule.alt[currentAlt].labelRefs.map((id!=null?id.getText():null), id);
currentRule.alt[currentAlt].labelDefs.map((id!=null?id.getText():null), id);
}
}

View File

@ -4,10 +4,7 @@ import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.BufferedTreeNodeStream;
import org.antlr.v4.parse.ASTVerifier;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarAST;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.*;
/** */
public class SemanticPipeline {
@ -59,12 +56,16 @@ public class SemanticPipeline {
public void checkAttributeExpressions(Grammar g, CollectSymbols collector) {
for (Rule r : collector.rules) {
for (GrammarAST a : r.namedActions.values()) {
AttributeChecks checker = new AttributeChecks(g, r, a, a.getText());
AttributeChecks checker = new AttributeChecks(g, r, null, a, a.getText());
checker.examine();
}
for (GrammarAST a : r.inlineActions) {
AttributeChecks checker = new AttributeChecks(g, r, a, a.getText());
checker.examine();
for (int i=1; i<=r.numberOfAlts; i++) {
Alternative alt = r.alt[i];
for (GrammarAST a : alt.actions) {
AttributeChecks checker =
new AttributeChecks(g, r, alt, a, a.getText());
checker.examine();
}
}
}
}

View File

@ -284,7 +284,7 @@ public class SymbolChecks {
for (GrammarAST e : alt.rewriteElements) {
if ( !(alt.ruleRefs.containsKey(e.getText()) ||
alt.tokenRefs.containsKey(e.getText()) ||
alt.labelRefs.containsKey(e.getText())) ) {
alt.labelDefs.containsKey(e.getText())) ) {
ErrorManager.grammarError(ErrorType.REWRITE_ELEMENT_NOT_PRESENT_ON_LHS,
g.fileName, e.token, e.getText());
}

View File

@ -13,15 +13,22 @@ public class Alternative {
// token IDs, string literals in this alt
public MultiMap<String, GrammarAST> tokenRefs = new MultiMap<String, GrammarAST>();
// token IDs, string literals in this alt
public MultiMap<String, GrammarAST> labelRefs = new MultiMap<String, GrammarAST>();
// all rule refs in this alt
public MultiMap<String, GrammarAST> ruleRefs = new MultiMap<String, GrammarAST>();
/** A list of all LabelElementPair attached to tokens like id=ID, ids+=ID */
public MultiMap<String, GrammarAST> labelDefs = new MultiMap<String, GrammarAST>();
// track all token, rule, label refs in rewrite (right of ->)
public List<GrammarAST> rewriteElements = new ArrayList<GrammarAST>();
/** Track all executable actions other than named actions like @init
* and catch/finally (not in an alt). Also tracks predicates, rewrite actions.
* We need to examine these actions before code generation so
* that we can detect refs to $rule.attr etc...
*/
public List<GrammarAST> actions = new ArrayList<GrammarAST>();
public Alternative() {
}
}

View File

@ -17,7 +17,9 @@ public class Attribute {
public String initValue;
public Attribute() {;}
public Attribute(String name) { this(name,null); }
public Attribute(String name, String decl) {
this.name = name;
this.decl = decl;

View File

@ -16,6 +16,21 @@ public class AttributeScope {
protected String name;
public GrammarAST ast;
/** All token scopes (token labels) share the same fixed scope of
* of predefined attributes. I keep this out of the runtime.Token
* object to avoid a runtime type leakage.
*/
public static AttributeScope predefinedTokenScope = new AttributeScope() {{
add(new Attribute("text"));
add(new Attribute("type"));
add(new Attribute("line"));
add(new Attribute("index"));
add(new Attribute("pos"));
add(new Attribute("channel"));
add(new Attribute("tree"));
add(new Attribute("int"));
}};
public static enum Type {
ARG, RET, TOKEN, PREDEFINED_RULE, PREDEFINED_LEXER_RULE,
GLOBAL_SCOPE, // scope symbols { ...}
@ -27,6 +42,7 @@ public class AttributeScope {
public LinkedHashMap<String, Attribute> attributes =
new LinkedHashMap<String, Attribute>();
public Attribute add(Attribute a) { return attributes.put(a.name, a); }
public Attribute get(String name) { return attributes.get(name); }
public String getName() {

View File

@ -8,6 +8,7 @@ import org.antlr.v4.Tool;
import org.antlr.v4.parse.ANTLRLexer;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.stringtemplate.v4.misc.MultiMap;
import java.util.*;
@ -20,6 +21,19 @@ public class Grammar {
}
};
public static Map<String, AttributeScope> grammarAndLabelRefTypeToScope =
new HashMap<String, AttributeScope>() {{
put("lexer:RULE_LABEL", Rule.predefinedLexerRulePropertiesScope);
put("lexer:LEXER_STRING_LABEL", Rule.predefinedLexerRulePropertiesScope);
put("parser:RULE_LABEL", Rule.predefinedRulePropertiesScope);
put("parser:TOKEN_LABEL", AttributeScope.predefinedTokenScope);
put("tree:RULE_LABEL", Rule.predefinedTreeRulePropertiesScope);
put("tree:TOKEN_LABEL", AttributeScope.predefinedTokenScope);
put("tree:WILDCARD_TREE_LABEL", AttributeScope.predefinedTokenScope);
put("combined:RULE_LABEL", Rule.predefinedRulePropertiesScope);
put("combined:TOKEN_LABEL", AttributeScope.predefinedTokenScope);
}};
public Tool tool;
public String name;
public GrammarRootAST ast;

View File

@ -32,7 +32,7 @@ public class LabelElementPair {
// now reset if lexer and string
if ( g.getType() == ANTLRParser.LEXER ) {
if ( element.getFirstDescendantWithType(ANTLRParser.STRING_LITERAL)!=null ) {
if ( labelOp==ANTLRParser.ASSIGN ) type = LabelType.CHAR_LABEL;
if ( labelOp==ANTLRParser.ASSIGN ) type = LabelType.LEXER_STRING_LABEL;
}
}
else if ( g.getType() == ANTLRParser.TREE ) {

View File

@ -6,7 +6,7 @@ public enum LabelType {
TOKEN_LABEL,
RULE_LIST_LABEL,
TOKEN_LIST_LABEL,
CHAR_LABEL, // used in lexer for x='a'
LEXER_STRING_LABEL, // used in lexer for x='a'
SUBRULE_LABEL, // x=(...)
SUBRULE_LIST_LABEL, // x+=(...)
WILDCARD_TREE_LABEL, // Used in tree grammar x=.

View File

@ -1,6 +1,7 @@
package org.antlr.v4.tool;
import org.antlr.runtime.Token;
import org.antlr.v4.parse.ANTLRParser;
import org.stringtemplate.v4.misc.MultiMap;
import java.util.ArrayList;
@ -9,6 +10,39 @@ import java.util.List;
import java.util.Map;
public class Rule {
/** Rule refs have a predefined set of attributes as well as
* the return values and args.
*/
public static AttributeScope predefinedRulePropertiesScope =
new AttributeScope() {{
add(new Attribute("text"));
add(new Attribute("start"));
add(new Attribute("stop"));
add(new Attribute("tree"));
add(new Attribute("st"));
}};
public static AttributeScope predefinedTreeRulePropertiesScope =
new AttributeScope() {{
add(new Attribute("text"));
add(new Attribute("start")); // note: no stop; not meaningful
add(new Attribute("tree"));
add(new Attribute("st"));
}};
public static AttributeScope predefinedLexerRulePropertiesScope =
new AttributeScope() {{
add(new Attribute("text"));
add(new Attribute("type"));
add(new Attribute("line"));
add(new Attribute("index"));
add(new Attribute("pos"));
add(new Attribute("channel"));
add(new Attribute("start"));
add(new Attribute("stop"));
add(new Attribute("int"));
}};
public String name;
public GrammarASTWithOptions ast;
public AttributeScope args;
@ -16,6 +50,7 @@ public class Rule {
public AttributeScope scope;
/** A list of scope names used by this rule */
public List<Token> useScopes;
public Grammar g;
/** Map a name to an action for this rule like @init {...}.
* The code generator will use this to fill holes in the rule template.
@ -25,13 +60,8 @@ public class Rule {
public Map<String, GrammarAST> namedActions =
new HashMap<String, GrammarAST>();
/** Track all executable actions other than named actions like @init
* including catch/finally so we can sniff attribute expressions.
* Also tracks exception handlers, predicates, and rewrite rewrites.
* We need to examine these actions before code generation so
* that we can detect refs to $rule.attr etc...
*/
public List<GrammarAST> inlineActions = new ArrayList<GrammarAST>();
/** Track exception handlers, finally action */
public List<GrammarAST> exceptionActions = new ArrayList<GrammarAST>();
public int numberOfAlts;
@ -44,7 +74,8 @@ public class Rule {
public Alternative[] alt;
public Rule(String name, GrammarASTWithOptions ast, int numberOfAlts) {
public Rule(Grammar g, String name, GrammarASTWithOptions ast, int numberOfAlts) {
this.g = g;
this.name = name;
this.ast = ast;
this.numberOfAlts = numberOfAlts;
@ -52,6 +83,60 @@ public class Rule {
for (int i=1; i<=numberOfAlts; i++) alt[i] = new Alternative();
}
public boolean resolves(String name, Alternative alt) {
Attribute a = resolve(name);
if ( a!=null ) return true; // ok
if ( alt.tokenRefs.get(name)!=null||
alt.ruleRefs.get(name)!=null ||
alt.labelDefs.get(name)!=null )
{
return true;
}
return false;
}
/** Look up name from context of this rule and an alternative.
* Find an arg, retval, predefined property, or label/rule/token ref.
*/
public Attribute resolve(String name) {
Attribute a = args.get(name); if ( a!=null ) return a;
a = retvals.get(name); if ( a!=null ) return a;
String grammarLabelKey = g.getTypeString() + ":" + LabelType.RULE_LABEL;
AttributeScope properties =
Grammar.grammarAndLabelRefTypeToScope.get(grammarLabelKey);
a = properties.get(name);
if ( a!=null ) return a;
//alt[currentAlt].tokenRefs
// not here? look in grammar for global scope
return null;
}
public AttributeScope resolveScope(String name, Alternative alt) {
AttributeScope s = args; if ( s.get(name)!=null ) return s;
s = retvals; if ( s.get(name)!=null ) return s;
s = retvals; if ( s.get(name)!=null ) return s;
String grammarLabelKey = g.getTypeString() + ":" + LabelType.RULE_LABEL;
s = Grammar.grammarAndLabelRefTypeToScope.get(grammarLabelKey);
if ( s.get(name)!=null ) return s;
if ( alt.tokenRefs.get(name)!=null ) {
grammarLabelKey = g.getTypeString() + ":" + LabelType.TOKEN_LABEL;
return Grammar.grammarAndLabelRefTypeToScope.get(grammarLabelKey);
}
if ( alt.ruleRefs.get(name)!=null ) {
grammarLabelKey = g.getTypeString() + ":" + LabelType.RULE_LABEL;
return Grammar.grammarAndLabelRefTypeToScope.get(grammarLabelKey);
}
List<LabelElementPair> labels = labelDefs.get(name);
if ( labels!=null ) {
// it's a label ref, compute scope from label type and grammar type
LabelElementPair anyLabelDef = labels.get(0);
grammarLabelKey = g.getTypeString() + ":" + anyLabelDef.type;
return Grammar.grammarAndLabelRefTypeToScope.get(grammarLabelKey);
}
return null;
}
@Override
public String toString() {
return "Rule{" +