def flatten(ctx: ParserRuleContext): """Takes a ParserRuleContext of a binary operator and "flattens" the operator if one of its operands is the same binary operator context. This function only flattens if the operator is the same and also keeps the operators intact.""" # If the child isn't the same construct, nothing to do. if ctx.getChild(0).__class__ != ctx.__class__: return lhs = ctx.getChild(0) op = ctx.getChild(1) rhs = ctx.getChild(2) lhsop = lhs.getChild(1) # If the operator of the nested Context isn't the same, nothing to do. # The operator is always in position 1 for infix operators. We do this # check because some Contexts that use the same context for multiple # operators. if op.getSymbol().type != lhsop.getSymbol().type: return # Clear all children. ctx.children.clear() # Add all children of lhs. (Also adds the operator of the lhs.) ctx.children.extend(lhs.children) # Finally, add the rhs back in. ctx.children.append(rhs)
def enterOuterAlt(self, localctx:ParserRuleContext, altNum:int): localctx.setAltNumber(altNum) # if we have new localctx, make sure we replace existing ctx # that is previous child of parse tree if self.buildParseTrees and self._ctx != localctx: if self._ctx.parentCtx is not None: self._ctx.parentCtx.removeLastChild() self._ctx.parentCtx.addChild(localctx) self._ctx = localctx
def enterOuterAlt(self, localctx: ParserRuleContext, altNum: int): localctx.setAltNumber(altNum) # if we have new localctx, make sure we replace existing ctx # that is previous child of parse tree if self.buildParseTrees and self._ctx != localctx: if self._ctx.parentCtx is not None: self._ctx.parentCtx.removeLastChild() self._ctx.parentCtx.addChild(localctx) self._ctx = localctx
def unrollRecursionContexts(self, parentCtx:ParserRuleContext): self._precedenceStack.pop() self._ctx.stop = self._input.LT(-1) retCtx = self._ctx # save current ctx (return value) # unroll so _ctx is as it was before call to recursive method if self._parseListeners is not None: while self._ctx is not parentCtx: self.triggerExitRuleEvent() self._ctx = self._ctx.parentCtx else: self._ctx = parentCtx # hook into tree retCtx.parentCtx = parentCtx if self.buildParseTrees and parentCtx is not None: # add return ctx into invoking rule's tree parentCtx.addChild(retCtx)
def unrollRecursionContexts(self, parentCtx: ParserRuleContext): self._precedenceStack.pop() self._ctx.stop = self._input.LT(-1) retCtx = self._ctx # save current ctx (return value) # unroll so _ctx is as it was before call to recursive method if self._parseListeners is not None: while self._ctx is not parentCtx: self.triggerExitRuleEvent() self._ctx = self._ctx.parentCtx else: self._ctx = parentCtx # hook into tree retCtx.parentCtx = parentCtx if self.buildParseTrees and parentCtx is not None: # add return ctx into invoking rule's tree parentCtx.addChild(retCtx)
def setAtIndex(self, ctx: ParserRuleContext, indexes: list, val: SiliconValue, newVal: SiliconValue): if not val.isList(): raise Exception('setAtIndex Exception' + ctx.getText()) for i in range(len(indexes) - 1): idx = self.visit(indexes[i]) if not idx.isNumber: raise Exception('setAtIndex Exception: Not a number' + ctx.getText()) val = val.asList()[int(idx.asDouble())] idx = self.visit(indexes[len(indexes) - 1]) if not idx.isNumber(): raise Exception('setAtIndex Exception: Not a number ' + ctx.getText()) val.asList()[int(idx.asDouble())] = newVal
def addChild(parent: ParserRuleContext, child: ParseTree, i: int = None): """Does what RuleContext.addChild is supposed to do. The ANTLR4 Python3 target doesn't follow the same API as the Java target. Some classes in the hierarchy don't have addChild, while others do.""" try: if i is None: parent.children.append(child) else: parent.children.insert(i, child) except: parent.children = [child]
def rewriteSpan(ctx: ParserRuleContext): opIndex = [i for (i, c) in enumerate(ctx.children) if c.getText() == ';;'] spanExpressions = [] opIndexSize = len(opIndex) childrenSize = len(ctx.children) # We emulate a for-loop with a while-loop. We can't use python's for # because we need to change the index variables in the loop body. i = 0 nextOp = 0 while True: if nextOp + 1 < opIndexSize \ and opIndex[nextOp + 1] + 1 < childrenSize \ and isinstance(ctx.children[opIndex[nextOp + 1] + 1], FoxySheepParser.ExprContext): # There is a next ";;" # and there is a node after the next ";;" # and there is a second ";;" followed by an expr. i = opIndex[nextOp + 1] + 1 spanExpressions.append(i) # We want nextOp to end at the last ";;" of the current expression. nextOp += 1 else: # There is no second ";;" belonging to this expression. if opIndex[nextOp] + 1 < childrenSize \ and isinstance(ctx.children[opIndex[nextOp + 1] + 1], FoxySheepParser.ExprContext): # There is a node after ";;" # and this span expression ends in an expr. i = opIndex[nextOp] + 1 spanExpressions.append(i) else: # This span expression ends in the current ";;". i = opIndex[nextOp] spanExpressions.append(i) # Check for end of for-loop if i >= childrenSize or nextOp >= opIndexSize: break # Set up the next loop. i += 1 nextOp += 1 # At this point spanExpressions holds the index of the last child of each # span expression. It might be that after all of this there is nothing to do. if len(spanExpressions) == 1: return # Otherwise there is more than one span expression, and we need to rewrite # the tree replacing the Span?Context this method was invoked on with a # TimesContext. timesctx = FoxySheepParser.TimesContext(None, ctx) timesctx.children = [] # Clear children # Add each span expression as a child to timesctx. j = 0 for i, spanExp in enumerate(spanExpressions): # i is the index of the current span expression in spanExpressions, # and j is the index to the beginning of the new span expression's # children in ctx.children. We make new SpanAContext objects for each # span expression. span = FoxySheepParser.SpanAContext(None, ctx) adopt(timesctx, span) span.children = ctx.children[j:spanExpressions[i]] # update j to be the beginning of the next expression. j = spanExpressions[i] + 1 # Finally, detach the span this method was invoked on from its parent and # replace with the TimesContext. parentsChildren = ctx.parentCtx.children ctxIndex = parentsChildren.index(ctx) parentsChildren[ctxIndex] = timesctx ctx.parentCtx = timesctx
def __init__(self, ctx: ParserRuleContext): self.evalException("Illegal expression: " + ctx.getText(), ctx)