Exemple #1
0
        private static void GetNextStates(Dictionary <int, State> states, State state, ref int stateCount)
        {
            var branchGroups = state.Branches.GroupBy(b => b.TokenType);

            foreach (var branchGroup in branchGroups)
            {
                if (branchGroup.Count(b => b.LookAheadHint == null) > 1)
                {
                    throw new ParserGeneratorException("Ambiguous rules. Provide more look-ahead hints. Branches: {0}{1}", Environment.NewLine, string.Join(Environment.NewLine, branchGroup.Where(b => b.LookAheadHint == null)));
                }

                foreach (var branch in branchGroup.OrderBy(b => b.LookAheadHint == null))
                {
                    var nextCallStackItem = new CallStackItem(branch.CallStackItem.Parent, branch.CallStackItem.Rule, AFTER_RULE_POSITION);
                    var nextBranches      = GetBranches(nextCallStackItem);
                    var lookAheadHint     = branchGroup.Count() == 1 ? null : branch.LookAheadHint;

                    var existingState = states.Values.FirstOrDefault(s => s.Equals(nextBranches));
                    if (existingState != null)
                    {
                        state.AddTransition(new StateTransition(branch.TokenType, existingState.Id, branch.OptimizedProductions, lookAheadHint));
                    }
                    else
                    {
                        var newState = new State(stateCount++, nextBranches)
                        {
                            Comment = branch.CallStackItem.ToString()
                        };
                        states.Add(newState.Id, newState);
                        state.AddTransition(new StateTransition(branch.TokenType, newState.Id, branch.OptimizedProductions, lookAheadHint));
                        GetNextStates(states, newState, ref stateCount);
                    }
                }
            }
        }
Exemple #2
0
        private static CallStackItem Advance(CallStackItem item, List <ProductionRule> productions)
        {
            var sequenceRule = item.Rule as SequenceRule;

            if (sequenceRule != null)
            {
                var ruleElement = sequenceRule.RuleElements[item.Position];

                if (ruleElement.Multilicator == Multilicator.Any /* OneOrMore is trasformed to One + Any already || ruleElement.Multilicator == Multilicator.OneOrMore*/)
                {
                    return(item);
                }

                if (item.Position != AFTER_RULE_POSITION && item.Position + 1 < sequenceRule.RuleElements.Length)
                {
                    return(new CallStackItem(item.Parent, item.Rule, item.Position + 1));
                }
            }

            // advance the level above
            if (item.Parent == null)
            {
                return(null);
            }

            productions.Add(new ProductionRule(ProductionRuleType.End, item.Rule));
            return(Advance(item.Parent, productions));
        }
Exemple #3
0
        public static Dictionary <int, State> CalculateStates(RuleSet ruleSet)
        {
            var startCallStackItem = new CallStackItem(null, ruleSet.StartRule);
            var branches           = GetBranches(startCallStackItem);

            int stateCount = 0;
            var states     = new Dictionary <int, State>();
            var startState = new State(stateCount++, branches)
            {
                Comment = "Start"
            };

            states.Add(startState.Id, startState);

            GetNextStates(states, startState, ref stateCount);

            foreach (var state in states.Values.Where(s => !s.IsEndState))
            {
                if (!state.Branches.Any(b => b.TokenType.Equals(TokenType.Other)))
                {
                    foreach (var ignoredToken in ruleSet.IgnoredTokens)
                    {
                        if (!state.Branches.Any(b => b.TokenType.Equals(ignoredToken)))
                        {
                            state.AddTransition(new StateTransition(ignoredToken, state.Id, new List <ProductionRule> {
                                new ProductionRule(ProductionRuleType.Process, null)
                            }, null));
                        }
                    }
                }
            }

            return(states);
        }
Exemple #4
0
 public bool Equals(Branch x, Branch y)
 {
     return(x.TokenType.Equals(y.TokenType) &&
            x.OptimizedProductions.SequenceEqual(y.OptimizedProductions) &&
            CallStackItem.PositionAgnosticEquals(x.CallStackItem, y.CallStackItem)
            );
 }
Exemple #5
0
        private static Branch CreateBranch(CallStackItem caller, List <ProductionRule> productions, LookAheadHint lookAheadHint)
        {
            var branch = new Branch(((TokenRule)caller.Rule).TokenType, caller, productions)
            {
                LookAheadHint = lookAheadHint
            };

            OptimizeProductions(branch);
            return(branch);
        }
Exemple #6
0
        private static int RuleCountInCallStack(Rule rule, CallStackItem callStackItem)
        {
            int result = callStackItem.Rule == rule ? 1 : 0;

            if (callStackItem.Parent == null)
            {
                return(result);
            }
            return(RuleCountInCallStack(rule, callStackItem.Parent) + result);
        }
Exemple #7
0
 public CallStackItem(CallStackItem parent, Rule rule, int position = 0)
 {
     if (rule == null)
     {
         throw new ArgumentNullException("rule");
     }
     this.parent   = parent;
     this.rule     = rule;
     this.position = position;
 }
