public override ParseAction ParseAction(State state, ITerminalSymbol symbol) { if (state.IsEmpty) { return(SyntaxError); } // If any of the rules allow a shift, do that (ignoring potential reduces) if (state.items.Any(i => !i.AtEnd)) { // TODO: Count shift/reduce conflicts // Shift the symbol onto the stack return((token, parser) => parser.Shift(token, state.terminalGotos[symbol.TerminalIndex])); } // We have one reduce rule if (state.items.Count == 1 && state.items.First().AtEnd) { // This is a "reduce" action return((token, parser) => state.items.First().Rule.function(token, parser)); } // We have more than one reduce rule: throw new ReduceReduceConflict(state.items.First().Rule, state.items.ElementAt(1).Rule); }
public State CreateInitialState(INonterminalSymbol s) { // Hack to find the "eof" symbol ITerminalSymbol eof = (ITerminalSymbol)s.Rules.First().rhs[1]; var state = new State(); foreach (var rule in s.Rules) { state.items.Add(new Item(rule, 0, eof)); } return(state); }
// Holds if the terminal can start this rule public bool Starts(ITerminalSymbol terminal) { foreach (var s in rhs) { if (s.First.Contains(terminal)) { return(true); } if (!s.CanBeEmpty) { return(false); } } return(false); }
public ParseAction ParseAction(State state, ITerminalSymbol symbol) { if (state.IsEmpty) { return(Error); } var matchingItems = state.items.Where(i => i.AtEnd && i.Lookahead[0] == symbol); if (matchingItems.Count() == 1) { if (symbol.IsEof) { return (token, parser) => { matchingItems.Single().Rule.function(token, parser); parser.ParseSuccess = true; } } ; state.ValidInputs[symbol.TerminalIndex] = true; return((token, parser) => matchingItems.Single().Rule.function(token, parser)); } if (matchingItems.Count() > 1) { throw new ReduceReduceConflict(matchingItems.ElementAt(0).Rule, matchingItems.ElementAt(1).Rule); } var targetState = state.terminalGotos[symbol.TerminalIndex]; if (targetState.IsEmpty) { // This is a syntax error. // The valid gotos are given in the state.terminalGotos // Bug: This excludes symbols that could be shifted following a reduction. // therefore this doesn't really work... return((token, parser) => parser.SyntaxError(token)); } state.ValidInputs[symbol.TerminalIndex] = true; // Default is to shift the symbol onto the stack return((token, parser) => parser.Shift(token, state.terminalGotos[symbol.TerminalIndex])); } }
public virtual ParseAction ParseAction(State state, ITerminalSymbol symbol) { if (state.IsEmpty) { return(SyntaxError); } // Are any of the items "reduce" if (state.items.Count == 1 && state.items.First().AtEnd) { if (symbol.IsEof) { return (token, parser) => { state.items.First().Rule.function(token, parser); parser.ParseSuccess = true; } } ; // This is a "reduce" action return((token, parser) => state.items.First().Rule.function(token, parser)); } var atEndRules = state.items.Where(i => i.AtEnd); if (atEndRules.Count() > 1) { throw new ReduceReduceConflict(atEndRules.First().Rule, atEndRules.ElementAt(1).Rule); } // Detect shift/reduce conflict if (state.items.Count > 1 && atEndRules.Count() == 1) { // A shift/reduce conflict throw new ShiftReduceConflict(state.items.Where(i => !i.AtEnd).First().Rule, atEndRules.First().Rule); } // Shift the symbol onto the stack return((token, parser) => parser.Shift(token, state.terminalGotos[symbol.TerminalIndex])); }
public void Delete(ITerminalSymbol terminalSymbol) { terminalSymbols.Remove(terminalSymbol); }
public void Add(ITerminalSymbol graphic) { terminalSymbols.Add(graphic); }