blob: 3d7c7af44ca4186209aaeb86c56df4ced77f349f [file] [log] [blame]
/**
* 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.tajo.engine.parser;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tajo.algebra.*;
import org.apache.tajo.common.TajoDataTypes;
import org.apache.tajo.engine.parser.HiveQLParser.TableAllColumnsContext;
import java.math.BigInteger;
import java.util.*;
public class HiveQLAnalyzer extends HiveQLParserBaseVisitor<Expr> {
private static final Log LOG = LogFactory.getLog(HiveQLAnalyzer.class.getName());
private HiveQLParser parser;
public Expr parse(String sql) {
HiveQLLexer lexer = new HiveQLLexer(new ANTLRNoCaseStringStream(sql));
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new HiveQLParser(tokens);
parser.setBuildParseTree(true);
HiveQLParser.StatementContext context;
try {
context = parser.statement();
} catch (SQLParseError e) {
throw new SQLSyntaxError(e);
}
return visit(context);
}
@Override
public Expr visitStatement(HiveQLParser.StatementContext ctx) {
return visitExecStatement(ctx.execStatement());
}
@Override
public Expr visitQueryStatement(HiveQLParser.QueryStatementContext ctx) {
Expr current = null;
if (ctx.body != null) {
current = visitBody(ctx.body(0));
}
if (ctx.regular_body() != null) {
current = visitRegular_body(ctx.regular_body());
}
return current;
}
@Override
public Expr visitBody(HiveQLParser.BodyContext ctx) {
Expr current = null;
Insert insert = null;
Projection select = null;
if (ctx.insertClause() != null) {
insert = visitInsertClause(ctx.insertClause());
}
if (ctx.selectClause() != null) {
select = (Projection) visitSelectClause(ctx.selectClause());
if (ctx.selectClause().KW_DISTINCT() != null) {
select.setDistinct();
}
}
for (int i = 0; i < ctx.getParent().getChildCount(); i++) {
if (ctx.getParent().getChild(i) instanceof HiveQLParser.FromClauseContext) {
HiveQLParser.FromClauseContext fromClauseContext = (HiveQLParser.FromClauseContext) ctx.getParent().getChild(i);
Expr from = visitFromClause(fromClauseContext);
current = from;
}
}
if (ctx.whereClause() != null) {
Selection where = new Selection(visitWhereClause(ctx.whereClause()));
where.setChild(current);
current = where;
}
if (ctx.groupByClause() != null) {
Aggregation aggregation = visitGroupByClause(ctx.groupByClause());
aggregation.setChild(current);
current = aggregation;
if (ctx.havingClause() != null) {
Expr havingCondition = visitHavingClause(ctx.havingClause());
Having having = new Having(havingCondition);
having.setChild(current);
current = having;
}
}
if (ctx.orderByClause() != null) {
Sort sort = visitOrderByClause(ctx.orderByClause());
sort.setChild(current);
current = sort;
}
if (ctx.clusterByClause() != null) {
visitClusterByClause(ctx.clusterByClause());
}
if (ctx.distributeByClause() != null) {
visitDistributeByClause(ctx.distributeByClause());
}
if (ctx.sortByClause() != null) {
Sort sort = visitSortByClause(ctx.sortByClause());
sort.setChild(current);
current = sort;
}
if (ctx.window_clause() != null) {
Expr window = visitWindow_clause(ctx.window_clause());
}
if (ctx.limitClause() != null) {
Limit limit = visitLimitClause(ctx.limitClause());
limit.setChild(current);
current = limit;
}
Projection projection = new Projection();
projection.setNamedExprs(select.getNamedExprs());
if (current != null)
projection.setChild(current);
if (select.isDistinct())
projection.setDistinct();
if (insert != null) {
insert.setSubQuery(projection);
current = insert;
} else {
current = projection;
}
return current;
}
@Override
public Expr visitRegular_body(HiveQLParser.Regular_bodyContext ctx) {
Expr current = null;
Insert insert = null;
if (ctx.selectStatement() != null) {
current = visitSelectStatement(ctx.selectStatement());
} else {
Projection select = null;
if (ctx.insertClause() != null) {
insert = visitInsertClause(ctx.insertClause());
}
if (ctx.selectClause() != null) {
select = (Projection) visitSelectClause(ctx.selectClause());
if (ctx.selectClause().KW_DISTINCT() != null) {
select.setDistinct();
}
}
if (ctx.fromClause() != null) {
Expr from = visitFromClause(ctx.fromClause());
current = from;
}
if (ctx.whereClause() != null) {
Selection where = new Selection(visitWhereClause(ctx.whereClause()));
where.setChild(current);
current = where;
}
if (ctx.groupByClause() != null) {
Aggregation aggregation = visitGroupByClause(ctx.groupByClause());
aggregation.setChild(current);
current = aggregation;
if (ctx.havingClause() != null) {
Expr havingCondition = visitHavingClause(ctx.havingClause());
Having having = new Having(havingCondition);
having.setChild(current);
current = having;
}
}
if (ctx.orderByClause() != null) {
Sort sort = visitOrderByClause(ctx.orderByClause());
sort.setChild(current);
current = sort;
}
if (ctx.clusterByClause() != null) {
visitClusterByClause(ctx.clusterByClause());
}
if (ctx.distributeByClause() != null) {
visitDistributeByClause(ctx.distributeByClause());
}
if (ctx.sortByClause() != null) {
Sort sort = visitSortByClause(ctx.sortByClause());
sort.setChild(current);
current = sort;
}
if (ctx.window_clause() != null) {
Expr window = visitWindow_clause(ctx.window_clause());
}
if (ctx.limitClause() != null) {
Limit limit = visitLimitClause(ctx.limitClause());
limit.setChild(current);
current = limit;
}
Projection projection = new Projection();
projection.setNamedExprs(select.getNamedExprs());
if (current != null)
projection.setChild(current);
if (select.isDistinct())
projection.setDistinct();
if (insert != null) {
insert.setSubQuery(projection);
current = insert;
} else {
current = projection;
}
}
return current;
}
/**
* This method implemented for parsing union all clause.
*
* @param ctx
* @return
*/
@Override
public Expr visitQueryStatementExpression(HiveQLParser.QueryStatementExpressionContext ctx) {
Expr left = null, right = null, current = null;
if (ctx.queryStatement() != null) {
if (ctx.queryStatement().size() == 1)
return visitQueryStatement(ctx.queryStatement(0));
for (int i = 0; i < ctx.queryStatement().size(); i++) {
if (i == 0)
current = visitQueryStatement(ctx.queryStatement(i));
else
left = current;
if (i > 0) {
right = visitQueryStatement(ctx.queryStatement(i));
current = new SetOperation(OpType.Union, left, right, false);
}
}
}
return current;
}
@Override
public Expr visitSelectStatement(HiveQLParser.SelectStatementContext ctx) {
Expr current = null;
Projection select = (Projection) visitSelectClause(ctx.selectClause());
if (ctx.selectClause().KW_DISTINCT() != null) {
select.setDistinct();
}
Expr from = visitFromClause(ctx.fromClause());
current = from;
if (ctx.whereClause() != null) {
Selection where = new Selection(visitWhereClause(ctx.whereClause()));
where.setChild(current);
current = where;
}
if (ctx.groupByClause() != null) {
Aggregation aggregation = visitGroupByClause(ctx.groupByClause());
aggregation.setChild(current);
current = aggregation;
if (ctx.havingClause() != null) {
Expr havingCondition = visitHavingClause(ctx.havingClause());
Having having = new Having(havingCondition);
having.setChild(current);
current = having;
}
}
if (ctx.orderByClause() != null) {
Sort sort = visitOrderByClause(ctx.orderByClause());
sort.setChild(current);
current = sort;
}
if (ctx.clusterByClause() != null) {
visitClusterByClause(ctx.clusterByClause());
}
if (ctx.distributeByClause() != null) {
visitDistributeByClause(ctx.distributeByClause());
}
if (ctx.sortByClause() != null) {
Sort sort = visitSortByClause(ctx.sortByClause());
sort.setChild(current);
current = sort;
}
if (ctx.window_clause() != null) {
Expr window = visitWindow_clause(ctx.window_clause());
}
if (ctx.limitClause() != null) {
Limit limit = visitLimitClause(ctx.limitClause());
limit.setChild(current);
current = limit;
}
Projection projection = new Projection();
projection.setNamedExprs(select.getNamedExprs());
if (current != null)
projection.setChild(current);
if (select.isDistinct())
projection.setDistinct();
current = projection;
return current;
}
@Override
public Expr visitFromClause(HiveQLParser.FromClauseContext ctx) {
return visitJoinSource(ctx.joinSource());
}
@Override
public Expr visitJoinSource(HiveQLParser.JoinSourceContext ctx) {
Expr[] relations = null;
RelationList relationList = null;
if (ctx.fromSource() != null) {
int fromCount = ctx.fromSource().size();
int uniqueJoinCount = ctx.uniqueJoinSource().size();
relations = new Expr[1];
Join current = null, parent = null;
JoinType type = null;
Expr left = null, right = null, condition = null;
if (fromCount == 1) {
relations[0] = visitFromSource(ctx.fromSource(0));
} else {
left = visitFromSource((HiveQLParser.FromSourceContext) ctx.getChild(0));
for (int i = 1; i < ctx.getChildCount(); i++) {
type = null;
right = null;
condition = null;
if (ctx.getChild(i) instanceof HiveQLParser.JoinTokenContext) {
type = getJoinType((HiveQLParser.JoinTokenContext) ctx.getChild(i));
if (i > 1)
left = parent;
if (i + 1 < ctx.getChildCount() && ctx.getChild(i + 1) instanceof HiveQLParser.FromSourceContext) {
right = visitFromSource((HiveQLParser.FromSourceContext) ctx.getChild(i + 1));
}
if (i + 3 < ctx.getChildCount() && ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) {
condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3));
}
if (type != null) {
current = new Join(type);
current.setLeft(left);
current.setRight(right);
if (condition != null)
current.setQual(condition);
parent = current;
}
}
}
relations[0] = current;
}
//TODO: implement unique join.
relationList = new RelationList(relations);
}
return relationList;
}
public JoinType getJoinType(HiveQLParser.JoinTokenContext context) {
JoinType type = JoinType.INNER;
if (context.KW_INNER() != null) {
type = JoinType.INNER;
}
if (context.KW_LEFT() != null && context.KW_OUTER() != null) {
type = JoinType.LEFT_OUTER;
}
if (context.KW_RIGHT() != null && context.KW_OUTER() != null) {
type = JoinType.RIGHT_OUTER;
}
if (context.KW_CROSS() != null) {
type = JoinType.CROSS;
}
if (context.KW_FULL() != null) {
type = JoinType.FULL_OUTER;
}
if (context.KW_SEMI() != null) {
type = null;
}
return type;
}
@Override
public Expr visitFromSource(HiveQLParser.FromSourceContext ctx) {
Expr current = null;
if (ctx.Identifier() != null && ctx.LPAREN() != null) {
current = new LiteralValue(ctx.Identifier().getText(), LiteralValue.LiteralType.String);
}
if (ctx.tableSource() != null) {
current = visitTableSource(ctx.tableSource());
}
if (ctx.subQuerySource() != null) {
current = visitSubQuerySource(ctx.subQuerySource());
String tableAlias = "";
for (int i = 0; i < ctx.subQuerySource().getChildCount(); i++) {
if (ctx.subQuerySource().getChild(i) instanceof HiveQLParser.IdentifierContext) {
tableAlias = (ctx.subQuerySource().getChild(i)).getText();
}
}
TablePrimarySubQuery subQuery = new TablePrimarySubQuery(tableAlias, current);
current = subQuery;
}
// TODO: implement lateralView
return current;
}
@Override
public Expr visitSubQuerySource(HiveQLParser.SubQuerySourceContext ctx) {
Expr current = visitQueryStatementExpression(ctx.queryStatementExpression());
return current;
}
@Override
public Expr visitTableSource(HiveQLParser.TableSourceContext ctx) {
String tableName = "", alias = "";
if (ctx.tableName() != null)
tableName = ctx.tableName().getText();
if (ctx.alias != null) {
alias = ctx.alias.getText();
for (String token : HiveQLParser.tokenNames) {
if (token.replaceAll("'", "").equalsIgnoreCase(alias))
alias = "";
}
}
Relation relation = new Relation(tableName);
if (!alias.equals(""))
relation.setAlias(alias);
return relation;
}
@Override
public Expr visitSelectList(HiveQLParser.SelectListContext ctx) {
Expr current = null;
Projection projection = new Projection();
NamedExpr[] targets = new NamedExpr[ctx.selectItem().size()];
for (int i = 0; i < targets.length; i++) {
targets[i] = visitSelectItem(ctx.selectItem(i));
}
projection.setNamedExprs(targets);
current = projection;
return current;
}
@Override
public NamedExpr visitSelectItem(HiveQLParser.SelectItemContext ctx) {
NamedExpr target = null;
if (ctx.selectExpression() != null) {
target = new NamedExpr(visitSelectExpression(ctx.selectExpression()));
} else if (ctx.window_specification() != null) {
// TODO: if there is a window specification clause, we should handle it properly.
}
if (ctx.identifier().size() > 0 && target != null) {
target.setAlias(ctx.identifier(0).getText());
}
return target;
}
@Override
public Expr visitSelectExpression(HiveQLParser.SelectExpressionContext ctx) {
Expr current = null;
if (ctx.tableAllColumns() != null) {
current = visitTableAllColumns(ctx.tableAllColumns());
} else {
if (ctx.expression() != null) {
current = visitExpression(ctx.expression());
}
}
return current;
}
@Override
public Expr visitTableAllColumns(TableAllColumnsContext ctx) {
QualifiedAsteriskExpr target = new QualifiedAsteriskExpr();
if (ctx.tableName() != null) {
target.setQualifier(ctx.tableName().getText());
}
return target;
}
@Override
public Expr visitExpression(HiveQLParser.ExpressionContext ctx) {
Expr current = visitPrecedenceOrExpression(ctx.precedenceOrExpression());
return current;
}
@Override
public Expr visitPrecedenceOrExpression(HiveQLParser.PrecedenceOrExpressionContext ctx) {
Expr current = null, left = null, right = null;
for (int i = 0; i < ctx.precedenceAndExpression().size(); i++) {
if (i == 0) {
left = visitPrecedenceAndExpression(ctx.precedenceAndExpression(i));
current = left;
} else {
left = current;
right = visitPrecedenceAndExpression(ctx.precedenceAndExpression(i));
current = new BinaryOperator(OpType.Or, left, right);
}
}
return current;
}
/**
* This method parse AND expressions at WHERE clause.
* And this convert 'x BETWEEN y AND z' expression into 'x >= y AND x <= z' expression
* because Tajo doesn't provide 'BETWEEN' expression.
*
* @param ctx
* @return
*/
@Override
public Expr visitPrecedenceAndExpression(HiveQLParser.PrecedenceAndExpressionContext ctx) {
Expr current = null, left = null, right = null;
for (int i = 0; i < ctx.precedenceNotExpression().size(); i++) {
Expr min = null, max = null;
if (ctx.precedenceNotExpression(i).precedenceEqualExpression() != null) {
HiveQLParser.PrecedenceEqualExpressionContext expressionContext = ctx.precedenceNotExpression(i)
.precedenceEqualExpression();
if (expressionContext.KW_BETWEEN() != null) {
if (expressionContext.min != null) {
min = visitPrecedenceBitwiseOrExpression(expressionContext.min);
}
if (expressionContext.max != null) {
max = visitPrecedenceBitwiseOrExpression(expressionContext.max);
}
}
}
if (min != null && max != null) {
left = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i));
if (left != null) {
if (i == 0) {
BinaryOperator minOperator = new BinaryOperator(OpType.GreaterThanOrEquals, left, min);
BinaryOperator maxOperator = new BinaryOperator(OpType.LessThanOrEquals, left, max);
current = new BinaryOperator(OpType.And, minOperator, maxOperator);
} else {
BinaryOperator minOperator = new BinaryOperator(OpType.GreaterThanOrEquals, left, min);
current = new BinaryOperator(OpType.And, current, minOperator);
BinaryOperator maxOperator = new BinaryOperator(OpType.LessThanOrEquals, left, max);
current = new BinaryOperator(OpType.And, current, maxOperator);
}
}
} else {
if (i == 0) {
left = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i));
current = left;
} else {
left = current;
right = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i));
current = new BinaryOperator(OpType.And, left, right);
}
}
}
return current;
}
@Override
public Expr visitPrecedenceNotExpression(HiveQLParser.PrecedenceNotExpressionContext ctx) {
HiveQLParser.PrecedenceEqualExpressionContext expressionContext = ctx.precedenceEqualExpression();
Expr current = visitPrecedenceEqualExpression(expressionContext);
return current;
}
/**
* This method parse operators for equals expressions as follows:
* =, <>, !=, >=, >, <=, <, IN, NOT IN, LIKE, REGEXP, RLIKE
* <p/>
* In this case, this make RuntimeException>
*
* @param ctx
* @return
*/
@Override
public Expr visitPrecedenceEqualExpression(HiveQLParser.PrecedenceEqualExpressionContext ctx) {
Expr current = null, left = null, right = null, min = null, max = null;
OpType type = null;
boolean isNot = false, isIn = false;
for (int i = 0; i < ctx.getChildCount(); i++) {
if (ctx.getChild(i) instanceof HiveQLParser.PrecedenceBitwiseOrExpressionContext) {
if (i == 0) {
left = visitPrecedenceBitwiseOrExpression((HiveQLParser.PrecedenceBitwiseOrExpressionContext) ctx.getChild(i));
} else {
right = visitPrecedenceBitwiseOrExpression((HiveQLParser.PrecedenceBitwiseOrExpressionContext) ctx.getChild(i));
}
} else if (ctx.getChild(i) instanceof HiveQLParser.ExpressionsContext) {
right = visitExpressions((HiveQLParser.ExpressionsContext) ctx.getChild(i));
} else if (ctx.getChild(i) instanceof TerminalNodeImpl) {
int symbolType = ((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType();
switch (symbolType) {
case HiveQLLexer.KW_NOT:
isNot = true;
break;
case HiveQLLexer.KW_IN:
isIn = true;
break;
default:
break;
}
} else if (ctx.getChild(i) instanceof HiveQLParser.PrecedenceEqualOperatorContext
|| ctx.getChild(i) instanceof HiveQLParser.PrecedenceEqualNegatableOperatorContext) {
String keyword = ctx.getChild(i).getText().toUpperCase();
if (keyword.equals(">")) {
type = OpType.GreaterThan;
} else if (keyword.equals("<=>")) {
throw new RuntimeException("Unexpected operator : <=>");
} else if (keyword.equals("=")) {
type = OpType.Equals;
} else if (keyword.equals("<=")) {
type = OpType.LessThanOrEquals;
} else if (keyword.equals("<")) {
type = OpType.LessThan;
} else if (keyword.equals(">=")) {
type = OpType.GreaterThanOrEquals;
} else if (keyword.equals("<>")) {
type = OpType.NotEquals;
} else if (keyword.equals("!=")) {
type = OpType.NotEquals;
} else if (keyword.equals("REGEXP")) {
type = OpType.Regexp;
} else if (keyword.equals("RLIKE")) {
type = OpType.Regexp;
} else if (keyword.equals("LIKE")) {
type = OpType.LikePredicate;
}
}
}
if (type != null && right != null) {
if (type.equals(OpType.LikePredicate)) {
PatternMatchPredicate like = new PatternMatchPredicate(OpType.LikePredicate,
isNot, left, right);
current = like;
} else if (type.equals(OpType.Regexp)) {
PatternMatchPredicate regex = new PatternMatchPredicate(OpType.Regexp, isNot, left, right);
current = regex;
} else {
BinaryOperator binaryOperator = new BinaryOperator(type, left, right);
current = binaryOperator;
}
} else if (isIn) {
InPredicate inPredicate = new InPredicate(left, right, isNot);
current = inPredicate;
} else {
current = left;
}
return current;
}
@Override
public ValueListExpr visitExpressions(HiveQLParser.ExpressionsContext ctx) {
int size = ctx.expression().size();
Expr[] exprs = new Expr[size];
for (int i = 0; i < size; i++) {
exprs[i] = visitExpression(ctx.expression(i));
}
return new ValueListExpr(exprs);
}
@Override
public Expr visitPrecedenceBitwiseOrExpression(HiveQLParser.PrecedenceBitwiseOrExpressionContext ctx) {
int expressionCount = ctx.precedenceAmpersandExpression().size();
Expr current = null, left = null, right = null, parentLeft, parentRight;
OpType type = null, parentType = null;
for (int i = 0; i < expressionCount; i += 2) {
int operatorIndex = (i == 0) ? 0 : i - 1;
if (ctx.precedenceBitwiseOrOperator(operatorIndex) != null) {
type = getPrecedenceBitwiseOrOperator(ctx.precedenceBitwiseOrOperator(operatorIndex));
}
if (i == 0) {
left = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i));
if (ctx.precedenceAmpersandExpression(i + 1) != null)
right = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i + 1));
} else {
parentType = getPrecedenceBitwiseOrOperator((ctx.precedenceBitwiseOrOperator(operatorIndex - 1)));
parentLeft = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i - 2));
parentRight = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i - 1));
left = new BinaryOperator(parentType, parentLeft, parentRight);
right = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i));
}
if (right != null) {
current = new BinaryOperator(type, left, right);
} else {
current = left;
}
}
return current;
}
public OpType getPrecedenceBitwiseOrOperator(HiveQLParser.PrecedenceBitwiseOrOperatorContext ctx) {
OpType type = null;
// TODO: It needs to consider how to support.
return type;
}
@Override
public Expr visitPrecedenceAmpersandExpression(HiveQLParser.PrecedenceAmpersandExpressionContext ctx) {
int expressionCount = ctx.precedencePlusExpression().size();
Expr current = null, left = null, right = null, parentLeft, parentRight;
OpType type = null, parentType = null;
for (int i = 0; i < expressionCount; i += 2) {
int operatorIndex = (i == 0) ? 0 : i - 1;
if (ctx.precedenceAmpersandOperator(operatorIndex) != null) {
type = getPrecedenceAmpersandOperator(ctx.precedenceAmpersandOperator(operatorIndex));
}
if (i == 0) {
left = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i));
if (ctx.precedencePlusExpression(i + 1) != null)
right = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i + 1));
} else {
parentType = getPrecedenceAmpersandOperator((ctx.precedenceAmpersandOperator(operatorIndex - 1)));
parentLeft = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i - 2));
parentRight = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i - 1));
left = new BinaryOperator(parentType, parentLeft, parentRight);
right = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i));
}
if (right != null) {
current = new BinaryOperator(type, left, right);
} else {
current = left;
}
}
return current;
}
public OpType getPrecedenceAmpersandOperator(HiveQLParser.PrecedenceAmpersandOperatorContext ctx) {
OpType type = null;
// TODO: It needs to consider how to support.
return type;
}
@Override
public Expr visitPrecedencePlusExpression(HiveQLParser.PrecedencePlusExpressionContext ctx) {
int expressionCount = ctx.precedenceStarExpression().size();
Expr current = null, left = null, right = null, parentLeft, parentRight;
OpType type = null, parentType = null;
for (int i = 0; i < expressionCount; i += 2) {
int operatorIndex = (i == 0) ? 0 : i - 1;
if (ctx.precedencePlusOperator(operatorIndex) != null) {
type = getPrecedencePlusOperator(ctx.precedencePlusOperator(operatorIndex));
}
if (i == 0) {
left = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i));
if (ctx.precedenceStarExpression(i + 1) != null)
right = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i + 1));
} else {
parentType = getPrecedencePlusOperator((ctx.precedencePlusOperator(operatorIndex - 1)));
parentLeft = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i - 2));
parentRight = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i - 1));
left = new BinaryOperator(parentType, parentLeft, parentRight);
right = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i));
}
if (right != null) {
current = new BinaryOperator(type, left, right);
} else {
current = left;
}
}
return current;
}
public OpType getPrecedencePlusOperator(HiveQLParser.PrecedencePlusOperatorContext ctx) {
OpType type = null;
if (ctx.MINUS() != null) {
type = OpType.Minus;
} else if (ctx.PLUS() != null) {
type = OpType.Plus;
}
return type;
}
@Override
public Expr visitPrecedenceStarExpression(HiveQLParser.PrecedenceStarExpressionContext ctx) {
int expressionCount = ctx.precedenceBitwiseXorExpression().size();
Expr current = null, left = null, right = null, parentLeft, parentRight;
OpType type = null, parentType = null;
for (int i = 0; i < expressionCount; i += 2) {
int operatorIndex = (i == 0) ? 0 : i - 1;
if (ctx.precedenceStarOperator(operatorIndex) != null) {
type = getPrecedenceStarOperator(ctx.precedenceStarOperator(operatorIndex));
}
if (i == 0) {
left = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i));
if (ctx.precedenceBitwiseXorExpression(i + 1) != null)
right = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i + 1));
} else {
parentType = getPrecedenceStarOperator((ctx.precedenceStarOperator(operatorIndex - 1)));
parentLeft = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i - 2));
parentRight = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i - 1));
left = new BinaryOperator(parentType, parentLeft, parentRight);
right = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i));
}
if (right != null) {
current = new BinaryOperator(type, left, right);
} else {
current = left;
}
}
return current;
}
public OpType getPrecedenceStarOperator(HiveQLParser.PrecedenceStarOperatorContext ctx) {
OpType type = null;
if (ctx.DIV() != null) {
type = OpType.Divide;
} else if (ctx.DIVIDE() != null) {
type = OpType.Divide;
} else if (ctx.MOD() != null) {
type = OpType.Modular;
} else if (ctx.STAR() != null) {
type = OpType.Multiply;
}
return type;
}
@Override
public Expr visitPrecedenceBitwiseXorExpression(HiveQLParser.PrecedenceBitwiseXorExpressionContext ctx) {
int expressionCount = ctx.precedenceUnarySuffixExpression().size();
Expr current = null, left = null, right = null, parentLeft, parentRight;
OpType type = null, parentType = null;
for (int i = 0; i < expressionCount; i += 2) {
int operatorIndex = (i == 0) ? 0 : i - 1;
if (ctx.precedenceBitwiseXorOperator(operatorIndex) != null) {
type = getPrecedenceBitwiseXorOperator(ctx.precedenceBitwiseXorOperator(operatorIndex));
}
if (i == 0) {
left = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i));
if (ctx.precedenceUnarySuffixExpression(i + 1) != null)
right = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i + 1));
} else {
parentType = getPrecedenceBitwiseXorOperator((ctx.precedenceBitwiseXorOperator(operatorIndex - 1)));
parentLeft = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i - 2));
parentRight = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i - 1));
left = new BinaryOperator(parentType, parentLeft, parentRight);
right = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i));
}
if (right != null) {
current = new BinaryOperator(type, left, right);
} else {
current = left;
}
}
return current;
}
public OpType getPrecedenceBitwiseXorOperator(HiveQLParser.PrecedenceBitwiseXorOperatorContext ctx) {
OpType type = null;
// TODO: It needs to consider how to support.
return type;
}
@Override
public Expr visitPrecedenceUnarySuffixExpression(HiveQLParser.PrecedenceUnarySuffixExpressionContext ctx) {
Expr current = visitPrecedenceUnaryPrefixExpression(ctx.precedenceUnaryPrefixExpression());
if (ctx.nullCondition() != null) {
boolean isNot = ctx.nullCondition().KW_NOT() == null ? false : true;
IsNullPredicate isNullPredicate = new IsNullPredicate(isNot, (ColumnReferenceExpr) current);
current = isNullPredicate;
}
return current;
}
@Override
public Expr visitPrecedenceUnaryPrefixExpression(HiveQLParser.PrecedenceUnaryPrefixExpressionContext ctx) {
Expr current = visitPrecedenceFieldExpression(ctx.precedenceFieldExpression());
return current;
}
@Override
public Expr visitNullCondition(HiveQLParser.NullConditionContext ctx) {
return new NullLiteral();
}
@Override
public Expr visitPrecedenceFieldExpression(HiveQLParser.PrecedenceFieldExpressionContext ctx) {
Expr current = visitAtomExpression(ctx.atomExpression());
if (ctx.DOT().size() > 0) {
ColumnReferenceExpr column = new ColumnReferenceExpr(ctx.identifier(0).getText());
ColumnReferenceExpr table = (ColumnReferenceExpr) current;
column.setQualifier(table.getName());
current = column;
}
return current;
}
@Override
public Expr visitAtomExpression(HiveQLParser.AtomExpressionContext ctx) {
Expr current = null;
if (ctx.KW_NULL() != null) {
current = new NullLiteral();
}
if (ctx.constant() != null) {
current = visitConstant(ctx.constant());
}
if (ctx.function() != null) {
current = visitFunction(ctx.function());
}
if (ctx.castExpression() != null) {
current = visitCastExpression(ctx.castExpression());
}
if (ctx.caseExpression() != null) {
current = visitCaseExpression(ctx.caseExpression());
}
if (ctx.whenExpression() != null) {
current = visitWhenExpression(ctx.whenExpression());
}
if (ctx.tableOrColumn() != null) {
current = visitTableOrColumn(ctx.tableOrColumn());
} else {
if (ctx.LPAREN() != null && ctx.RPAREN() != null) {
current = visitExpression(ctx.expression());
}
}
return current;
}
@Override
public Expr visitTableOrColumn(HiveQLParser.TableOrColumnContext ctx) {
ColumnReferenceExpr columnReferenceExpr = new ColumnReferenceExpr(ctx.identifier().getText());
return columnReferenceExpr;
}
@Override
public Expr visitIdentifier(HiveQLParser.IdentifierContext ctx) {
Expr current = null;
if (ctx.nonReserved() != null) {
current = new LiteralValue(ctx.nonReserved().getText(), LiteralValue.LiteralType.String);
} else {
current = new LiteralValue(ctx.Identifier().getText(), LiteralValue.LiteralType.String);
}
return current;
}
@Override
public LiteralValue visitConstant(HiveQLParser.ConstantContext ctx) {
LiteralValue literalValue = null;
if (ctx.StringLiteral() != null) {
String value = ctx.StringLiteral().getText();
String strValue = "";
if ((value.startsWith("'") && value.endsWith("'")) || value.startsWith("\"") && value.endsWith("\"")) {
strValue = value.substring(1, value.length() - 1);
} else {
strValue = value;
}
literalValue = new LiteralValue(strValue, LiteralValue.LiteralType.String);
} else if (ctx.TinyintLiteral() != null) {
literalValue = new LiteralValue(ctx.TinyintLiteral().getSymbol().getText(),
LiteralValue.LiteralType.Unsigned_Integer);
} else if (ctx.BigintLiteral() != null) {
literalValue = new LiteralValue(ctx.BigintLiteral().getSymbol().getText(),
LiteralValue.LiteralType.Unsigned_Large_Integer);
} else if (ctx.DecimalLiteral() != null) {
literalValue = new LiteralValue(ctx.DecimalLiteral().getSymbol().getText(),
LiteralValue.LiteralType.Unsigned_Integer);
} else if (ctx.Number() != null) {
try {
float floatValue = NumberUtils.createFloat(ctx.getText());
literalValue = new LiteralValue(ctx.Number().getSymbol().getText(), LiteralValue.LiteralType.Unsigned_Float);
} catch (NumberFormatException nf) {
}
// TODO: double type
try {
BigInteger bigIntegerVallue = NumberUtils.createBigInteger(ctx.getText());
literalValue = new LiteralValue(ctx.Number().getSymbol().getText(),
LiteralValue.LiteralType.Unsigned_Large_Integer);
} catch (NumberFormatException nf) {
}
try {
int intValue = NumberUtils.createInteger(ctx.getText());
literalValue = new LiteralValue(ctx.Number().getSymbol().getText(), LiteralValue.LiteralType.Unsigned_Integer);
} catch (NumberFormatException nf) {
}
} else if (ctx.SmallintLiteral() != null) {
literalValue = new LiteralValue(ctx.SmallintLiteral().getSymbol().getText(),
LiteralValue.LiteralType.Unsigned_Integer);
} else if (ctx.booleanValue() != null) {
// TODO: boolean type
}
return literalValue;
}
@Override
public Expr visitFunction(HiveQLParser.FunctionContext ctx) {
Expr current = null;
String signature = ctx.functionName().getText();
boolean isDistinct = false;
if (ctx.getChild(2) != null) {
if (ctx.getChild(2) instanceof TerminalNodeImpl
&& ctx.getChild(2).getText().equalsIgnoreCase("DISTINCT_GROUP_BY")) {
isDistinct = true;
}
}
if (signature.equalsIgnoreCase("MIN")
|| signature.equalsIgnoreCase("MAX")
|| signature.equalsIgnoreCase("SUM")
|| signature.equalsIgnoreCase("AVG")
|| signature.equalsIgnoreCase("COUNT")
) {
if (ctx.selectExpression().size() > 1) {
throw new RuntimeException("Exactly expected one argument.");
}
if (ctx.selectExpression().size() == 0) {
CountRowsFunctionExpr countRowsFunctionExpr = new CountRowsFunctionExpr();
current = countRowsFunctionExpr;
} else {
GeneralSetFunctionExpr setFunctionExpr = new GeneralSetFunctionExpr(signature, isDistinct, new Expr [] {
visitSelectExpression(ctx.selectExpression(0))});
current = setFunctionExpr;
}
} else {
FunctionExpr functionExpr = new FunctionExpr(signature);
Expr[] params = new Expr[ctx.selectExpression().size()];
for (int i = 0; i < ctx.selectExpression().size(); i++) {
params[i] = visitSelectExpression(ctx.selectExpression(i));
}
functionExpr.setParams(params);
current = functionExpr;
}
return current;
}
/**
* This method parse CAST expression.
* This returns only expression field without casting type
* because Tajo doesn't provide CAST expression.
*
* @param ctx
* @return
*/
@Override
public Expr visitCastExpression(HiveQLParser.CastExpressionContext ctx) {
DataTypeExpr castTarget = getDataTypeExpr(ctx.primitiveType());
Expr expr = visitExpression(ctx.expression());
Expr current = new CastExpr(expr, castTarget);
return current;
}
@Override
public Expr visitCaseExpression(HiveQLParser.CaseExpressionContext ctx) {
CaseWhenPredicate caseWhen = new CaseWhenPredicate();
Expr condition = null, result = null;
for (int i = 1; i < ctx.getChildCount(); i++) {
if (ctx.getChild(i) instanceof TerminalNodeImpl) {
if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_WHEN) {
condition = null;
result = null;
if (ctx.getChild(i + 1) instanceof HiveQLParser.ExpressionContext) {
condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1));
}
if (ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) {
result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3));
}
if (condition != null && result != null) {
caseWhen.addWhen(condition, result);
}
} else if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_ELSE) {
result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1));
caseWhen.setElseResult(result);
}
}
}
return caseWhen;
}
@Override
public Expr visitWhenExpression(HiveQLParser.WhenExpressionContext ctx) {
CaseWhenPredicate caseWhen = new CaseWhenPredicate();
Expr condition = null, result = null;
for (int i = 1; i < ctx.getChildCount(); i++) {
if (ctx.getChild(i) instanceof TerminalNodeImpl) {
if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_WHEN) {
condition = null;
result = null;
if (ctx.getChild(i + 1) instanceof HiveQLParser.ExpressionContext) {
condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1));
}
if (ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) {
result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3));
}
if (condition != null && result != null) {
caseWhen.addWhen(condition, result);
}
} else if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_ELSE) {
result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1));
caseWhen.setElseResult(result);
}
}
}
return caseWhen;
}
@Override
public Aggregation visitGroupByClause(HiveQLParser.GroupByClauseContext ctx) {
Aggregation clause = new Aggregation();
if (ctx.groupByExpression().size() > 0) {
int elementSize = ctx.groupByExpression().size();
ArrayList<Aggregation.GroupElement> groups = new ArrayList<Aggregation.GroupElement>(elementSize + 1);
ArrayList<Expr> ordinaryExprs = new ArrayList<Expr>();
int groupSize = 1;
groups.add(null);
for (int i = 0; i < ctx.groupByExpression().size(); i++) {
Expr expr = visitGroupByExpression(ctx.groupByExpression(i));
if (expr instanceof FunctionExpr) {
FunctionExpr function = (FunctionExpr) expr;
if (function.getSignature().equalsIgnoreCase("ROLLUP")) {
groupSize++;
groups.add(new Aggregation.GroupElement(Aggregation.GroupType.Rollup,
function.getParams()));
} else if (function.getSignature().equalsIgnoreCase("CUBE")) {
groupSize++;
groups.add(new Aggregation.GroupElement(Aggregation.GroupType.Cube, function.getParams()));
} else {
Collections.addAll(ordinaryExprs, function);
}
} else {
Collections.addAll(ordinaryExprs, (ColumnReferenceExpr)expr);
}
}
if (ordinaryExprs != null) {
groups.set(0, new Aggregation.GroupElement(Aggregation.GroupType.OrdinaryGroup, ordinaryExprs.toArray(new Expr[ordinaryExprs.size()])));
clause.setGroups(groups.subList(0, groupSize).toArray(new Aggregation.GroupElement[groupSize]));
} else if (groupSize > 1) {
clause.setGroups(groups.subList(1, groupSize).toArray(new Aggregation.GroupElement[groupSize - 1]));
}
}
//TODO: grouping set expression
return clause;
}
@Override
public Sort visitOrderByClause(HiveQLParser.OrderByClauseContext ctx) {
Sort clause = null;
Sort.SortSpec[] specs = null;
if (ctx.columnRefOrder().size() > 0) {
specs = new Sort.SortSpec[ctx.columnRefOrder().size()];
for (int i = 0; i < ctx.columnRefOrder().size(); i++) {
ColumnReferenceExpr column = (ColumnReferenceExpr) visitExpression(ctx.columnRefOrder().get(i).expression());
specs[i] = new Sort.SortSpec(column);
if (ctx.columnRefOrder(i).KW_DESC() != null) {
specs[i].setDescending();
}
}
clause = new Sort(specs);
}
return clause;
}
@Override
public Expr visitHavingClause(HiveQLParser.HavingClauseContext ctx) {
return visitHavingCondition(ctx.havingCondition());
}
@Override
public Expr visitClusterByClause(HiveQLParser.ClusterByClauseContext ctx) {
// TODO: It needs to consider how to support.
return null;
}
@Override
public Expr visitDistributeByClause(HiveQLParser.DistributeByClauseContext ctx) {
// TODO: It needs to consider how to support.
return null;
}
@Override
public Sort visitSortByClause(HiveQLParser.SortByClauseContext ctx) {
Sort clause = null;
Sort.SortSpec[] specs = null;
if (ctx.columnRefOrder().size() > 0) {
specs = new Sort.SortSpec[ctx.columnRefOrder().size()];
for (int i = 0; i < ctx.columnRefOrder().size(); i++) {
ColumnReferenceExpr column = (ColumnReferenceExpr) visitColumnRefOrder(ctx.columnRefOrder(i));
specs[i] = new Sort.SortSpec(column);
if (ctx.columnRefOrder(i).KW_DESC() != null) {
specs[i].setDescending();
}
}
clause = new Sort(specs);
}
return clause;
}
@Override
public Limit visitLimitClause(HiveQLParser.LimitClauseContext ctx) {
LiteralValue expr = new LiteralValue(ctx.Number().getText(), LiteralValue.LiteralType.Unsigned_Integer);
Limit limit = new Limit(expr);
return limit;
}
@Override
public Expr visitWindow_clause(HiveQLParser.Window_clauseContext ctx) {
// TODO: It needs to consider how to support.
return null;
}
@Override
public Insert visitInsertClause(HiveQLParser.InsertClauseContext ctx) {
Insert insert = new Insert();
if (ctx.KW_OVERWRITE() != null)
insert.setOverwrite();
if (ctx.tableOrPartition() != null) {
HiveQLParser.TableOrPartitionContext partitionContext = ctx.tableOrPartition();
if (partitionContext.tableName() != null) {
insert.setTableName(ctx.tableOrPartition().tableName().getText());
}
}
if (ctx.destination() != null) {
HiveQLParser.DestinationContext destination = ctx.destination();
if (destination.KW_DIRECTORY() != null) {
String location = destination.StringLiteral().getText();
location = location.replaceAll("\\'", "");
insert.setLocation(location);
} else if (destination.KW_TABLE() != null) {
if (destination.tableOrPartition() != null) {
HiveQLParser.TableOrPartitionContext partitionContext = destination.tableOrPartition();
if (partitionContext.tableName() != null) {
insert.setTableName(partitionContext.tableName().getText());
}
}
if (destination.tableFileFormat() != null) {
if (destination.tableFileFormat().KW_RCFILE() != null) {
insert.setStorageType("rcfile");
} else if (destination.tableFileFormat().KW_TEXTFILE() != null) {
insert.setStorageType("csv");
}
}
}
}
return insert;
}
@Override
public Expr visitCreateTableStatement(HiveQLParser.CreateTableStatementContext ctx) {
CreateTable createTable = null;
Map<String, String> params = new HashMap<String, String>();
if (ctx.name != null) {
createTable = new CreateTable(ctx.name.getText(), ctx.ifNotExists() != null);
if (ctx.KW_EXTERNAL() != null) {
createTable.setExternal();
}
if (ctx.tableFileFormat() != null) {
if (ctx.tableFileFormat().KW_RCFILE() != null) {
createTable.setStorageType("rcfile");
} else if (ctx.tableFileFormat().KW_TEXTFILE() != null) {
createTable.setStorageType("csv");
}
}
if (ctx.tableRowFormat() != null) {
if (ctx.tableRowFormat().rowFormatDelimited() != null) {
String delimiter = ctx.tableRowFormat().rowFormatDelimited().tableRowFormatFieldIdentifier().getChild(3)
.getText().replaceAll("'", "");
params.put("csvfile.delimiter", SQLAnalyzer.escapeDelimiter(delimiter));
}
}
if (ctx.tableLocation() != null) {
String location = ctx.tableLocation().StringLiteral().getText();
location = location.replaceAll("'", "");
createTable.setLocation(location);
}
if (ctx.columnNameTypeList() != null) {
List<HiveQLParser.ColumnNameTypeContext> list = ctx.columnNameTypeList().columnNameType();
ColumnDefinition[] columns = new ColumnDefinition[list.size()];
for (int i = 0; i < list.size(); i++) {
HiveQLParser.ColumnNameTypeContext eachColumn = list.get(i);
String type = null;
if (eachColumn.colType().type() != null) {
if (eachColumn.colType().type().primitiveType() != null) {
HiveQLParser.PrimitiveTypeContext primitiveType = eachColumn.colType().type().primitiveType();
type = getDataTypeExpr(primitiveType).getTypeName();
columns[i] = new ColumnDefinition(eachColumn.colName.Identifier().getText(), type);
}
}
}
if (columns != null) {
createTable.setTableElements(columns);
}
if (!params.isEmpty()) {
createTable.setParams(params);
}
}
}
return createTable;
}
private DataTypeExpr getDataTypeExpr(HiveQLParser.PrimitiveTypeContext primitiveType) {
DataTypeExpr typeDefinition = null;
if (primitiveType.KW_STRING() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.TEXT.name());
} else if (primitiveType.KW_TINYINT() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT1.name());
} else if (primitiveType.KW_SMALLINT() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT2.name());
} else if (primitiveType.KW_INT() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT4.name());
} else if (primitiveType.KW_BIGINT() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT8.name());
} else if (primitiveType.KW_FLOAT() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.FLOAT4.name());
} else if (primitiveType.KW_DOUBLE() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.FLOAT8.name());
} else if (primitiveType.KW_DECIMAL() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.NUMERIC.name());
} else if (primitiveType.KW_BOOLEAN() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.BOOLEAN.name());
} else if (primitiveType.KW_DATE() != null) {
} else if (primitiveType.KW_DATETIME() != null) {
//TODO
} else if (primitiveType.KW_TIMESTAMP() != null) {
typeDefinition = new DataTypeExpr(TajoDataTypes.Type.TIMESTAMP.name());
}
return typeDefinition;
}
@Override
public Expr visitDropTableStatement(HiveQLParser.DropTableStatementContext ctx) {
DropTable dropTable = new DropTable(ctx.tableName().getText(), false, ctx.ifExists() != null);
return dropTable;
}
/**
* This class provides and implementation for a case insensitive token checker
* for the lexical analysis part of antlr. By converting the token stream into
* upper case at the time when lexical rules are checked, this class ensures that the
* lexical rules need to just match the token with upper case letters as opposed to
* combination of upper case and lower case characteres. This is purely used for matching lexical
* rules. The actual token text is stored in the same way as the user input without
* actually converting it into an upper case. The token values are generated by the consume()
* function of the super class ANTLRStringStream. The LA() function is the lookahead funtion
* and is purely used for matching lexical rules. This also means that the grammar will only
* accept capitalized tokens in case it is run from other tools like antlrworks which
* do not have the ANTLRNoCaseStringStream implementation.
*/
public class ANTLRNoCaseStringStream extends ANTLRInputStream {
public ANTLRNoCaseStringStream(String input) {
super(input);
}
@Override
public int LA(int i) {
int returnChar = super.LA(i);
if (returnChar == CharStream.EOF) {
return returnChar;
} else if (returnChar == 0) {
return returnChar;
}
return Character.toUpperCase((char) returnChar);
}
}
}