Esempio n. 1
0
        private string dumpNfaCell(NfaCell <int, object> nfaCell, string symbolTypeName, Func <int, string> symbolNameConvert, string treeNodeName)
        {
            string code_str = null;

            if (nfaCell.ProductionUserAction != null)
            {
                // launch the fake action to retrieve the code of the action stored as string
                CodeLambda code = (CodeLambda)nfaCell.ProductionUserAction.Code(null);
                code_str = "ProductionAction<" + treeNodeName + ">.Convert(" + code.Make() + "," + code.RhsUnusedParamsCount + ")";
                //code_str = (string)nfaCell.ProductionUserAction(null);
            }

            return("NfaCell<" + symbolTypeName + "," + treeNodeName + ">.Create(" + Environment.NewLine
                   + symbolNameConvert(nfaCell.LhsSymbol) + "," + Environment.NewLine
                   + nfaCell.RhsSeenCount + "," + Environment.NewLine
                   + (!nfaCell.RecoveryTerminals.Any()
                        ? CodeWords.Null
                        : (CodeWords.New + "[]{" + nfaCell.RecoveryTerminals.Select(it => symbolNameConvert(it)).Join(",") + "}")) + "," + Environment.NewLine

                   // markings are really raw ints (they are not symbols)
                   + nfaCell.ProductionMark + "," + Environment.NewLine
                   + "\"" + nfaCell.ProductionCoordinates + "\"," + Environment.NewLine

                   + (nfaCell.ProductionTabooSymbols.Any(col => col.Count > 0) ?
                      (CodeWords.New + " []{"
                       + String.Join(",", nfaCell.ProductionTabooSymbols.Select(col => CodeWords.New + " HashSet<int>(" + CodeWords.New + " int[]{"
                                                                                + String.Join(",", col.Select(it => it)) + "})"))
                       + "}") : CodeWords.Null) + "," + Environment.NewLine

                   + (code_str == null ? CodeWords.Null : code_str)
                   + ")" + Environment.NewLine);
        }
Esempio n. 2
0
        public NfaCell <SYMBOL_ENUM, TREE_NODE> CreateCell()
        {
            FirstSets <SYMBOL_ENUM> firstSets = Production.Productions.FirstSets;

            return(NfaCell <SYMBOL_ENUM, TREE_NODE> .Create(
                       lhs : LhsSymbol,
                       rhsSeen : RhsSeenCount,
                       recovery : IsAtRecoveryPoint?firstSets[RecoveryMarkerSymbol].Chunks.Select(it => it.Symbols.First()) : null,
                       productionMark : Production.Productions.GetMarkingId(Production.MarkWith),
                       coords : Production.PositionDescription,
                       taboo : Production.TabooSymbols.Select(col => new HashSet <int>(Production.Productions.GetMarkingIds(col))).ToArray(),
                       action : Production.UserAction));
        }
Esempio n. 3
0
        private bool makeReduction(ActionRecoveryEnum findAction, NfaCell <SYMBOL_ENUM, TREE_NODE> reduceItem,
                                   AttachPoint <SYMBOL_ENUM, TREE_NODE> attachPoint,
                                   IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > stackTail)
        {
            // if taboo symbol was used, ignore this reduction
            if (reduceItem.ProductionTabooSymbols != null &&
                reduceItem.ProductionTabooSymbols.SyncZip(stackTail.Select(it => it.MarkedWith)).Any(it => it.Item1.Contains(it.Item2)))
            {
                if (options.Trace)
                {
                    parseLog.Last.Value.Reduced.Add(ParseHistory.Reduce + " rejected (taboo filter)");
                }
                return(false);
            }

            string trace = null;

            if (options.Trace)
            {
                trace = ParseHistory.Reduce + " " + symbolsRep.Get(reduceItem.LhsSymbol);
            }

            // no recovery from reduce (reduce cannot be recovered by itself, only by prior recovery point)
            StackElement <SYMBOL_ENUM, TREE_NODE> added = addToStack(Command.Reduced(reduceItem),
                                                                     attachPoint: attachPoint,
                                                                     symbol: reduceItem.LhsSymbol,
                                                                     markWith: reduceItem.ProductionMark,
                                                                     text: String.Join(textInfoSep, stackTail.Select(it => it.TextInfo)),
                                                                     userObject: new Option <object>(),
                                                                     recovered: findAction == ActionRecoveryEnum.Recovered);

            if (options.Trace)
            {
                parseLog.Last.Value.Reduced.Add(trace + "[" + added.ForkId + "]");
            }

            return(true);
        }
