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); }
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)); }
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); }
// 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; } } } }
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); }
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)); }
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)); }
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)); }