Example #1
0
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)
Example #2
0
 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
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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
Example #7
0
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]
Example #8
0
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
Example #9
0
 def __init__(self, ctx: ParserRuleContext):
     self.evalException("Illegal expression: " + ctx.getText(), ctx)