Esempio n. 4
0
        // if we have clear action to do (shift/reduce) pass it forward
        // if not, here we try to recover from syntax error
        private ActionRecoveryEnum getActionOrRecover(int nodeId,
                                                      out IEnumerable <ParseAction <SYMBOL_ENUM, TREE_NODE> > parseActions,
                                                      bool startWithRecovering)
        {
            ActionRecoveryEnum success_result = ActionRecoveryEnum.Success;

            while (true)
            {
                if (startWithRecovering)
                {
                    parseActions = null;
                }
                else
                {
                    // in normal run we ignore grammar conflicts, user should get conflicts just once, at validating stage
                    parseActions = actionTable.Get(nodeId, stackMaster.InputView);
                }

                startWithRecovering = false;

                if (parseActions != null)
                {
                    ++consecutiveCorrectActionsCount;
                    // it could be success after naive recovery
                    return(success_result);
                }



                // trying to recover from old recovery point
                if (stackMaster.IsForked)
                {
                    return(ActionRecoveryEnum.SyntaxError);
                }
                else
                {
                    // make a lazy message
                    if (!callUserErrorHandler(stackMaster.InputHead, () => "No action defined at node " + nodeId
                                              + " for input \"" + SymbolChunk.Create(stackMaster.InputTokens.Take(lookaheadWidth)).ToString(symbolsRep) + "\" with stack \""
                                              + String.Join(" ", stackMaster.Stack.TakeTail(historyHorizon)
                                                            .Select(it => symbolsRep.Get(it.Symbol))) + "\"."))
                    {
                        return(ActionRecoveryEnum.StopParsing);
                    }

                    consecutiveCorrectActionsCount = 0;
                    IEnumerable <NfaCell <SYMBOL_ENUM, TREE_NODE> > recovery_items;

                    if (stack.FindLastWhere(it => it.IsRecoverable, it => it.RecoveryItems, out recovery_items))
                    {
                        if (options.Trace)
                        {
                            parseLog.Last.Value.Recovered = true;
                        }

                        // we would like to get minimal recovery item
                        // i.e. the one which wastes the minimum of the input in order to recover
                        NfaCell <SYMBOL_ENUM, TREE_NODE> min_recovery_item = recovery_items
                                                                             .ArgMin(rec => stackMaster.Input
                                                                             // for each recovery item compute the count of required tokens from input
                                                                                     .TakeWhile(it => !rec.MatchesRecoveryTerminal(it.Token) && !it.Token.Equals(EofSymbol)).Count())
                                                                             // not single, because we could hit EOF in several cases
                                                                             .First();

                        parseActions = new[] { new ParseAction <SYMBOL_ENUM, TREE_NODE>(false, ReductionAction.Create(min_recovery_item)) };

                        stackMaster.AdvanceInputWhile(it => !min_recovery_item.MatchesRecoveryTerminal(it.Token) && !it.Token.Equals(EofSymbol));

                        // we hit the wall
                        if (IsEndOfInput)
                        {
                            return(ActionRecoveryEnum.SyntaxError);
                        }

                        stackMaster.AdvanceInput(); // advance past the marker

                        // setting stack as if we were the old recovery point
                        // (sometimes we really are, because the last element on the stack can be recovery point)
                        stackMaster.RemoveLastWhile(it => !it.IsRecoverable);

                        return(ActionRecoveryEnum.Recovered);
                    }
                    else if (IsEndOfInput)
                    {
                        return(ActionRecoveryEnum.SyntaxError);
                    }
                    else
                    {
                        if (options.Trace)
                        {
                            parseLog.Last.Value.Recovered = true;
                        }

                        // there is no recovery rule defined by the user so try to
                        // "fix" the errors step by step
                        stackMaster.AdvanceInput();
                        // further success will be in fact the result of recovery
                        success_result = ActionRecoveryEnum.Recovered;
                    }
                }
            }
        }
