package org.antlr.tool;
import org.antlr.analysis.Label;
import org.antlr.runtime.Token;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class NameSpaceChecker {
protected Grammar grammar;
public NameSpaceChecker(Grammar grammar) {
this.grammar = grammar;
}
public void checkConflicts() {
for (int i = CompositeGrammar.MIN_RULE_INDEX; i < grammar.composite.ruleIndexToRuleList.size(); i++) {
Rule r = grammar.composite.ruleIndexToRuleList.elementAt(i);
if ( r==null ) {
continue;
}
if ( r.labelNameSpace!=null ) {
for (Grammar.LabelElementPair pair : r.labelNameSpace.values()) {
checkForLabelConflict(r, pair.label);
}
}
if ( r.ruleScope!=null ) {
List<Attribute> attributes = r.ruleScope.getAttributes();
for (int j = 0; j < attributes.size(); j++) {
Attribute attribute = attributes.get(j);
checkForRuleScopeAttributeConflict(r, attribute);
}
}
checkForRuleDefinitionProblems(r);
checkForRuleArgumentAndReturnValueConflicts(r);
}
for (AttributeScope scope : grammar.getGlobalScopes().values()) {
checkForGlobalScopeTokenConflict(scope);
}
lookForReferencesToUndefinedSymbols();
}
protected void checkForRuleArgumentAndReturnValueConflicts(Rule r) {
if ( r.returnScope!=null ) {
Set<String> conflictingKeys = r.returnScope.intersection(r.parameterScope);
if (conflictingKeys!=null) {
for (String key : conflictingKeys) {
ErrorManager.grammarError(
ErrorManager.MSG_ARG_RETVAL_CONFLICT,
grammar,
r.tree.getToken(),
key,
r.name);
}
}
}
}
protected void checkForRuleDefinitionProblems(Rule r) {
String ruleName = r.name;
Token ruleToken = r.tree.getToken();
int msgID = 0;
if ( (grammar.type==Grammar.PARSER||grammar.type==Grammar.TREE_PARSER) &&
Character.isUpperCase(ruleName.charAt(0)) )
{
msgID = ErrorManager.MSG_LEXER_RULES_NOT_ALLOWED;
}
else if ( grammar.type==Grammar.LEXER &&
Character.isLowerCase(ruleName.charAt(0)) &&
!r.isSynPred )
{
msgID = ErrorManager.MSG_PARSER_RULES_NOT_ALLOWED;
}
else if ( grammar.getGlobalScope(ruleName)!=null ) {
msgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
}
if ( msgID!=0 ) {
ErrorManager.grammarError(msgID, grammar, ruleToken, ruleName);
}
}
protected void lookForReferencesToUndefinedSymbols() {
for (GrammarAST refAST : grammar.ruleRefs) {
Token tok = refAST.token;
String ruleName = tok.getText();
Rule localRule = grammar.getLocallyDefinedRule(ruleName);
Rule rule = grammar.getRule(ruleName);
if ( localRule==null && rule!=null ) {
grammar.delegatedRuleReferences.add(rule);
rule.imported = true;
}
if ( rule==null && grammar.getTokenType(ruleName)!=Label.EOF ) {
ErrorManager.grammarError(ErrorManager.MSG_UNDEFINED_RULE_REF,
grammar,
tok,
ruleName);
}
}
if ( grammar.type==Grammar.COMBINED ) {
for (Token tok : grammar.tokenIDRefs) {
String tokenID = tok.getText();
if ( !grammar.composite.lexerRules.contains(tokenID) &&
grammar.getTokenType(tokenID)!=Label.EOF )
{
ErrorManager.grammarWarning(ErrorManager.MSG_NO_TOKEN_DEFINITION,
grammar,
tok,
tokenID);
}
}
}
for (GrammarAST scopeAST : grammar.scopedRuleRefs) {
Grammar scopeG = grammar.composite.getGrammar(scopeAST.getText());
GrammarAST refAST = (GrammarAST)scopeAST.getChild(1);
String ruleName = refAST.getText();
if ( scopeG==null ) {
ErrorManager.grammarError(ErrorManager.MSG_NO_SUCH_GRAMMAR_SCOPE,
grammar,
scopeAST.getToken(),
scopeAST.getText(),
ruleName);
}
else {
Rule rule = grammar.getRule(scopeG.name, ruleName);
if ( rule==null ) {
ErrorManager.grammarError(ErrorManager.MSG_NO_SUCH_RULE_IN_SCOPE,
grammar,
scopeAST.getToken(),
scopeAST.getText(),
ruleName);
}
}
}
}
protected void checkForGlobalScopeTokenConflict(AttributeScope scope) {
if ( grammar.getTokenType(scope.getName())!=Label.INVALID ) {
ErrorManager.grammarError(ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE,
grammar, null, scope.getName());
}
}
public void checkForRuleScopeAttributeConflict(Rule r, Attribute attribute) {
int msgID = 0;
Object arg2 = null;
String attrName = attribute.name;
if ( r.name.equals(attrName) ) {
msgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE;
arg2 = r.name;
}
else if ( (r.returnScope!=null&&r.returnScope.getAttribute(attrName)!=null) ||
(r.parameterScope!=null&&r.parameterScope.getAttribute(attrName)!=null) )
{
msgID = ErrorManager.MSG_ATTRIBUTE_CONFLICTS_WITH_RULE_ARG_RETVAL;
arg2 = r.name;
}
if ( msgID!=0 ) {
ErrorManager.grammarError(msgID,grammar,r.tree.getToken(),attrName,arg2);
}
}
protected void checkForLabelConflict(Rule r, Token label) {
int msgID = 0;
Object arg2 = null;
if ( grammar.getGlobalScope(label.getText())!=null ) {
msgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE;
}
else if ( grammar.getRule(label.getText())!=null ) {
msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE;
}
else if ( grammar.getTokenType(label.getText())!=Label.INVALID ) {
msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_TOKEN;
}
else if ( r.ruleScope!=null && r.ruleScope.getAttribute(label.getText())!=null ) {
msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_SCOPE_ATTRIBUTE;
arg2 = r.name;
}
else if ( (r.returnScope!=null&&r.returnScope.getAttribute(label.getText())!=null) ||
(r.parameterScope!=null&&r.parameterScope.getAttribute(label.getText())!=null) )
{
msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL;
arg2 = r.name;
}
if ( msgID!=0 ) {
ErrorManager.grammarError(msgID,grammar,label,label.getText(),arg2);
}
}
public boolean checkForLabelTypeMismatch(Rule r, Token label, int type) {
Grammar.LabelElementPair prevLabelPair =
r.labelNameSpace.get(label.getText());
if ( prevLabelPair!=null ) {
if ( prevLabelPair.type != type ) {
String typeMismatchExpr =
Grammar.LabelTypeToString[type]+"!="+
Grammar.LabelTypeToString[prevLabelPair.type];
ErrorManager.grammarError(
ErrorManager.MSG_LABEL_TYPE_CONFLICT,
grammar,
label,
label.getText(),
typeMismatchExpr);
return true;
}
}
return false;
}
}