cleaned up resolving. resolver interface is only 3 methods now

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6699]
This commit is contained in:
parrt 2010-02-16 14:25:02 -08:00
parent 6ec90d61d9
commit 340af98839
8 changed files with 78 additions and 165 deletions

View File

@ -122,7 +122,7 @@ UNKNOWN_RULE_ATTRIBUTE(arg,arg2,arg3) ::=
"unknown attribute <arg> for rule <arg2> in <arg3>" "unknown attribute <arg> for rule <arg2> in <arg3>"
UNKNOWN_SIMPLE_ATTRIBUTE(arg,arg2) ::= UNKNOWN_SIMPLE_ATTRIBUTE(arg,arg2) ::=
"unknown attribute reference <arg> in <arg2>" "unknown attribute reference <arg> in <arg2>"
ISOLATED_RULE_SCOPE(arg,arg2) ::= ISOLATED_RULE_REF(arg,arg2) ::=
"missing attribute access on rule reference <arg> in <arg2>" "missing attribute access on rule reference <arg> in <arg2>"
INVALID_RULE_PARAMETER_REF(arg,arg2) ::= INVALID_RULE_PARAMETER_REF(arg,arg2) ::=
"cannot access rule <arg>'s parameter: <arg2>" "cannot access rule <arg>'s parameter: <arg2>"

View File

