| # 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 InputStream, CommonTokenStream, ParserRuleContext | |
| from antlr4.tree.Tree import TerminalNode | |
| from decimal import Decimal | |
| resultHandler = None | |
| 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 | |
| global resultHandler | |
| if (resultHandler == None): | |
| resultHandler = Antlr4ResultHandler(None) | |
| try: | |
| return resultHandler.parse(value) | |
| except Exception as ex: | |
| raise AGTypeError(value, ex) | |
| 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) |