public override void Apply(LanguageData language, Construction.LRItem owner) { //Create custom action and put it into state.Actions table var state = owner.State; var action = new CustomParserAction(language, state, _executeMethod); if (_previewMethod != null) { _previewMethod(action); } if (!state.BuilderData.IsInadequate) // adequate state, with a single possible action which is DefaultAction { state.DefaultAction = action; } else if (owner.Core.Current != null) //shift action { state.Actions[owner.Core.Current] = action; } else { foreach (var lkh in owner.Lookaheads) { state.Actions[lkh] = action; } } //We consider all conflicts handled by the action state.BuilderData.Conflicts.Clear(); } //method
public override void Apply(LanguageData language, Construction.LRItem owner) { //Create custom action and put it into state.Actions table var state = owner.State; var action = new CustomParserAction(language, state, _executeMethod); if (_previewMethod != null) _previewMethod(action); if (!state.BuilderData.IsInadequate) // adequate state, with a single possible action which is DefaultAction state.DefaultAction = action; else if (owner.Core.Current != null) //shift action state.Actions[owner.Core.Current] = action; else foreach (var lkh in owner.Lookaheads) state.Actions[lkh] = action; //We consider all conflicts handled by the action state.BuilderData.Conflicts.Clear(); }//method
// Only parse a literal array if we're not inside a pameter list. We check the context sensitivity by // using implict beginParamList and endParamList symbols void ResolveLiteralArrayConflict(ParsingContext context, CustomParserAction customAction) { // First check for a comma term. Any other is not a list, so it must be a reduction to unary_expression if (context.CurrentParserInput.Term.Name != ",") { customAction.ReduceActions.First().Execute(context); return; } // if there is no possibility to reduce, just do a shift var firstCorrectShiftAction = customAction.ShiftActions.First(a => a.Term.Name == ","); if (customAction.ReduceActions.Count < 1) { firstCorrectShiftAction.Execute(context); return; } // so we can shift or reduce. Let's look if we're in a paramBlock // we do this be iterating over the read tokens backwards and checking for a marker token which marks // the beginning and end of a parameter list var tokens = context.CurrentParseTree.Tokens; var isParamList = false; for (int i = tokens.Count - 1; i >= 0; i--) { var tk = tokens[i]; if (tk.Terminal == _begin_paramlist_marker) { isParamList = true; // yes, inside a param block break; } else if (tk.Terminal == _end_paramlist_marker) { break; // we're outside a param block } } // if we're inside a parameter list, reduce (so not array literal is parsed) if (isParamList) { customAction.ReduceActions.First().Execute(context); return; } // otherwise just shift to parse the array literal firstCorrectShiftAction.Execute(context); }
/* The shift-reduce conflict for "<" symbol is the problem of deciding what is "<" symbol in the input - is it * opening brace for generic reference, or logical operator. The following is a printout of parser state that has a conflict * The handling code needs to run ahead and decide a proper action: if we see ">", then it is a generic bracket and we do shift; * otherwise, it is an operator and we make Reduce * State S188 (Inadequate) Shift items: member_access_segments_opt -> member_access_segments_opt ·member_access_segment member_access_segment -> ·. Identifier member_access_segment -> ·array_indexer array_indexer -> ·[ expression_list ] member_access_segment -> ·argument_list_par argument_list_par -> ·( argument_list_opt ) member_access_segment -> ·type_argument_list type_argument_list -> ·_<_ type_ref_list > _<_ -> ·< Reduce items: member_access -> identifier_ext member_access_segments_opt · [? , ) : ; } ] Identifier ++ -- || && | ^ & == != > <= >= << >> + - * / % = += -= *= /= %= &= |= ^= <<= >>= is as ?? <] Shifts: member_access_segment->S220, .->S221, array_indexer->S222, [->S223, argument_list_par->S224, (->S225, type_argument_list->S226, _<_->S59, */ //Here is an elaborate generic declaration which can be used as a good test. Perfectly legal, uncomment it to check that c# // accepts it: // List<Dictionary<string, object[,]>> genericVar; private void ResolveLessThanConflict(ParsingContext context, CustomParserAction customAction) { var scanner = context.Parser.Scanner; string previewSym = null; if (context.CurrentParserInput.Term.Name == "<") { scanner.BeginPreview(); int ltCount = 0; while(true) { //Find first token ahead (using preview mode) that is either end of generic parameter (">") or something else Token preview; do { preview = scanner.GetToken(); } while (_skipTokensInPreview.Contains(preview.Terminal) && preview.Terminal != base.Eof); //See what did we find previewSym = preview.Terminal.Name; if (previewSym == "<") ltCount++; else if (previewSym == ">" && ltCount > 0) { ltCount--; continue; } else break; } scanner.EndPreview(true); //keep previewed tokens; important to keep ">>" matched to two ">" symbols, not one combined symbol (see method below) }//if //if we see ">", then it is type argument, not operator ParserAction action; if (previewSym == ">") action = customAction.ShiftActions.First(a => a.Term.Name == "<"); else action = customAction.ReduceActions.First(); // Actually execute action action.Execute(context); }
private void ResolveConflicts(ParsingContext context, CustomParserAction action) { }