cleaned up, added $ids check for list labels

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6700]
This commit is contained in:
parrt 2010-02-16 17:03:55 -08:00
parent 340af98839
commit c08812ea54
6 changed files with 130 additions and 35 deletions

View File

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

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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;

View File

@ -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" +