Skip to content

Commit

Permalink
Merge 9c0dbef into 09e8a98
Browse files Browse the repository at this point in the history
  • Loading branch information
gaurav274 committed Jan 28, 2021
2 parents 09e8a98 + 9c0dbef commit 105e9fb
Show file tree
Hide file tree
Showing 11 changed files with 802 additions and 635 deletions.
632 changes: 0 additions & 632 deletions src/parser/parser_visitor.py

This file was deleted.

56 changes: 56 additions & 0 deletions src/parser/parser_visitor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# coding=utf-8
# Copyright 2018-2020 EVA
#
# Licensed 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.

from antlr4 import TerminalNode
from src.parser.evaql.evaql_parser import evaql_parser

from src.parser.parser_visitor._common_clauses_ids import CommonClauses
from src.parser.parser_visitor._create_statements import CreateTable
from src.parser.parser_visitor._expressions import Expressions
from src.parser.parser_visitor._functions import Functions
from src.parser.parser_visitor._insert_statements import Insert
from src.parser.parser_visitor._select_statement import Select
from src.parser.parser_visitor._table_sources import TableSources
from src.parser.parser_visitor._load_statement import Load

# To add new functionality to the parser, create a new file under
# the parser_visitor directory, and implement a new class which
# overloads the required visitors' functions.
# Then make the new class as a parent class for ParserVisitor.


class ParserVisitor(CommonClauses, CreateTable, Expressions,
Functions, Insert, Select, TableSources,
Load):
def visitRoot(self, ctx: evaql_parser.RootContext):
for child in ctx.children:
if child is not TerminalNode:
return self.visit(child)

def visitSqlStatements(self, ctx: evaql_parser.SqlStatementsContext):
eva_statements = []
sql_statement_count = len(ctx.sqlStatement())
for child_index in range(sql_statement_count):
statement = self.visit(ctx.sqlStatement(child_index))
eva_statements.append(statement)
return eva_statements

##################################################################
# STATEMENTS
##################################################################

def visitDdlStatement(self, ctx: evaql_parser.DdlStatementContext):
ddl_statement = self.visitChildren(ctx)
return ddl_statement
69 changes: 69 additions & 0 deletions src/parser/parser_visitor/_common_clauses_ids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# coding=utf-8
# Copyright 2018-2020 EVA
#
# Licensed 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.

import warnings
from src.parser.evaql.evaql_parserVisitor import evaql_parserVisitor

from src.expression.tuple_value_expression import TupleValueExpression

from src.parser.table_ref import TableRef, TableInfo

from src.parser.evaql.evaql_parser import evaql_parser

from src.utils.logging_manager import LoggingLevel, LoggingManager


##################################################################
# COMMON CLAUSES Ids, Column_names, Table_names
##################################################################
class CommonClauses(evaql_parserVisitor):
def visitTableName(self, ctx: evaql_parser.TableNameContext):

table_name = self.visit(ctx.fullId())
if table_name is not None:
table_info = TableInfo(table_name=table_name)
return TableRef(table_info)
else:
warnings.warn("Invalid from table", SyntaxWarning)

def visitFullColumnName(self, ctx: evaql_parser.FullColumnNameContext):
# Adding support for a.b
# Will restrict implementation to raise error for a.b.c
dottedIds = []
if ctx.dottedId():
if len(ctx.dottedId()) != 1:
LoggingManager().log("Only tablename.colname syntax supported",
LoggingLevel.ERROR)
return
for id in ctx.dottedId():
dottedIds.append(self.visit(id))

uid = self.visit(ctx.uid())

if len(dottedIds):
return TupleValueExpression(table_name=uid, col_name=dottedIds[0])
else:
return TupleValueExpression(col_name=uid)

def visitSimpleId(self, ctx: evaql_parser.SimpleIdContext):
# todo handle children, right now assuming TupleValueExpr
return ctx.getText()
# return self.visitChildren(ctx)

def visitDottedId(self, ctx: evaql_parser.DOT_ID):
if ctx.DOT_ID():
return ctx.getText()[1:]
if ctx.uid():
return self.visit(ctx.uid())
184 changes: 184 additions & 0 deletions src/parser/parser_visitor/_create_statements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# coding=utf-8
# Copyright 2018-2020 EVA
#
# Licensed 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.

from src.parser.evaql.evaql_parserVisitor import evaql_parserVisitor
from src.parser.create_statement import CreateTableStatement, ColumnDefinition
from src.parser.evaql.evaql_parser import evaql_parser
from src.parser.types import ParserColumnDataType
from src.parser.types import ColumnConstraintEnum
from src.parser.create_statement import ColConstraintInfo


##################################################################
# CREATE STATEMENTS
##################################################################
class CreateTable(evaql_parserVisitor):
def visitColumnCreateTable(
self, ctx: evaql_parser.ColumnCreateTableContext):

