private static int Main( string[] args ) { Stream inputFile = null; Grammar grammar = null; ErrorHandler handler = new ErrorHandler(); string inputFileInfo = null; // Filename plus revision time. Lexers.Scanner scanner = null; Parser.Parser parser = null; Assembly assm = Assembly.GetExecutingAssembly(); object info = Attribute.GetCustomAttribute( assm, typeof( AssemblyFileVersionAttribute ) ); versionInfo = ((AssemblyFileVersionAttribute)info).Version; try { string filename = ProcessOptions( args ); if (filename == null) return MC_OK; try { inputFile = new FileStream( filename, FileMode.Open, FileAccess.Read, FileShare.Read ); inputFileInfo = filename + " - " + File.GetLastWriteTime( filename ).ToString(); } catch (IOException x) { string message; inputFile = null; if (x is FileNotFoundException) message = String.Format( CultureInfo.InvariantCulture, "Source file <{0}> not found{1}", filename, Environment.NewLine ); else message = String.Format( CultureInfo.InvariantCulture, "Source file <{0}> could not be opened{1}", filename, Environment.NewLine ); handler.AddError( 4, message, null ); // aast.AtStart; return MC_FILEERROR; } scanner = new Lexers.Scanner( inputFile ); scanner.SetHandler( handler ); parser = new Parser.Parser( filename, inputFileInfo, scanner, handler ); // // If the parse is successful, then process the grammar. // Otherwise just report the errors that have been listed. // if (parser.Parse()) { grammar = parser.Grammar; if (Terminal.Max > 255) handler.ListError( null, 103, CharacterUtilities.Map( Terminal.Max ), '\'' ); LALRGenerator generator = new LALRGenerator( grammar ); List<AutomatonState> states = generator.BuildStates(); generator.ComputeLookAhead(); generator.BuildParseTable(); if (!grammar.CheckGrammar( handler )) throw new ArgumentException( "Non-terminating grammar" ); // // If the grammar has non-terminating non-terms we cannot // create a diagnostic report as the grammar is incomplete. // if (!handler.Errors) { CodeGenerator code = new CodeGenerator(); code.Generate( states, grammar ); } bool DoDiagnose = Diagnose && !grammar.HasNonTerminatingNonTerms; if (Report || DoDiagnose) { string htmlName = System.IO.Path.ChangeExtension( filename, ".report.html" ); try { System.IO.FileStream htmlFile = new System.IO.FileStream( htmlName, System.IO.FileMode.Create ); System.IO.StreamWriter htmlWriter = new System.IO.StreamWriter( htmlFile ); Grammar.HtmlHeader( htmlWriter, filename ); if (Report && DoDiagnose) grammar.GenerateCompoundReport( htmlWriter, inputFileInfo, states ); else if (Report) grammar.GenerateReport( htmlWriter, inputFileInfo, states ); Grammar.HtmlTrailer( htmlWriter ); if (htmlFile != null) { htmlWriter.Flush(); htmlFile.Close(); } } catch (System.IO.IOException) { Console.Error.WriteLine( "Cannot create html output file {0}", htmlName ); } } } } catch (System.Exception e) { if (e is TooManyErrorsException) return MC_TOOMANYERRORS; Console.Error.WriteLine( "Unexpected Error {0}", e.Message ); if (NoThrowOnError) { // report the error, do not let it go into the void Console.Error.WriteLine( e ); return MC_EXCEPTION; } } finally { if (handler.Errors || handler.Warnings) handler.DumpAll( (scanner == null ? null : scanner.Buffer), Console.Error ); if ((Listing || handler.Errors || handler.Warnings) && parser != null) { string listName = parser.ListfileName; StreamWriter listStream = ListingFile( listName ); if (listStream != null) handler.MakeListing( scanner.Buffer, listStream, parser.SourceFileInfo, versionInfo ); } } return MC_OK; }
// Modified code contributed by Emmo Emminghaus. internal void GenerateCode( CodeGenerator codeGenerator ) { int i = 0; int line = codeSpan.startLine; bool doLines = GPCG.Lines; int length = commands.Length; if (doLines) { Console.WriteLine( "#line {0} \"{1}\"", line, GPCG.LinesFilename ?? codeGenerator.grammar.InputFilename ); for (int j = 0; j < codeSpan.startColumn; j++) Console.Write( " " ); } while (i < length) { switch (commands[i]) { case 'Y': { int j = i; do { j++; } while (j < length && char.IsLetter( commands, j )); string substr = commands.Substring( i, j - i ); if (substr.Equals( "YYACCEPT" )) { i = j; Console.Write( "YYAccept()" ); } else if (substr.Equals( "YYABORT" )) { i = j; Console.Write( "YYAbort()" ); } else if (substr.Equals( "YYERROR" )) { i = j; Console.Write( "YYError()" ); } else Output( i++ ); break; } case '/': Output( i++ ); if (i < length && commands[i] == '/') // C++ style comments { while (i < length && commands[i] != '\n') Output( i++ ); if (i < length) Output( i++ ); } else if (i < length && commands[i] == '*') // C style comments { Output( i++ ); do { while (i < length && commands[i] != '*') Output( i++ ); if (i < length) Output( i++ ); } while (i < length && commands[i] != '/'); if (i < length) Output( i++ ); } break; case '"': // start of string literal Output( i++ ); while (i < length && commands[i] != '"') { if (commands[i] == '\\') Output( i++ ); if (i < length) Output( i++ ); } if (i < length) Output( i++ ); break; case '@': // Possible start of verbatim string literal // but also possible location marker access if (i + 1 < length) { char la = commands[i + 1]; // lookahead character if (la == '$') { i += 2; // read past '@', '$' Console.Write( "CurrentLocationSpan" ); } else if (Char.IsDigit( la )) { i++; int num = (int)commands[i++] - (int)'0'; while (i < length && char.IsDigit( commands[i] )) num = num * 10 + (int)commands[i++] - (int)'0'; //if (num > this.production.rhs.Count) // ErrReport(lineTag, String.Format("Index @{0} is out of bounds", num)); Console.Write( "LocationStack[LocationStack.Depth-{0}]", pos - num + 1 ); } else { Output( i++ ); if (la == '"') { Output( i++ ); while (i < length && commands[i] != '"') Output( i++ ); if (i < length) Output( i++ ); break; } } } //else // ErrReport(lineTag, "Invalid use of '@'"); break; case '\'': // start of char literal Output( i++ ); while (i < length && commands[i] != '\'') { if (commands[i] == '\\') Output( i++ ); if (i < length) Output( i++ ); } if (i < length) Output( i++ ); break; case '$': // $$ or $n placeholder i++; if (i < length) { string kind = null; if (commands[i] == '<') // $<kind>n { i++; StringBuilder builder = new StringBuilder(); while (i < length && commands[i] != '>') { builder.Append( commands[i] ); i++; } if (i < length) { i++; kind = builder.ToString(); } } if (commands[i] == '$') { i++; if (kind == null) kind = production.lhs.kind; Console.Write( "CurrentSemanticValue" ); if (kind != null) Console.Write( ".{0}", kind ); } else if (char.IsDigit( commands[i] )) { int num = (int)commands[i++] - (int)'0'; while (i < length && char.IsDigit( commands[i] )) num = num * 10 + (int)commands[i++] - (int)'0'; //if (num > this.production.rhs.Count) // ErrReport(lineTag, String.Format("Index ${0} is out of bounds", num)); if (kind == null) kind = production.rhs[num - 1].kind; Console.Write( "ValueStack[ValueStack.Depth-{0}]", pos - num + 1 ); if (kind != null) Console.Write( ".{0}", kind ); } } //else // ErrReport(lineTag, "Unexpected '$'"); break; case '\n': Output( i ); i++; line++; break; default: Output( i++ ); break; } } Console.WriteLine(); if (doLines) Console.WriteLine( "#line default" ); }