示例#1
0
        public static int Run(string[] args, TextReader stdin, TextWriter stdout, TextWriter stderr)
        {
            // our return code
            var result = 0;
            // app parameters
            string inputfile     = null;
            string outputfile    = null;
            string codeclass     = null;
            string codelanguage  = null;
            string codenamespace = null;
            string externaltoken = null;
            string nfagraph      = null;
            string dfagraph      = null;
            bool   ignorecase    = false;
            bool   noshared      = false;
            bool   ifstale       = false;
            // our working variables
            TextReader input  = null;
            TextWriter output = null;

            try
            {
                if (0 == args.Length)
                {
                    _PrintUsage(stderr);
                    result = -1;
                }
                else if (args[0].StartsWith("/"))
                {
                    throw new ArgumentException("Missing input file.");
                }
                else
                {
                    // process the command line args
                    inputfile = args[0];
                    for (var i = 1; i < args.Length; ++i)
                    {
                        switch (args[i].ToLowerInvariant())
                        {
                        case "/output":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            outputfile = args[i];
                            break;

                        case "/class":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codeclass = args[i];
                            break;

                        case "/language":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codelanguage = args[i];
                            break;

                        case "/namespace":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codenamespace = args[i];
                            break;

                        case "/external":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            externaltoken = args[i];
                            break;

                        case "/nfagraph":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            nfagraph = args[i];
                            break;

                        case "/dfagraph":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            dfagraph = args[i];
                            break;

                        case "/ignorecase":
                            ignorecase = true;
                            break;

                        case "/noshared":
                            noshared = true;
                            break;

                        case "/ifstale":
                            ifstale = true;
                            break;


                        default:
                            throw new ArgumentException(string.Format("Unknown switch {0}", args[i]));
                        }
                    }
                    // now build it
                    if (string.IsNullOrEmpty(codeclass))
                    {
                        // default we want it to be named after the code file
                        // otherwise we'll use inputfile
                        if (null != outputfile)
                        {
                            codeclass = Path.GetFileNameWithoutExtension(outputfile);
                        }
                        else
                        {
                            codeclass = Path.GetFileNameWithoutExtension(inputfile);
                        }
                    }
                    if (string.IsNullOrEmpty(codelanguage))
                    {
                        if (!string.IsNullOrEmpty(outputfile))
                        {
                            codelanguage = Path.GetExtension(outputfile);
                            if (codelanguage.StartsWith("."))
                            {
                                codelanguage = codelanguage.Substring(1);
                            }
                        }
                        if (string.IsNullOrEmpty(codelanguage))
                        {
                            codelanguage = "cs";
                        }
                    }
                    var stale = true;
                    if (ifstale && null != outputfile)
                    {
                        stale = _IsStale(inputfile, outputfile);
                        if (!stale)
                        {
                            stale = _IsStale(CodeBase, outputfile);
                        }
                    }
                    if (!stale)
                    {
                        stderr.WriteLine("{0} skipped building {1} because it was not stale.", Name, outputfile);
                    }
                    else
                    {
                        if (null != outputfile)
                        {
                            stderr.Write("{0} is building file: {1}", Name, outputfile);
                        }
                        else
                        {
                            stderr.Write("{0} is building tokenizer.", Name);
                        }
                        input = new StreamReader(inputfile);
                        var    rules = new List <LexRule>();
                        string line;
                        while (null != (line = input.ReadLine()))
                        {
                            var lc = LexContext.Create(line);
                            lc.TrySkipCCommentsAndWhiteSpace();
                            if (-1 != lc.Current)
                            {
                                rules.Add(LexRule.Parse(lc));
                            }
                        }
                        input.Close();
                        input = null;
                        LexRule.FillRuleIds(rules);

                        var ccu = new CodeCompileUnit();
                        var cns = new CodeNamespace();
                        if (!string.IsNullOrEmpty(codenamespace))
                        {
                            cns.Name = codenamespace;
                        }
                        ccu.Namespaces.Add(cns);
                        var fa          = _BuildLexer(rules, ignorecase, inputfile);
                        var symbolTable = _BuildSymbolTable(rules);
                        var symids      = new int[symbolTable.Length];
                        for (var i = 0; i < symbolTable.Length; ++i)
                        {
                            symids[i] = i;
                        }
                        var blockEnds = _BuildBlockEnds(rules);
                        var nodeFlags = _BuildNodeFlags(rules);
                        if (null != nfagraph)
                        {
                            fa.RenderToFile(nfagraph);
                        }

                        fa = fa.ToDfa();
                        DfaEntry[] dfaTable = null;
                        dfaTable = _ToDfaStateTable(fa, symids);
                        if (!noshared)
                        {
                            if (string.IsNullOrEmpty(externaltoken))
                            {
                                // import our Export/Token.cs into the library
                                _ImportCompileUnit(Deslanged.Token, cns);
                            }

                            // import our Export/TableTokenizer.cs into the library
                            _ImportCompileUnit(Deslanged.TableTokenizer, cns);
                        }
                        if (!string.IsNullOrEmpty(externaltoken))
                        {
                            cns.Imports.Add(new CodeNamespaceImport(externaltoken));
                        }
                        var origName           = "Rolex.";
                        CodeTypeDeclaration td = null;
                        if (null == td)
                        {
                            td        = Deslanged.TableTokenizerTemplate.Namespaces[1].Types[0];
                            origName += td.Name;
                            td.Name   = codeclass;
                            CodeGenerator.GenerateSymbolConstants(td, symbolTable);
                        }
                        CodeDomVisitor.Visit(td, (ctx) =>
                        {
                            var tr = ctx.Target as CodeTypeReference;
                            if (null != tr)
                            {
                                if (0 == string.Compare(origName, tr.BaseType, StringComparison.InvariantCulture))
                                {
                                    tr.BaseType = codeclass;
                                }
                            }
                        });
                        CodeMemberField f = null;

                        f = CodeDomUtility.GetByName("DfaTable", td.Members) as CodeMemberField;
                        f.InitExpression = CodeGenerator.GenerateDfaTableInitializer(dfaTable);

                        f = CodeDomUtility.GetByName("NodeFlags", td.Members) as CodeMemberField;
                        f.InitExpression = CodeDomUtility.Literal(nodeFlags);
                        f = CodeDomUtility.GetByName("BlockEnds", td.Members) as CodeMemberField;
                        f.InitExpression = CodeDomUtility.Literal(blockEnds);

                        cns.Types.Add(td);

                        var hasColNS = false;
                        foreach (CodeNamespaceImport nsi in cns.Imports)
                        {
                            if (0 == string.Compare(nsi.Namespace, "System.Collections.Generic", StringComparison.InvariantCulture))
                            {
                                hasColNS = true;
                                break;
                            }
                        }
                        if (!hasColNS)
                        {
                            cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
                        }

                        stderr.WriteLine();
                        var prov = CodeDomProvider.CreateProvider(codelanguage);
                        var opts = new CodeGeneratorOptions();
                        opts.BlankLinesBetweenMembers = false;
                        opts.VerbatimOrder            = true;
                        if (null == outputfile)
                        {
                            output = stdout;
                        }
                        else
                        {
                            // open the file and truncate it if necessary
                            var stm = File.Open(outputfile, FileMode.Create);
                            stm.SetLength(0);
                            output = new StreamWriter(stm);
                        }
                        prov.GenerateCodeFromCompileUnit(ccu, output, opts);
                    }
                }
            }
            // we don't like to catch in debug mode
#if !DEBUG
            catch (Exception ex)
            {
                result = _ReportError(ex, stderr);
            }
#endif
            finally
            {
                // close the input file if necessary
                if (null != input)
                {
                    input.Close();
                }
                // close the output file if necessary
                if (null != outputfile && null != output)
                {
                    output.Close();
                }
            }
            return(result);
        }