table_ref = None
if_not_exists = False
create_definitions = []

# first two children will be CREATE TABLE terminal token
for child in ctx.children[2:]:
try:
rule_idx = child.getRuleIndex()

if rule_idx == evaql_parser.RULE_tableName:
table_ref = self.visit(ctx.tableName())

elif rule_idx == evaql_parser.RULE_ifNotExists:
if_not_exists = True

elif rule_idx == evaql_parser.RULE_createDefinitions:
create_definitions = self.visit(ctx.createDefinitions())

except BaseException:
print("Exception")
# stop parsing something bad happened
return None

create_stmt = CreateTableStatement(table_ref,
if_not_exists,
create_definitions)
return create_stmt

def visitCreateDefinitions(
self, ctx: evaql_parser.CreateDefinitionsContext):
column_definitions = []
child_index = 0
for child in ctx.children:
create_definition = ctx.createDefinition(child_index)
if create_definition is not None:
column_definition = self.visit(create_definition)
column_definitions.append(column_definition)
child_index = child_index + 1

return column_definitions

def visitColumnDeclaration(
self, ctx: evaql_parser.ColumnDeclarationContext):

data_type, dimensions, column_constraint_information = self.visit(
ctx.columnDefinition())

column_name = self.visit(ctx.uid())

if column_name is not None:
return ColumnDefinition(
column_name, data_type, dimensions,
column_constraint_information)

def visitColumnDefinition(self, ctx: evaql_parser.ColumnDefinitionContext):

data_type, dimensions = self.visit(ctx.dataType())

constraint_count = len(ctx.columnConstraint())

column_constraint_information = ColConstraintInfo()

for i in range(constraint_count):
return_type = self.visit(ctx.columnConstraint(i))
if return_type == ColumnConstraintEnum.UNIQUE:

column_constraint_information.unique = True

return data_type, dimensions, column_constraint_information

def visitUniqueKeyColumnConstraint(
self, ctx: evaql_parser.UniqueKeyColumnConstraintContext):
return ColumnConstraintEnum.UNIQUE

def visitSimpleDataType(self, ctx: evaql_parser.SimpleDataTypeContext):

data_type = None
dimensions = []

if ctx.BOOLEAN() is not None:
data_type = ParserColumnDataType.BOOLEAN

return data_type, dimensions

def visitIntegerDataType(self, ctx: evaql_parser.IntegerDataTypeContext):

data_type = None
dimensions = []

if ctx.INTEGER() is not None:
data_type = ParserColumnDataType.INTEGER
elif ctx.UNSIGNED() is not None:
data_type = ParserColumnDataType.INTEGER

return data_type, dimensions

def visitDimensionDataType(
self, ctx: evaql_parser.DimensionDataTypeContext):
data_type = None
dimensions = []

if ctx.FLOAT() is not None:
data_type = ParserColumnDataType.FLOAT
dimensions = self.visit(ctx.lengthTwoDimension())
elif ctx.TEXT() is not None:
data_type = ParserColumnDataType.TEXT
dimensions = self.visit(ctx.lengthOneDimension())
elif ctx.NDARRAY() is not None:
data_type = ParserColumnDataType.NDARRAY
dimensions = self.visit(ctx.lengthDimensionList())

return data_type, dimensions

def visitLengthOneDimension(
self, ctx: evaql_parser.LengthOneDimensionContext):
dimensions = []

if ctx.decimalLiteral() is not None:
dimensions = [self.visit(ctx.decimalLiteral())]

return dimensions

def visitLengthTwoDimension(
self, ctx: evaql_parser.LengthTwoDimensionContext):
first_decimal = self.visit(ctx.decimalLiteral(0))
second_decimal = self.visit(ctx.decimalLiteral(1))

dimensions = [first_decimal, second_decimal]
return dimensions

def visitLengthDimensionList(
self, ctx: evaql_parser.LengthDimensionListContext):
dimensions = []
dimension_list_length = len(ctx.decimalLiteral())
for dimension_list_index in range(dimension_list_length):
decimal_literal = ctx.decimalLiteral(dimension_list_index)
decimal = self.visit(decimal_literal)
dimensions.append(decimal)

return dimensions

def visitDecimalLiteral(self, ctx: evaql_parser.DecimalLiteralContext):

decimal = None
if ctx.DECIMAL_LITERAL() is not None:
decimal = int(str(ctx.DECIMAL_LITERAL()))
elif ctx.ONE_DECIMAL() is not None:
decimal = int(str(ctx.ONE_DECIMAL()))
elif ctx.TWO_DECIMAL() is not None:
decimal = int(str(ctx.TWO_DECIMAL()))
elif ctx.ZERO_DECIMAL() is not None:
decimal = int(str(ctx.ZERO_DECIMAL()))

return decimal
Loading

0 comments on commit 105e9fb

Please sign in to comment.