public virtual MatchResult <TInput, TResult> GetMatch( MatchState <TInput, TResult> state, Action <MatchState <TInput, TResult>, int, IEnumerable <MatchItem <TInput, TResult> > > production, int index) { if (state == null) { throw new ArgumentNullException("state"); } if (production == null) { throw new ArgumentNullException("production"); } MatchItem <TInput, TResult> result = null; if (BeforeMatch != null) { BeforeMatch(state, state.InputList, production); } try { if (Terminals == null) { Terminals = new HashSet <string>(); } result = _MemoCall(state, production.Method.Name, index, production, null); } catch (MatcherException me) { state.ClearErrors(); state.AddError(me.Index, me.Message); } catch (Exception e) { state.ClearErrors(); state.AddError(0, e.Message #if DEBUG + "\n" + e.StackTrace #endif ); } state.ClearMemoTable(); // allow memo tables to be gc'd string GetLastError() => state.LastError; var match_result = result != null ? new MatchResult <TInput, TResult>(this, state, true, result.StartIndex, result.NextIndex, result.Results, GetLastError, state.LastErrorIndex) : new MatchResult <TInput, TResult>(this, state, false, -1, -1, null, GetLastError, state.LastErrorIndex); if (AfterMatch != null) { AfterMatch(match_result); } return(match_result); }
#pragma warning disable 0219 /// <summary> /// Matches any input. /// </summary> /// <param name="memo">Memo.</param> /// <param name="index">Index.</param> protected MatchItem <TInput, TResult> _ParseAny(MatchState <TInput, TResult> memo, ref int index) { if (!(memo.InputString != null && index >= memo.InputString.Length)) { try { var _temp = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index); var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = index + 1, InputEnumerable = memo.InputEnumerable, }; ++index; memo.Results.Push(result); return(result); } catch { } } memo.Results.Push(null); memo.AddError(index, () => "unexpected end of file"); return(null); }
/// <summary> /// Matches a set of characters. Only used for matchers over <c>char</c> enumerables. /// </summary> /// <param name="memo">Memo.</param> /// <param name="index">Index.</param> /// <param name="chars">Characters to match.</param> protected MatchItem <TInput, TResult> _ParseInputClass(MatchState <TInput, TResult> memo, ref int index, params char[] chars) { if (!(memo.InputString != null && index >= memo.InputString.Length)) { try { TInput input = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index); if (Array.IndexOf(chars, input) != -1) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = index + 1, InputEnumerable = memo.InputEnumerable, }; ++index; memo.Results.Push(result); return(result); } } catch { } } memo.Results.Push(null); //memo.AddError(index, () => "expected one of [" + Regex.Escape(new string(chars)) + "]"); return(null); }
/// <summary> /// Matches a literal char (only used with matchers on a <c>char</c> enumerable). /// </summary> /// <param name="memo">Memo.</param> /// <param name="index">Index.</param> /// <param name="ch">Character to match.</param> protected MatchItem <TInput, TResult> _ParseLiteralChar(MatchState <TInput, TResult> memo, ref int index, char ch) { if (!(memo.InputString != null && index >= memo.InputString.Length)) { try { char cur_ch = memo.InputString != null ? memo.InputString[index] : (char)(object)memo.InputEnumerable.ElementAt(index); if (cur_ch == ch) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = index + 1, InputEnumerable = memo.InputEnumerable, }; ++index; memo.Results.Push(result); return(result); } } catch { } } memo.Results.Push(null); //memo.AddError(index, () => string.Format("expected '{0}'", Regex.Escape(new string(ch, 1)))); return(null); }
/// <summary> /// Find the memo of a given rule call. /// </summary> /// <param name="expansion">The production expansion.</param> /// <param name="index">The input position.</param> /// <param name="item">The result.</param> /// <returns>True if there is a memo record for the rule at the index.</returns> public bool TryGetMemo(Expansion expansion, int index, out MatchItem <TInput, TResult> item) { Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > > expansion_dict; Dictionary <int, MatchItem <TInput, TResult> > rule_dict; if (memo_table.TryGetValue(expansion.Name, out expansion_dict) && expansion_dict.TryGetValue(expansion.Num, out rule_dict) && rule_dict.TryGetValue(index, out item)) { return(true); } item = default(MatchItem <TInput, TResult>); return(false); }
/// <summary> /// Matches a literal string (only used with matchers on a <c>char</c> enumerable). /// </summary> /// <param name="memo">Memo.</param> /// <param name="index">Index.</param> /// <param name="str">String to match.</param> protected MatchItem <TInput, TResult> _ParseLiteralString(MatchState <TInput, TResult> memo, ref int index, string str) { int cur_index = index; bool failed = false; try { foreach (var ch in str) { if (memo.InputString != null && cur_index >= memo.InputString.Length) { failed = true; break; } char cur_ch = memo.InputString != null ? memo.InputString[cur_index] : (char)(object)memo.InputEnumerable.ElementAt(cur_index); ++cur_index; if (cur_ch != ch) { failed = true; break; } } } catch { failed = true; } if (!failed) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = cur_index, InputEnumerable = memo.InputEnumerable }; index = cur_index; memo.Results.Push(result); return(result); } memo.Results.Push(null); //memo.AddError(index, () => "expected \"" + Regex.Escape(str) + "\""); return(null); }
/// <summary> /// Try to match the input. /// </summary> /// <param name="input">The input to be matched.</param> /// <param name="production">The top-level grammar production (rule) of the generated parser class to use.</param> /// <returns>The result of the match.</returns> public virtual MatchResult <TInput, TResult> GetMatch(IEnumerable <TInput> input, Action <Memo <TInput, TResult>, int, IEnumerable <MatchItem <TInput, TResult> > > production) { var memo = new Memo <TInput, TResult>(input); MatchItem <TInput, TResult> result = null; if (BeforeMatch != null) { BeforeMatch(memo, input, production); } try { if (Terminals == null) { Terminals = new HashSet <string>(); } result = _MemoCall(memo, production.Method.Name, 0, production, null); } catch (MatcherException me) { memo.ClearErrors(); memo.AddError(me.Index, me.Message); } catch (Exception e) { memo.ClearErrors(); memo.AddError(0, e.Message #if DEBUG + "\n" + e.StackTrace #endif ); } memo.ClearMemoTable(); // allow memo tables to be gc'd var match_result = result != null ? new MatchResult <TInput, TResult>(this, memo, true, result.StartIndex, result.NextIndex, result.Results, memo.LastError, memo.LastErrorIndex) : new MatchResult <TInput, TResult>(this, memo, false, -1, -1, null, memo.LastError, memo.LastErrorIndex); if (AfterMatch != null) { AfterMatch(match_result); } return(match_result); }
/// <summary> /// Matches a set of characters in an argument stream. /// </summary> /// <param name="memo">Memo.</param> /// <param name="item_index">Item index.</param> /// <param name="input_index">Input index.</param> /// <param name="args">Argument stream.</param> /// <param name="chars">Characters to match.</param> protected MatchItem <TInput, TResult> _ParseInputClassArgs(MatchState <TInput, TResult> memo, ref int item_index, ref int input_index, IEnumerable <MatchItem <TInput, TResult> > args, params char[] chars) { try { int cur_item_index = item_index; int cur_input_index = input_index; var cur_item = args.ElementAt(cur_item_index); TInput cur_input = cur_item.Inputs.ElementAt(cur_input_index); if (Array.IndexOf(chars, cur_input) != -1) { if (cur_input_index + 1 >= cur_item.Inputs.Count()) { ++cur_item_index; cur_input_index = 0; } else { ++cur_input_index; } var result = new MatchItem <TInput, TResult> { StartIndex = item_index, NextIndex = cur_item_index, Inputs = new List <TInput> { cur_input }, }; item_index = cur_item_index; input_index = cur_input_index; memo.ArgResults.Push(result); return(result); } } catch { } memo.ArgResults.Push(null); //memo.AddError(input_index, () => "expected " + args); return(null); }
/// <summary> /// Memoize the result of a production at a given index. /// </summary> /// <param name="expansion">The production expansion.</param> /// <param name="index">The input position.</param> /// <param name="item">The result of the parse.</param> public void Memoize(Expansion expansion, int index, MatchItem <TInput, TResult> item) { Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > > expansion_dict; if (!memo_table.TryGetValue(expansion.Name, out expansion_dict)) { expansion_dict = new Dictionary <int, Dictionary <int, MatchItem <TInput, TResult> > >(); memo_table.Add(expansion.Name, expansion_dict); } Dictionary <int, MatchItem <TInput, TResult> > rule_dict; if (!expansion_dict.TryGetValue(expansion.Num, out rule_dict)) { rule_dict = new Dictionary <int, MatchItem <TInput, TResult> >(); expansion_dict.Add(expansion.Num, rule_dict); } rule_dict[index] = item; }
protected MatchItem <TInput, TResult> _ParseRegexp(MatchState <TInput, TResult> memo, ref int index, Verophyle.Regexp.StringRegexp re) { int cur_index = index; int succ_index = -1; try { re.Reset(); do { re.ProcessInput(memo.InputString[cur_index]); if (re.Succeeded) { succ_index = cur_index; } }while (++cur_index < memo.InputString.Length && !re.Failed); } catch { succ_index = -1; } if (succ_index >= 0) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = succ_index + 1, InputEnumerable = memo.InputEnumerable }; index = succ_index + 1; memo.Results.Push(result); return(result); } else { memo.Results.Push(null); return(null); } }
/// <summary> /// Matches a literal object in an argument stream. /// </summary> /// <param name="memo">Memo.</param> /// <param name="item_index">Item index.</param> /// <param name="input_index">Input index.</param> /// <param name="obj">Object to match.</param> /// <param name="args">Argument stream.</param> protected MatchItem <TInput, TResult> _ParseLiteralArgs(MatchState <TInput, TResult> memo, ref int item_index, ref int input_index, object obj, IEnumerable <MatchItem <TInput, TResult> > args) { if (args != null) { try { if (obj is IEnumerable <TInput> ) { int old_item_index = item_index; int cur_item_index = item_index; int cur_input_index = input_index; var input_list = new List <TInput>(); foreach (TInput input in ((IEnumerable <TInput>)obj)) { var cur_item = args.ElementAt(cur_item_index); TInput cur_input = cur_item.Inputs.ElementAt(cur_input_index); if (ObjectEquals(input, cur_input)) { input_list.Add(cur_input); if (cur_input_index + 1 >= cur_item.Inputs.Count()) { ++cur_item_index; cur_input_index = 0; } else { ++input_index; } } else { } } // item_index = cur_item_index; input_index = cur_input_index; var result = new MatchItem <TInput, TResult> { StartIndex = old_item_index, NextIndex = item_index, Inputs = input_list, }; memo.ArgResults.Push(result); return(result); } else { int old_item_index = item_index; var cur_item = args.ElementAt(item_index); TInput cur_input = cur_item.Inputs.ElementAt(input_index); if (ObjectEquals(obj, cur_input)) { // increment if (input_index + 1 >= cur_item.Inputs.Count()) { ++item_index; input_index = 0; } else { ++input_index; } // var result = new MatchItem <TInput, TResult> { StartIndex = old_item_index, NextIndex = item_index, Inputs = new List <TInput> { cur_input }, }; memo.ArgResults.Push(result); return(result); } } } catch { } } memo.ArgResults.Push(null); //memo.AddError(input_index, () => "expected " + obj); return(null); }
/// <summary> /// Matches a literal object. /// </summary> /// <param name="memo">Memo.</param> /// <param name="index">Index.</param> /// <param name="obj">Object to match.</param> protected MatchItem <TInput, TResult> _ParseLiteralObj(MatchState <TInput, TResult> memo, ref int index, object obj) { if (obj is IEnumerable <TInput> ) { int cur_index = index; bool failed = false; try { foreach (var input in (IEnumerable <TInput>)obj) { TInput cur_input = memo.InputList != null ? memo.InputList[cur_index] : memo.InputEnumerable.ElementAt(cur_index); ++cur_index; if (!ObjectEquals(input, cur_input)) { failed = true; break; } } } catch { failed = true; } if (!failed) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = cur_index, InputEnumerable = memo.InputEnumerable, }; memo.Results.Push(result); index = cur_index; return(result); } } else { try { TInput cur_input = memo.InputList != null ? memo.InputList[index] : memo.InputEnumerable.ElementAt(index); if (ObjectEquals(obj, cur_input)) { var result = new MatchItem <TInput, TResult> { StartIndex = index, NextIndex = index + 1, InputEnumerable = memo.InputEnumerable, }; memo.Results.Push(result); ++index; return(result); } } catch { } } memo.Results.Push(null); //memo.AddError(index, () => "expected " + obj); return(null); }
/// <summary> /// Utility function for getting the input that matched from a variable. /// </summary> /// <param name="item">Variable that matched.</param> /// <returns>The input that matched the variable, with whitspace trimmed.</returns> protected static string Trimmed(MatchItem <char, TResult> item) { return(new string(item.Inputs.ToArray()).Trim()); }