blob: a13de471769d609e6fcc1fef71bc50460304ce80 [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.
from . import gen
from .gen.AgtypeLexer import AgtypeLexer
from .gen.AgtypeParser import AgtypeParser
from .gen.AgtypeVisitor import AgtypeVisitor
from .models import *
from .exceptions import *
from antlr4 import *
from antlr4.tree.Tree import *
from decimal import Decimal
class ResultHandler:
def parse(ageData):
pass
def newResultHandler(query=""):
resultHandler = Antlr4ResultHandler(None, query)
return resultHandler
def parseAgeValue(value, cursor=None):
if value is None:
return None
resultHandler = Antlr4ResultHandler(None)
try:
return resultHandler.parse(value)
except Exception as ex:
raise AGTypeError(value)
class Antlr4ResultHandler(ResultHandler):
def __init__(self, vertexCache, query=None):
self.lexer = AgtypeLexer()
self.parser = AgtypeParser(None)
self.visitor = ResultVisitor(vertexCache)
def parse(self, ageData):
if not ageData:
return None
# print("Parse::", ageData)
self.lexer.inputStream = InputStream(ageData)
self.parser.setTokenStream(CommonTokenStream(self.lexer))
self.parser.reset()
tree = self.parser.agType()
parsed = tree.accept(self.visitor)
return parsed
# print raw result String
class DummyResultHandler(ResultHandler):
def parse(self, ageData):
print(ageData)
# default agType visitor
class ResultVisitor(AgtypeVisitor):
vertexCache = None
def __init__(self, cache) -> None:
super().__init__()
self.vertexCache = cache
def visitAgType(self, ctx:AgtypeParser.AgTypeContext):
agVal = ctx.agValue()
if agVal != None:
obj = ctx.agValue().accept(self)
return obj
return None
def visitAgValue(self, ctx:AgtypeParser.AgValueContext):
annoCtx = ctx.typeAnnotation()
valueCtx = ctx.value()
if annoCtx is not None:
annoCtx.accept(self)
anno = annoCtx.IDENT().getText()
return self.handleAnnotatedValue(anno, valueCtx)
else:
return valueCtx.accept(self)
# Visit a parse tree produced by AgtypeParser#StringValue.
def visitStringValue(self, ctx:AgtypeParser.StringValueContext):
return ctx.STRING().getText().strip('"')
# Visit a parse tree produced by AgtypeParser#IntegerValue.
def visitIntegerValue(self, ctx:AgtypeParser.IntegerValueContext):
return int(ctx.INTEGER().getText())
# Visit a parse tree produced by AgtypeParser#floatLiteral.
def visitFloatLiteral(self, ctx:AgtypeParser.FloatLiteralContext):
c = ctx.getChild(0)
tp = c.symbol.type
text = ctx.getText()
if tp == AgtypeParser.RegularFloat:
return float(text)
elif tp == AgtypeParser.ExponentFloat:
return float(text)
else:
if text == 'NaN':
return float('nan')
elif text == '-Infinity':
return float('-inf')
elif text == 'Infinity':
return float('inf')
else:
return Exception("Unknown float expression:"+text)
# Visit a parse tree produced by AgtypeParser#TrueBoolean.
def visitTrueBoolean(self, ctx:AgtypeParser.TrueBooleanContext):
return True
# Visit a parse tree produced by AgtypeParser#FalseBoolean.
def visitFalseBoolean(self, ctx:AgtypeParser.FalseBooleanContext):
return False
# Visit a parse tree produced by AgtypeParser#NullValue.
def visitNullValue(self, ctx:AgtypeParser.NullValueContext):
return None
# Visit a parse tree produced by AgtypeParser#obj.
def visitObj(self, ctx:AgtypeParser.ObjContext):
obj = dict()
for c in ctx.getChildren():
if isinstance(c, AgtypeParser.PairContext):
namVal = self.visitPair(c)
name = namVal[0]
valCtx = namVal[1]
val = valCtx.accept(self)
obj[name] = val
return obj
# Visit a parse tree produced by AgtypeParser#pair.
def visitPair(self, ctx:AgtypeParser.PairContext):
self.visitChildren(ctx)
return (ctx.STRING().getText().strip('"') , ctx.agValue())
# Visit a parse tree produced by AgtypeParser#array.
def visitArray(self, ctx:AgtypeParser.ArrayContext):
li = list()
for c in ctx.getChildren():
if not isinstance(c, TerminalNode):
val = c.accept(self)
li.append(val)
return li
def handleAnnotatedValue(self, anno:str, ctx:ParserRuleContext):
if anno == "numeric":
return Decimal(ctx.getText())
elif anno == "vertex":
dict = ctx.accept(self)
vid = dict["id"]
vertex = None
if self.vertexCache != None and vid in self.vertexCache :
vertex = self.vertexCache[vid]
else:
vertex = Vertex()
vertex.id = dict["id"]
vertex.label = dict["label"]
vertex.properties = dict["properties"]
if self.vertexCache != None:
self.vertexCache[vid] = vertex
return vertex
elif anno == "edge":
edge = Edge()
dict = ctx.accept(self)
edge.id = dict["id"]
edge.label = dict["label"]
edge.end_id = dict["end_id"]
edge.start_id = dict["start_id"]
edge.properties = dict["properties"]
return edge
elif anno == "path":
arr = ctx.accept(self)
path = Path(arr)
return path
return ctx.accept(self)