Esempio n. 5
0
        private bool process()
        {
            Command <SYMBOL_ENUM, TREE_NODE> command = commands.First.Value;

            NfaCell <SYMBOL_ENUM, TREE_NODE> reduce_item = command.ReduceItem;

            commands.RemoveFirst();

            if (reduce_item == null) // shift
            {
                ITokenMatch <SYMBOL_ENUM> input_head = tokens.Head;

                addToStack(advanceInput: true,
                           symbol: input_head.Token,
                           userObject: new Option <object>(input_head.Value),
                           coordinates: input_head.Coordinates);
            }
            else
            {
                // here we have to use RhsSeenCount from state, not from production to use the same code as in parsers
                List <StackElement <SYMBOL_ENUM, TREE_NODE> > stack_tail = stack.RemoveLast(reduce_item.RhsSeenCount).ToList();

                bool           is_exact = true;
                SymbolPosition first_position;
                SymbolPosition last_position;
                {
                    SymbolCoordinates first_coords = stack_tail.Select(it => it.Coordinates).FirstOrDefault(it => it.IsExact);
                    if (first_coords != null)
                    {
                        first_position = first_coords.FirstPosition;
                    }
                    else
                    {
                        is_exact = false;

                        first_coords = stack.Select(it => it.Coordinates).LastOrDefault(it => it.IsExact);
                        if (first_coords != null)
                        {
                            first_position = first_coords.LastPosition;
                        }
                        else
                        {
                            first_position = initCoordinates.FirstPosition;
                        }
                    }
                }
                {
                    SymbolCoordinates last_coords = stack_tail.Select(it => it.Coordinates).LastOrDefault(it => it.IsExact);
                    if (last_coords != null)
                    {
                        last_position = last_coords.LastPosition;
                    }
                    else
                    {
                        last_position = tokens.Head.Coordinates.FirstPosition;
                    }
                }

                var coordinates = new SymbolCoordinates(is_exact, first_position, last_position);
                positionUpdate(coordinates);

                // no value for user object -- for 2 reasons:
                // * in case of exception we have to pass no value further
                // * if stack already contains no value we have to pass no value again
                var user_object = new Option <object>();

                // [@PARSER_USER_ACTION]
                // this is shortcut -- instead of passing function that returns nulls (when bulding parser)
                // we set user actions to null and here we can handle it
                if (reduce_item.ProductionUserAction == null)
                {
                    // return null as user object (it is a valid value)
                    user_object = new Option <object>(null);
                }
                else if (stack_tail.All(it => it.UserObject.HasValue))
                {
                    try
                    {
                        object value = reduce_item.ProductionUserAction.Code(stack_tail.Select(it => it.UserObject.Value).ToArray());
                        if (value is RichParseControl)
                        {
                            addWarningMessages(coordinates.FirstPosition.ToString(), (value as RichParseControl).Warnings);
                            user_object = new Option <object>((value as RichParseControl).Value);
                        }
                        else
                        {
                            user_object = new Option <object>(value);
                        }
                    }
                    catch (ParseControlException ex)
                    {
                        addErrorMessage(coordinates.FirstPosition.ToString() + ": " + ex.Message);
                        if (!ex.ContinueOnError)
                        {
                            return(false);
                        }
                    }
                    catch (Exception ex)
                    {
                        addErrorMessage("User action error in production : " + reduce_item.ProductionCoordinates + Environment.NewLine + ex.Message
                                        + Environment.NewLine + ex.ToString());
                        addErrorMessage(ex.StackTrace);
                        return(false);
                    }
                }

                addToStack(advanceInput: false,
                           symbol: reduce_item.LhsSymbol,
                           userObject: user_object,
                           coordinates: coordinates);
            }

            return(true);
        }
Esempio n. 6
0
 public static Command <SYMBOL_ENUM, TREE_NODE> Reduced <SYMBOL_ENUM, TREE_NODE>(NfaCell <SYMBOL_ENUM, TREE_NODE> reduceItem)
     where SYMBOL_ENUM : struct
     where TREE_NODE : class
 {
     return(new Command <SYMBOL_ENUM, TREE_NODE>(reduceItem));
 }
Esempio n. 7
0
 public static ReductionAction <SYMBOL_ENUM, TREE_NODE> Create <SYMBOL_ENUM, TREE_NODE>(NfaCell <SYMBOL_ENUM, TREE_NODE> cell,
                                                                                        SymbolChunkSet <SYMBOL_ENUM> acceptHorizon, SymbolChunkSet <SYMBOL_ENUM> rejectHorizon)
     where SYMBOL_ENUM : struct
     where TREE_NODE : class
 {
     return(new ReductionAction <SYMBOL_ENUM, TREE_NODE>(cell, acceptHorizon, rejectHorizon));
 }
Esempio n. 8
0
 public static ReductionAction <SYMBOL_ENUM, TREE_NODE> Create <SYMBOL_ENUM, TREE_NODE>(NfaCell <SYMBOL_ENUM, TREE_NODE> cell)
     where SYMBOL_ENUM : struct
     where TREE_NODE : class
 {
     return(new ReductionAction <SYMBOL_ENUM, TREE_NODE>(cell, null, null));
 }