예제 #1
0
파일: Program.cs 프로젝트: sndjones002/LL
        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);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
0
        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);
        }