@ -71,19 +71,18 @@ public class AttributeChecks implements ActionSplitterListener {
// $x.y // $x.y
public void qualifiedAttr(String expr, Token x, Token y) { public void qualifiedAttr(String expr, Token x, Token y) {
if ( node.resolver.resolveToAttribute(x.getText(), y.getText(), node)==null ) { if ( node.resolver.resolveToAttribute(x.getText(), y.getText(), node)==null ) {
Rule r = node.resolver.resolveToRule(x.getText(), node); Rule rref = isolatedRuleRef(x.getText());
if ( r!=null ) { if ( rref!=null ) {
Rule rref = g.getRule(x.getText());
if ( rref!=null && rref.args!=null && rref.args.get(y.getText())!=null ) { if ( rref!=null && rref.args!=null && rref.args.get(y.getText())!=null ) {
ErrorManager.grammarError(ErrorType.INVALID_RULE_PARAMETER_REF, ErrorManager.grammarError(ErrorType.INVALID_RULE_PARAMETER_REF,
g.fileName, y, y.getText(), expr); g.fileName, y, y.getText(), expr);
} }
else { else {
ErrorManager.grammarError(ErrorType.UNKNOWN_RULE_ATTRIBUTE, ErrorManager.grammarError(ErrorType.UNKNOWN_RULE_ATTRIBUTE,
g.fileName, y, y.getText(), r.name, expr); g.fileName, y, y.getText(), rref.name, expr);
} }
} }
else if ( !node.resolver.resolvesToAttributeDict(x.getText(), node) ) { else if ( !resolvesToAttributeDict(x.getText()) ) {
ErrorManager.grammarError(ErrorType.UNKNOWN_SIMPLE_ATTRIBUTE, ErrorManager.grammarError(ErrorType.UNKNOWN_SIMPLE_ATTRIBUTE,
g.fileName, x, x.getText(), expr); g.fileName, x, x.getText(), expr);
} }
@ -107,8 +106,8 @@ public class AttributeChecks implements ActionSplitterListener {
if ( node.resolver.resolveToDynamicScope(x.getText(), node)!=null ) { if ( node.resolver.resolveToDynamicScope(x.getText(), node)!=null ) {
return; // $S for scope S is ok return; // $S for scope S is ok
} }
if ( node.resolver.resolveToRule(x.getText(), node)!=null ) { if ( isolatedRuleRef(x.getText())!=null ) {
ErrorManager.grammarError(ErrorType.ISOLATED_RULE_SCOPE, ErrorManager.grammarError(ErrorType.ISOLATED_RULE_REF,
g.fileName, x, x.getText(), expr); g.fileName, x, x.getText(), expr);
return; return;
} }
@ -174,4 +173,53 @@ public class AttributeChecks implements ActionSplitterListener {
public void setExprAttribute(String expr) { } public void setExprAttribute(String expr) { }
public void setAttribute(String expr) { } public void setAttribute(String expr) { }
public void templateExpr(String expr) { } public void templateExpr(String expr) { }
// SUPPORT
public Rule isolatedRuleRef(String x) {
if ( node.resolver instanceof Grammar ) return null;
if ( x.equals(r.name) ) return r;
List<LabelElementPair> labels = null;
if ( node.resolver instanceof Rule ) {
labels = r.getLabelDefs().get(x);
}
else if ( node.resolver instanceof Alternative ) {
labels = ((Alternative)node.resolver).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 g.getRule(anyLabelDef.element.getText());
}
}
if ( node.resolver instanceof Alternative ) {
if ( ((Alternative)node.resolver).ruleRefs.get(x)!=null ) {
return g.getRule(x);
}
}
return null;
}
public boolean resolvesToAttributeDict(String x) {
if ( node.resolver instanceof Grammar ) return g.scopes.get(x)!=null;
List<LabelElementPair> labels = null;
if ( node.resolver instanceof Rule ) {
labels = r.getLabelDefs().get(x);
}
else if ( node.resolver instanceof Alternative ) {
labels = ((Alternative)node.resolver).labelDefs.get(x);
}
if ( labels!=null ) { // it's a label ref. is it a token label?
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

@ -33,8 +33,6 @@ public class Alternative implements AttributeResolver {
public Alternative(Rule r) { this.rule = r; } public Alternative(Rule r) { this.rule = r; }
private AttributeResolver getParent() { return rule; }
/** $x Attribute: rule arguments, return values, predefined rule prop. /** $x Attribute: rule arguments, return values, predefined rule prop.
*/ */
public Attribute resolveToAttribute(String x, ActionAST node) { public Attribute resolveToAttribute(String x, ActionAST node) {
@ -70,56 +68,13 @@ public class Alternative implements AttributeResolver {
return null; return null;
} }
/** $x 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.
*
* x can also be surrounding rule since we use for error checking.
*/
public boolean resolvesToAttributeDict(String x, ActionAST node) {
if ( tokenRefs.get(x)!=null ) return true;
List<LabelElementPair> labels = labelDefs.get(x);
if ( labels!=null ) { // it's a label ref. is it a token label?
LabelElementPair anyLabelDef = labels.get(0);
if ( anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
}
if ( x.equals(rule.name) ) return true; // $r for action in rule r, $r is a dict
Rule r = rule.g.getRule(x);
if ( r!=null && r.scope!=null ) return true;
if ( rule.g.scopes.get(x)!=null ) return true;
return false;
}
// public boolean resolves(String x, ActionAST node) {
// boolean inAlt =
// tokenRefs.get(x)!=null||
// ruleRefs.get(x)!=null ||
// labelDefs.get(x)!=null;
// if ( inAlt ) return inAlt;
// return getParent().resolves(x, node);
// }
//
// /** Find x as token/rule/label ref then find y in properties list. */
// public boolean resolves(String x, String y, ActionAST node) {
// if ( tokenRefs.get(x)!=null ) { // token ref in this alt?
// return rule.getPredefinedScope(LabelType.TOKEN_LABEL).get(y)!=null;
// }
// 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).resolvesAsRetvalOrProperty(y);
// }
// Rule r = resolveRule(x, node);
// if ( r!=null ) return r.resolvesAsRetvalOrProperty(y);
// return getParent().resolves(x, y, node);
// }
public AttributeDict resolveToDynamicScope(String x, ActionAST node) { public AttributeDict resolveToDynamicScope(String x, ActionAST node) {
Rule r = resolveToRule(x, node); Rule r = resolveToRule(x, node);
if ( r!=null && r.scope !=null ) return r.scope; if ( r!=null && r.scope !=null ) return r.scope;
return getParent().resolveToDynamicScope(x, node); return rule.resolveToDynamicScope(x, node);
} }
/** x can be ruleref or rule label. */
public Rule resolveToRule(String x, ActionAST node) { public Rule resolveToRule(String x, ActionAST node) {
if ( ruleRefs.get(x)!=null ) return rule.g.getRule(x); if ( ruleRefs.get(x)!=null ) return rule.g.getRule(x);
List<LabelElementPair> labels = labelDefs.get(x); List<LabelElementPair> labels = labelDefs.get(x);
@ -129,6 +84,7 @@ public class Alternative implements AttributeResolver {
return rule.g.getRule(anyLabelDef.element.getText()); return rule.g.getRule(anyLabelDef.element.getText());
} }
} }
return getParent().resolveToRule(x, node); if ( x.equals(rule.name) ) return rule;
return null;
} }
} }

View File

@ -30,10 +30,5 @@ package org.antlr.v4.tool;
public interface AttributeResolver { public interface AttributeResolver {
public Attribute resolveToAttribute(String x, ActionAST node); public Attribute resolveToAttribute(String x, ActionAST node);
public Attribute resolveToAttribute(String x, String y, ActionAST node); public Attribute resolveToAttribute(String x, String y, ActionAST node);
/** Error checking when $x.y is not attribute. We ask if $x is a dict. */
public boolean resolvesToAttributeDict(String x, ActionAST node);
public AttributeDict resolveToDynamicScope(String x, ActionAST node); public AttributeDict resolveToDynamicScope(String x, ActionAST node);
//public Attribute resolveToDynamicScopeAttribute(String x, String y, ActionAST node);
/** Resolve to surrounding rule, rule ref/label if in alt, or other rule */
public Rule resolveToRule(String x, ActionAST node);
} }

View File

@ -80,7 +80,7 @@ public enum ErrorType {
INVALID_RULE_PARAMETER_REF(ErrorSeverity.ERROR, true, true), INVALID_RULE_PARAMETER_REF(ErrorSeverity.ERROR, true, true),
UNKNOWN_RULE_ATTRIBUTE(ErrorSeverity.ERROR, true, true), UNKNOWN_RULE_ATTRIBUTE(ErrorSeverity.ERROR, true, true),
UNKNOWN_ATTRIBUTE_IN_SCOPE(ErrorSeverity.ERROR, true, true), UNKNOWN_ATTRIBUTE_IN_SCOPE(ErrorSeverity.ERROR, true, true),
ISOLATED_RULE_SCOPE(ErrorSeverity.ERROR, true, true), ISOLATED_RULE_REF(ErrorSeverity.ERROR, true, true),
SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE(ErrorSeverity.ERROR, true, true), SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE(ErrorSeverity.ERROR, true, true),
LABEL_CONFLICTS_WITH_RULE(ErrorSeverity.ERROR, true, true), LABEL_CONFLICTS_WITH_RULE(ErrorSeverity.ERROR, true, true),
LABEL_CONFLICTS_WITH_TOKEN(ErrorSeverity.ERROR, true, true), LABEL_CONFLICTS_WITH_TOKEN(ErrorSeverity.ERROR, true, true),
@ -130,7 +130,7 @@ public enum ErrorType {
AST_OP_IN_ALT_WITH_REWRITE(ErrorSeverity.ERROR, true, true), AST_OP_IN_ALT_WITH_REWRITE(ErrorSeverity.ERROR, true, true),
WILDCARD_AS_ROOT(ErrorSeverity.ERROR, true, true), WILDCARD_AS_ROOT(ErrorSeverity.ERROR, true, true),
CONFLICTING_OPTION_IN_TREE_FILTER(ErrorSeverity.ERROR, true, true), CONFLICTING_OPTION_IN_TREE_FILTER(ErrorSeverity.ERROR, true, true),
/** Documentation comment is unterminated */ /** Documentation comment is unterminated */
//UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true), //UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
// Dependency sorting errors // Dependency sorting errors

View File

@ -222,19 +222,8 @@ public class Grammar implements AttributeResolver {
return null; return null;
} }
/** $s AttributeDict: s is a global scope */
public boolean resolvesToAttributeDict(String x, ActionAST node) {
return scopes.get(x)!=null;
}
public AttributeDict resolveToDynamicScope(String x, ActionAST node) { public AttributeDict resolveToDynamicScope(String x, ActionAST node) {
AttributeDict s = scopes.get(x); return scopes.get(x);
if ( s !=null ) return s;
if ( node.resolver != this ) { // if not member action, can ref rule
Rule r = rules.get(x);
if ( r!=null ) return r.scope;
}
return null;
} }
// /** $x in grammar action can only be scope name */ // /** $x in grammar action can only be scope name */
@ -247,9 +236,6 @@ public class Grammar implements AttributeResolver {
// */ // */
// public boolean resolves(String x, String y, ActionAST node) { return false; } // public boolean resolves(String x, String y, ActionAST node) { return false; }
/** Can't be a rule ref in grammar named action */
public Rule resolveToRule(String x, ActionAST node) { return null; }
/** Given a grammar type, what should be the default action scope? /** Given a grammar type, what should be the default action scope?
* If I say @members in a COMBINED grammar, for example, the * If I say @members in a COMBINED grammar, for example, the
* default scope should be "parser". * default scope should be "parser".

View File

@ -135,8 +135,6 @@ public class Rule implements AttributeResolver {
return defs; return defs;
} }
private AttributeResolver getParent() { return g; }
/** $x Attribute: rule arguments, return values, predefined rule prop. */ /** $x Attribute: rule arguments, return values, predefined rule prop. */
public Attribute resolveToAttribute(String x, ActionAST node) { public Attribute resolveToAttribute(String x, ActionAST node) {
Attribute a = args.get(x); if ( a!=null ) return a; Attribute a = args.get(x); if ( a!=null ) return a;
@ -163,93 +161,23 @@ public class Rule implements AttributeResolver {
} }
/** $x AttributeDict: references to token labels in *any* alt. x can
* be any rule with scope or global scope or surrounding rule x.
*/
public boolean resolvesToAttributeDict(String x, ActionAST node) {
List<LabelElementPair> labels = getLabelDefs().get(x);
if ( labels!=null ) { // it's a label ref. is it a token label?
LabelElementPair anyLabelDef = labels.get(0);
if ( anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
}
if ( x.equals(this.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 AttributeDict resolveToDynamicScope(String x, ActionAST node) { 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; if ( r!=null && r.scope!=null ) return r.scope;
return getParent().resolveToDynamicScope(x, node); return g.scopes.get(x);
} }
public Rule resolveToRule(String x, ActionAST node) { public Rule resolveToRule(String x) {
if ( x.equals(this.name) ) return this; if ( x.equals(this.name) ) return this;
if ( node.resolver == this ) { // action not in alt (attr space is this rule) List<LabelElementPair> labels = getLabelDefs().get(x);
List<LabelElementPair> labels = getLabelDefs().get(x); if ( labels!=null ) { // it's a label ref. is it a rule label?
if ( labels!=null ) { // it's a label ref. is it a rule label? LabelElementPair anyLabelDef = labels.get(0);
LabelElementPair anyLabelDef = labels.get(0); if ( anyLabelDef.type==LabelType.RULE_LABEL ) {
if ( anyLabelDef.type==LabelType.RULE_LABEL ) { return g.getRule(anyLabelDef.element.getText());
return g.getRule(anyLabelDef.element.getText()); }
} }
} return g.getRule(x);
}
return null; // don't look for general rule (not one ref'd in this rule)
} }
/** 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;
// AttributeScope properties = getPredefinedScope(LabelType.RULE_LABEL);
// a = properties.get(name);
// if ( a!=null ) return a;
//
// //alt[currentAlt].tokenRefs
// // not here? look in grammar for global scope
// return null;
// }
/** Resolve x in $x.y to
*/
// public AttributeScope resolveScope(String name, Alternative alt) {
// AttributeScope s = null;
// if ( this.name.equals(name) ) { // $r ref in rule r
// s = resolveLocalAttributeScope(name);
// if ( s!=null ) return s;
// }
//
// if ( alt.tokenRefs.get(name)!=null ) { // token ref in this alt?
// return getPredefinedScope(LabelType.TOKEN_LABEL);
// }
// if ( alt.ruleRefs.get(name)!=null ) { // rule ref in this alt?
// s = getLocalAttributeScope(name);
// if ( s!=null ) return s;
// }
// List<GrammarAST> labels = alt.labelDefs.get(name); // label
// if ( labels!=null ) {
// // it's a label ref, compute scope from label type and grammar type
// LabelElementPair anyLabelDef = labels.get(0);
// return getPredefinedScope(anyLabelDef.type);
// }
// return null;
// }
//
// /** Look for name in the arg, return value, predefined property,
// * or dynamic scope attribute list for this rule.
// */
// public AttributeScope resolveLocalAttributeScope(String name) {
// if ( args.get(name)!=null ) return args;
// if ( retvals.get(name)!=null ) return retvals;
// AttributeScope s = getPredefinedScope(LabelType.RULE_LABEL);
// if ( s.get(name)!=null ) return s;
// if ( scope!=null && scope.get(name)!=null ) return scope;
// return null;
// }
public AttributeDict getPredefinedScope(LabelType ltype) { public AttributeDict getPredefinedScope(LabelType ltype) {
String grammarLabelKey = g.getTypeString() + ":" + ltype; String grammarLabelKey = g.getTypeString() + ":" + ltype;

View File

@ -73,7 +73,7 @@ public class TestAttributeChecks extends BaseTest {
"$a.ick = 3;", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick = 3;", "$a.ick = 3;", "error(31): A.g:6:6: unknown attribute ick for rule a in $a.ick = 3;",
"$b.d", "error(30): A.g:6:6: cannot access rule d's parameter: $b.d", // can't see rule ref's arg "$b.d", "error(30): A.g:6:6: cannot access rule d's parameter: $b.d", // can't see rule ref's arg
"$d.text", "error(29): A.g:6:4: unknown attribute reference d in $d.text", // valid rule, but no ref "$d.text", "error(29): A.g:6:4: unknown attribute reference d in $d.text", // valid rule, but no ref
"$lab.d", "error(31): A.g:6:8: unknown attribute d for rule b in $lab.d", "$lab.d", "error(30): A.g:6:8: cannot access rule d's parameter: $lab.d",
}; };
String[] finallyChecks = { String[] finallyChecks = {
@ -91,7 +91,7 @@ public class TestAttributeChecks extends BaseTest {
"$b", "error(29): A.g:9:14: unknown attribute reference b in $b", "$b", "error(29): A.g:9:14: unknown attribute reference b in $b",
"$b.d", "error(29): A.g:9:14: unknown attribute reference b in $b.d", "$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", "$c.text", "error(29): A.g:9:14: unknown attribute reference c in $c.text",
"$lab.d", "error(31): A.g:9:18: unknown attribute d for rule b in $lab.d", "$lab.d", "error(30): A.g:9:18: cannot access rule d's parameter: $lab.d",
}; };
String[] dynMembersChecks = { String[] dynMembersChecks = {