public static Token ReadToken(LocatedTextReaderWrapper input) { input.SkipWhiteSpace(); int nextCharacterCode = input.Peek(); if(nextCharacterCode < 0) { return null; } char nextCharacter = (char)nextCharacterCode; var startLocation = input.Location.Clone(); Token token; if(IsStringStart(nextCharacter)) { token = ReadString(input); } else if(IsNumberChar(nextCharacter)) { token = ReadNumber(input); } else if(IsIdentifierStart(nextCharacter)) { token = ReadIdentifier(input); } else if(IsSymbolChar(nextCharacter)) { token = ReadSymbol(input); } else { throw new BadDataException("Unknown token starting with " + nextCharacter, startLocation); } token.Location = startLocation; return token; }
private void osq2osb_Click(object sender, EventArgs e) { using(var reader = new LocatedTextReaderWrapper(osqScript.Text)) { reverser.Parser.InputReader = reader; osbScript.Text = reverser.Encode(); } osb2osq.Enabled = true; }
static void Main(string[] args) { if(args.Length == 0) { Console.WriteLine("Parsing from console..."); var executionContext = new ExecutionContext(); while(true) { try { using(var console = Console.OpenStandardInput()) using(var reader = new LocatedTextReaderWrapper(console)) { var parser = new Parser(reader); foreach(var node in parser.ReadNodes()) { string output = node.Execute(executionContext); Console.Write(output); } } } catch(Exception e) { Console.WriteLine("Error: " + e); } } } else { watchers = new Dictionary<FileCollectionWatcher, string>(); foreach(var filename in args) { var watcher = new FileCollectionWatcher(); watcher.Changed += FileChanged; watchers[watcher] = filename; ParseFile(watcher, filename); Console.WriteLine("Watching " + filename + " for changes..."); } Thread.Sleep(-1); } }
private static void ParseFile(FileCollectionWatcher watcher, string filename) { Console.Write("Parsing " + filename + "..."); using(var inputFile = File.Open(filename, FileMode.Open, FileAccess.Read)) using(var outputFile = File.Open(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)) + ".osb", FileMode.Create, FileAccess.Write)) { var executionContext = new ExecutionContext(); using(var reader = new LocatedTextReaderWrapper(inputFile, new Location(filename))) using(var writer = new StreamWriter(outputFile)) { try { var parser = new Parser(reader); foreach(var node in parser.ReadNodes()) { string output = node.Execute(executionContext); writer.Write(output); } watcher.Clear(); } catch(Exception e) { Console.WriteLine("\nError: " + e); return; } finally { if(!watcher.Contains(filename)) { watcher.Add(filename); } foreach(string file in executionContext.Dependencies.Where((file) => !watcher.Contains(file))) { watcher.Add(file); } } } } Console.WriteLine(" Done!"); }
/// <summary> /// Initializes a new instance of the <see cref="Encoder"/> class with sensible defaults. /// </summary> /// <param name="reader">The reader.</param> /// <remarks>The <see cref="Encoder"/> instance created is readily usable with a default <see cref="Parser"/> and <see cref="ExecutionContext"/>.</remarks> public Encoder(LocatedTextReaderWrapper reader) { Parser = new Parser.Parser(reader); ExecutionContext = new ExecutionContext(); }
/// <summary> /// Transforms the osq script into an osb script. /// </summary> /// <returns>The osb script.</returns> public string Encode() { if(ExecutionContext == null) { throw new InvalidOperationException("ExecutionContext must not be null"); } if(Parser == null) { throw new InvalidOperationException("Parser must not be null"); } scriptNodes = new List<ConvertedNode>(); var output = new StringBuilder(); using(var bufferingReader = new BufferingTextReaderWrapper(Parser.InputReader)) using(var myReader = new LocatedTextReaderWrapper(bufferingReader, Parser.InputReader.Location.Clone())) { // Sorry we have to do this... var parser = new Parser.Parser(Parser, myReader); NodeBase node; while((node = parser.ReadNode()) != null) { string curOutput = node.Execute(ExecutionContext); output.Append(curOutput); var converted = new ConvertedNode { Node = node, NodeOutput = curOutput, OriginalScript = bufferingReader.BufferedText }; scriptNodes.Add(converted); bufferingReader.ClearBuffer(); } } return output.ToString(); }
/// <summary> /// Initializes a new instance of the <see cref="Parser"/> class. /// </summary> /// <param name="reader">The reader with which to parse.</param> public Parser(LocatedTextReaderWrapper reader) { InputReader = reader; }
/// <summary> /// Initializes a new instance of the <see cref="Parser"/> class given a <see cref="Parser"/> to model after and a new reader. /// </summary> /// <param name="other">Parser to copy the options from.</param> /// <param name="newReader">The new reader.</param> public Parser(Parser other, LocatedTextReaderWrapper newReader) : this(other) { InputReader = newReader; }
public static IEnumerable<Token> ReadTokens(LocatedTextReaderWrapper input) { Token curToken; while((curToken = ReadToken(input)) != null) { yield return curToken; } }
private static Token ReadString(LocatedTextReaderWrapper input) { var str = new StringBuilder(); input.Read(); // Consume ". while(true) { int rawChar = input.Read(); if(rawChar < 0) { throw new MissingDataException("End-of-string terminator", input.Location); } char nextCharacter = (char)rawChar; if(nextCharacter == '"') { break; } if(nextCharacter == '\\') { nextCharacter = ReadEscapeCode(input); } str.Append(nextCharacter); } return new Token(TokenType.String, str.ToString()); }
private static Token ReadSymbol(LocatedTextReaderWrapper input) { var curToken = ""; while(input.Peek() >= 0) { char nextCharacter = (char)input.Peek(); if(!IsSymbolChar(nextCharacter)) { break; } string newToken = curToken + nextCharacter; if(!IsSymbolStart(newToken)) { break; } curToken = newToken; input.Read(); // Discard. } return new Token(TokenType.Symbol, curToken); }
private static Token ReadNumber(LocatedTextReaderWrapper input) { var startLocation = input.Location.Clone(); var numberString = new StringBuilder(); while(IsNumberChar((char)input.Peek())) { numberString.Append((char)input.Read()); } double number; if(!double.TryParse(numberString.ToString(), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Parser.DefaultCulture, out number)) { throw new BadDataException("Number", startLocation); } return new Token(TokenType.Number, number); }
private static Token ReadIdentifier(LocatedTextReaderWrapper input) { var token = new StringBuilder(); while(input.Peek() >= 0) { char nextCharacter = (char)input.Peek(); if(!IsIdentifierChar(nextCharacter)) { break; } token.Append(nextCharacter); input.Read(); // Discard. } return new Token(TokenType.Identifier, token.ToString()); }
private static char ReadEscapeCode(LocatedTextReaderWrapper input) { int nextCharacter = input.Read(); if(nextCharacter < 0) { throw new MissingDataException("Code following \\", input.Location); } switch((char)nextCharacter) { case 'n': return '\n'; case 't': return '\t'; case 'r': return '\r'; case '\\': return '\\'; case '"': return '"'; default: var e = new BadDataException("Unknown escape character", input.Location); e.Data["character"] = (char)nextCharacter; throw e; } }
/// <summary> /// Initializes a new instance of the <see cref="Encoder"/> class. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The execution context.</param> public Encoder(LocatedTextReaderWrapper reader, ExecutionContext context) : this(new Parser(reader), context) { }
/// <summary> /// Initializes a new instance of the <see cref="Encoder"/> class. /// </summary> /// <param name="reader">The reader.</param> public Encoder(LocatedTextReaderWrapper reader) : this(new Parser(reader)) { }