| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| package org.apache.impala.analysis; |
| |
| import java_cup.runtime.Symbol; |
| import java.lang.Integer; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ArrayList; |
| |
| import org.apache.impala.analysis.SqlParserSymbols; |
| |
| %% |
| |
| %class SqlScanner |
| %cup |
| %public |
| %final |
| %eofval{ |
| return newToken(SqlParserSymbols.EOF, null); |
| %eofval} |
| %unicode |
| %line |
| %column |
| %{ |
| // Map from keyword string to token id. |
| // We use a linked hash map because the insertion order is important. |
| // for example, we want "and" to come after "&&" to make sure error reporting |
| // uses "and" as a display name and not "&&". |
| // Please keep the puts sorted alphabetically by keyword (where the order |
| // does not affect the desired error reporting) |
| public static final Map<String, Integer> keywordMap = |
| new LinkedHashMap<String, Integer>(); |
| static { |
| keywordMap.put("&&", new Integer(SqlParserSymbols.KW_AND)); |
| keywordMap.put("add", new Integer(SqlParserSymbols.KW_ADD)); |
| keywordMap.put("aggregate", new Integer(SqlParserSymbols.KW_AGGREGATE)); |
| keywordMap.put("all", new Integer(SqlParserSymbols.KW_ALL)); |
| keywordMap.put("alter", new Integer(SqlParserSymbols.KW_ALTER)); |
| keywordMap.put("analytic", new Integer(SqlParserSymbols.KW_ANALYTIC)); |
| keywordMap.put("and", new Integer(SqlParserSymbols.KW_AND)); |
| keywordMap.put("anti", new Integer(SqlParserSymbols.KW_ANTI)); |
| keywordMap.put("api_version", new Integer(SqlParserSymbols.KW_API_VERSION)); |
| keywordMap.put("array", new Integer(SqlParserSymbols.KW_ARRAY)); |
| keywordMap.put("as", new Integer(SqlParserSymbols.KW_AS)); |
| keywordMap.put("asc", new Integer(SqlParserSymbols.KW_ASC)); |
| keywordMap.put("avro", new Integer(SqlParserSymbols.KW_AVRO)); |
| keywordMap.put("between", new Integer(SqlParserSymbols.KW_BETWEEN)); |
| keywordMap.put("bigint", new Integer(SqlParserSymbols.KW_BIGINT)); |
| keywordMap.put("binary", new Integer(SqlParserSymbols.KW_BINARY)); |
| keywordMap.put("block_size", new Integer(SqlParserSymbols.KW_BLOCKSIZE)); |
| keywordMap.put("boolean", new Integer(SqlParserSymbols.KW_BOOLEAN)); |
| keywordMap.put("by", new Integer(SqlParserSymbols.KW_BY)); |
| keywordMap.put("cached", new Integer(SqlParserSymbols.KW_CACHED)); |
| keywordMap.put("case", new Integer(SqlParserSymbols.KW_CASE)); |
| keywordMap.put("cascade", new Integer(SqlParserSymbols.KW_CASCADE)); |
| keywordMap.put("cast", new Integer(SqlParserSymbols.KW_CAST)); |
| keywordMap.put("change", new Integer(SqlParserSymbols.KW_CHANGE)); |
| keywordMap.put("char", new Integer(SqlParserSymbols.KW_CHAR)); |
| keywordMap.put("class", new Integer(SqlParserSymbols.KW_CLASS)); |
| keywordMap.put("close_fn", new Integer(SqlParserSymbols.KW_CLOSE_FN)); |
| keywordMap.put("column", new Integer(SqlParserSymbols.KW_COLUMN)); |
| keywordMap.put("columns", new Integer(SqlParserSymbols.KW_COLUMNS)); |
| keywordMap.put("comment", new Integer(SqlParserSymbols.KW_COMMENT)); |
| keywordMap.put("compression", new Integer(SqlParserSymbols.KW_COMPRESSION)); |
| keywordMap.put("compute", new Integer(SqlParserSymbols.KW_COMPUTE)); |
| keywordMap.put("create", new Integer(SqlParserSymbols.KW_CREATE)); |
| keywordMap.put("cross", new Integer(SqlParserSymbols.KW_CROSS)); |
| keywordMap.put("current", new Integer(SqlParserSymbols.KW_CURRENT)); |
| keywordMap.put("data", new Integer(SqlParserSymbols.KW_DATA)); |
| keywordMap.put("database", new Integer(SqlParserSymbols.KW_DATABASE)); |
| keywordMap.put("databases", new Integer(SqlParserSymbols.KW_DATABASES)); |
| keywordMap.put("date", new Integer(SqlParserSymbols.KW_DATE)); |
| keywordMap.put("datetime", new Integer(SqlParserSymbols.KW_DATETIME)); |
| keywordMap.put("decimal", new Integer(SqlParserSymbols.KW_DECIMAL)); |
| keywordMap.put("default", new Integer(SqlParserSymbols.KW_DEFAULT)); |
| keywordMap.put("delete", new Integer(SqlParserSymbols.KW_DELETE)); |
| keywordMap.put("delimited", new Integer(SqlParserSymbols.KW_DELIMITED)); |
| keywordMap.put("desc", new Integer(SqlParserSymbols.KW_DESC)); |
| keywordMap.put("describe", new Integer(SqlParserSymbols.KW_DESCRIBE)); |
| keywordMap.put("distinct", new Integer(SqlParserSymbols.KW_DISTINCT)); |
| keywordMap.put("div", new Integer(SqlParserSymbols.KW_DIV)); |
| keywordMap.put("double", new Integer(SqlParserSymbols.KW_DOUBLE)); |
| keywordMap.put("drop", new Integer(SqlParserSymbols.KW_DROP)); |
| keywordMap.put("else", new Integer(SqlParserSymbols.KW_ELSE)); |
| keywordMap.put("encoding", new Integer(SqlParserSymbols.KW_ENCODING)); |
| keywordMap.put("end", new Integer(SqlParserSymbols.KW_END)); |
| keywordMap.put("escaped", new Integer(SqlParserSymbols.KW_ESCAPED)); |
| keywordMap.put("exists", new Integer(SqlParserSymbols.KW_EXISTS)); |
| keywordMap.put("explain", new Integer(SqlParserSymbols.KW_EXPLAIN)); |
| keywordMap.put("extended", new Integer(SqlParserSymbols.KW_EXTENDED)); |
| keywordMap.put("external", new Integer(SqlParserSymbols.KW_EXTERNAL)); |
| keywordMap.put("false", new Integer(SqlParserSymbols.KW_FALSE)); |
| keywordMap.put("fields", new Integer(SqlParserSymbols.KW_FIELDS)); |
| keywordMap.put("fileformat", new Integer(SqlParserSymbols.KW_FILEFORMAT)); |
| keywordMap.put("files", new Integer(SqlParserSymbols.KW_FILES)); |
| keywordMap.put("finalize_fn", new Integer(SqlParserSymbols.KW_FINALIZE_FN)); |
| keywordMap.put("first", new Integer(SqlParserSymbols.KW_FIRST)); |
| keywordMap.put("float", new Integer(SqlParserSymbols.KW_FLOAT)); |
| keywordMap.put("following", new Integer(SqlParserSymbols.KW_FOLLOWING)); |
| keywordMap.put("for", new Integer(SqlParserSymbols.KW_FOR)); |
| keywordMap.put("format", new Integer(SqlParserSymbols.KW_FORMAT)); |
| keywordMap.put("formatted", new Integer(SqlParserSymbols.KW_FORMATTED)); |
| keywordMap.put("from", new Integer(SqlParserSymbols.KW_FROM)); |
| keywordMap.put("full", new Integer(SqlParserSymbols.KW_FULL)); |
| keywordMap.put("function", new Integer(SqlParserSymbols.KW_FUNCTION)); |
| keywordMap.put("functions", new Integer(SqlParserSymbols.KW_FUNCTIONS)); |
| keywordMap.put("grant", new Integer(SqlParserSymbols.KW_GRANT)); |
| keywordMap.put("group", new Integer(SqlParserSymbols.KW_GROUP)); |
| keywordMap.put("hash", new Integer(SqlParserSymbols.KW_HASH)); |
| keywordMap.put("having", new Integer(SqlParserSymbols.KW_HAVING)); |
| keywordMap.put("if", new Integer(SqlParserSymbols.KW_IF)); |
| keywordMap.put("ilike", new Integer(SqlParserSymbols.KW_ILIKE)); |
| keywordMap.put("ignore", new Integer(SqlParserSymbols.KW_IGNORE)); |
| keywordMap.put("in", new Integer(SqlParserSymbols.KW_IN)); |
| keywordMap.put("incremental", new Integer(SqlParserSymbols.KW_INCREMENTAL)); |
| keywordMap.put("init_fn", new Integer(SqlParserSymbols.KW_INIT_FN)); |
| keywordMap.put("inner", new Integer(SqlParserSymbols.KW_INNER)); |
| keywordMap.put("inpath", new Integer(SqlParserSymbols.KW_INPATH)); |
| keywordMap.put("insert", new Integer(SqlParserSymbols.KW_INSERT)); |
| keywordMap.put("int", new Integer(SqlParserSymbols.KW_INT)); |
| keywordMap.put("integer", new Integer(SqlParserSymbols.KW_INT)); |
| keywordMap.put("intermediate", new Integer(SqlParserSymbols.KW_INTERMEDIATE)); |
| keywordMap.put("interval", new Integer(SqlParserSymbols.KW_INTERVAL)); |
| keywordMap.put("into", new Integer(SqlParserSymbols.KW_INTO)); |
| keywordMap.put("invalidate", new Integer(SqlParserSymbols.KW_INVALIDATE)); |
| keywordMap.put("iregexp", new Integer(SqlParserSymbols.KW_IREGEXP)); |
| keywordMap.put("is", new Integer(SqlParserSymbols.KW_IS)); |
| keywordMap.put("join", new Integer(SqlParserSymbols.KW_JOIN)); |
| keywordMap.put("kudu", new Integer(SqlParserSymbols.KW_KUDU)); |
| keywordMap.put("last", new Integer(SqlParserSymbols.KW_LAST)); |
| keywordMap.put("left", new Integer(SqlParserSymbols.KW_LEFT)); |
| keywordMap.put("like", new Integer(SqlParserSymbols.KW_LIKE)); |
| keywordMap.put("limit", new Integer(SqlParserSymbols.KW_LIMIT)); |
| keywordMap.put("lines", new Integer(SqlParserSymbols.KW_LINES)); |
| keywordMap.put("load", new Integer(SqlParserSymbols.KW_LOAD)); |
| keywordMap.put("location", new Integer(SqlParserSymbols.KW_LOCATION)); |
| keywordMap.put("map", new Integer(SqlParserSymbols.KW_MAP)); |
| keywordMap.put("merge_fn", new Integer(SqlParserSymbols.KW_MERGE_FN)); |
| keywordMap.put("metadata", new Integer(SqlParserSymbols.KW_METADATA)); |
| keywordMap.put("not", new Integer(SqlParserSymbols.KW_NOT)); |
| keywordMap.put("null", new Integer(SqlParserSymbols.KW_NULL)); |
| keywordMap.put("nulls", new Integer(SqlParserSymbols.KW_NULLS)); |
| keywordMap.put("offset", new Integer(SqlParserSymbols.KW_OFFSET)); |
| keywordMap.put("on", new Integer(SqlParserSymbols.KW_ON)); |
| keywordMap.put("||", new Integer(SqlParserSymbols.KW_OR)); |
| keywordMap.put("or", new Integer(SqlParserSymbols.KW_OR)); |
| keywordMap.put("order", new Integer(SqlParserSymbols.KW_ORDER)); |
| keywordMap.put("outer", new Integer(SqlParserSymbols.KW_OUTER)); |
| keywordMap.put("over", new Integer(SqlParserSymbols.KW_OVER)); |
| keywordMap.put("overwrite", new Integer(SqlParserSymbols.KW_OVERWRITE)); |
| keywordMap.put("parquet", new Integer(SqlParserSymbols.KW_PARQUET)); |
| keywordMap.put("parquetfile", new Integer(SqlParserSymbols.KW_PARQUETFILE)); |
| keywordMap.put("partition", new Integer(SqlParserSymbols.KW_PARTITION)); |
| keywordMap.put("partitioned", new Integer(SqlParserSymbols.KW_PARTITIONED)); |
| keywordMap.put("partitions", new Integer(SqlParserSymbols.KW_PARTITIONS)); |
| keywordMap.put("preceding", new Integer(SqlParserSymbols.KW_PRECEDING)); |
| keywordMap.put("prepare_fn", new Integer(SqlParserSymbols.KW_PREPARE_FN)); |
| keywordMap.put("primary", new Integer(SqlParserSymbols.KW_PRIMARY)); |
| keywordMap.put("produced", new Integer(SqlParserSymbols.KW_PRODUCED)); |
| keywordMap.put("purge", new Integer(SqlParserSymbols.KW_PURGE)); |
| keywordMap.put("range", new Integer(SqlParserSymbols.KW_RANGE)); |
| keywordMap.put("rcfile", new Integer(SqlParserSymbols.KW_RCFILE)); |
| keywordMap.put("real", new Integer(SqlParserSymbols.KW_DOUBLE)); |
| keywordMap.put("recover", new Integer(SqlParserSymbols.KW_RECOVER)); |
| keywordMap.put("refresh", new Integer(SqlParserSymbols.KW_REFRESH)); |
| keywordMap.put("regexp", new Integer(SqlParserSymbols.KW_REGEXP)); |
| keywordMap.put("rename", new Integer(SqlParserSymbols.KW_RENAME)); |
| keywordMap.put("repeatable", new Integer(SqlParserSymbols.KW_REPEATABLE)); |
| keywordMap.put("replace", new Integer(SqlParserSymbols.KW_REPLACE)); |
| keywordMap.put("replication", new Integer(SqlParserSymbols.KW_REPLICATION)); |
| keywordMap.put("restrict", new Integer(SqlParserSymbols.KW_RESTRICT)); |
| keywordMap.put("returns", new Integer(SqlParserSymbols.KW_RETURNS)); |
| keywordMap.put("revoke", new Integer(SqlParserSymbols.KW_REVOKE)); |
| keywordMap.put("right", new Integer(SqlParserSymbols.KW_RIGHT)); |
| keywordMap.put("rlike", new Integer(SqlParserSymbols.KW_RLIKE)); |
| keywordMap.put("role", new Integer(SqlParserSymbols.KW_ROLE)); |
| keywordMap.put("roles", new Integer(SqlParserSymbols.KW_ROLES)); |
| keywordMap.put("row", new Integer(SqlParserSymbols.KW_ROW)); |
| keywordMap.put("rows", new Integer(SqlParserSymbols.KW_ROWS)); |
| keywordMap.put("schema", new Integer(SqlParserSymbols.KW_SCHEMA)); |
| keywordMap.put("schemas", new Integer(SqlParserSymbols.KW_SCHEMAS)); |
| keywordMap.put("select", new Integer(SqlParserSymbols.KW_SELECT)); |
| keywordMap.put("semi", new Integer(SqlParserSymbols.KW_SEMI)); |
| keywordMap.put("sequencefile", new Integer(SqlParserSymbols.KW_SEQUENCEFILE)); |
| keywordMap.put("serdeproperties", new Integer(SqlParserSymbols.KW_SERDEPROPERTIES)); |
| keywordMap.put("serialize_fn", new Integer(SqlParserSymbols.KW_SERIALIZE_FN)); |
| keywordMap.put("set", new Integer(SqlParserSymbols.KW_SET)); |
| keywordMap.put("show", new Integer(SqlParserSymbols.KW_SHOW)); |
| keywordMap.put("smallint", new Integer(SqlParserSymbols.KW_SMALLINT)); |
| keywordMap.put("sort", new Integer(SqlParserSymbols.KW_SORT)); |
| keywordMap.put("stats", new Integer(SqlParserSymbols.KW_STATS)); |
| keywordMap.put("stored", new Integer(SqlParserSymbols.KW_STORED)); |
| keywordMap.put("straight_join", new Integer(SqlParserSymbols.KW_STRAIGHT_JOIN)); |
| keywordMap.put("string", new Integer(SqlParserSymbols.KW_STRING)); |
| keywordMap.put("struct", new Integer(SqlParserSymbols.KW_STRUCT)); |
| keywordMap.put("symbol", new Integer(SqlParserSymbols.KW_SYMBOL)); |
| keywordMap.put("table", new Integer(SqlParserSymbols.KW_TABLE)); |
| keywordMap.put("tables", new Integer(SqlParserSymbols.KW_TABLES)); |
| keywordMap.put("tablesample", new Integer(SqlParserSymbols.KW_TABLESAMPLE)); |
| keywordMap.put("tblproperties", new Integer(SqlParserSymbols.KW_TBLPROPERTIES)); |
| keywordMap.put("terminated", new Integer(SqlParserSymbols.KW_TERMINATED)); |
| keywordMap.put("textfile", new Integer(SqlParserSymbols.KW_TEXTFILE)); |
| keywordMap.put("then", new Integer(SqlParserSymbols.KW_THEN)); |
| keywordMap.put("timestamp", new Integer(SqlParserSymbols.KW_TIMESTAMP)); |
| keywordMap.put("tinyint", new Integer(SqlParserSymbols.KW_TINYINT)); |
| keywordMap.put("to", new Integer(SqlParserSymbols.KW_TO)); |
| keywordMap.put("true", new Integer(SqlParserSymbols.KW_TRUE)); |
| keywordMap.put("truncate", new Integer(SqlParserSymbols.KW_TRUNCATE)); |
| keywordMap.put("unbounded", new Integer(SqlParserSymbols.KW_UNBOUNDED)); |
| keywordMap.put("uncached", new Integer(SqlParserSymbols.KW_UNCACHED)); |
| keywordMap.put("union", new Integer(SqlParserSymbols.KW_UNION)); |
| keywordMap.put("update", new Integer(SqlParserSymbols.KW_UPDATE)); |
| keywordMap.put("update_fn", new Integer(SqlParserSymbols.KW_UPDATE_FN)); |
| keywordMap.put("upsert", new Integer(SqlParserSymbols.KW_UPSERT)); |
| keywordMap.put("use", new Integer(SqlParserSymbols.KW_USE)); |
| keywordMap.put("using", new Integer(SqlParserSymbols.KW_USING)); |
| keywordMap.put("values", new Integer(SqlParserSymbols.KW_VALUES)); |
| keywordMap.put("varchar", new Integer(SqlParserSymbols.KW_VARCHAR)); |
| keywordMap.put("view", new Integer(SqlParserSymbols.KW_VIEW)); |
| keywordMap.put("when", new Integer(SqlParserSymbols.KW_WHEN)); |
| keywordMap.put("where", new Integer(SqlParserSymbols.KW_WHERE)); |
| keywordMap.put("with", new Integer(SqlParserSymbols.KW_WITH)); |
| } |
| |
| // map from token id to token description |
| public static final Map<Integer, String> tokenIdMap = |
| new HashMap<Integer, String>(); |
| static { |
| Iterator<Map.Entry<String, Integer>> it = keywordMap.entrySet().iterator(); |
| while (it.hasNext()) { |
| Map.Entry<String, Integer> pairs = (Map.Entry<String, Integer>) it.next(); |
| tokenIdMap.put(pairs.getValue(), pairs.getKey().toUpperCase()); |
| } |
| |
| // add non-keyword tokens |
| tokenIdMap.put(new Integer(SqlParserSymbols.IDENT), "IDENTIFIER"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.COLON), ":"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.SEMICOLON), ";"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.COMMA), "COMMA"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.BITNOT), "~"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.LPAREN), "("); |
| tokenIdMap.put(new Integer(SqlParserSymbols.RPAREN), ")"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.LBRACKET), "["); |
| tokenIdMap.put(new Integer(SqlParserSymbols.RBRACKET), "]"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.DECIMAL_LITERAL), "DECIMAL LITERAL"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.INTEGER_LITERAL), "INTEGER LITERAL"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.NOT), "!"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.LESSTHAN), "<"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.GREATERTHAN), ">"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.UNMATCHED_STRING_LITERAL), |
| "UNMATCHED STRING LITERAL"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.MOD), "%"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.ADD), "+"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.DIVIDE), "/"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.EQUAL), "="); |
| tokenIdMap.put(new Integer(SqlParserSymbols.STAR), "*"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.BITOR), "|"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.DOT), "."); |
| tokenIdMap.put(new Integer(SqlParserSymbols.DOTDOTDOT), "..."); |
| tokenIdMap.put(new Integer(SqlParserSymbols.STRING_LITERAL), "STRING LITERAL"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.EOF), "EOF"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.SUBTRACT), "-"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.BITAND), "&"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.UNEXPECTED_CHAR), "Unexpected character"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.BITXOR), "^"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.NUMERIC_OVERFLOW), "NUMERIC OVERFLOW"); |
| tokenIdMap.put(new Integer(SqlParserSymbols.EMPTY_IDENT), "EMPTY IDENTIFIER"); |
| } |
| |
| public static boolean isKeyword(Integer tokenId) { |
| String token = tokenIdMap.get(tokenId); |
| if (token == null) return false; |
| return keywordMap.containsKey(token.toLowerCase()); |
| } |
| |
| public static boolean isKeyword(String ident) { |
| return keywordMap.containsKey(ident.toLowerCase()); |
| } |
| |
| private Symbol newToken(int id, Object value) { |
| return new Symbol(id, yyline+1, yycolumn+1, value); |
| } |
| %} |
| |
| LineTerminator = \r|\n|\r\n |
| Whitespace = {LineTerminator} | [ \t\f] |
| |
| // Order of rules to resolve ambiguity: |
| // The rule for recognizing integer literals must come before the rule for |
| // double literals to, e.g., recognize "1234" as an integer literal. |
| // The rule for recognizing double literals must come before the rule for |
| // identifiers to, e.g., recognize "1e6" as a double literal. |
| IntegerLiteral = [:digit:][:digit:]* |
| FLit1 = [0-9]+ \. [0-9]* |
| FLit2 = \. [0-9]+ |
| FLit3 = [0-9]+ |
| Exponent = [eE] [+-]? [0-9]+ |
| DecimalLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}? |
| |
| IdentifierOrKw = [:digit:]*[:jletter:][:jletterdigit:]* | "&&" | "||" |
| QuotedIdentifier = \`(\\.|[^\\\`])*\` |
| SingleQuoteStringLiteral = \'(\\.|[^\\\'])*\' |
| DoubleQuoteStringLiteral = \"(\\.|[^\\\"])*\" |
| |
| EolHintBegin = "--" " "* "+" |
| CommentedHintBegin = "/*" " "* "+" |
| CommentedHintEnd = "*/" |
| |
| // Both types of plan hints must appear within a single line. |
| HintContent = " "* "+" [^\r\n]* |
| |
| Comment = {TraditionalComment} | {EndOfLineComment} |
| |
| // Match anything that has a comment end (*/) in it. |
| ContainsCommentEnd = [^]* "*/" [^]* |
| // Match anything that has a line terminator in it. |
| ContainsLineTerminator = [^]* {LineTerminator} [^]* |
| |
| // A traditional comment is anything that starts and ends like a comment and has neither a |
| // plan hint inside nor a CommentEnd (*/). |
| TraditionalComment = "/*" !({HintContent}|{ContainsCommentEnd}) "*/" |
| // Similar for a end-of-line comment. |
| EndOfLineComment = "--" !({HintContent}|{ContainsLineTerminator}) {LineTerminator}? |
| |
| // This additional state is needed because newlines signal the end of a end-of-line hint |
| // if one has been started earlier. Hence we need to discern between newlines within and |
| // outside of end-of-line hints. |
| %state EOLHINT |
| |
| %% |
| // Put '...' before '.' |
| "..." { return newToken(SqlParserSymbols.DOTDOTDOT, null); } |
| |
| // single-character tokens |
| ":" { return newToken(SqlParserSymbols.COLON, null); } |
| ";" { return newToken(SqlParserSymbols.SEMICOLON, null); } |
| "," { return newToken(SqlParserSymbols.COMMA, null); } |
| "." { return newToken(SqlParserSymbols.DOT, null); } |
| "*" { return newToken(SqlParserSymbols.STAR, null); } |
| "(" { return newToken(SqlParserSymbols.LPAREN, null); } |
| ")" { return newToken(SqlParserSymbols.RPAREN, null); } |
| "[" { return newToken(SqlParserSymbols.LBRACKET, null); } |
| "]" { return newToken(SqlParserSymbols.RBRACKET, null); } |
| "/" { return newToken(SqlParserSymbols.DIVIDE, null); } |
| "%" { return newToken(SqlParserSymbols.MOD, null); } |
| "+" { return newToken(SqlParserSymbols.ADD, null); } |
| "-" { return newToken(SqlParserSymbols.SUBTRACT, null); } |
| "&" { return newToken(SqlParserSymbols.BITAND, null); } |
| "|" { return newToken(SqlParserSymbols.BITOR, null); } |
| "^" { return newToken(SqlParserSymbols.BITXOR, null); } |
| "~" { return newToken(SqlParserSymbols.BITNOT, null); } |
| "=" { return newToken(SqlParserSymbols.EQUAL, null); } |
| "!" { return newToken(SqlParserSymbols.NOT, null); } |
| "<" { return newToken(SqlParserSymbols.LESSTHAN, null); } |
| ">" { return newToken(SqlParserSymbols.GREATERTHAN, null); } |
| "\"" { return newToken(SqlParserSymbols.UNMATCHED_STRING_LITERAL, null); } |
| "'" { return newToken(SqlParserSymbols.UNMATCHED_STRING_LITERAL, null); } |
| "`" { return newToken(SqlParserSymbols.UNMATCHED_STRING_LITERAL, null); } |
| |
| // double-character tokens |
| "!=" { return newToken(SqlParserSymbols.NOTEQUAL, null); } |
| |
| // The rules for IntegerLiteral and DecimalLiteral are the same, but it is useful |
| // to distinguish them, e.g., so the Parser can use integer literals without analysis. |
| {IntegerLiteral} { |
| BigDecimal val = null; |
| try { |
| val = new BigDecimal(yytext()); |
| } catch (NumberFormatException e) { |
| return newToken(SqlParserSymbols.NUMERIC_OVERFLOW, yytext()); |
| } |
| return newToken(SqlParserSymbols.INTEGER_LITERAL, val); |
| } |
| |
| {DecimalLiteral} { |
| BigDecimal val = null; |
| try { |
| val = new BigDecimal(yytext()); |
| } catch (NumberFormatException e) { |
| return newToken(SqlParserSymbols.NUMERIC_OVERFLOW, yytext()); |
| } |
| return newToken(SqlParserSymbols.DECIMAL_LITERAL, val); |
| } |
| |
| {QuotedIdentifier} { |
| // Remove the quotes and trim whitespace. |
| String trimmedIdent = yytext().substring(1, yytext().length() - 1).trim(); |
| if (trimmedIdent.isEmpty()) { |
| return newToken(SqlParserSymbols.EMPTY_IDENT, yytext()); |
| } |
| return newToken(SqlParserSymbols.IDENT, trimmedIdent); |
| } |
| |
| {IdentifierOrKw} { |
| String text = yytext(); |
| Integer kw_id = keywordMap.get(text.toLowerCase()); |
| if (kw_id != null) { |
| return newToken(kw_id.intValue(), text); |
| } else { |
| return newToken(SqlParserSymbols.IDENT, text); |
| } |
| } |
| |
| {SingleQuoteStringLiteral} { |
| return newToken(SqlParserSymbols.STRING_LITERAL, yytext().substring(1, yytext().length()-1)); |
| } |
| |
| {DoubleQuoteStringLiteral} { |
| return newToken(SqlParserSymbols.STRING_LITERAL, yytext().substring(1, yytext().length()-1)); |
| } |
| |
| {CommentedHintBegin} { |
| return newToken(SqlParserSymbols.COMMENTED_PLAN_HINT_START, null); |
| } |
| |
| {CommentedHintEnd} { |
| return newToken(SqlParserSymbols.COMMENTED_PLAN_HINT_END, null); |
| } |
| |
| {EolHintBegin} { |
| yybegin(EOLHINT); |
| return newToken(SqlParserSymbols.COMMENTED_PLAN_HINT_START, null); |
| } |
| |
| <EOLHINT> {LineTerminator} { |
| yybegin(YYINITIAL); |
| return newToken(SqlParserSymbols.COMMENTED_PLAN_HINT_END, null); |
| } |
| |
| {Comment} { /* ignore */ } |
| {Whitespace} { /* ignore */ } |
| |
| // Provide a default error token when nothing matches, otherwise the user sees |
| // "Error: could not match input" which is confusing. |
| [^] { return newToken(SqlParserSymbols.UNEXPECTED_CHAR, yytext()); } |