private Token ReadString() { StartRead(); char startSymbol = LA(0); Consume(); // consume first string character while (true) { char ch = LA(0); if (ch == startSymbol) { Consume(); string tokenData = data.Substring(savePos + 1, pos - savePos - 2); return(CreateToken(TokenType.String, tokenData)); } else if (ch == '\\') { if (LA(1) == 'n' || LA(1) == 'r' || LA(1) == '\'' || LA(1) == '"') { // string escape Consume(2); continue; } else { ParserException ex = new ParserException("Unknown escape sequence. Supported escapes: \\n, \\r, \\\", \\'", line, column, pos, 2); ex.Data["code"] = LEXER_ERROR_UNKNOWN_ESCAPE; throw ex; } } else if (ch == EOF) { ParserException ex = new ParserException("Unterminated string constant", saveLine, saveColumn, savePos, pos - savePos); ex.Data["code"] = LEXER_ERROR_UNTERMINATED_STRING; throw ex; } else { // consume next string symbol Consume(); } } }
private Token ReadString() { StartRead(); char startSymbol = LA(0); Consume(); // consume first string character while (true) { char ch = LA(0); if (ch == startSymbol) { Consume(); string tokenData = data.Substring(savePos + 1, pos - savePos - 2); return CreateToken(TokenType.String, tokenData); } else if(ch == '\\') { if (LA(1) == 'n' || LA(1) == 'r' || LA(1) == '\'' || LA(1) == '"') { // string escape Consume(2); continue; } else { ParserException ex = new ParserException("Unknown escape sequence. Supported escapes: \\n, \\r, \\\", \\'", line, column, pos, 2); ex.Data["code"] = LEXER_ERROR_UNKNOWN_ESCAPE; throw ex; } } else if (ch == EOF) { ParserException ex = new ParserException("Unterminated string constant", saveLine, saveColumn, savePos, pos - savePos); ex.Data["code"] = LEXER_ERROR_UNTERMINATED_STRING; throw ex; } else { // consume next string symbol Consume(); } } }
private Token ReadExpression() { StartRead(); start: char ch = LA(0); switch (ch) { case EOF: return CreateToken(TokenType.EOF); case ':': Consume(); return CreateToken(TokenType.Colon); case '.': Consume(); return CreateToken(TokenType.Dot); case ',': Consume(); return CreateToken(TokenType.Comma); case '(': Consume(); return CreateToken(TokenType.LParen); case ')': Consume(); return CreateToken(TokenType.RParen); case '[': Consume(); return CreateToken(TokenType.LBracket); case ']': Consume(); return CreateToken(TokenType.RBracket); case '#': // end of expression Consume(); printStart = false; expressionBody = false; return Next(); case '+': Consume(); return CreateToken(TokenType.Plus); case '-': Consume(); return CreateToken(TokenType.Minus); case '*': Consume(); return CreateToken(TokenType.Mult); case '/': Consume(); return CreateToken(TokenType.Div); case '%': Consume(); return CreateToken(TokenType.Mod); case '<': if (LA(1) == '=') { Consume(2); return CreateToken(TokenType.LessOrEqual); } else { Consume(); return CreateToken(TokenType.Less); } case '>': if (LA(1) == '=') { Consume(2); return CreateToken(TokenType.GreaterOrEqual); } else { Consume(); return CreateToken(TokenType.Greater); } case '=': if (LA(1) == '=') { Consume(2); return CreateToken(TokenType.Equal); } else { Consume(); return CreateToken(TokenType.Assign); } case '!': if (LA(1) == '=') { Consume(2); return CreateToken(TokenType.NotEqual); } else { Consume(); return CreateToken(TokenType.Not); } case '|': if (LA(1) == '|') { Consume(2); return CreateToken(TokenType.Or); } else { Consume(); return CreateToken(TokenType.BinOr); } case '&': if (LA(1) == '&') { Consume(2); return CreateToken(TokenType.And); } else { Consume(); return CreateToken(TokenType.BinAnd); } case ' ': case '\t': case '\r': case '\n': ReadWhitespace(); goto start; case '"': case '\'': return ReadString(); default: if (Char.IsNumber(ch)) return ReadNumber(); else if (Char.IsLetter(ch) || ch == '_') return ReadIdentifier(); else { string symbol = ch.ToString(); ParserException ex = new ParserException(String.Format("Unexpected symbol: '{0}'", symbol), saveLine, saveColumn, pos, 1); ex.Data["code"] = LEXER_ERROR_UNEXPECTED_SYMBOL; ex.Data["symbol"] = symbol; throw ex; } } }
private Token ReadTagBody() { StartRead(); start: char ch = LA(0); switch (ch) { case EOF: return CreateToken(TokenType.EOF); case '>': Consume(); tagBody = false; return Next(); case '=': Consume(); return CreateToken(TokenType.Assign); case ' ': case '\t': case '\r': case '\n': ReadWhitespace(); goto start; case '"': if (attributeBody) { // end of attribute Consume(); // eat " attributeBody = false; } else { // start of attribute attributeBody = true; if (LA(1) == '#') { Consume(2); // eat "# expressionBody = true; return Next(); } else { attributeBody = false; if (Char.IsNumber(LA(1))) { Consume(); // eat " Token num = ReadNumber(); Consume(); // eat " return num; } else return ReadString(); } } goto start; case '\'': return ReadString(); default: if (ch == '/' && LA(1) == '>') { // "empty" tag Consume(2); tagBody = false; return CreateToken(TokenType.EmptyTag); } else if (Char.IsLetter(ch) || ch == '_') { return ReadAttribute(); } else { string symbol = ch.ToString(); ParserException ex = new ParserException(String.Format("Unexpected symbol: '{0}'", symbol), saveLine, saveColumn, pos, 1); ex.Data["code"] = LEXER_ERROR_UNEXPECTED_SYMBOL; ex.Data["symbol"] = symbol; throw ex; } } }
private Token ReadExpression() { StartRead(); start: char ch = LA(0); switch (ch) { case EOF: return(CreateToken(TokenType.EOF)); case ':': Consume(); return(CreateToken(TokenType.Colon)); case '.': Consume(); return(CreateToken(TokenType.Dot)); case ',': Consume(); return(CreateToken(TokenType.Comma)); case '(': Consume(); return(CreateToken(TokenType.LParen)); case ')': Consume(); return(CreateToken(TokenType.RParen)); case '[': Consume(); return(CreateToken(TokenType.LBracket)); case ']': Consume(); return(CreateToken(TokenType.RBracket)); case '#': // end of expression Consume(); printStart = false; expressionBody = false; return(Next()); case '+': Consume(); return(CreateToken(TokenType.Plus)); case '-': Consume(); return(CreateToken(TokenType.Minus)); case '*': Consume(); return(CreateToken(TokenType.Mult)); case '/': Consume(); return(CreateToken(TokenType.Div)); case '%': Consume(); return(CreateToken(TokenType.Mod)); case '<': if (LA(1) == '=') { Consume(2); return(CreateToken(TokenType.LessOrEqual)); } else { Consume(); return(CreateToken(TokenType.Less)); } case '>': if (LA(1) == '=') { Consume(2); return(CreateToken(TokenType.GreaterOrEqual)); } else { Consume(); return(CreateToken(TokenType.Greater)); } case '=': if (LA(1) == '=') { Consume(2); return(CreateToken(TokenType.Equal)); } else { Consume(); return(CreateToken(TokenType.Assign)); } case '!': if (LA(1) == '=') { Consume(2); return(CreateToken(TokenType.NotEqual)); } else { Consume(); return(CreateToken(TokenType.Not)); } case '|': if (LA(1) == '|') { Consume(2); return(CreateToken(TokenType.Or)); } else { Consume(); return(CreateToken(TokenType.BinOr)); } case '&': if (LA(1) == '&') { Consume(2); return(CreateToken(TokenType.And)); } else { Consume(); return(CreateToken(TokenType.BinAnd)); } case ' ': case '\t': case '\r': case '\n': ReadWhitespace(); goto start; case '"': case '\'': return(ReadString()); default: if (Char.IsNumber(ch)) { return(ReadNumber()); } else if (Char.IsLetter(ch) || ch == '_') { return(ReadIdentifier()); } else { string symbol = ch.ToString(); ParserException ex = new ParserException(String.Format("Unexpected symbol: '{0}'", symbol), saveLine, saveColumn, pos, 1); ex.Data["code"] = LEXER_ERROR_UNEXPECTED_SYMBOL; ex.Data["symbol"] = symbol; throw ex; } } }
private Token ReadTagBody() { StartRead(); start: char ch = LA(0); switch (ch) { case EOF: return(CreateToken(TokenType.EOF)); case '>': Consume(); tagBody = false; return(Next()); case '=': Consume(); return(CreateToken(TokenType.Assign)); case ' ': case '\t': case '\r': case '\n': ReadWhitespace(); goto start; case '"': if (attributeBody) { // end of attribute Consume(); // eat " attributeBody = false; } else { // start of attribute attributeBody = true; if (LA(1) == '#') { Consume(2); // eat "# expressionBody = true; return(Next()); } else { attributeBody = false; if (Char.IsNumber(LA(1))) { Consume(); // eat " Token num = ReadNumber(); Consume(); // eat " return(num); } else { return(ReadString()); } } } goto start; case '\'': return(ReadString()); default: if (ch == '/' && LA(1) == '>') { // "empty" tag Consume(2); tagBody = false; return(CreateToken(TokenType.EmptyTag)); } else if (Char.IsLetter(ch) || ch == '_') { return(ReadAttribute()); } else { string symbol = ch.ToString(); ParserException ex = new ParserException(String.Format("Unexpected symbol: '{0}'", symbol), saveLine, saveColumn, pos, 1); ex.Data["code"] = LEXER_ERROR_UNEXPECTED_SYMBOL; ex.Data["symbol"] = symbol; throw ex; } } }