internal void SetInput(InputScanner input, bool versionWillBeError) { Debug.Assert(inputStack.Count == 0); pushInput(new StringInput(this, input)); errorOnVersion = versionWillBeError; versionSeen = false; }
internal bool DoStuff(ParseContext parseContext, PreprocessorContext ppContext, InputScanner input, bool versionWillBeError) { //bool versionWillBeError = true; var unNeededSpaceTokens = new HashSet <char>(new char[] { ';', '(', ')', '[', ']' }); var noSpaceBeforeTokens = new HashSet <char>(new char[] { ',' }); var outputStream = new StringBuilder(); int lastLine = -1; // lastLine is the line number of the last token // processed. It is tracked in order for new-lines to be inserted when // a token appears on a new line. int lastToken = -1; parseContext.setScanner(input); ppContext.setInput(input, versionWillBeError); // Inserts newlines and incremnets lastLine until // lastLine >= line. Action <int> adjustLine = (line) => { int tokenLine = line - 1; while (lastLine < tokenLine) { if (lastLine >= 0) { outputStream.AppendLine(); } ++lastLine; } }; parseContext.ExtensionCallback = (int line, string extension, string behavior) => { adjustLine(line); outputStream.Append("#extension ").Append(extension).Append(" : ").Append(behavior); }; parseContext.LineCallback = (int line, bool hasSource, int sourceNum) => { // SourceNum is the number of the source-string that is being parsed. if (lastLine != -1) { outputStream.AppendLine(); } outputStream.Append("#line ").Append(line); if (hasSource) { outputStream.Append(" ").Append(sourceNum); } outputStream.AppendLine(); lastLine = System.Math.Max(line - 1, 1); }; parseContext.VersionCallback = (int line, int version, string str) => { adjustLine(line); outputStream.Append("#version ").Append(version); if (str != null) { outputStream.Append(" ").Append(str); } outputStream.AppendLine(); ++lastLine; }; parseContext.PragmaCallback = (int line, List <string> ops) => { adjustLine(line); outputStream.Append("#pragma "); foreach (var op in ops) { outputStream.Append(op); } }; parseContext.ErrorCallback = (int line, string errorMessage) => { adjustLine(line); outputStream.Append("#error ").Append(errorMessage); }; var token = new PreprocessorToken(); string tok = ppContext.tokenize(ref token); while (tok != null) { int tokenLine = token.loc.line - 1; // start at 0; bool newLine = false; while (lastLine < tokenLine) { if (lastLine > -1) { outputStream.AppendLine(); newLine = true; } ++lastLine; if (lastLine == tokenLine) { // Don't emit whitespace onto empty lines. // Copy any whitespace characters at the start of a line // from the input to the output. for (int i = 0; i < token.loc.column - 1; ++i) { outputStream.Append(" "); } } } // Output a space in between tokens, but not at the start of a line, // and also not around special tokens. This helps with readability // and consistency. if (!newLine && lastToken != -1 && (!unNeededSpaceTokens.Contains((char)token.token)) && (!unNeededSpaceTokens.Contains((char)lastToken)) && (!noSpaceBeforeTokens.Contains((char)token.token))) { outputStream.Append(" "); } lastToken = token.token; outputStream.Append(tok); tok = ppContext.tokenize(ref token); } outputStream.AppendLine(); Output = outputStream.ToString(); return(true); }
internal void setInput(InputScanner input, bool versionWillBeError) { if (inputStack.Count != 0) { throw new Exception ("Stack is use"); } pushInput(new StringInput(this, input)); errorOnVersion = versionWillBeError; versionSeen = false; }
internal void setScanner(InputScanner scanner) { currentScanner = scanner; }
/// <summary> /// Processes the deferred. /// </summary> /// <returns><c>true</c>, if deferred was processed, <c>false</c> otherwise.</returns> /// <param name="shaderStrings">Shader strings.</param> /// <param name="defaultVersion">use 100 for ES environment, 110 for desktop</param> /// <param name="defaultProfile">Default profile.</param> /// <param name="forceDefaultVersionAndProfile">set version/profile to defaultVersion/defaultProfile regardless of the #version directive in the source code </param> /// <param name="forwardCompatible">give errors for use of deprecated features</param> /// <param name="messages">warnings/errors/AST; things to print out</param> /// <param name="processingContext">Processing context.</param> private bool ProcessDeferred( string[] shaderStrings, int defaultVersion, Profile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, MessageType messages, Func <ParseContext, PreprocessorContext, InputScanner, bool, bool> processingContext) { if (shaderStrings.Length == 0) { return(true); } // First, without using the preprocessor or parser, find the #version, so we know what // symbol tables, processing rules, etc. to set up. This does not need the extra strings // outlined above, just the user shader. int version; Profile profile; var userInput = new InputScanner(shaderStrings, 0, 0); // no preamble bool versionNotFirstToken; bool versionNotFirst = userInput.scanVersion(out version, out profile, out versionNotFirstToken); bool versionNotFound = version == 0; if (forceDefaultVersionAndProfile) { if (((messages & MessageType.SuppressWarnings) == 0) && !versionNotFound && (version != defaultVersion || profile != defaultProfile)) { mInfoSink.Info .Append("Warning, (version, profile) forced to be (") .Append(defaultVersion.ToString()) .Append(", ") .Append(ProfileName(defaultProfile)) .Append("), while in source code it is (") .Append(version.ToString()) .Append(", ") .Append(ProfileName(profile)) .Append(")\n"); } if (versionNotFound) { versionNotFirstToken = false; versionNotFirst = false; versionNotFound = false; } version = defaultVersion; profile = defaultProfile; } bool goodVersion = DeduceVersionProfile( mInfoSink, mLanguage, versionNotFirst, defaultVersion, ref version, ref profile); bool versionWillBeError = (versionNotFound || (profile == Profile.EsProfile && version >= 300 && versionNotFirst)); bool warnVersionNotFirst = false; if (!versionWillBeError && versionNotFirstToken) { if ((messages & MessageType.RelaxedErrors) > 0) { warnVersionNotFirst = true; } else { versionWillBeError = true; } } mIntermediate.setVersion(version); mIntermediate.setProfile(profile); // // Now we can process the full shader under proper symbols and rules. // var parseContext = new ParseContext(version, profile, mInfoSink, forwardCompatible, mSymbols, mIntermediate); var ppContext = new PreprocessorContext(parseContext, mSymbols); parseContext.setPpContext(ppContext); if (!goodVersion) { parseContext.addError(); } if (warnVersionNotFirst) { SourceLocation loc = new SourceLocation(); parseContext.Warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", ""); } parseContext.initializeExtensionBehavior(); var fullInput = new InputScanner(shaderStrings, 0, 0); bool success = processingContext(parseContext, ppContext, fullInput, versionWillBeError); return(success); }
internal bool DoStuff(ParseContext parseContext, PreprocessorContext ppContext, InputScanner input, bool versionWillBeError) { //bool versionWillBeError = true; var unNeededSpaceTokens = new HashSet<char>(new char[]{';','(',')','[',']'}); var noSpaceBeforeTokens = new HashSet<char>(new char[]{','}); var outputStream = new StringBuilder(); int lastLine = -1; // lastLine is the line number of the last token // processed. It is tracked in order for new-lines to be inserted when // a token appears on a new line. int lastToken = -1; parseContext.setScanner(input); ppContext.setInput(input, versionWillBeError); // Inserts newlines and incremnets lastLine until // lastLine >= line. Action<int> adjustLine = (line) => { int tokenLine = line - 1; while(lastLine < tokenLine) { if (lastLine >= 0) { outputStream.AppendLine(); } ++lastLine; } }; parseContext.ExtensionCallback = (int line, string extension, string behavior) => { adjustLine(line); outputStream.Append("#extension ").Append(extension).Append(" : ").Append(behavior); }; parseContext.LineCallback = (int line, bool hasSource, int sourceNum) => { // SourceNum is the number of the source-string that is being parsed. if (lastLine != -1) { outputStream.AppendLine(); } outputStream.Append("#line ").Append(line); if (hasSource) { outputStream.Append(" ").Append(sourceNum); } outputStream.AppendLine(); lastLine = System.Math.Max(line - 1, 1); }; parseContext.VersionCallback = (int line, int version, string str) => { adjustLine(line); outputStream.Append("#version ").Append(version); if (str != null) { outputStream.Append(" ").Append(str); } outputStream.AppendLine(); ++lastLine; }; parseContext.PragmaCallback = (int line, List<string> ops) => { adjustLine(line); outputStream.Append("#pragma "); foreach(var op in ops) { outputStream.Append(op); } }; parseContext.ErrorCallback = (int line, string errorMessage) => { adjustLine(line); outputStream.Append("#error ").Append(errorMessage); }; var token = new PreprocessorToken(); string tok = ppContext.tokenize (ref token); while (tok != null) { int tokenLine = token.loc.line - 1; // start at 0; bool newLine = false; while (lastLine < tokenLine) { if (lastLine > -1) { outputStream.AppendLine(); newLine = true; } ++lastLine; if (lastLine == tokenLine) { // Don't emit whitespace onto empty lines. // Copy any whitespace characters at the start of a line // from the input to the output. for(int i = 0; i < token.loc.column - 1; ++i) { outputStream.Append(" "); } } } // Output a space in between tokens, but not at the start of a line, // and also not around special tokens. This helps with readability // and consistency. if (!newLine && lastToken != -1 && (!unNeededSpaceTokens.Contains ((char)token.token)) && (!unNeededSpaceTokens.Contains((char)lastToken)) && (!noSpaceBeforeTokens.Contains ((char)token.token))) { outputStream.Append(" "); } lastToken = token.token; outputStream.Append(tok); tok = ppContext.tokenize (ref token); } outputStream.AppendLine(); Output = outputStream.ToString(); return true; }