Exemple #1
0
        /// <summary>
        ///     This function analyzes a token and either:
        ///     1. Makes a SINGLE reduction and pushes a complete Reduction object on the _stack
        ///     2. Accepts the token and shifts
        ///     3. Errors and places the expected symbol indexes in the Tokens list
        ///     The Token is assumed to be valid and WILL be checked
        ///     If an action is performed that requires controlt to be returned to the user, the function returns true.
        ///     The Message parameter is then set to the type of action.
        /// </summary>
        /// <param name="nextToken"></param>
        /// <returns></returns>
        private ParseResult ParseLALR(Token nextToken)
        {
            ParseResult result      = default(ParseResult);
            LRAction    parseAction = _lrStates[_currentLALR][(nextToken.Parent)];

            // Work - shift or reduce
            if ((parseAction != null))
            {
                _haveReduction = false;
                //Will be set true if a reduction is made
                //'Debug.WriteLine("Action: " & ParseAction.Text)

                switch (parseAction.Type)
                {
                case LRActionType.Accept:
                    _haveReduction = true;
                    result         = ParseResult.Accept;

                    break;

                case LRActionType.Shift:
                    _currentLALR    = parseAction.Value;
                    nextToken.State = (short)_currentLALR;
                    _stack.Push(nextToken);
                    result = ParseResult.Shift;

                    break;

                case LRActionType.Reduce:
                    //Produce a reduction - remove as many tokens as members in the rule & push a nonterminal token
                    Production prod = _productionTable[parseAction.Value];

                    //======== Create Reduction
                    Token head;
                    int   n;
                    if (TrimReductions && prod.ContainsOneNonTerminal())
                    {
                        //The current rule only consists of a single nonterminal and can be trimmed from the
                        //parse tree. Usually we create a new Reduction, assign it to the Data property
                        //of Head and push it on the _stack. However, in this case, the Data property of the
                        //Head will be assigned the Data property of the reduced token (i.e. the only one
                        //on the _stack).
                        //In this case, to save code, the value popped of the _stack is changed into the head.

                        head        = _stack.Pop();
                        head.Parent = prod.RuleNonterminal;

                        result = ParseResult.ReduceEliminated;
                        //Build a Reduction
                    }
                    else
                    {
                        _haveReduction = true;
                        var newReduction = new Reduction(prod.Handle.Count);

                        newReduction.ParentRule = prod;
                        for (n = prod.Handle.Count - 1; n >= 0; n += -1)
                        {
                            newReduction[n] = _stack.Pop();
                        }

                        head = new Token(prod.RuleNonterminal, newReduction);
                        //bool IsFirst;
                        //if (_stack.Count == 0)
                        //{
                        //    IsFirst = true;
                        //}
                        //else
                        //{
                        //    IsFirst = false;
                        //}
                        //newReduction.EndNoise = _lastNoise;
                        result = ParseResult.ReduceNormal;
                    }

                    //========== Goto
                    short index = _stack.Peek().State;

                    //========= If n is -1 here, then we have an Internal Table Error!!!!
                    n = _lrStates[index].IndexOf(prod.RuleNonterminal);
                    if (n != -1)
                    {
                        _currentLALR = _lrStates[index][n].Value;

                        head.State = (short)_currentLALR;
                        _stack.Push(head);
                    }
                    else
                    {
                        result = ParseResult.InternalError;
                    }
                    break;
                }
            }
            else
            {
                //=== Syntax Error! Fill Expected Tokens
                _expectedSymbols.Clear();
                //.Count - 1
                foreach (LRAction action in _lrStates[_currentLALR])
                {
                    switch (action.Symbol.Type)
                    {
                    case SymbolType.Terminal:
                    case SymbolType.End:
                    case SymbolType.GroupStart:
                    case SymbolType.GroupEnd:
                        _expectedSymbols.Add(action.Symbol);
                        break;
                    }
                }
                result = ParseResult.SyntaxError;
            }

            return(result);
        }
