static int Main(string[] args) { if (1 < args.Length) { _PrintUsage(); return(1); } EbnfDocument ebnf; if (1 == args.Length) { ebnf = EbnfDocument.ReadFrom(args[0]); } else { ebnf = EbnfDocument.ReadFrom(Console.In); } ebnf.Validate(true); ebnf.Prepare(true); var cfg = ebnf.ToCfg(); cfg.PrepareLL1(false); cfg.PrepareLL1(false); cfg.PrepareLL1(false); cfg.PrepareLL1(false); foreach (var conflict in cfg.FillConflicts()) { switch (conflict.Kind) { case CfgConflictKind.FirstFirst: Console.WriteLine("First first conflict on {0} between rules:", conflict.Symbol); Console.WriteLine("\t{0}", conflict.Rule1); Console.Write("\t{0} k = ", conflict.Rule2); Console.WriteLine(cfg.GetK(conflict.Rule1, conflict.Rule2, 5)); break; case CfgConflictKind.FirstFollows: Console.WriteLine("First follows conflict on {0} between rules:", conflict.Symbol); Console.WriteLine("\t{0}", conflict.Rule1); Console.Write("\t{0} k = ", conflict.Rule2); Console.WriteLine(cfg.GetK(conflict.Rule1, conflict.Rule2, 5)); break; } } return(0); }
static int Main(string[] args) { if (2 > args.Length) { _PrintUsage(); return(1); } var ebnf = EbnfDocument.ReadFrom(args[0]); var cfg = ebnf.ToCfg(); cfg.PrepareLL1(); var lexer = ebnf.ToLexer(cfg); var parser1 = new DebugLL1Parser(cfg, null); parser1.ShowHidden = true; // won't work without these var parser2 = cfg.ToLL1Parser(null); parser2.ShowHidden = true; var failed = false; for (var i = 1; i < args.Length; ++i) { Console.WriteLine("For \"{0}\"...", args[i]); string input; using (var sr = File.OpenText(args[i])) input = sr.ReadToEnd(); var tokenizer = new DebugTokenizer(cfg, lexer, input); parser1.Restart(tokenizer); var pass = _TestParser(parser1, input); Console.WriteLine("Debug Test {0}", pass? "passed" : "failed"); parser2.Restart(tokenizer); if (!pass) { failed = true; } pass = _TestParser(parser2, input); Console.WriteLine("Table Test {0}", pass? "passed" : "failed"); if (!pass) { failed = true; } } return(failed ? 1 : 0); }
/// <summary> /// Usage: lltree $grammarfile $inputfile /// </summary> /// <param name="args">The grammar file and the input file to parse</param> /// <returns></returns> static int Main(string[] args) { if (2 != args.Length) { _PrintUsage(); return(1); } // read the ebnf document from the file. var ebnf = EbnfDocument.ReadFrom(args[0]); var hasErrors = false; // here we validate the document and print any // validation errors to the console. foreach (var msg in ebnf.Validate(false)) { if (EbnfErrorLevel.Error == msg.ErrorLevel) { hasErrors = true; Console.Error.WriteLine(msg); } } foreach (var msg in ebnf.Prepare(false)) { if (EbnfErrorLevel.Error == msg.ErrorLevel) { hasErrors = true; Console.Error.WriteLine(msg); } } // even if we have errors, we keep going. // create a CFG from the EBNF document var cfg = ebnf.ToCfg(); // we have to prepare a CFG to be parsable by an LL(1) // parser. This means removing left recursion, and // factoring out first-first and first-follows conflicts // where possible. // here we do that, and print any errors we encounter. foreach (var msg in cfg.PrepareLL1(false)) { if (CfgErrorLevel.Error == msg.ErrorLevel) { hasErrors = true; Console.Error.WriteLine(msg); } } // if we don't have errors let's set up our parse. if (!hasErrors) { // the tokenizer is created from the EBNF document becase // it has the terminal definitions, unlike the CFG, // see https://www.codeproject.com/Articles/5162249/How-to-Make-an-LL-1-Parser-Lesson-1 // The FileReaderEnumerable takes a filename and exposes IEnumerable<char> from // them. Tokenizers expect IEnumerable<char> (typically a string or char array) var tokenizer = ebnf.ToTokenizer(cfg, new FileReaderEnumerable(args[1])); // now create our parser. and since the parser *might* return multiple parse trees // in some cases, we keep reading until the end of document, calling ParseSubtree() // each time to get the result back as a ParseNode tree. We then take those nodes and // write them to the console via an implicit call to their ToString method using (var parser = cfg.ToLL1Parser(tokenizer)) while (ParserNodeType.EndDocument != parser.NodeType) { Console.WriteLine(parser.ParseSubtree()); } return(0); } return(1); }
public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress) { pcbOutput = 0; try { ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.Progress(0, 4); var hasErrors = false; using (var stm = new MemoryStream()) { EbnfDocument ebnf = null; try { ebnf = EbnfDocument.ReadFrom(wszInputFilePath); } catch (ExpectingException ee) { hasErrors = true; ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.GeneratorError(0, 0, "Error parsing the EBNF: " + ee.Message, (uint)ee.Line - 1, (uint)ee.Column - 1); } ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.Progress(1, 4); foreach (var msg in ebnf.Validate(false)) { switch (msg.ErrorLevel) { case EbnfErrorLevel.Error: ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.GeneratorError(0, 0, "EBNF " + msg.Message, (uint)msg.Line - 1, (uint)msg.Column - 1); hasErrors = true; break; case EbnfErrorLevel.Warning: ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.GeneratorError(1, 0, "EBNF " + msg.Message, (uint)msg.Line - 1, (uint)msg.Column - 1); break; } } ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.Progress(3, 4); var cfg = ebnf.ToCfg(); foreach (var msg in cfg.PrepareLL1(false)) { switch (msg.ErrorLevel) { case CfgErrorLevel.Error: ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.GeneratorError(0, 0, "CFG " + msg.Message, 0, 0); hasErrors = true; break; case CfgErrorLevel.Warning: ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.GeneratorError(1, 0, "CFG " + msg.Message, 0, 0); break; } } if (!hasErrors) { var sw = new StreamWriter(stm); LLCodeGenerator.WriteParserAndGeneratorClassesTo(ebnf, cfg, wszDefaultNamespace, null, Path.GetFileNameWithoutExtension(wszInputFilePath), "cs", sw); sw.Flush(); int length = (int)stm.Length; rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length); Marshal.Copy(stm.GetBuffer(), 0, rgbOutputFileContents[0], length); pcbOutput = (uint)length; } ThreadHelper.ThrowIfNotOnUIThread(); pGenerateProgress.Progress(4, 4); } } catch (Exception ex) { string s = string.Concat("/* ", ex.Message, " */"); byte[] b = Encoding.UTF8.GetBytes(s); int length = b.Length; rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length); Marshal.Copy(b, 0, rgbOutputFileContents[0], length); pcbOutput = (uint)length; } return(VSConstants.S_OK); }