public ActionAnalysisLexer(Grammar grammar, string ruleName, GrammarAST actionAST) : this(new ANTLRStringStream(actionAST.Token.Text)) { this.grammar = grammar; this.enclosingRule = grammar.GetLocallyDefinedRule(ruleName); this.actionToken = actionAST.Token; this.outerAltNum = actionAST.outerAltNum; }
/** If type of previous label differs from new label's type, that's an error. */ public virtual bool CheckForLabelTypeMismatch( Rule r, IToken label, LabelType type ) { Grammar.LabelElementPair prevLabelPair = (Grammar.LabelElementPair)r.labelNameSpace.get( label.Text ); if ( prevLabelPair != null ) { // label already defined; if same type, no problem if ( prevLabelPair.type != type ) { string typeMismatchExpr = Grammar.LabelTypeToString[(int)type] + "!=" + Grammar.LabelTypeToString[(int)prevLabelPair.type]; ErrorManager.GrammarError( ErrorManager.MSG_LABEL_TYPE_CONFLICT, grammar, label, label.Text, typeMismatchExpr ); return true; } } return false; }
/** For reference to rule r, build * * o-e->(r) o * * where (r) is the start of rule r and the trailing o is not linked * to from rule ref state directly (it's done thru the transition(0) * RuleClosureTransition. * * If the rule r is just a list of tokens, it's block will be just * a set on an edge o->o->o-set->o->o->o, could inline it rather than doing * the rule reference, but i'm not doing this yet as I'm not sure * it would help much in the NFA->DFA construction. * * TODO add to codegen: collapse alt blks that are sets into single matchSet */ public virtual StateCluster BuildRuleRef( Rule refDef, NFAState ruleStart ) { //System.Console.Out.WriteLine( "building ref to rule " + nfa.grammar.name + "." + refDef.name ); NFAState left = NewState(); //left.Description = "ref to " + ruleStart.Description; NFAState right = NewState(); //right.Description = "NFAState following ref to " + ruleStart.Description; Transition e = new RuleClosureTransition( refDef, ruleStart, right ); left.AddTransition( e ); StateCluster g = new StateCluster( left, right ); return g; }
protected virtual void WriteGraphFile( Grammar g, Rule r, string graph, string formatExtension ) { WriteGraphFile( g, r.Grammar.name + "." + r.Name, graph, formatExtension ); }
/** Define a label defined in a rule r; check the validity then ask the * Rule object to actually define it. */ protected virtual void DefineLabel( Rule r, IToken label, GrammarAST element, LabelType type ) { bool err = nameSpaceChecker.CheckForLabelTypeMismatch( r, label, type ); if ( err ) { return; } r.DefineLabel( label, element, type ); }
/** Define a new rule. A new rule index is created by incrementing * ruleIndex. */ public virtual void DefineRule( IToken ruleToken, string modifier, IDictionary<string,object> options, GrammarAST tree, GrammarAST argActionAST, int numAlts ) { string ruleName = ruleToken.Text; if ( GetLocallyDefinedRule( ruleName ) != null ) { ErrorManager.GrammarError( ErrorManager.MSG_RULE_REDEFINITION, this, ruleToken, ruleName ); return; } if ( ( type == GrammarType.Parser || type == GrammarType.TreeParser ) && Rule.GetRuleType(ruleName) == RuleType.Lexer) { ErrorManager.GrammarError( ErrorManager.MSG_LEXER_RULES_NOT_ALLOWED, this, ruleToken, ruleName ); return; } Rule r = new Rule( this, ruleName, composite.RuleIndex, numAlts ); /* [email protected]("defineRule("+ruleName+",modifier="+modifier+ "): index="+r.index+", nalts="+numAlts); */ r.Modifier = modifier ?? DefaultRuleModifier; nameToRuleMap[ruleName] = r; SetRuleAST( ruleName, tree ); r.SetOptions( options, ruleToken ); r.ArgActionAST = argActionAST; composite.RuleIndexToRuleList.Resize( composite.RuleIndex + 1 ); composite.RuleIndexToRuleList[composite.RuleIndex] = r; composite.RuleIndex++; if ( ruleName.StartsWith( SynpredRulePrefix ) ) { r.IsSynPred = true; } }
protected virtual void WriteDOTFile( Grammar g, Rule r, string dot ) { WriteDOTFile( g, r.grammar.name + "." + r.Name, dot ); }
protected virtual void CheckForRuleArgumentAndReturnValueConflicts( Rule r ) { if ( r.returnScope != null ) { HashSet<object> conflictingKeys = r.returnScope.Intersection( r.parameterScope ); if ( conflictingKeys != null ) { foreach ( string key in conflictingKeys ) { ErrorManager.GrammarError( ErrorManager.MSG_ARG_RETVAL_CONFLICT, grammar, r.tree.Token, key, r.Name ); } } } }
private void HandleRuleAfterOptionsSpec(ref string name, ref Rule r, IDictionary<string, object> opts, GrammarAST start, GrammarAST id, string modifier, GrammarAST args, GrammarAST ret, HashSet<string> exceptions) { name = id.Text; currentRuleName = name; if (Rule.GetRuleType(name) == RuleType.Lexer && grammar.type == GrammarType.Combined) { // a merged grammar spec, track lexer rules and send to another grammar grammar.DefineLexerRuleFoundInParser(id.Token, start); } else { int numAlts = CountAltsForRule(start); grammar.DefineRule(id.Token, modifier, opts, start, args, numAlts); r = grammar.GetRule(name); if (args != null) { r.ParameterScope = grammar.CreateParameterScope(name, args.Token); r.ParameterScope.AddAttributes(args.Text, ','); } if (ret != null) { r.ReturnScope = grammar.CreateReturnScope(name, ret.Token); r.ReturnScope.AddAttributes(ret.Text, ','); } if (exceptions != null) { foreach (string exception in exceptions) r.ThrowsSpec.Add(exception); } } }
private void HandleRuleAction(Rule r, GrammarAST amp, GrammarAST id, GrammarAST action) { if (r != null) r.DefineNamedAction(amp, id, action); }
/** From state s, look for any transition to a rule that is currently * being traced. When tracing r, visitedDuringRecursionCheck has r * initially. If you reach an accept state, return but notify the * invoking rule that it is nullable, which implies that invoking * rule must look at follow transition for that invoking state. * The visitedStates tracks visited states within a single rule so * we can avoid epsilon-loop-induced infinite recursion here. Keep * filling the cycles in listOfRecursiveCycles and also, as a * side-effect, set leftRecursiveRules. */ protected virtual bool TraceStatesLookingForLeftRecursion(NFAState s, HashSet <object> visitedStates, IList <HashSet <Rule> > listOfRecursiveCycles) { if (s.IsAcceptState) { // this rule must be nullable! // At least one epsilon edge reached accept state return(true); } if (visitedStates.Contains(s)) { // within same rule, we've hit same state; quit looping return(false); } visitedStates.Add(s); bool stateReachesAcceptState = false; Transition t0 = s.transition[0]; if (t0 is RuleClosureTransition) { RuleClosureTransition refTrans = (RuleClosureTransition)t0; Rule refRuleDef = refTrans.Rule; //String targetRuleName = ((NFAState)t0.target).getEnclosingRule(); if (visitedDuringRecursionCheck.Contains(refRuleDef)) { // record left-recursive rule, but don't go back in grammar.leftRecursiveRules.Add(refRuleDef); //System.Console.Out.WriteLine( "already visited " + refRuleDef + ", calling from " + s.enclosingRule ); AddRulesToCycle(refRuleDef, s.enclosingRule, listOfRecursiveCycles); } else { // must visit if not already visited; send new visitedStates set visitedDuringRecursionCheck.Add(refRuleDef); bool callReachedAcceptState = TraceStatesLookingForLeftRecursion((NFAState)t0.Target, new HashSet <object>(), listOfRecursiveCycles); // we're back from visiting that rule visitedDuringRecursionCheck.Remove(refRuleDef); // must keep going in this rule then if (callReachedAcceptState) { NFAState followingState = ((RuleClosureTransition)t0).FollowState; stateReachesAcceptState |= TraceStatesLookingForLeftRecursion(followingState, visitedStates, listOfRecursiveCycles); } } } else if (t0.Label.IsEpsilon || t0.Label.IsSemanticPredicate) { stateReachesAcceptState |= TraceStatesLookingForLeftRecursion((NFAState)t0.Target, visitedStates, listOfRecursiveCycles); } // else it has a labeled edge // now do the other transition if it exists Transition t1 = s.transition[1]; if (t1 != null) { stateReachesAcceptState |= TraceStatesLookingForLeftRecursion((NFAState)t1.Target, visitedStates, listOfRecursiveCycles); } return(stateReachesAcceptState); }
public virtual void CheckRuleReference(GrammarAST scopeAST, GrammarAST refAST, GrammarAST argsAST, string currentRuleName) { Rule r = grammar.GetRule(refAST.Text); if (refAST.Type == ANTLRParser.RULE_REF) { if (argsAST != null) { // rule[args]; ref has args if (r != null && r.ArgActionAST == null) { // but rule def has no args ErrorManager.GrammarError( ErrorManager.MSG_RULE_HAS_NO_ARGS, grammar, argsAST.Token, r.Name); } } else { // rule ref has no args if (r != null && r.ArgActionAST != null) { // but rule def has args ErrorManager.GrammarError( ErrorManager.MSG_MISSING_RULE_ARGS, grammar, refAST.Token, r.Name); } } } else if (refAST.Type == ANTLRParser.TOKEN_REF) { if (grammar.type != GrammarType.Lexer) { if (argsAST != null) { // args on a token ref not in a lexer rule ErrorManager.GrammarError( ErrorManager.MSG_ARGS_ON_TOKEN_REF, grammar, refAST.Token, refAST.Text); } return; // ignore token refs in nonlexers } if (argsAST != null) { // tokenRef[args]; ref has args if (r != null && r.ArgActionAST == null) { // but token rule def has no args ErrorManager.GrammarError( ErrorManager.MSG_RULE_HAS_NO_ARGS, grammar, argsAST.Token, r.Name); } } else { // token ref has no args if (r != null && r.ArgActionAST != null) { // but token rule def has args ErrorManager.GrammarError( ErrorManager.MSG_MISSING_RULE_ARGS, grammar, refAST.Token, r.Name); } } } }
/** enclosingRuleName calls targetRuleName, find the cycle containing * the target and add the caller. Find the cycle containing the caller * and add the target. If no cycles contain either, then create a new * cycle. listOfRecursiveCycles is List<Set<String>> that holds a list * of cycles (sets of rule names). */ protected virtual void AddRulesToCycle( Rule targetRule, Rule enclosingRule, IList<HashSet<Rule>> listOfRecursiveCycles ) { bool foundCycle = false; for ( int i = 0; i < listOfRecursiveCycles.Count; i++ ) { HashSet<Rule> rulesInCycle = listOfRecursiveCycles[i]; // ensure both rules are in same cycle if ( rulesInCycle.Contains( targetRule ) ) { rulesInCycle.Add( enclosingRule ); foundCycle = true; } if ( rulesInCycle.Contains( enclosingRule ) ) { rulesInCycle.Add( targetRule ); foundCycle = true; } } if ( !foundCycle ) { HashSet<Rule> cycle = new HashSet<Rule>(); cycle.Add( targetRule ); cycle.Add( enclosingRule ); listOfRecursiveCycles.Add( cycle ); } }
public static ReportData GetReportData(Grammar g) { ReportData data = new ReportData(); data.version = Version; data.gname = g.name; data.gtype = g.GrammarTypeString; data.language = (string)g.GetOption("language"); data.output = (string)g.GetOption("output"); if (data.output == null) { data.output = "none"; } string k = (string)g.GetOption("k"); if (k == null) { k = "none"; } data.grammarLevelk = k; string backtrack = (string)g.GetOption("backtrack"); if (backtrack == null) { backtrack = "false"; } data.grammarLevelBacktrack = backtrack; int totalNonSynPredProductions = 0; int totalNonSynPredRules = 0; ICollection <Rule> rules = g.Rules; foreach (Rule r in rules) { if (!r.Name.StartsWith(Grammar.SynpredRulePrefix, StringComparison.OrdinalIgnoreCase)) { totalNonSynPredProductions += r.NumberOfAlts; totalNonSynPredRules++; } } data.numRules = totalNonSynPredRules; data.numOuterProductions = totalNonSynPredProductions; int numACyclicDecisions = g.NumberOfDecisions - g.GetNumberOfCyclicDecisions(); List <int> depths = new List <int>(); int[] acyclicDFAStates = new int[numACyclicDecisions]; int[] cyclicDFAStates = new int[g.GetNumberOfCyclicDecisions()]; int acyclicIndex = 0; int cyclicIndex = 0; int numLL1 = 0; int blocksWithSynPreds = 0; int dfaWithSynPred = 0; int numDecisions = 0; int numCyclicDecisions = 0; for (int i = 1; i <= g.NumberOfDecisions; i++) { Grammar.Decision d = g.GetDecision(i); if (d.dfa == null) { //System.out.println("dec "+d.decision+" has no AST"); continue; } Rule r = d.dfa.NFADecisionStartState.enclosingRule; if (r.Name.StartsWith(Grammar.SynpredRulePrefix, StringComparison.OrdinalIgnoreCase)) { //System.out.println("dec "+d.decision+" is a synpred"); continue; } numDecisions++; if (BlockHasSynPred(d.blockAST)) { blocksWithSynPreds++; } //if (g.decisionsWhoseDFAsUsesSynPreds.contains(d.dfa)) // dfaWithSynPred++; if (d.dfa.HasSynPred) { dfaWithSynPred++; } // NFAState decisionStartState = g.getDecisionNFAStartState(d.decision); // int nalts = g.getNumberOfAltsForDecisionNFA(decisionStartState); // for (int alt = 1; alt <= nalts; alt++) { // int walkAlt = // decisionStartState.translateDisplayAltToWalkAlt(alt); // NFAState altLeftEdge = g.getNFAStateForAltOfDecision(decisionStartState, walkAlt); // } // int nalts = g.getNumberOfAltsForDecisionNFA(d.dfa.decisionNFAStartState); // for (int a=1; a<nalts; a++) { // NFAState altStart = // g.getNFAStateForAltOfDecision(d.dfa.decisionNFAStartState, a); // } if (!d.dfa.IsCyclic) { if (d.dfa.IsClassicDFA) { int maxk = d.dfa.MaxLookaheadDepth; //System.out.println("decision "+d.dfa.decisionNumber+" k="+maxk); if (maxk == 1) { numLL1++; } depths.Add(maxk); } else { acyclicDFAStates[acyclicIndex] = d.dfa.NumberOfStates; acyclicIndex++; } } else { //System.out.println("CYCLIC decision "+d.dfa.decisionNumber); numCyclicDecisions++; cyclicDFAStates[cyclicIndex] = d.dfa.NumberOfStates; cyclicIndex++; } } data.numLL1 = numLL1; data.numberOfFixedKDecisions = depths.Count; data.mink = depths.DefaultIfEmpty(int.MaxValue).Min(); data.maxk = depths.DefaultIfEmpty(int.MinValue).Max(); data.avgk = depths.DefaultIfEmpty(0).Average(); data.numberOfDecisionsInRealRules = numDecisions; data.numberOfDecisions = g.NumberOfDecisions; data.numberOfCyclicDecisions = numCyclicDecisions; // Map synpreds = g.getSyntacticPredicates(); // int num_synpreds = synpreds!=null ? synpreds.Count : 0; // data.num_synpreds = num_synpreds; data.blocksWithSynPreds = blocksWithSynPreds; data.decisionsWhoseDFAsUsesSynPreds = dfaWithSynPred; // // data. = Stats.stddev(depths); // // data. = Stats.min(acyclicDFAStates); // // data. = Stats.max(acyclicDFAStates); // // data. = Stats.avg(acyclicDFAStates); // // data. = Stats.stddev(acyclicDFAStates); // // data. = Stats.sum(acyclicDFAStates); // // data. = Stats.min(cyclicDFAStates); // // data. = Stats.max(cyclicDFAStates); // // data. = Stats.avg(cyclicDFAStates); // // data. = Stats.stddev(cyclicDFAStates); // // data. = Stats.sum(cyclicDFAStates); data.numTokens = g.TokenTypes.Length; data.DFACreationWallClockTimeInMS = g.DFACreationWallClockTimeInMS; // includes true ones and preds in synpreds I think; strip out. data.numberOfSemanticPredicates = g.numberOfSemanticPredicates; data.numberOfManualLookaheadOptions = g.numberOfManualLookaheadOptions; data.numNonLLStarDecisions = g.numNonLLStar; data.numNondeterministicDecisions = g.setOfNondeterministicDecisionNumbers.Count; data.numNondeterministicDecisionNumbersResolvedWithPredicates = g.setOfNondeterministicDecisionNumbersResolvedWithPredicates.Count; data.errors = ErrorManager.GetErrorState().errors; data.warnings = ErrorManager.GetErrorState().warnings; data.infos = ErrorManager.GetErrorState().infos; data.blocksWithSemPreds = g.blocksWithSemPreds.Count; data.decisionsWhoseDFAsUsesSemPreds = g.decisionsWhoseDFAsUsesSemPreds.Count; return(data); }
/** Check for collision of a rule-scope dynamic attribute with: * arg, return value, rule name itself. Labels are checked elsewhere. */ public virtual 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.Token, attrName, arg2 ); } }
private void HandleRuleScopeSpecAction(Rule r, GrammarAST attrs, IDictionary<GrammarAST, GrammarAST> actions) { r.RuleScope = grammar.CreateRuleScope(r.Name, attrs.Token); r.RuleScope.IsDynamicRuleScope = true; r.RuleScope.AddAttributes(attrs.Text, ';'); foreach (var action in actions) r.RuleScope.DefineNamedAction(action.Key, action.Value); }
/** Make sure a label doesn't conflict with another symbol. * Labels must not conflict with: rules, tokens, scope names, * return values, parameters, and rule-scope dynamic attributes * defined in surrounding rule. */ protected virtual void CheckForLabelConflict( Rule r, IToken label ) { int msgID = 0; object arg2 = null; if ( grammar.GetGlobalScope( label.Text ) != null ) { msgID = ErrorManager.MSG_SYMBOL_CONFLICTS_WITH_GLOBAL_SCOPE; } else if ( grammar.GetRule( label.Text ) != null ) { msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE; } else if ( grammar.GetTokenType( label.Text ) != Label.INVALID ) { msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_TOKEN; } else if ( r.ruleScope != null && r.ruleScope.GetAttribute( label.Text ) != null ) { msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_SCOPE_ATTRIBUTE; arg2 = r.Name; } else if ( ( r.returnScope != null && r.returnScope.GetAttribute( label.Text ) != null ) || ( r.parameterScope != null && r.parameterScope.GetAttribute( label.Text ) != null ) ) { msgID = ErrorManager.MSG_LABEL_CONFLICTS_WITH_RULE_ARG_RETVAL; arg2 = r.Name; } if ( msgID != 0 ) { ErrorManager.GrammarError( msgID, grammar, label, label.Text, arg2 ); } }
private void HandleRuleScopeSpecUses(Rule r, GrammarAST uses) { if (grammar.GetGlobalScope(uses.Text) == null) { ErrorManager.GrammarError(ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE, grammar, uses.Token, uses.Text); } else { if (r.UseScopes == null) r.UseScopes = new List<string>(); r.UseScopes.Add(uses.Text); } }
protected virtual void CheckForRuleDefinitionProblems( Rule r ) { string ruleName = r.Name; IToken ruleToken = r.tree.Token; int msgID = 0; if ( ( grammar.type == GrammarType.Parser || grammar.type == GrammarType.TreeParser ) && Rule.GetRuleType(ruleName) == RuleType.Lexer) { msgID = ErrorManager.MSG_LEXER_RULES_NOT_ALLOWED; } else if ( grammar.type == GrammarType.Lexer && Rule.GetRuleType(ruleName) == RuleType.Parser && !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 ); } }
public RuleLabelScope( Rule referencedRule, IToken actionToken ) : base("ref_" + referencedRule.Name, actionToken) { this.referencedRule = referencedRule; }