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); }
internal static LexRule Parse(LexContext lc) { lc.Expecting(); var result = new LexRule(); result.Line = lc.Line; result.Column = lc.Column; result.Position = lc.Position; var ll = lc.CaptureBuffer.Length; if (!lc.TryReadCIdentifier()) { throw new ExpectingException("Expecting identifier", lc.Line, lc.Column, lc.Position, lc.FileOrUrl, "identifier"); } result.Symbol = lc.GetCapture(ll); lc.TrySkipCCommentsAndWhiteSpace(); lc.Expecting('=', '<'); if ('<' == lc.Current) { lc.Advance(); lc.Expecting(); var attrs = new List <KeyValuePair <string, object> >(); while (-1 != lc.Current && '>' != lc.Current) { lc.TrySkipCCommentsAndWhiteSpace(); lc.ClearCapture(); var l = lc.Line; var c = lc.Column; var p = lc.Position; if (!lc.TryReadCIdentifier()) { throw new ExpectingException("Identifier expected", l, c, p, "identifier"); } var aname = lc.GetCapture(); lc.TrySkipCCommentsAndWhiteSpace(); lc.Expecting('=', '>', ','); if ('=' == lc.Current) { lc.Advance(); lc.TrySkipCCommentsAndWhiteSpace(); l = lc.Line; c = lc.Column; p = lc.Position; var value = lc.ParseJsonValue(); attrs.Add(new KeyValuePair <string, object>(aname, value)); if (0 == string.Compare("id", aname) && (value is double)) { result.Id = (int)((double)value); if (0 > result.Id) { throw new ExpectingException("Expecting a non-negative integer", l, c, p, "nonNegativeInteger"); } } } else { // boolean true attrs.Add(new KeyValuePair <string, object>(aname, true)); } lc.TrySkipCCommentsAndWhiteSpace(); lc.Expecting(',', '>'); if (',' == lc.Current) { lc.Advance(); } } lc.Expecting('>'); lc.Advance(); result.Attributes = attrs; lc.TrySkipCCommentsAndWhiteSpace(); } lc.Advance(); lc.TrySkipCCommentsAndWhiteSpace(); lc.Expecting('\'', '\"'); result.ExpressionLine = lc.Line; result.ExpressionColumn = lc.Column; result.ExpressionPosition = lc.Position; if ('\'' == lc.Current) { lc.ClearCapture(); lc.Capture(); lc.Advance(); lc.TryReadUntil('\'', '\\', false); lc.Expecting('\''); lc.Capture(); result.Expression = lc.GetCapture(); lc.Advance(); } else { lc.ClearCapture(); lc.Capture(); lc.Advance(); lc.TryReadUntil('\"', '\\', false); lc.Expecting('\"'); lc.Capture(); result.Expression = lc.GetCapture(); } return(result); }