Exemple #8
0
        private static List <Branch> GetBranchesInternal(CallStackItem caller, List <ProductionRule> productions)
        {
            productions = productions ?? new List <ProductionRule>();

            bool ruleCanFinish;
            var  branches = GetBranchesInSubRules(caller, out ruleCanFinish, productions);

            if (ruleCanFinish && caller.Parent != null)
            {
                productions.Add(new ProductionRule(ProductionRuleType.End, caller.Rule));
                var nextInParent = Advance(caller.Parent, productions);
                if (nextInParent != null)
                {
                    branches.AddRange(GetBranchesInternal(nextInParent, productions));
                }
            }

            return(branches);
        }
Exemple #9
0
        private static List <Branch> GetBranchesInSubRules(CallStackItem caller, out bool ruleCanFinish, List <ProductionRule> productions, LookAheadHint lookAheadHint = null)
        {
            var result    = new List <Branch>();
            var lookAhead = caller.Rule.LookAheadHint ?? lookAheadHint;

            if (caller.Position == AFTER_RULE_POSITION)
            {
                ruleCanFinish = true;
                return(result);
            }

            if (caller.Rule is TokenRule)
            {
                ruleCanFinish = false;
                productions.Add(new ProductionRule(ProductionRuleType.Process, caller.Rule));
                result.Add(CreateBranch(caller, productions, lookAhead));
                return(result);
            }

            var ruleElements = ((DerivedRule)caller.Rule).RuleElements;

            if (caller.Rule is SequenceRule)
            {
                int subRuleIndex = caller.Position;
                for (; subRuleIndex < ruleElements.Length; subRuleIndex++)
                {
                    var subRuleElement = ruleElements[subRuleIndex];

                    if (RuleCountInCallStack(subRuleElement.ResolvedRule, caller) > 3)
                    {
                        ruleCanFinish = false;
                        return(result);
                    }

                    var  subRuleCaller        = new CallStackItem(caller.Parent, caller.Rule, subRuleIndex);
                    var  subRuleCallStackItem = new CallStackItem(subRuleCaller, subRuleElement.ResolvedRule);
                    bool subRuleCanFinish;

                    var subRuleProductions = new List <ProductionRule>(productions)
                    {
                        new ProductionRule(ProductionRuleType.Start, subRuleElement.ResolvedRule)
                    };
                    var subRuleBranches = GetBranchesInSubRules(subRuleCallStackItem, out subRuleCanFinish, subRuleProductions, lookAhead);

                    result.AddRange(subRuleBranches);

                    bool continueWithNext = subRuleCanFinish ||
                                            subRuleElement.Multilicator == Multilicator.Any ||
                                            subRuleElement.Multilicator == Multilicator.OneOrZero;

                    if (!continueWithNext)
                    {
                        break;
                    }
                }
                ruleCanFinish = subRuleIndex == ruleElements.Length;
                return(result);
            }

            Debug.Assert(caller.Rule is AlternateRule);
            if (caller.Rule is AlternateRule)
            {
                Debug.Assert(caller.Position == 0);

                ruleCanFinish = false;
                for (int subRuleIndex = 0; subRuleIndex < ruleElements.Length; subRuleIndex++)
                {
                    var  subRuleElement       = ruleElements[subRuleIndex];
                    var  subRuleCaller        = new CallStackItem(caller.Parent, caller.Rule, subRuleIndex);
                    var  subRuleCallStackItem = new CallStackItem(subRuleCaller, subRuleElement.ResolvedRule);
                    bool subRuleCanFinish;

                    var subRuleProductions = new List <ProductionRule>(productions)
                    {
                        new ProductionRule(ProductionRuleType.Start, subRuleElement.ResolvedRule)
                    };
                    var subRuleBranches = GetBranchesInSubRules(subRuleCallStackItem, out subRuleCanFinish, subRuleProductions, lookAhead);

                    result.AddRange(subRuleBranches);
                    ruleCanFinish |= subRuleCanFinish;
                }
                return(result);
            }

            throw new NotSupportedException();
        }
Exemple #10
0
 private static List <Branch> GetBranches(CallStackItem caller)
 {
     return(GetBranchesInternal(caller, new List <ProductionRule>()));
 }
Exemple #11
0
 protected bool Equals(Branch other)
 {
     return(TokenType.Equals(other.TokenType) &&
            CallStackItem.Equals(other.CallStackItem) &&
            OptimizedProductions.SequenceEqual(other.OptimizedProductions));
 }
Exemple #12
0
 public Branch(TokenType tokenType, CallStackItem callStackItem, List <ProductionRule> productions)
 {
     TokenType     = tokenType;
     CallStackItem = callStackItem;
     Productions   = productions;
 }
Exemple #13
0
 public static bool PositionAgnosticEquals(CallStackItem x, CallStackItem y)
 {
     return(((x.parent == null && y.parent == null) ||
             (x.parent != null && y.parent != null && PositionAgnosticEquals(x.parent, y.parent))) &&
            Equals(x.rule, y.rule));
 }
Exemple #14
0
 protected bool Equals(CallStackItem other)
 {
     return(Equals(parent, other.parent) && Equals(rule, other.rule) && position == other.position);
 }