protected async IAsyncEnumerable <Token> DoPreprocess(IAsyncStream <Token> input) { while (!await input.Eof()) { Token token; if ((await input.Peek()).Kind == Pound) { await input.Read(); if ((await input.Peek()).Kind == Identifier) { switch ((await input.Read() as ValueToken <string>) !.Value.ToLower()) {
protected async IAsyncEnumerable <string> asyncStreamFuncQueries(IAsyncStream <string> input) { while (!await input.Eof()) { yield return((await input.Read()) + "?"); } }
protected async IAsyncEnumerable <char> CountLines(IAsyncStream <char> input) { await foreach (char c in input) { yield return(c); if (c == '\r') { if (!await input.Eof() && await input.Peek() == '\n') { yield return(await input.Read()); } TranslationUnit.CurrentLine++; TranslationUnit.CurrentColumn = 1; } else if (c == '\n') { TranslationUnit.CurrentLine++; TranslationUnit.CurrentColumn = 1; } else if (c == '\t') { // TODO: Is this the expectation for tabs? TranslationUnit.CurrentColumn += TAB_WIDTH - ((TranslationUnit.CurrentColumn - 1) % TAB_WIDTH); } else { TranslationUnit.CurrentColumn++; } } }
protected async IAsyncEnumerable <string> asyncStreamFuncLessThan6(IAsyncStream <int> input) { while (!await input.Eof()) { if (await input.Peek() <= 5) { yield return((await input.Read()).ToString()); } else { yield break; } } }
protected async Task ProcessIncludeFileLine(IAsyncStream <Token> input, BufferBlock <Token> tokenBuffer) { Terminal?t = default; if ((await input.Peek()).Kind == Pound) { var poundToken = (await input.Read()); if ((await input.Peek()).Kind == Identifier) { ValueToken <string> directiveToken; switch ((directiveToken = (ValueToken <string>)(await input.Read())).Value.ToLower()) { case "include": if ((t = (await input.Peek()).Kind) == LessThan || t == StringLiteral) { string?filename = null; if (t == StringLiteral) { var token = await input.Read(); filename = ((ValueToken <string>)token).Value; if (!await input.Eof()) { if ((await input.Peek()).Kind != Newline) { // TODO: Error } else { tokenBuffer.Post(await input.Read()); } // TODO: Error } } else { try { var token = await input.Read(); TranslationUnit.LexerState = LexerState.LexingLibraryFilename; if ((await input.Peek()).Kind == Filename) { filename = ((ValueToken <string>) await input.Read()).Value; } } finally { TranslationUnit.LexerState = LexerState.LexerReady; } if ((await input.Peek()).Kind != GreaterThan) { // TODO: Error } else { await input.Read(); } if (!await input.Eof()) { if ((await input.Peek()).Kind != Newline) { // TODO: Error } else { tokenBuffer.Post(await input.Read()); } // TODO: Error } } if (filename != null) { var dummyTask = tokenBuffer.PostAllAsync( ProcessPipeline(filename, IncludePipeline() ! .Chain(FilterEof !))) .ContinueWith(_ => tokenBuffer.Complete()); } } break; default: { // Pass directive on to the rest of the pipeline // (this method only handles the #include directive) tokenBuffer.Post(poundToken); tokenBuffer.Post(directiveToken); while (!await input.Eof()) { var token = await input.Read(); tokenBuffer.Post(token); if (token.Kind == Newline) { break; } } tokenBuffer.Complete(); break; } } } else { // Pass line on to the rest of the pipeline tokenBuffer.Post(poundToken); while (!await input.Eof()) { var token = await input.Read(); tokenBuffer.Post(token); if (token.Kind == Newline) { break; } } tokenBuffer.Complete(); } } else { while (!await input.Eof()) { var token = await input.Read(); tokenBuffer.Post(token); if (token.Kind == Newline) { break; } } tokenBuffer.Complete(); } }
protected async IAsyncEnumerable <char> SpliceLines(IAsyncStream <char> input) { char c; while (!await input.Eof()) { switch (c = await input.Read()) { // Splice lines ending in '\' with the next line. case '\\': bool whitespace = false; while (!await input.Eof() && (await input.Peek() == ' ' || await input.Peek() == '\t')) { whitespace = true; await input.Read(); } if (await input.Eof()) { if (whitespace) { yield return(' '); } yield return('\\'); } else { c = await input.Read(); if (c == '\r') { if (!await input.Eof() && await input.Peek() == '\n') { await input.Read(); } } else if (c != '\n') { yield return('\\'); if (whitespace) { yield return(' '); } yield return(c); } } break; case '\r': // Convert "\r\n" to "\n" if (!await input.Eof() && await input.Peek() == '\n') { await input.Read(); } yield return('\n'); break; default: yield return(c); break; } } }
protected async IAsyncEnumerable <char> ReplaceTrigraphs(IAsyncStream <char> input) { int num_question_marks = 0; char c; while (!await input.Eof()) { switch (c = await input.Read()) { case '?': num_question_marks++; break; default: if (num_question_marks >= 2) { while (num_question_marks > 2) { yield return('?'); num_question_marks--; } switch (c) { case '=': yield return('#'); break; case '/': yield return('\\'); break; case '\'': yield return('^'); break; case '(': yield return('['); break; case ')': yield return(']'); break; case '!': yield return('|'); break; case '<': yield return('{'); break; case '>': yield return('}'); break; case '-': yield return('~'); break; default: while (num_question_marks > 0) { yield return('?'); } yield return(c); break; } num_question_marks = 0; } else { yield return(c); } break; } } while (num_question_marks > 0) { yield return('?'); } }