示例#2
0
        static void Demo()
        {
            // note that in the real world cases, you'd need to use SlangPatcher.Patch()
            // on whole compile units to get proper codedom objects back. This method is
            // simply "close enough for government work" and may not work for languages
            // other than VB
            while (true)
            {
                Console.Write("Slang>");
                var s = Console.ReadLine();
                if (null != s)
                {
                    s = s.Trim();
                }
                if (string.IsNullOrEmpty(s))
                {
                    break;
                }
                var        isStatement = s.EndsWith(";") || s.EndsWith("}");
                CodeObject co          = null;
                try
                {
                    if (isStatement)
                    {
                        co = SlangParser.ParseStatement(s, true);
                    }
                    else
                    {
                        co = SlangParser.ParseExpression(s);
                    }
                }
                catch (SlangSyntaxException ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                }
                if (null != co)
                {
                    var ccu = _RootCode(co);
                    try
                    {
                        SlangPatcher.Patch(ccu);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Warning: Error resolving code - " + ex.Message);
                    }
                    var tc   = new CodeDomTypeConverter();
                    var item = (ccu.Namespaces[0].Types[0].Members[0] as CodeMemberMethod).Statements[0];

                    if (!isStatement)
                    {
                        co = item;
                        var es = item as CodeExpressionStatement;
                        if (null != es)
                        {
                            co = es.Expression;
                        }
                    }
                    else
                    {
                        co = item;
                    }

                    s = CodeDomUtility.ToString(co);
                    s = s.Trim();
                    Console.Write("C#: ");
                    Console.WriteLine(s);
                    s = CodeDomUtility.ToString(co, "vb");
                    s = s.Trim();
                    Console.Write("VB: ");
                    Console.WriteLine(s);

                    s = CodeDomUtility.ToString(CodeDomUtility.Literal(co, tc));
                    s = s.Trim();

                    Console.Write("CodeDom: ");
                    Console.WriteLine(s);
                    if (null != SlangPatcher.GetNextUnresolvedElement(ccu))
                    {
                        Console.WriteLine("Warning: Not all of the code could be resolved.");
                    }
                }
            }
        }
示例#3
0
 static void _GenerateSymbolConstants(CodeTypeDeclaration target, IList <string> symbolTable)
 {
     // generate symbol constants
     for (int ic = symbolTable.Count, i = 0; i < ic; ++i)
     {
         var symbol = symbolTable[i];
         if (null != symbol)
         {
             var s = _MakeSafeName(symbol);
             s = _MakeUniqueMember(target, s);
             var constField = CodeDomUtility.Field(typeof(int), s, MemberAttributes.Const | MemberAttributes.Public, CodeDomUtility.Literal(i));
             target.Members.Add(constField);
         }
     }
 }