static void Main(string[] args) { #if !REGEN Console.WriteLine("Simple Expression Evaluator"); Console.WriteLine("Hit Enter on a new line to exit."); var parser = new ExprParser(); while (true) { Console.Write(">"); var line = Console.ReadLine(); if (string.IsNullOrEmpty(line)) { return; } var pc = ParseContext.Create(line); parser.Restart(pc); var ptree = parser.ParseSubtree(); // parse subtree will not read the whole // text, just the subtree so in order to // validate the *entire* input we must read // the rest. while (parser.Read()) { switch (parser.NodeType) { case LLNodeType.Error: Console.Error.WriteLine("Error: " + parser.Value); break; } } // check if there's an error currently. switch (parser.NodeType) { case LLNodeType.Error: Console.Error.WriteLine("Error in line after expression"); break; } Console.WriteLine(ptree); Console.WriteLine(); try { Console.WriteLine("Evaluation: {0} = {1}", line, Eval(ptree)); } catch (Exception ex) { Console.Error.WriteLine("Evaluation error: " + ex.Message); } } #endif }
static void _ReadAttributes(IDictionary <string, object> attrs, EbnfParser parser) { parser.Read(); while (EbnfParser.attribute == parser.SymbolId) { parser.Read(); var id = parser.Value; parser.Read(); object val = true; if (EbnfParser.eq == parser.SymbolId) { parser.Read(); parser.Read(); switch (parser.SymbolId) { case EbnfParser.identifier: if ("null" == parser.Value) { val = null; } else if ("true" == parser.Value) { val = true; } else if ("false" == parser.Value) { val = false; } else { throw new ExpectingException("Expecting true, false, or null."); } break; case EbnfParser.integer: val = int.Parse(parser.Value); break; case EbnfParser.literal: val = ParseContext.Create(parser.Value).ParseJsonString(); break; } parser.Read(); } attrs.Add(id, val); if (EbnfParser.comma == parser.SymbolId) { parser.Read(); } } }
static IList <EbnfMessage> _TryParseProduction(ParseNode pn, out KeyValuePair <string, EbnfProduction> result) { Debug.Assert(EbnfParser.production == pn.SymbolId, "Not positioned on production"); var msgs = new List <EbnfMessage>(); string name = pn.Children[0].Value; if ("production" == name) { Debugger.Break(); } var prod = new EbnfProduction(); prod.SetLocationInfo(pn.Line, pn.Column, pn.Position); var i = 0; if (EbnfParser.lt == pn.Children[1].SymbolId) { i = 2; while (EbnfParser.gt != pn.Children[i].SymbolId) { var attrnode = pn.Children[i]; var attrname = attrnode.Children[0].Value; var attrval = (object)true; if (3 == attrnode.Children.Count) { var s = attrnode.Children[2].Children[0].Value; if (!ParseContext.Create(s).TryParseJsonValue(out attrval)) { attrval = null; } } prod.Attributes.Add(attrname, attrval); ++i; if (EbnfParser.comma == pn.Children[i].SymbolId) { ++i; } } ++i; } ++i; EbnfExpression e; _TryParseExpressions(pn, i, out e); prod.Expression = e; result = new KeyValuePair <string, EbnfProduction>(name, prod); return(msgs); }
static void Main(string[] args) { var file = @"..\..\..\ebnf.ebnf"; var doc = EbnfDocument.ReadFrom(file); doc.Prepare(); var cfg = doc.ToCfg(); cfg.PrepareLL1(); var lexer = doc.ToLexer(cfg); string filestring; using (var sr = File.OpenText(file)) filestring = sr.ReadToEnd(); LLParser parser = cfg.ToLL1Parser(lexer); parser.Restart(ParseContext.Create(filestring)); Console.WriteLine(parser.ParseSubtree()); var sw = new Stopwatch(); sw.Restart(); for (var i = 0; i < 100; ++i) { parser.Restart(ParseContext.Create(filestring)); while (parser.Read()) { ; } } sw.Stop(); Console.WriteLine("Runtime Parser: {0}", sw.Elapsed / 100); parser = new EbnfParser(); sw.Restart(); for (var i = 0; i < 100; ++i) { parser.Restart(ParseContext.Create(filestring)); while (parser.Read()) { ; } } sw.Stop(); Console.WriteLine("Generated Parser: {0}", sw.Elapsed / 100); }
static void _RunMatch() { var test = "foo123_ _bar"; var word = CharFA <string> .Repeat( CharFA <string> .Set(new CharRange[] { new CharRange('A', 'Z'), new CharRange('a', 'z') }), 1, -1 , "Word"); var dfaWord = word.ToDfa(); var dfaTableWord = word.ToDfaStateTable(); CharFAMatch match; var pc = ParseContext.Create(test); Console.WriteLine("Matching words with an NFA:"); while (null != (match = word.Match(pc))) { Console.WriteLine("Found match at {0}: {1}", match.Position, match.Value); } Console.WriteLine(); pc = ParseContext.Create(test); Console.WriteLine("Matching words with a DFA:"); while (null != (match = dfaWord.MatchDfa(pc))) { Console.WriteLine("Found match at {0}: {1}", match.Position, match.Value); } Console.WriteLine(); pc = ParseContext.Create(test); Console.WriteLine("Matching words with a DFA state table:"); while (null != (match = CharFA <string> .MatchDfa(dfaTableWord, pc))) { Console.WriteLine("Found match at {0}: {1}", match.Position, match.Value); } Console.WriteLine(); pc = ParseContext.Create(test); Console.WriteLine("Matching words with a compiled DFA:"); while (null != (match = Match(pc))) { Console.WriteLine("Found match at {0}: {1}", match.Position, match.Value); } Console.WriteLine(); }
public IEnumerable <string> ExpandMatchingStepPatternWithAllPossibleParameter(SpecflowStepInfo stepDefinitionInfo, string partialStepText, string fullStepText) { var matchedText = string.Empty; if (partialStepText.Length > 0) { var result = stepDefinitionInfo.RegexForPartialMatch?.Match(ParseContext.Create(partialStepText), successOnAnyState: true); if (result == null || result.Position != 0) { return(EmptyList <string> .Enumerable); } matchedText = result.Value; } var tokenizedStepPattern = TokenizeStepPattern(stepDefinitionInfo.Pattern).ToList(); var captureValues = RetrieveParameterValues(stepDefinitionInfo, partialStepText, fullStepText, tokenizedStepPattern); var stringBuilder = new StringBuilder(); var results = new List <string>(); BuildAllPossibleSteps(matchedText, stringBuilder, results, tokenizedStepPattern.ToArray(), captureValues, 0, 0); return(results); }
public static EbnfDocument ReadFrom(TextReader reader) => _Parse(ParseContext.Create(reader));
static void _RunLexer() { var digits = CharFA <string> .Repeat( CharFA <string> .Set("0123456789"), 1, -1 , "Digits"); var word = CharFA <string> .Repeat( CharFA <string> .Set(new CharRange[] { new CharRange('A', 'Z'), new CharRange('a', 'z') }), 1, -1 , "Word"); var whitespace = CharFA <string> .Repeat( CharFA <string> .Set(" \t\r\n\v\f"), 1, -1 , "Whitespace"); var lexer = CharFA <string> .ToLexer(digits, word, whitespace); var lexerDfa = lexer.ToDfa(); lexerDfa.TrimDuplicates(); // we use a symbol table with the DFA state table to map ids back to strings var symbolTable = new string[] { "Digits", "Word", "Whitespace", "#ERROR" }; // make sure to pass the symbol table if you're using one var dfaTable = lexer.ToDfaStateTable(symbolTable); var test = "foo123_ _bar"; Console.WriteLine("Lex using the NFA"); // create a parse context over our test string var pc = ParseContext.Create(test); // while not end of input while (-1 != pc.Current) { // clear the capture so that we don't keep appending the token data pc.ClearCapture(); // lex the next token var acc = lexer.Lex(pc, "#ERROR"); // write the result Console.WriteLine("{0}: {1}", acc, pc.GetCapture()); } Console.WriteLine(); Console.WriteLine("Lex using the DFA"); // create a new parse context over our test string // because our old parse context is now past the end pc = ParseContext.Create(test); while (-1 != pc.Current) { pc.ClearCapture(); // lex using the DFA. This works exactly like // the previous Lex method except that it's // optimized for DFA traversal. // DO NOT use this with an NFA. It won't work // but won't error (can't check for perf reasons) var acc = lexerDfa.LexDfa(pc, "#ERROR"); // write the result Console.WriteLine("{0}: {1}", acc, pc.GetCapture()); } Console.WriteLine(); Console.WriteLine("Lex using the DFA state table"); pc = ParseContext.Create(test); while (-1 != pc.Current) { pc.ClearCapture(); // Lex using our DFA table. This is a little different // because it's a static method that takes CharDfaEntry[] // as its first parameter. It also uses symbol ids instead // of the actual symbol. You must map them back using the // symbol table you created earlier. var acc = CharFA <string> .LexDfa(dfaTable, pc, 3); // when we write this, we map our symbol id back to the // symbol using our symbol table Console.WriteLine("{0}: {1}", symbolTable[acc], pc.GetCapture()); } Console.WriteLine(); Console.WriteLine("Lex using our compiled lex method"); pc = ParseContext.Create(test); while (-1 != pc.Current) { pc.ClearCapture(); // Lex using our compiledDFA. Like the table driven lex // this also uses symbol ids instead of the actual symbol. var acc = Lex(pc); // when we write this, we map our symbol id back to the // symbol using our symbol table Console.WriteLine("{0}: {1}", symbolTable[acc], pc.GetCapture()); } Console.WriteLine(); }
public static Cfg ReadFrom(TextReader reader) => _Parse(ParseContext.Create(reader));
public static Cfg Parse(IEnumerable <char> @string) => _Parse(ParseContext.Create(@string));
/// <summary> /// Parses a regular expresion from the specified <see cref="TextReader"/> /// </summary> /// <param name="reader">The text reader</param> /// <param name="accepting">The symbol reported when accepting the specified expression</param> /// <returns>A new machine that matches the regular expression</returns> public static CharFA <TAccept> ReadFrom(TextReader reader, TAccept accept = default(TAccept)) => _Parse(ParseContext.Create(reader), accept);
static IList <EbnfMessage> _TryParseExpression(ParseNode pn, out EbnfExpression result) { result = null; Debug.Assert(EbnfParser.expression == pn.SymbolId, "Not positioned on expression"); var msgs = new List <EbnfMessage>(); if (1 == pn.Children.Count) { var c = pn.Children[0]; if (EbnfParser.symbol == c.SymbolId) { ParseContext pc; var cc = c.Children[0]; //TODO: parse the regular expressions and literals to make sure they're valid. switch (cc.SymbolId) { case EbnfParser.identifier: result = new EbnfRefExpression(cc.Value); return(msgs); case EbnfParser.regex: pc = ParseContext.Create(cc.Value); pc.EnsureStarted(); pc.Advance(); pc.TryReadUntil('\'', '\\', false); result = new EbnfRegexExpression(pc.GetCapture()); return(msgs); case EbnfParser.literal: pc = ParseContext.Create(cc.Value); pc.EnsureStarted(); pc.Advance(); pc.TryReadUntil('\"', '\\', false); result = new EbnfLiteralExpression(pc.GetCapture()); return(msgs); case EbnfParser.lbrace: msgs.AddRange(_TryParseExpressions(c, 1, out result)); result = new EbnfRepeatExpression(result); if (EbnfParser.rbracePlus == c.Children[c.Children.Count - 1].SymbolId) { ((EbnfRepeatExpression)result).IsOptional = false; } return(msgs); case EbnfParser.lbracket: msgs.AddRange(_TryParseExpressions(c, 1, out result)); result = new EbnfOptionalExpression(result); return(msgs); case EbnfParser.lparen: msgs.AddRange(_TryParseExpressions(c, 1, out result)); return(msgs); default: break; } } } return(msgs); }
/// <summary> /// Parses a regular expresion from the specified string /// </summary> /// <param name="string">The string</param> /// <param name="accepting">The symbol reported when accepting the specified expression</param> /// <returns>A new expression that represents the regular expression</returns> public static RegexExpression Parse(IEnumerable <char> @string) => Parse(ParseContext.Create(@string));
void Colorize() { #if PARSER if (_colorizing) { return; } _colorizing = true; var text = EditBox.Text; var sel = EditBox.SelectionStart; EditBox.Clear(); var sb = new StringBuilder(); sb.Append("{\\rtf1"); sb.Append(RtfUtility.ToColorTable( Color.Black, Color.DarkGreen, Color.DarkRed, Color.DarkOliveGreen, Color.Blue, Color.DarkCyan, Color.BlueViolet, Color.DarkGray)); var p = new EbnfParser(ParseContext.Create(text)); var pos = 0L; var cols = new Stack <int>(); cols.Push(0); while (p.Read()) { switch (p.NodeType) { case LLNodeType.NonTerminal: switch (p.SymbolId) { case EbnfParser.attribute: cols.Push(3); break; case EbnfParser.symbol: case EbnfParser.expressions: cols.Push(4); break; default: cols.Push(0); break; } break; case LLNodeType.EndNonTerminal: cols.Pop(); break; case LLNodeType.Terminal: case LLNodeType.Error: if (p.Position > pos) { sb.Append("\\cf1 "); sb.Append(RtfUtility.Escape(text.Substring((int)pos, (int)(p.Position - pos)))); } if (LLNodeType.Error == p.NodeType) { sb.Append("\\cf2"); } else { sb.Append("\\cf"); switch (p.SymbolId) { case EbnfParser.literal: sb.Append(5); break; case EbnfParser.regex: sb.Append(6); break; default: sb.Append(cols.Peek()); break; } } sb.Append(RtfUtility.Escape(p.Value)); pos = p.Position + p.Value.Length; break; } } sb.Append("}"); System.Diagnostics.Debug.WriteLine(sb.ToString()); EditBox.Rtf = sb.ToString(); EditBox.SelectionStart = sel; _colorizing = false; #endif }
/// <summary> /// Parses a regular expresion from the specified string /// </summary> /// <param name="string">The string</param> /// <param name="accepting">The symbol reported when accepting the specified expression</param> /// <returns>A new machine that matches the regular expression</returns> public static CharFA <TAccept> Parse(IEnumerable <char> @string, TAccept accept = default(TAccept)) => _Parse(ParseContext.Create(@string), accept);
public static XbnfDocument Parse(IEnumerable <char> @string) => Parse(ParseContext.Create(@string));
internal static LexDocument Parse(ParseContext pc) { var result = new LexDocument(); while (-1 != pc.Current) { var line = pc.Line; var column = pc.Column; var position = pc.Position; LexNode.SkipCommentsAndWhitespace(pc); while ('\n' == pc.Current) { pc.Advance(); LexNode.SkipCommentsAndWhitespace(pc); } var id = LexNode.ParseIdentifier(pc); if (string.IsNullOrEmpty(id)) { pc.Advance(); LexNode.SkipCommentsAndWhitespace(pc); continue; } LexNode.SkipCommentsAndWhitespace(pc); pc.Expecting(':', '-', '='); if (':' == pc.Current) // attribute set { pc.Advance(); var d = new LexAttributeList(); while (-1 != pc.Current && '\n' != pc.Current) { var attr = LexAttribute.Parse(pc); d.Add(attr); LexNode.SkipCommentsAndWhitespace(pc); pc.Expecting('\n', ',', -1); if (',' == pc.Current) { pc.Advance(); } } result.AttributeSets.Add(id, d); LexNode.SkipCommentsAndWhitespace(pc); } else if ('=' == pc.Current) { pc.Advance(); LexNode.SkipCommentsAndWhitespace(pc); pc.Expecting('\''); pc.Advance(); var l = pc.CaptureBuffer.Length; pc.TryReadUntil('\'', '\\', false); pc.Expecting('\''); pc.Advance(); var rx = pc.GetCapture(l); // make sure to capture the line numbers properly: var rpc = ParseContext.Create(rx); rpc.EnsureStarted(); rpc.SetLocation(pc.Line, pc.Column, pc.Position); var rule = new LexRule(id, RegexExpression.Parse(rpc)); rule.SetLocation(line, column, position); result.Rules.Add(rule); } else if ('-' == pc.Current) { pc.TrySkipUntil('\n', true); } LexNode.SkipCommentsAndWhitespace(pc); if ('\n' == pc.Current) { pc.Advance(); } } return(result); }