public ScriptParser(Stream stream, string scriptName) { using (var reader = new StreamReaderCursor(stream)) { Parse(reader, scriptName); } }
public ScriptParser(string path) { using (var reader = new StreamReaderCursor(path)) { FileInfo file = new FileInfo(path); string prevCWD = CWD; CWD = file.DirectoryName; Environment.CurrentDirectory = CWD; Parse(reader, path); Environment.CurrentDirectory = prevCWD; } }
void Parse(StreamReaderCursor reader, string scriptName) { var tokenList = Scanner(reader, scriptName); this.CommandRoot = new Command(ExprType.Root); foreach (var tokens in tokenList) { int tokenIdx = 0; while (tokenIdx < tokens.Count) { Expr expr = ParseStmt(tokens, ref tokenIdx); if (expr != null) { this.CommandRoot.Args.Add(expr); } } } }
List<List<Token>> Scanner(StreamReaderCursor reader, string scriptName) { var tokenList = new List<List<Token>>(); var tokens = new List<Token>(); tokenList.Add(tokens); int line = 1; int column = 1; while (!reader.EndOfStream) { char c = (char)reader.Read(ref line, ref column); if (Char.IsWhiteSpace(c)) { if ((c == '\r') || (c == '\n')) { if (tokens.Count > 0) { tokens = new List<Token>(); tokenList.Add(tokens); } } } else if (c == ';') { while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if ((c == '\r') || (c == '\n')) { break; } reader.Read(ref line, ref column); } } else if (c == '/') { if (reader.Peek() != -1) { c = (char)reader.Peek(); if (c == '/') { reader.Read(ref line, ref column); while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if ((c == '\r') || (c == '\n')) { break; } reader.Read(ref line, ref column); } } else if (c == '*') { reader.Read(ref line, ref column); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if ((c == '*') && (reader.Peek() != -1) && ((char)reader.Peek() == '/')) { reader.Read(ref line, ref column); break; } } } else { tokens.Add(new Token(c.ToString(), TokenType.Div, scriptName, line, column)); } } else { tokens.Add(new Token(c.ToString(), TokenType.Div, scriptName, line, column)); } } else if (c == '\"') { var sb = new StringBuilder(); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if ((c == '\\') && (reader.Peek() != -1) && ((char)reader.Peek() == '\"')) { c = (char)reader.Read(ref line, ref column); sb.Append(c); } else { if (c != '\"') { sb.Append(c); } else { break; } } } tokens.Add(new Token(sb.ToString(), TokenType.String, scriptName, line, column)); } else if (c == '[') { var sb = new StringBuilder(); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if (c != ']') { sb.Append(c); } else { break; } } string idx = sb.ToString(); TokenType tType; int dummy; if (idx.Length == 0 || idx.Length > 1 && idx[0].IsHex() && idx[1].IsHex() && (idx.Length == 2 || idx.Length > 2 && idx[2] == '-') || Int32.TryParse(idx, out dummy)) { tType = TokenType.HexOrIndex; } else { tType = TokenType.Name; } tokens.Add(new Token(idx, tType, scriptName, line, column)); } else if (Char.IsLetter(c) || c == '_') { var sb = new StringBuilder(); sb.Append(c); while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsLetterOrDigit(c) || (c == '_')) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), TokenType.Name, scriptName, line, column)); } else if (Char.IsDigit(c)) { var sb = new StringBuilder(); bool hex = c == '0' && (char)reader.Peek() == 'x'; if (hex) reader.Read(ref line, ref column); else sb.Append(c); while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsDigit(c) || hex && (c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), hex ? TokenType.HexInt : TokenType.Number, scriptName, line, column)); } else if (c == '.') { var sb = new StringBuilder(); sb.Append(c); if (!reader.EndOfStream && (reader.Peek() != -1) && Char.IsDigit((char)reader.Peek())) { while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsDigit(c)) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), TokenType.Number, scriptName, line, column)); } else { tokens.Add(new Token(sb.ToString(), TokenType.Dot, scriptName, line, column)); } } else if (c == '(') { tokens.Add(new Token(c.ToString(), TokenType.LP, scriptName, line, column)); } else if (c == ')') { tokens.Add(new Token(c.ToString(), TokenType.RP, scriptName, line, column)); } else if (c == '{') { tokens.Add(new Token(c.ToString(), TokenType.LCB, scriptName, line, column)); } else if (c == '}') { tokens.Add(new Token(c.ToString(), TokenType.RCB, scriptName, line, column)); } else if (c == ',') { tokens.Add(new Token(c.ToString(), TokenType.Comma, scriptName, line, column)); } else if (c == '%') { tokens.Add(new Token(c.ToString(), TokenType.Mod, scriptName, line, column)); } else if (c == '*') { tokens.Add(new Token(c.ToString(), TokenType.Mul, scriptName, line, column)); } else if (c == '+') { tokens.Add(new Token(c.ToString(), TokenType.Plus, scriptName, line, column)); } else if (c == '-') { tokens.Add(new Token(c.ToString(), TokenType.Minus, scriptName, line, column)); } else if (c == '=') { tokens.Add(new Token(c.ToString(), TokenType.Equals, scriptName, line, column)); } else { throw new Exception("Unexpected char: " + c + " (" + Path.GetFileName(scriptName) + ", line " + line + ", column " + column); } } if (tokens.Count <= 0) { tokenList.RemoveAt(tokenList.Count - 1); } return tokenList; }
List <List <Token> > Scanner(StreamReaderCursor reader, string scriptName) { var tokenList = new List <List <Token> >(); var tokens = new List <Token>(); tokenList.Add(tokens); int line = 1; int column = 1; while (!reader.EndOfStream) { char c = (char)reader.Read(ref line, ref column); if (Char.IsWhiteSpace(c)) { if ((c == '\r') || (c == '\n')) { if (tokens.Count > 0) { tokens = new List <Token>(); tokenList.Add(tokens); } } } else if (c == ';') { while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if ((c == '\r') || (c == '\n')) { break; } reader.Read(ref line, ref column); } } else if (c == '/') { if (reader.Peek() != -1) { c = (char)reader.Peek(); if (c == '/') { reader.Read(ref line, ref column); while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if ((c == '\r') || (c == '\n')) { break; } reader.Read(ref line, ref column); } } else if (c == '*') { reader.Read(ref line, ref column); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if ((c == '*') && (reader.Peek() != -1) && ((char)reader.Peek() == '/')) { reader.Read(ref line, ref column); break; } } } else { tokens.Add(new Token(c.ToString(), TokenType.Div, scriptName, line, column)); } } else { tokens.Add(new Token(c.ToString(), TokenType.Div, scriptName, line, column)); } } else if (c == '\"') { var sb = new StringBuilder(); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if ((c == '\\') && (reader.Peek() != -1) && ((char)reader.Peek() == '\"')) { c = (char)reader.Read(ref line, ref column); sb.Append(c); } else { if (c != '\"') { sb.Append(c); } else { break; } } } tokens.Add(new Token(sb.ToString(), TokenType.String, scriptName, line, column)); } else if (c == '[') { var sb = new StringBuilder(); while (!reader.EndOfStream) { c = (char)reader.Read(ref line, ref column); if (c != ']') { sb.Append(c); } else { break; } } tokens.Add(new Token(sb.ToString(), TokenType.HexOrIndex, scriptName, line, column)); } else if (Char.IsLetter(c) || c == '_') { var sb = new StringBuilder(); sb.Append(c); while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsLetterOrDigit(c) || (c == '_')) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), TokenType.Name, scriptName, line, column)); } else if (Char.IsDigit(c)) { var sb = new StringBuilder(); bool hex = c == '0' && (char)reader.Peek() == 'x'; if (hex) { reader.Read(ref line, ref column); } else { sb.Append(c); } while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsDigit(c) || hex && (c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), hex ? TokenType.HexInt : TokenType.Number, scriptName, line, column)); } else if (c == '.') { var sb = new StringBuilder(); sb.Append(c); if (!reader.EndOfStream && (reader.Peek() != -1) && Char.IsDigit((char)reader.Peek())) { while (!reader.EndOfStream && (reader.Peek() != -1)) { c = (char)reader.Peek(); if (Char.IsDigit(c)) { sb.Append(c); reader.Read(ref line, ref column); } else { break; } } tokens.Add(new Token(sb.ToString(), TokenType.Number, scriptName, line, column)); } else { tokens.Add(new Token(sb.ToString(), TokenType.Dot, scriptName, line, column)); } } else if (c == '(') { tokens.Add(new Token(c.ToString(), TokenType.LP, scriptName, line, column)); } else if (c == ')') { tokens.Add(new Token(c.ToString(), TokenType.RP, scriptName, line, column)); } else if (c == '{') { tokens.Add(new Token(c.ToString(), TokenType.LCB, scriptName, line, column)); } else if (c == '}') { tokens.Add(new Token(c.ToString(), TokenType.RCB, scriptName, line, column)); } else if (c == ',') { tokens.Add(new Token(c.ToString(), TokenType.Comma, scriptName, line, column)); } else if (c == '%') { tokens.Add(new Token(c.ToString(), TokenType.Mod, scriptName, line, column)); } else if (c == '*') { tokens.Add(new Token(c.ToString(), TokenType.Mul, scriptName, line, column)); } else if (c == '+') { tokens.Add(new Token(c.ToString(), TokenType.Plus, scriptName, line, column)); } else if (c == '-') { tokens.Add(new Token(c.ToString(), TokenType.Minus, scriptName, line, column)); } else if (c == '=') { tokens.Add(new Token(c.ToString(), TokenType.Equals, scriptName, line, column)); } else { throw new Exception("Unexpected char: " + c + " (" + Path.GetFileName(scriptName) + ", line " + line + ", column " + column); } } if (tokens.Count <= 0) { tokenList.RemoveAt(tokenList.Count - 1); } return(tokenList); }