コード例 #1
0
ファイル: BnfParser.cs プロジェクト: AleksaMCode/bnf-parser
        public void AddRule(BnfRule rule)
        {
            NonTerminalToken lhs = rule.LeftHandSide;

            foreach (BnfRule ruleIn in rules)
            {
                if (lhs.equals(ruleIn.LeftHandSide))
                {
                    ruleIn.AddPossibilities(rule.GetPossibilities());
                    break;
                }
            }
            this.rules.Add(rule); // No rule with the same LHS found
        }
コード例 #2
0
ファイル: BnfParser.cs プロジェクト: AleksaMCode/bnf-parser
        public ParseNode Parse(BnfRule rule, ref string input, int recursionStep, int lineNum)
        {
            // When the maximum recursion depth is reached program throws exception.
            if (recursionStep > maxRecursionSteps)
            {
                throw new Exception(string.Format("Max. number of recursion steps reached. Error line : {0}", lineNum));
            }

            ParseNode node       = null;
            bool      wrongToken = true;
            string    inputCpy   = "";

            inputCpy += input;
            foreach (TokenList poss in rule.GetPossibilities())
            {
                node       = new ParseNode();
                node.Token = node.Value = rule.LeftHandSide.Name;
                TokenList           newPossib      = poss.getCopy();
                IEnumerator <Token> possibIterator = newPossib.GetEnumerator();
                wrongToken = false;
                inputCpy   = "";
                inputCpy  += input;
                while (possibIterator.MoveNext() && !wrongToken) // checks if it has next token
                {
                    inputCpy = inputCpy.Trim();
                    Token possToken = possibIterator.Current;
                    if (possToken is TerminalToken)
                    {
                        if (string.IsNullOrEmpty(inputCpy))
                        {
                            wrongToken = true;
                            break;
                        }

                        int limit = possToken.match(inputCpy);
                        if (limit > 0)
                        {
                            ParseNode child          = new ParseNode();
                            string    inputSubstring = inputCpy.Substring(0, limit);
                            inputCpy = inputCpy.Remove(0, inputSubstring.Length);

                            if (possToken is RegexTerminalToken)
                            {
                                child = AddRegexToken(child, (RegexTerminalToken)possToken, inputSubstring);
                            }

                            child.Token = inputSubstring;
                            node.AddChild(child);
                        }
                        //else if (limit == -1)
                        //{
                        //    if (possToken is StandardExpressionTerminalToken && !((StandardExpressionTerminalToken)possToken).IsItAMatch(inputCpy))
                        //        throw new Exception("Regex not mached [" + possToken.Name + "] -> " + inputCpy + "\n");

                        //    else if (possToken is BigCityTerminalToken && !((BigCityTerminalToken)possToken).IsItAMatch(inputCpy))
                        //        throw new Exception("City not mached! City: " + inputCpy + "\n");
                        //}
                        else // No match; rule expects token
                        {
                            wrongToken = true;
                            node       = null;
                            break;
                        }
                    }
                    else // Parse non-terminal token
                    {
                        ParseNode child   = null;
                        BnfRule   newRule = GetRule(possToken);
                        if (newRule == null)
                        {
                            throw new Exception("There is rule missing for the non-terminal token '" + possToken.Name + "'!\n");
                        }

                        child = Parse(newRule, ref inputCpy, recursionStep + 1, lineNum);
                        if (child == null) // Parsing failed!
                        {
                            wrongToken = true;
                            node       = null;
                            break;
                        }
                        node.AddChild(child);
                    }
                }
                if (!wrongToken)
                {
                    if (!possibIterator.MoveNext())
                    {
                        if (recursionStep > 0 || (recursionStep == 0 && inputCpy.Trim().Length == 0))
                        {
                            break;
                        }
                    }
                    else
                    {
                        wrongToken = true;
                        inputCpy   = "";
                        inputCpy  += input;
                        break;
                    }
                }
            }
            int consumedLength = input.Length - inputCpy.Length;

            if (wrongToken || consumedLength == 0)
            {
                return(null);
            }

            input = input.Substring(consumedLength);
            if (recursionStep == 0 && !string.IsNullOrEmpty(input))
            {
                return(null);
            }

            return(node);
        }