public Precedence(SymbolCoordinates coords, AssociativityEnum associativity, IEnumerable <PrecedenceWord> usedTokens) { this.Coords = coords; this.Associativity = associativity; this.usedTokens = usedTokens.ToArray(); // each entry is its own micro group this.PriorityGroupStart = true; this.PriorityGroupEnd = true; }
protected IEnumerable <ITokenMatch <SYMBOL_ENUM> > initParse(IEnumerable <ITokenMatch <SYMBOL_ENUM> > tokens, ParserOptions options) { messages = null; if (actionTable == null) { throw new Exception("The grammar is not correct."); } this.options = options; if (options.Trace) { parseLog = new LinkedList <ParseHistory>(); } else { parseLog = null; } consecutiveCorrectActionsCount = 0; if (tokens.Any(it => SyntaxErrorSymbol.Equals(it.Token))) { throw new ArgumentException("All tokens have to be recognized."); } // nothing wrong if the last token is already an EOF, so skipping it if (tokens.SkipTail(1).Any(it => EofSymbol.Equals(it.Token))) { throw new ArgumentException("EOF token in the middle of the tokens."); } // if there are more tokens than just EOF, we strip EOF // because we would like to add new EOF with its position set just right after last token // this is solely for purpose of more precise line numbering if (tokens.Count() > 1 && EofSymbol.Equals(tokens.Last().Token)) { tokens = tokens.SkipTail(1).ToArray(); } tokens = tokens.Concat(Enumerable.Range(1, lookaheadWidth).Select(_ => new TokenMatch <SYMBOL_ENUM>(symbolsRep) { Token = EofSymbol, Coordinates = tokens.Last().Coordinates })).ToArray(); Coordinates = new SymbolCoordinates(false, new SymbolPosition(tokens.First().Coordinates.FirstPosition.Filename, LineNumberInit, ColumnNumberInit), new SymbolPosition(tokens.First().Coordinates.FirstPosition.Filename, LineNumberInit, ColumnNumberInit)); return(tokens); }
public Playback(SymbolCoordinates initCoordinates, Action <SymbolCoordinates> positionUpdate, Action <string, IEnumerable <string> > addWarningMessages, Action <string> addErrorMessage, Func <bool> isSuccessfulParse) { this.initCoordinates = initCoordinates; this.positionUpdate = positionUpdate; this.addWarningMessages = addWarningMessages; this.addErrorMessage = addErrorMessage; this.isSuccessfulParse = isSuccessfulParse; }
public static Precedence Create(SymbolCoordinates coords, string mode, string associativity, IEnumerable <string> inputSymbols, IEnumerable <PrecedenceWord> conflictProds) { precedenceMode prec = getPrec(mode); AssociativityEnum assoc = getAssoc(associativity); switch (prec) { case precedenceMode.Operator: return(new OperatorPrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds)); case precedenceMode.ReduceShift: return(new ReduceShiftPrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds)); case precedenceMode.ReduceReduce: return(new ReduceReducePrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds)); } throw ParseControlException.NewAndRun("Not recognized precedence"); }
public ReduceReducePrecedence(SymbolCoordinates coords, AssociativityEnum associativity, IEnumerable <PrecedenceWord> inputTokens, IEnumerable <PrecedenceWord> conflictTokens) : base(coords, associativity, inputTokens.Concat(conflictTokens)) { try { InputSet = inputTokens.ToArray(); ReduceSymbols = conflictTokens.ToArray(); if (ReduceSymbols.Count() < 2) { throw new Exception(); } } catch { throw ParseControlException.NewAndRun("Incorrect reduce/reduce precedence rule"); } }
// in case of operator precedence -- it is just a list of tokens, not conflict resolution really // so we don't have do anything special public OperatorPrecedence(SymbolCoordinates coords, AssociativityEnum associativity, IEnumerable <PrecedenceWord> inputTokens, IEnumerable <PrecedenceWord> conflictTokens) : base(coords, associativity, inputTokens.Concat(conflictTokens)) { }
internal static IEnumerable <Precedence> CreateOperators(SymbolCoordinates coords, string mode, IEnumerable <Tuple <string, string> > __opPairs, // it can be single and then serves as both reduce production and shift production // or it can be many, but then remember to put reduce production as first one (exactly as in RS rule) IEnumerable <string> __conflictProds) { if (!__conflictProds.Any()) { throw ParseControlException.NewAndRun("There has to be at least one production given for operator precedence."); } string reduce_prod = __conflictProds.First(); IEnumerable <string> shift_prod = __conflictProds.Count() == 1 ? new [] { __conflictProds.Single() }: __conflictProds.Skip(1).ToArray(); precedenceMode prec = getPrec(mode); if (prec != precedenceMode.ReduceShift) { throw ParseControlException.NewAndRun("Only shift-reduce mode is supported with this syntax."); } Tuple <string, string>[] op_pairs = __opPairs.ToArray(); var result = new List <Precedence>(); for (int i = 0; i < op_pairs.Length; ++i) { string input_sym = op_pairs[i].Item2; var group = new List <Precedence>(); { // same vs same // here we go as given associativity, because priority is the same (of course) AssociativityEnum assoc = getAssoc(op_pairs[i].Item1); group.Add(new ReduceShiftPrecedence(coords, assoc, new[] { new PrecedenceWord(input_sym) }, PrecedenceWord.Create(reduce_prod, input_sym).Concat(shift_prod.Select(it => new PrecedenceWord(it)))) { PriorityGroupEnd = false, PriorityGroupStart = false }); } if (i > 0) { // higher priority means that if master is in input we shift, and when it is on stack we reduce group.Add(new ReduceShiftPrecedence(coords, AssociativityEnum.Reduce, op_pairs.Take(i).Select(it => new PrecedenceWord(it.Item2)), PrecedenceWord.Create(reduce_prod, input_sym).Concat(shift_prod.Select(it => new PrecedenceWord(it)))) { PriorityGroupEnd = false, PriorityGroupStart = false }); group.Add(new ReduceShiftPrecedence(coords, AssociativityEnum.Shift, new[] { new PrecedenceWord(input_sym) }, new PrecedenceWord(reduce_prod, op_pairs.Take(i).Select(it => it.Item2)).Concat(shift_prod.Select(it => new PrecedenceWord(it)))) { PriorityGroupEnd = false, PriorityGroupStart = false }); } group.First().PriorityGroupStart = true; group.Last().PriorityGroupEnd = true; result.AddRange(group); } return(result); }
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); }
private void addToStack(bool advanceInput, SYMBOL_ENUM symbol, Option <object> userObject, SymbolCoordinates coordinates) { stack.Add(new StackElement <SYMBOL_ENUM, TREE_NODE>() { Symbol = symbol, UserObject = userObject, Coordinates = coordinates, }); if (advanceInput) { ++tokens.Offset; } }