Exemple #2
0
        /// <summary>
        ///     Loads parse tables from the specified BinaryReader. Only EGT (version 5.0) is supported.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public bool LoadCompiledGrammar(BinaryReader reader)
        {
            var egt = new EGTReader();

            try
            {
                egt.Open(reader);

                Restart();
                while (!egt.EndOfFile())
                {
                    egt.GetNextRecord();
                    var recordType = (EGTRecord)egt.RetrieveByte();

                    if (recordType == EGTRecord.Property)
                    {
                        //Index, Name, ValueExpression
                        int index = egt.RetrieveInt16();
                        egt.RetrieveString();
                        //Just discard
                        _grammar.SetValue(index, egt.RetrieveString());
                    }
                    else if (recordType == EGTRecord.TableCounts)
                    {
                        //Symbol, CharacterSet, Rule, DFA, LALR
                        _symbolTable     = new SymbolList(egt.RetrieveInt16());
                        _charSetTable    = new CharacterSetList(egt.RetrieveInt16());
                        _productionTable = new ProductionList(egt.RetrieveInt16());
                        _dfa             = new FAStateList(egt.RetrieveInt16());
                        _lrStates        = new LRStateList(egt.RetrieveInt16());
                        _groupTable      = new GroupList(egt.RetrieveInt16());
                    }
                    else if (recordType == EGTRecord.InitialStates)
                    {
                        //DFA, LALR
                        _dfa.InitialState      = (short)egt.RetrieveInt16();
                        _lrStates.InitialState = (short)egt.RetrieveInt16();
                    }
                    else if (recordType == EGTRecord.Symbol)
                    {
                        //#, Name, Kind

                        int    index = egt.RetrieveInt16();
                        string name  = egt.RetrieveString();
                        var    type  = (SymbolType)egt.RetrieveInt16();

                        _symbolTable[index] = new Symbol(name, type, (short)index);
                    }
                    else if (recordType == EGTRecord.Group)
                    {
                        //#, Name, Container#, Start#, End#, Tokenized, Open Ended, Reserved, Count, (Nested Group #...)
                        var group = new Group();

                        int index = egt.RetrieveInt16();
                        group.Name      = egt.RetrieveString();
                        group.Container = SymbolTable[egt.RetrieveInt16()];
                        group.Start     = SymbolTable[egt.RetrieveInt16()];
                        group.End       = SymbolTable[egt.RetrieveInt16()];

                        group.Advance = (Group.AdvanceMode)egt.RetrieveInt16();
                        group.Ending  = (Group.EndingMode)egt.RetrieveInt16();
                        egt.RetrieveEntry();
                        //Reserved
                        int count = egt.RetrieveInt16();
                        for (int n = 0; n < count; n++)
                        {
                            group.Nesting.Add(egt.RetrieveInt16());
                        }


                        //=== Link back
                        group.Container.Group = group;
                        group.Start.Group     = group;
                        group.End.Group       = group;

                        _groupTable[index] = group;
                    }
                    else if (recordType == EGTRecord.CharRanges)
                    {
                        //#, Total Sets, RESERVED, (Start#, End#  ...)

                        int index = egt.RetrieveInt16();
                        egt.RetrieveInt16();
                        egt.RetrieveInt16();
                        egt.RetrieveEntry();

                        _charSetTable[index] = new CharacterSet();
                        while (!egt.RecordComplete())
                        {
                            _charSetTable[index].Add(new CharacterRange((ushort)egt.RetrieveInt16(), (ushort)egt.RetrieveInt16()));
                        }
                    }
                    else if (recordType == EGTRecord.Production)
                    {
                        //#, ID#, Reserved, (Symbol#,  ...)

                        int index     = egt.RetrieveInt16();
                        int headIndex = egt.RetrieveInt16();
                        egt.RetrieveEntry();

                        _productionTable[index] = new Production(_symbolTable[headIndex], (short)index);

                        while (!(egt.RecordComplete()))
                        {
                            int symbolIndex = egt.RetrieveInt16();
                            _productionTable[index].Handle.Add(_symbolTable[symbolIndex]);
                        }
                    }
                    else if (recordType == EGTRecord.DfaState)
                    {
                        //#, Accept?, Accept#, Reserved (CharSet#, Target#, Reserved)...

                        int  index       = egt.RetrieveInt16();
                        bool accept      = egt.RetrieveBoolean();
                        int  acceptIndex = egt.RetrieveInt16();
                        egt.RetrieveEntry();

                        if (accept)
                        {
                            _dfa[index] = new FAState(_symbolTable[acceptIndex]);
                        }
                        else
                        {
                            _dfa[index] = new FAState();
                        }

                        //(Edge chars, Target#, Reserved)...
                        while (!egt.RecordComplete())
                        {
                            int setIndex = egt.RetrieveInt16();
                            int target   = egt.RetrieveInt16();
                            egt.RetrieveEntry();

                            _dfa[index].Edges.Add(new FAEdge(_charSetTable[setIndex], target));
                        }
                    }
                    else if (recordType == EGTRecord.LrState)
                    {
                        //#, Reserved (Symbol#, Action, Target#, Reserved)...

                        int index = egt.RetrieveInt16();
                        egt.RetrieveEntry();

                        _lrStates[index] = new LRState();

                        //(Symbol#, Action, Target#, Reserved)...
                        while (!(egt.RecordComplete()))
                        {
                            int symbolIndex = egt.RetrieveInt16();
                            int action      = egt.RetrieveInt16();
                            int target      = egt.RetrieveInt16();
                            egt.RetrieveEntry();

                            _lrStates[index].Add(new LRAction(_symbolTable[symbolIndex], (LRActionType)action, (short)target));
                        }
                    }
                    else
                    {
                        throw new EngineException("File Error. A record of type '" + recordType + "' was read. This is not a valid code.");
                    }
                }
            }
            catch (EngineException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new EngineException("Error while loading tables.", ex);
            }

            _areTablesLoaded = true;
            return(true);
        }