forked from jasder/antlr
cleaned up, added $ids check for list labels
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6700]
This commit is contained in:
parent
340af98839
commit
c08812ea54
|
@ -106,6 +106,12 @@ public class AttributeChecks implements ActionSplitterListener {
|
|||
if ( node.resolver.resolveToDynamicScope(x.getText(), node)!=null ) {
|
||||
return; // $S for scope S is ok
|
||||
}
|
||||
if ( resolvesToToken(x.getText()) ) {
|
||||
return; // $ID for token ref or label of token
|
||||
}
|
||||
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
|
||||
return; // $ids for ids+=ID etc...
|
||||
}
|
||||
if ( isolatedRuleRef(x.getText())!=null ) {
|
||||
ErrorManager.grammarError(ErrorType.ISOLATED_RULE_REF,
|
||||
g.fileName, x, x.getText(), expr);
|
||||
|
@ -202,8 +208,24 @@ public class AttributeChecks implements ActionSplitterListener {
|
|||
}
|
||||
|
||||
public boolean resolvesToAttributeDict(String x) {
|
||||
if ( resolvesToToken(x) ) return true;
|
||||
if ( node.resolver instanceof Grammar ) return g.scopes.get(x)!=null;
|
||||
|
||||
if ( x.equals(r.name) ) return true; // $r for action in rule r, $r is a dict
|
||||
Rule r = g.getRule(x);
|
||||
if ( r!=null && r.scope!=null ) return true;
|
||||
if ( g.scopes.get(x)!=null ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean resolvesToToken(String x) {
|
||||
if ( node.resolver instanceof Grammar ) return false;
|
||||
|
||||
if ( node.resolver instanceof Alternative &&
|
||||
((Alternative)node.resolver).tokenRefs.get(x)!=null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
List<LabelElementPair> labels = null;
|
||||
if ( node.resolver instanceof Rule ) {
|
||||
labels = r.getLabelDefs().get(x);
|
||||
|
@ -215,11 +237,7 @@ public class AttributeChecks implements ActionSplitterListener {
|
|||
LabelElementPair anyLabelDef = labels.get(0);
|
||||
if ( anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
|
||||
}
|
||||
if ( x.equals(r.name) ) return true; // $r for action in rule r, $r is a dict
|
||||
Rule r = g.getRule(x);
|
||||
if ( r!=null && r.scope!=null ) return true;
|
||||
if ( g.scopes.get(x)!=null ) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,34 +55,43 @@ public class Alternative implements AttributeResolver {
|
|||
}
|
||||
if ( ruleRefs.get(x)!=null ) { // rule ref in this alt?
|
||||
// look up rule, ask it to resolve y (must be retval or predefined)
|
||||
return rule.g.getRule(x).resolveRetvalOrProperty(y);
|
||||
}
|
||||
List<LabelElementPair> labels = labelDefs.get(x);
|
||||
if ( labels!=null ) { // it's a label ref. is it a rule label?
|
||||
LabelElementPair anyLabelDef = labels.get(0);
|
||||
if ( anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return rule.g.getRule(anyLabelDef.element.getText()).resolveRetvalOrProperty(y);
|
||||
}
|
||||
return rule.g.getRule(x).resolveRetvalOrProperty(y);
|
||||
}
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return rule.g.getRule(anyLabelDef.element.getText()).resolveRetvalOrProperty(y);
|
||||
}
|
||||
else if ( anyLabelDef!=null ) {
|
||||
return rule.getPredefinedScope(anyLabelDef.type).get(y);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttributeDict resolveToDynamicScope(String x, ActionAST node) {
|
||||
Rule r = resolveToRule(x, node);
|
||||
Rule r = resolveToRule(x);
|
||||
if ( r!=null && r.scope !=null ) return r.scope;
|
||||
return rule.resolveToDynamicScope(x, node);
|
||||
}
|
||||
|
||||
public boolean resolvesToListLabel(String x, ActionAST node) {
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
return anyLabelDef!=null &&
|
||||
(anyLabelDef.type==LabelType.RULE_LIST_LABEL ||
|
||||
anyLabelDef.type==LabelType.TOKEN_LIST_LABEL);
|
||||
}
|
||||
|
||||
public LabelElementPair getAnyLabelDef(String x) {
|
||||
List<LabelElementPair> labels = labelDefs.get(x);
|
||||
if ( labels!=null ) return labels.get(0);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** x can be ruleref or rule label. */
|
||||
public Rule resolveToRule(String x, ActionAST node) {
|
||||
public Rule resolveToRule(String x) {
|
||||
if ( ruleRefs.get(x)!=null ) return rule.g.getRule(x);
|
||||
List<LabelElementPair> labels = labelDefs.get(x);
|
||||
if ( labels!=null ) { // it's a label ref. is it a rule label?
|
||||
LabelElementPair anyLabelDef = labels.get(0);
|
||||
if ( anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return rule.g.getRule(anyLabelDef.element.getText());
|
||||
}
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return rule.g.getRule(anyLabelDef.element.getText());
|
||||
}
|
||||
if ( x.equals(rule.name) ) return rule;
|
||||
return null;
|
||||
|
|
|
@ -11,6 +11,7 @@ package org.antlr.v4.tool;
|
|||
* AttributeDict: references to tokens and token labels in the
|
||||
* current alt (including any elements within subrules contained
|
||||
* in that outermost alt). x can be rule with scope or a global scope.
|
||||
* List label: x is a token/rule list label.
|
||||
* $x.y Attribute: x is surrounding rule, rule/token/label ref
|
||||
* $s::y Attribute: s is any rule with scope or global scope; y is prop within
|
||||
*
|
||||
|
@ -19,6 +20,7 @@ package org.antlr.v4.tool;
|
|||
* $x Attribute: rule arguments, return values, predefined rule prop.
|
||||
* AttributeDict: references to token labels in *any* alt. x can
|
||||
* be any rule with scope or global scope.
|
||||
* List label: x is a token/rule list label.
|
||||
* $x.y Attribute: x is surrounding rule, label ref (in any alts)
|
||||
* $s::y Attribute: s is any rule with scope or global scope; y is prop within
|
||||
*
|
||||
|
@ -28,6 +30,7 @@ package org.antlr.v4.tool;
|
|||
* $s::y Attribute: s is a global scope; y is prop within
|
||||
*/
|
||||
public interface AttributeResolver {
|
||||
public boolean resolvesToListLabel(String x, ActionAST node);
|
||||
public Attribute resolveToAttribute(String x, ActionAST node);
|
||||
public Attribute resolveToAttribute(String x, String y, ActionAST node);
|
||||
public AttributeDict resolveToDynamicScope(String x, ActionAST node);
|
||||
|
|
|
@ -226,6 +226,8 @@ public class Grammar implements AttributeResolver {
|
|||
return scopes.get(x);
|
||||
}
|
||||
|
||||
public boolean resolvesToListLabel(String x, ActionAST node) { return false; }
|
||||
|
||||
// /** $x in grammar action can only be scope name */
|
||||
// public boolean resolves(String x, ActionAST node) {
|
||||
// return scopes.get(x)!=null;
|
||||
|
|
|
@ -135,7 +135,9 @@ public class Rule implements AttributeResolver {
|
|||
return defs;
|
||||
}
|
||||
|
||||
/** $x Attribute: rule arguments, return values, predefined rule prop. */
|
||||
/** $x Attribute: rule arguments, return values, predefined rule prop,
|
||||
* or a token/rule list label.
|
||||
*/
|
||||
public Attribute resolveToAttribute(String x, ActionAST node) {
|
||||
Attribute a = args.get(x); if ( a!=null ) return a;
|
||||
a = retvals.get(x); if ( a!=null ) return a;
|
||||
|
@ -149,13 +151,14 @@ public class Rule implements AttributeResolver {
|
|||
AttributeDict d = getPredefinedScope(LabelType.RULE_LABEL);
|
||||
return d.get(y);
|
||||
}
|
||||
List<LabelElementPair> labels = getLabelDefs().get(x);
|
||||
if ( labels!=null ) { // it's a label ref. is it a rule label?
|
||||
LabelElementPair anyLabelDef = labels.get(0);
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef!=null ) {
|
||||
if ( anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return g.getRule(anyLabelDef.element.getText()).resolveRetvalOrProperty(y);
|
||||
}
|
||||
return getPredefinedScope(anyLabelDef.type).get(y);
|
||||
else {
|
||||
return getPredefinedScope(anyLabelDef.type).get(y);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
|
@ -167,17 +170,27 @@ public class Rule implements AttributeResolver {
|
|||
return g.scopes.get(x);
|
||||
}
|
||||
|
||||
public boolean resolvesToListLabel(String x, ActionAST node) {
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
return anyLabelDef!=null &&
|
||||
(anyLabelDef.type==LabelType.RULE_LIST_LABEL ||
|
||||
anyLabelDef.type==LabelType.TOKEN_LIST_LABEL);
|
||||
}
|
||||
|
||||
public Rule resolveToRule(String x) {
|
||||
if ( x.equals(this.name) ) return this;
|
||||
List<LabelElementPair> labels = getLabelDefs().get(x);
|
||||
if ( labels!=null ) { // it's a label ref. is it a rule label?
|
||||
LabelElementPair anyLabelDef = labels.get(0);
|
||||
if ( anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return g.getRule(anyLabelDef.element.getText());
|
||||
}
|
||||
LabelElementPair anyLabelDef = getAnyLabelDef(x);
|
||||
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) {
|
||||
return g.getRule(anyLabelDef.element.getText());
|
||||
}
|
||||
return g.getRule(x);
|
||||
}
|
||||
return g.getRule(x);
|
||||
}
|
||||
|
||||
public LabelElementPair getAnyLabelDef(String x) {
|
||||
List<LabelElementPair> labels = getLabelDefs().get(x);
|
||||
if ( labels!=null ) return labels.get(0);
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttributeDict getPredefinedScope(LabelType ltype) {
|
||||
String grammarLabelKey = g.getTypeString() + ":" + ltype;
|
||||
|
|
|
@ -11,7 +11,7 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"@members {<members>}\n" +
|
||||
"a[int x] returns [int y]\n" +
|
||||
"@init {<init>}\n" +
|
||||
" : lab=b[34] {\n" +
|
||||
" : id=ID ids+=ID lab=b[34] {\n" +
|
||||
" <inline>\n" +
|
||||
" }\n" +
|
||||
" c\n" +
|
||||
|
@ -50,13 +50,32 @@ public class TestAttributeChecks extends BaseTest {
|
|||
};
|
||||
|
||||
String[] initChecks = {
|
||||
"$text", "",
|
||||
"$start", "",
|
||||
"$x = $y", "",
|
||||
"$y = $x", "",
|
||||
"$lab.e", "",
|
||||
"$ids", "",
|
||||
|
||||
"$a", "error(33): A.g:4:8: missing attribute access on rule reference a in $a",
|
||||
"$c", "error(29): A.g:4:8: unknown attribute reference c in $c",
|
||||
"$a.q", "error(31): A.g:4:10: unknown attribute q for rule a in $a.q",
|
||||
};
|
||||
|
||||
String[] inlineChecks = {
|
||||
"$text", "",
|
||||
"$start", "",
|
||||
"$x = $y", "",
|
||||
"$y = $x", "",
|
||||
"$lab.e", "",
|
||||
"$lab.text", "",
|
||||
"$b.e", "",
|
||||
"$c.text", "",
|
||||
"$ID", "",
|
||||
"$ID.text", "",
|
||||
"$id", "",
|
||||
"$id.text", "",
|
||||
"$ids", "",
|
||||
|
||||
"$a", "error(33): A.g:6:4: missing attribute access on rule reference a in $a",
|
||||
"$b", "error(33): A.g:6:4: missing attribute access on rule reference b in $b",
|
||||
|
@ -77,6 +96,16 @@ public class TestAttributeChecks extends BaseTest {
|
|||
};
|
||||
|
||||
String[] finallyChecks = {
|
||||
"$text", "",
|
||||
"$start", "",
|
||||
"$x = $y", "",
|
||||
"$y = $x", "",
|
||||
"$lab.e", "",
|
||||
"$lab.text", "",
|
||||
"$id", "",
|
||||
"$id.text", "",
|
||||
"$ids", "",
|
||||
|
||||
"$lab", "error(33): A.g:9:14: missing attribute access on rule reference lab in $lab",
|
||||
"$a", "error(33): A.g:9:14: missing attribute access on rule reference a in $a",
|
||||
"$q", "error(29): A.g:9:14: unknown attribute reference q in $q",
|
||||
|
@ -89,12 +118,17 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"$a.ick", "error(31): A.g:9:16: unknown attribute ick for rule a in $a.ick",
|
||||
"$a.ick = 3;", "error(31): A.g:9:16: unknown attribute ick for rule a in $a.ick = 3;",
|
||||
"$b", "error(29): A.g:9:14: unknown attribute reference b in $b",
|
||||
"$b.e", "error(29): A.g:9:14: unknown attribute reference b in $b.e", // can't see rule refs outside alts
|
||||
"$b.d", "error(29): A.g:9:14: unknown attribute reference b in $b.d",
|
||||
"$c.text", "error(29): A.g:9:14: unknown attribute reference c in $c.text",
|
||||
"$lab.d", "error(30): A.g:9:18: cannot access rule d's parameter: $lab.d",
|
||||
};
|
||||
|
||||
String[] dynMembersChecks = {
|
||||
"$S", "",
|
||||
"$S::i", "",
|
||||
"$S::i=$S::i", "",
|
||||
|
||||
"$b::f", "error(54): A.g:3:1: unknown dynamic scope: b in $b::f",
|
||||
"$S::j", "error(55): A.g:3:4: unknown dynamically-scoped attribute for scope S: j in $S::j",
|
||||
"$S::j = 3;", "error(55): A.g:3:4: unknown dynamically-scoped attribute for scope S: j in $S::j = 3;",
|
||||
|
@ -107,6 +141,11 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"$b", "",
|
||||
"$lab", "",
|
||||
"$b::f", "",
|
||||
"$S::i", "",
|
||||
"$S::i=$S::i", "",
|
||||
"$a::z", "",
|
||||
"$S", "",
|
||||
|
||||
"$S::j", "error(55): A.g:8:11: unknown dynamically-scoped attribute for scope S: j in $S::j",
|
||||
"$S::j = 3;", "error(55): A.g:8:11: unknown dynamically-scoped attribute for scope S: j in $S::j = 3;",
|
||||
"$S::j = $S::k;", "error(55): A.g:8:11: unknown dynamically-scoped attribute for scope S: j in $S::j = $S::k;\n" +
|
||||
|
@ -119,6 +158,9 @@ public class TestAttributeChecks extends BaseTest {
|
|||
"$lab", "",
|
||||
"$b::f", "",
|
||||
"$S", "",
|
||||
"$S::i", "",
|
||||
"$S::i=$S::i", "",
|
||||
"$a::z", "",
|
||||
|
||||
"$S::j", "error(55): A.g:10:7: unknown dynamically-scoped attribute for scope S: j in $S::j",
|
||||
"$S::j = 3;", "error(55): A.g:10:7: unknown dynamically-scoped attribute for scope S: j in $S::j = 3;",
|
||||
|
@ -144,7 +186,15 @@ public class TestAttributeChecks extends BaseTest {
|
|||
};
|
||||
|
||||
String[] dynFinallyChecks = {
|
||||
"$a", "",
|
||||
"$b", "",
|
||||
"$lab", "",
|
||||
"$b::f", "",
|
||||
"$S", "",
|
||||
"$S::i", "",
|
||||
"$S::i=$S::i", "",
|
||||
"$a::z", "",
|
||||
|
||||
"$S::j", "error(55): A.g:12:17: unknown dynamically-scoped attribute for scope S: j in $S::j",
|
||||
"$S::j = 3;", "error(55): A.g:12:17: unknown dynamically-scoped attribute for scope S: j in $S::j = 3;",
|
||||
"$S::j = $S::k;", "error(55): A.g:12:17: unknown dynamically-scoped attribute for scope S: j in $S::j = $S::k;\n" +
|
||||
|
|
Loading…
Reference in New Issue