Module src.optimizer.import_ir

This module handles ir input from a file

Expand source code
"""
This module handles ir input from a file
"""
from rply import LexerGenerator
from rply.errors import LexingError
from copy import deepcopy
import re
import os
from inspect import getsourcefile
from importlib.machinery import SourceFileLoader

irl = SourceFileLoader("IRLine", f"{os.path.dirname(os.path.abspath(getsourcefile(lambda:0)))}/IRLine.py").load_module()

class import_ir():
    def __init__(self, filename):
        """
        This function initializes the object that imports the IR, it takes in the filename of the file being imported.

        Args:
            filename: The filename of the IR

        """
        self.IR = []
        with open(filename,"r") as fd:
            self.data = fd.read()
            self.tokens = None

    def tokenize(self):
        """
        This will tokenize the IR that has been read in.

        """

        text_input = self.data.strip()
        lexer = IR_Lexer().get_lexer()
        tokens = lexer.lex(text_input)
        self.tokens = tokens

    def parse(self):
        """
        This function parses the IR after it has been tokenized, and returns the list of lines in the IR as IRNodes

        Returns:
            A list of the IRNodes that make up this IR file
        """

        pg = Parser()
        pg.parse()
        parser = pg.get_parser()
        parser.parse(self.tokens)

        head = pg.getTree()
        # here, sort the list of IRNodes that have been generated by the parser,
        # since the bottom up nature of the parse means it will parse function_definitions after lines
        finalLs = []
        tempLs = []
        for i in pg.ls:
            if(isinstance(i,irl.IRFunctionDecl)):
                tempLs.insert(0,i)
                tempLs.insert(1,irl.IRBracket(True))
                finalLs += tempLs
                finalLs.append(irl.IRBracket(False))
                tempLs = []
            else:
                tempLs.append(i)
        for i in finalLs:
            toAdd = irl.IRLine(None)
            toAdd.treeList = [i]
            self.IR.append(toAdd)
        return finalLs

    def __str__(self):
        return "\n".join([str(x) for x in finalLs])

def tokensToString(tokens):
    """
    Iterates through the tokens and generates a string of all of them

    Args:
        tokens: The token object that is returned from the lexer.
    """
    return "\n".join([str(x) for x in tokens])


class IR_Lexer():
    """
    The lexer class definition to tokenize a gimple IR
    """
    def __init__(self):
        """
        Constructs the Lexer object.
        """
        self.lexer = LexerGenerator()

    def _add_tokens(self):
        """
        Adds tokens to the rply lexer object
        """
        self.lexer.add("D_NUM", r"D\.[0-9]*")
        self.lexer.add("INT",r"([1-9]\d*|\d)")
        self.lexer.add("FLOAT",r"(\d|[1-9]\d+)\.\d*")
        self.lexer.add("CHAR",r"\'\\?[\w\;\\ \%\"\']\'")
        self.lexer.add("STRING",r"(\"[^\n]*?(?<!\\)\")|(\'[^\n]*?(?<!\\)\')")
        self.lexer.add("PLUS",r"\+")
        self.lexer.add("MINUS",r"-")
        self.lexer.add("DIVIDE",r"/")
        self.lexer.add("TIMES",r"\*")
        self.lexer.add("MODULUS",r"%")
        self.lexer.add("LEFT_SHIFT",r"<<")
        self.lexer.add("RIGHT_SHIFT",r">>")
        self.lexer.add("NOT_EQUAL_TO",r"!=")
        self.lexer.add("NOT",r"!")
        self.lexer.add("XOR",r"\^")
        self.lexer.add("NEGATE",r"~")
        self.lexer.add("SEMICOLON",r";")
        self.lexer.add("RETURN",r"\breturn\b")
        self.lexer.add("GOTO",r"\bgoto\b")
        self.lexer.add("IF",r"\bif\b")
        self.lexer.add("ELSE",r"\belse\b")
        self.lexer.add("GEQ",r">=")
        self.lexer.add("LEQ",r"<=")
        self.lexer.add("GREATER_THAN",r">")
        self.lexer.add("LESS_THAN",r"<")
        self.lexer.add("EQUAL_TO",r"={2}")
        self.lexer.add("EQUALS",r"=")
        self.lexer.add("NULL",r"\bNULL\b")
        self.lexer.add("KEYWORD","\b(const|signed|static|unsigned|extern)\b")
        self.lexer.add("COMMA",r",")
        self.lexer.add("COLON",r":")
        self.lexer.add("AND",r"&{2}")
        self.lexer.add("OR",r"\|{2}")
        self.lexer.add("BW_AND",r"&")
        self.lexer.add("BW_OR",r"\|")
        self.lexer.add("TYPE",r"\b(auto|long double|double|float|long long( int)?|long|int|short|char|void)\b")
        self.lexer.add("VAR_NAME",r"tV_[a-zA-Z_]\w*|rV_[a-zA-Z_]\w*")
        self.lexer.add("OPEN_PAREN",r"\(")
        self.lexer.add("CLOSE_PAREN",r"\)")
        self.lexer.add("OPEN_BRACK",r"\{")
        self.lexer.add("CLOSE_BRACK",r"\}")
        self.lexer.ignore(r'\s+')
        self.lexer.ignore(r'\n')
        self.lexer.ignore(r'\t')


    def get_lexer(self):
        """
        Retrieves the lexer, with the tokens added to the inner lexer object.

        Returns:
            The lexer, now built with the tokens added
        """
        self._add_tokens()
        return self.lexer.build()

def print_error(token):
    """
    Prints lexer error message. Currently we only experience invalid token
    errors. The input `token` is a `Token` object, imported from `rply`.

    Args:
        token: The token object that is returned from the lexer.
    """
    print(f"LexingError: Invalid Token \'{token.value}\' at, {token.source_pos}\n")





"""
This module contains definitions for the ParseTree and Parser classes, as well as some ansillary functions to assist.
"""
from rply import ParserGenerator
from rply.errors import ParserGeneratorWarning
from warnings import simplefilter
from rply.token import Token

#we get werid 'non-descriptive' warnings from ParserGenerator, this ignores those
simplefilter('ignore', ParserGeneratorWarning)

class ParseTree():
    """
    ParseTree is a class that acts as each node in an ParseTree
    """
    def __init__(self, token, content):
        """
        Construct a new ParseTree object

        Args:
            token: The token type of the node.
            content: The content of that is tokenized.
        """
        self.token = token
        self.content = content

    def print_ParseTree(self, file=None, _prefix="", _last=True):
        """
        Prints the ParseTree in depth first order

        Args:
            file: The file to be written to (Defaults to Stdout).
            _prefix: A string indicating the spacing from the left side of the screen.
            _last: A boolean that indicates if a self is the last in it's immediate surroundings.
        """
        print(f"{_prefix}{'`-- ' if _last else '|-- '}{self.token}", file=file)
        _prefix += "    " if _last else "|   "
        for i, child in enumerate(self.content):
            _last = i == len(self.content)-1
            if 'content' in child.__dict__:
                child.print_ParseTree(file, _prefix, _last)
            else:
                print(f"{_prefix}{'`-- ' if _last else '|-- '}{child}", file=file)

    def __str__(self):
        """
        Produces a string representation of the Parse Tree
        """
        li = []

        ntv = [("", self, True)]

        while ntv:
            li.append(ntv[0])

            ntv = [(f"{ntv[0][0]}{'    ' if ntv[0][2] else '|   '}", x, i == len(ntv[0][1].content)-1 ) for i, x in enumerate(ntv[0][1].content)] + ntv[1:] if 'content' in ntv[0][1].__dict__ else ntv[1:]

        return "".join([f"{x[0]}{'`-- ' if x[2] else '|-- '}{x[1].token if 'token' in x[1].__dict__ else x[1]}" for x in li]) + ""

    def __repr__(self):
        """
        Constructs a list based string representation of the parse tree
        """

        li = []

        ntv = [(1, self)]

        while ntv:
            li.append((ntv[0][0], ntv[0][1].content))

            ntv = [(ntv[0][0]+1, x) for x in ntv[0][1].content if 'content' in x.__dict__] + ntv[1:]

        return "".join([f"{x[0]} : {[y.token if 'content' in y.__dict__ else y for y in x[1]]}" for x in li])

    def getListView(self, level):
        """
        Prints a simple list version of the tree for output. Calls itself recursively

        Args:
            level: The current level of the tree.
        """

        li = []
        li.append(f"{level+1} : {[x if 'content' not in x.__dict__ else x.token for x in self.content]}")

        for x in self.content:
            if "content" in x.__dict__:
                li.extend(x.getListView(level+1))

        if level == 0:
            return "".join(li)
        return li

#setup parser class
class Parser():
    """
    Definition for the Parser object, works off of rply. Contains rules for parsing a gimple IR.
    """

    def __init__(self):
        """
        Initializes the parser and tells it the allowed tokens

        """

        self.pg = ParserGenerator(
            ['PROGRAM','VAR_NAME','OPEN_PAREN','CLOSE_PAREN','OPEN_BRACK','CLOSE_BRACK','FUNCTION_DEF','TYPE','COMMA','PARAMATERS','PARAMETERS','CONTENT','D_NUM','SEMICOLON','LINE','EQUALS','STRING','CHAR','MINUS','PLUS','NEGATE','NOT','NULL','RETURN','IF','GOTO','LESS_THAN','GREATER_THAN','ELSE','COLON','KEWORD','CONDITION','FUNC_CALL','FUNC_INPUT','COMP','EQUAL_TO','LEQ','GEQ','NOT_EQUAL_TO','OP','DIVIDE','TIMES','MODULUS','BW_AND','BW_OR','LEFT_SHIFT','RIGHT_SHIFT','XOR','INT','DIG','FLOAT'] ,
        )
        #initialzie head and current node
        self.Head = None
        self.ls = []


    def parse(self):
        """
        The list of BNF functions and their behavior for the gimple IR.
        """

        @self.pg.production('program : function_def ')
        def program___function_def_(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('program : function_def program ')
        def program___function_def_program_(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('program :  ')
        def program____(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('function_def : VAR_NAME OPEN_PAREN parameters CLOSE_PAREN OPEN_BRACK content CLOSE_BRACK ')
        def function_def___VAR_NAME_OPEN_PAREN_parameters_CLOSE_PAREN_OPEN_BRACK_content_CLOSE_BRACK_(p):

            newNode = ParseTree("FUNCTION_DEF",p)
            self.Head = newNode
            #first, convert parameters to a string form
            #also, get the string representation of VAR_NAME

            tokens = []
            tokens += [x.value for x in p[2].content if isinstance(x,Token)]
            tokenSets = [x for x in p[2].content if isinstance(x,ParseTree)]
            while tokenSets != []:
                for i in tokenSets:
                    tokens += [x.value for x in i.content if isinstance(x,Token)]
                    tokenSets = [x for x in i.content if isinstance(x,ParseTree)]


            functioName = p[0].value
            params = " ".join(tokens)
            IRNodeToReturn = irl.IRFunctionDecl(functioName,params)
            self.ls.append(IRNodeToReturn)
            return newNode

        @self.pg.production('parameters : TYPE VAR_NAME COMMA parameters ')
        def parameters___TYPE_VAR_NAME_COMMA_parameters_(p):
            newNode = ParseTree("PARAMATERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('parameters : TYPE VAR_NAME ')
        def parameters___TYPE_VAR_NAME_(p):
            newNode = ParseTree("PARAMETERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('parameters : ')
        def parameters___(p):
            newNode = ParseTree("PARAMETERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : line ')
        def content___line_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : content content ')
        def content___content_content_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : ')
        def content___(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : OPEN_BRACK content CLOSE_BRACK ')
        def content___OPEN_BRACK_content_CLOSE_BRACK_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('line : TYPE D_NUM SEMICOLON ')
        def line___TYPE_D_NUM_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            typ = p[0]
            name = p[1]
            IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
            self.ls.append(IRNodeToReturn)

            return newNode

        @self.pg.production('line : TYPE VAR_NAME SEMICOLON ')
        def line___TYPE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #needs modifiers, type, and varname
            #modifiers is none
            typ = p[0]
            name = p[1]
            IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
            self.ls.append(IRNodeToReturn)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig op dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_op_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].content[0].value
            rhs = p[4].content[0].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].content[0].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS STRING SEMICOLON ')
        def line___VAR_NAME_EQUALS_STRING_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS CHAR SEMICOLON ')
        def line___VAR_NAME_EQUALS_CHAR_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_op_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].value
            rhs = p[4].content[0].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig op VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_op_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].content[0].value
            rhs = p[4].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_op_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].value
            rhs = p[4].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS MINUS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_MINUS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS MINUS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_MINUS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS PLUS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_PLUS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS PLUS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_PLUS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NEGATE dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_NEGATE_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NOT dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_NOT_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NOT VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_NOT_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NEGATE VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_NEGATE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NULL SEMICOLON ')
        def line___VAR_NAME_EQUALS_NULL_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)

            return newNode

        @self.pg.production('line : D_NUM EQUALS VAR_NAME SEMICOLON ')
        def line___D_NUM_EQUALS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS dig SEMICOLON ')
        def line___D_NUM_EQUALS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].content[0].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS STRING SEMICOLON ')
        def line___D_NUM_EQUALS_STRING_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS CHAR SEMICOLON ')
        def line___D_NUM_EQUALS_CHAR_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : RETURN D_NUM SEMICOLON ')
        def line___RETURN_D_NUM_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #just needs value, should be p[1]
            value = p[1].value
            NodeToBeReturned = irl.IRReturn(value)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : func_call SEMICOLON ')
        def line___func_call_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            func_name = p[0].content[0].value
            contentList = p[0].content[2]
            params = []
            while contentList != []:
                # print("SJSD")
                params.append(contentList.content[0].value)
                if(len(contentList.content) == 3):
                    contentList = contentList.content[2]
                else:
                    contentList =[]
            #NEED TO IDENTIF WHAT IR NODE THIS BECOMES, WE HAVE THE PARAMS AND THE NAME
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS func_call SEMICOLON ')
        def line___VAR_NAME_EQUALS_func_call_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            func_name = p[2].content[0].value
            contentList = p[2].content[2]
            params = []
            lhs = p[0].value
            while contentList != []:
                params.append(contentList.content[0].value)
                if(len(contentList.content) == 3):
                    contentList = contentList.content[2]
                else:
                    contentList =[]
            IRNodeToBeReturned = irl.IRFunctionAssign(None,None,None)
            IRNodeToBeReturned.LineFromFile(lhs,func_name,params)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : IF OPEN_PAREN condition CLOSE_PAREN GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ELSE GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
        def line___IF_OPEN_PAREN_condition_CLOSE_PAREN_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_ELSE_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[2].content[0].value
            rhs = p[2].content[2].value
            compOp = p[2].content[1].content[0].value
            succ = p[6].value.split(".")[1]
            fail = p[12].value.split(".")[1]
            IRNodeToBeReturned = irl.IRIf(None,None,None,None)
            IRNodeToBeReturned.fileInit(lhs,rhs,compOp,succ,fail)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : LESS_THAN D_NUM GREATER_THAN COLON ')
        def line___LESS_THAN_D_NUM_GREATER_THAN_COLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #name of the label
            nameLabel = p[1].value
            IRNodeToBeReturned = irl.IRJump(nameLabel)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
        def line___GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            name = "".join([p[1].value, p[2].value, p[3].value])
            IRNodeToBeReturned = irl.IRGoTo(name)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : GOTO VAR_NAME SEMICOLON ')
        def line___GOTO_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            name = p[1].value
            IRNodeToBeReturned = irl.IRGoTo(name)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME COLON ')
        def line___VAR_NAME_COLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            nameLabel = p[0].value
            IRNodeToBeReturned = irl.IRJump(nameLabel)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : KEWORD TYPE VAR_NAME SEMICOLON ')
        def line___KEWORD_TYPE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            return newNode

        @self.pg.production('line : RETURN SEMICOLON ')
        def line___RETURN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            value = ""
            NodeToBeReturned = irl.IRReturn(value)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('condition : VAR_NAME comp VAR_NAME ')
        def condition___VAR_NAME_comp_VAR_NAME_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : VAR_NAME comp dig ')
        def condition___VAR_NAME_comp_dig_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : dig comp dig ')
        def condition___dig_comp_dig_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : dig comp VAR_NAME ')
        def condition___dig_comp_VAR_NAME_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_call : VAR_NAME OPEN_PAREN func_input CLOSE_PAREN ')
        def func_call___VAR_NAME_OPEN_PAREN_func_input_CLOSE_PAREN_(p):
            newNode = ParseTree("FUNC_CALL",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : ')
        def func_input___(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : STRING COMMA func_input ')
        def func_input___STRING_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : CHAR COMMA func_input ')
        def func_input___CHAR_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : dig COMMA func_input ')
        def func_input___dig_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : VAR_NAME COMMA func_input ')
        def func_input___VAR_NAME_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : STRING  ')
        def func_input___STRING__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : CHAR  ')
        def func_input___CHAR__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : dig  ')
        def func_input___dig__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : VAR_NAME ')
        def func_input___VAR_NAME_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : LESS_THAN ')
        def comp___LESS_THAN_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : GREATER_THAN ')
        def comp___GREATER_THAN_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : EQUAL_TO ')
        def comp___EQUAL_TO_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : LEQ ')
        def comp___LEQ_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : GEQ ')
        def comp___GEQ_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : NOT_EQUAL_TO ')
        def comp___NOT_EQUAL_TO_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : PLUS ')
        def op___PLUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : MINUS ')
        def op___MINUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : DIVIDE ')
        def op___DIVIDE_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : TIMES ')
        def op___TIMES_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : MODULUS ')
        def op___MODULUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : BW_AND ')
        def op___BW_AND_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : BW_OR ')
        def op___BW_OR_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : NEGATE ')
        def op___NEGATE_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : LEFT_SHIFT ')
        def op___LEFT_SHIFT_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : RIGHT_SHIFT ')
        def op___RIGHT_SHIFT_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : XOR ')
        def op___XOR_(p):
            newNode = ParseTree("",p)
            self.Head = newNode
            return newNode

        @self.pg.production('dig : INT ')
        def dig___INT_(p):
            newNode = ParseTree("DIG",p)
            self.Head = newNode
            return newNode

        @self.pg.production('dig : FLOAT ')
        def dig___FLOAT_(p):
            newNode = ParseTree("DIG",p)
            self.Head = newNode
            return newNode


        @self.pg.error
        def error_handle(token):
            """
            Boilerplate error handling function

            Args:
                token: The token that caused an error.
            """
            return ValueError(token)

    #boilerplate function
    def get_parser(self):
        """
        Retrieves the built version of the parser.

        Returns:
            The built parser.
        """
        return self.pg.build()

    #retrieve the trees head
    def getTree(self):
        """
        Getter for the head of the tree.

        Returns:
            The head of the tree.
        """

        return self.Head

    def print_error(self):
        """
        Prints parser error message. This function ultimately iterates through the ParseTree that was returned after the parser found an error. ParseTree's consist of tokens as well as other ParseTree's so we need to iterate to find the first token and then print its source position.
        """
        # TODO: add some more in-depth error processing to print
        # out a more detailed description of what went wrong, and possibly some suggestions
        # at to why there was a parse/syntax error. (i.e. suggest a missing semicolon)

        head = self.getTree()
        token = 0 # token hasn't been found yet, so we set value to 0

        while True and head:
            # Iterate through list of elements
            for i in head.content:

                # Could be a Token
                if(type(i) == type(Token("sample", "sample"))):

                    # Found a Token
                    token = i
                    break

            # Check again (to break out of while loop and not iterate again)
            if (type(token) == type(Token("sample", "sample"))):
                break
            else:
                # Set head to last element.
                # If this code executes then I can assume that the
                # last element is an ParseTree.
                head = head.content[len(head.content)-1]

        if token:
            print(f"ParsingError: Last token  \'{token.value}\' parsed successfully at, {token.source_pos}\n")
        else:
            # Never found a token to report, need to exit
            print("ParsingError: No ParseTree obtained\n")
            exit()

Functions

def print_error(token)

Prints lexer error message. Currently we only experience invalid token errors. The input token is a Token object, imported from rply.

Args

token
The token object that is returned from the lexer.
Expand source code
def print_error(token):
    """
    Prints lexer error message. Currently we only experience invalid token
    errors. The input `token` is a `Token` object, imported from `rply`.

    Args:
        token: The token object that is returned from the lexer.
    """
    print(f"LexingError: Invalid Token \'{token.value}\' at, {token.source_pos}\n")
def tokensToString(tokens)

Iterates through the tokens and generates a string of all of them

Args

tokens
The token object that is returned from the lexer.
Expand source code
def tokensToString(tokens):
    """
    Iterates through the tokens and generates a string of all of them

    Args:
        tokens: The token object that is returned from the lexer.
    """
    return "\n".join([str(x) for x in tokens])

Classes

class IR_Lexer

The lexer class definition to tokenize a gimple IR

Constructs the Lexer object.

Expand source code
class IR_Lexer():
    """
    The lexer class definition to tokenize a gimple IR
    """
    def __init__(self):
        """
        Constructs the Lexer object.
        """
        self.lexer = LexerGenerator()

    def _add_tokens(self):
        """
        Adds tokens to the rply lexer object
        """
        self.lexer.add("D_NUM", r"D\.[0-9]*")
        self.lexer.add("INT",r"([1-9]\d*|\d)")
        self.lexer.add("FLOAT",r"(\d|[1-9]\d+)\.\d*")
        self.lexer.add("CHAR",r"\'\\?[\w\;\\ \%\"\']\'")
        self.lexer.add("STRING",r"(\"[^\n]*?(?<!\\)\")|(\'[^\n]*?(?<!\\)\')")
        self.lexer.add("PLUS",r"\+")
        self.lexer.add("MINUS",r"-")
        self.lexer.add("DIVIDE",r"/")
        self.lexer.add("TIMES",r"\*")
        self.lexer.add("MODULUS",r"%")
        self.lexer.add("LEFT_SHIFT",r"<<")
        self.lexer.add("RIGHT_SHIFT",r">>")
        self.lexer.add("NOT_EQUAL_TO",r"!=")
        self.lexer.add("NOT",r"!")
        self.lexer.add("XOR",r"\^")
        self.lexer.add("NEGATE",r"~")
        self.lexer.add("SEMICOLON",r";")
        self.lexer.add("RETURN",r"\breturn\b")
        self.lexer.add("GOTO",r"\bgoto\b")
        self.lexer.add("IF",r"\bif\b")
        self.lexer.add("ELSE",r"\belse\b")
        self.lexer.add("GEQ",r">=")
        self.lexer.add("LEQ",r"<=")
        self.lexer.add("GREATER_THAN",r">")
        self.lexer.add("LESS_THAN",r"<")
        self.lexer.add("EQUAL_TO",r"={2}")
        self.lexer.add("EQUALS",r"=")
        self.lexer.add("NULL",r"\bNULL\b")
        self.lexer.add("KEYWORD","\b(const|signed|static|unsigned|extern)\b")
        self.lexer.add("COMMA",r",")
        self.lexer.add("COLON",r":")
        self.lexer.add("AND",r"&{2}")
        self.lexer.add("OR",r"\|{2}")
        self.lexer.add("BW_AND",r"&")
        self.lexer.add("BW_OR",r"\|")
        self.lexer.add("TYPE",r"\b(auto|long double|double|float|long long( int)?|long|int|short|char|void)\b")
        self.lexer.add("VAR_NAME",r"tV_[a-zA-Z_]\w*|rV_[a-zA-Z_]\w*")
        self.lexer.add("OPEN_PAREN",r"\(")
        self.lexer.add("CLOSE_PAREN",r"\)")
        self.lexer.add("OPEN_BRACK",r"\{")
        self.lexer.add("CLOSE_BRACK",r"\}")
        self.lexer.ignore(r'\s+')
        self.lexer.ignore(r'\n')
        self.lexer.ignore(r'\t')


    def get_lexer(self):
        """
        Retrieves the lexer, with the tokens added to the inner lexer object.

        Returns:
            The lexer, now built with the tokens added
        """
        self._add_tokens()
        return self.lexer.build()

Methods

def get_lexer(self)

Retrieves the lexer, with the tokens added to the inner lexer object.

Returns

The lexer, now built with the tokens added
 
Expand source code
def get_lexer(self):
    """
    Retrieves the lexer, with the tokens added to the inner lexer object.

    Returns:
        The lexer, now built with the tokens added
    """
    self._add_tokens()
    return self.lexer.build()
class ParseTree (token, content)

ParseTree is a class that acts as each node in an ParseTree

Construct a new ParseTree object

Args

token
The token type of the node.
content
The content of that is tokenized.
Expand source code
class ParseTree():
    """
    ParseTree is a class that acts as each node in an ParseTree
    """
    def __init__(self, token, content):
        """
        Construct a new ParseTree object

        Args:
            token: The token type of the node.
            content: The content of that is tokenized.
        """
        self.token = token
        self.content = content

    def print_ParseTree(self, file=None, _prefix="", _last=True):
        """
        Prints the ParseTree in depth first order

        Args:
            file: The file to be written to (Defaults to Stdout).
            _prefix: A string indicating the spacing from the left side of the screen.
            _last: A boolean that indicates if a self is the last in it's immediate surroundings.
        """
        print(f"{_prefix}{'`-- ' if _last else '|-- '}{self.token}", file=file)
        _prefix += "    " if _last else "|   "
        for i, child in enumerate(self.content):
            _last = i == len(self.content)-1
            if 'content' in child.__dict__:
                child.print_ParseTree(file, _prefix, _last)
            else:
                print(f"{_prefix}{'`-- ' if _last else '|-- '}{child}", file=file)

    def __str__(self):
        """
        Produces a string representation of the Parse Tree
        """
        li = []

        ntv = [("", self, True)]

        while ntv:
            li.append(ntv[0])

            ntv = [(f"{ntv[0][0]}{'    ' if ntv[0][2] else '|   '}", x, i == len(ntv[0][1].content)-1 ) for i, x in enumerate(ntv[0][1].content)] + ntv[1:] if 'content' in ntv[0][1].__dict__ else ntv[1:]

        return "".join([f"{x[0]}{'`-- ' if x[2] else '|-- '}{x[1].token if 'token' in x[1].__dict__ else x[1]}" for x in li]) + ""

    def __repr__(self):
        """
        Constructs a list based string representation of the parse tree
        """

        li = []

        ntv = [(1, self)]

        while ntv:
            li.append((ntv[0][0], ntv[0][1].content))

            ntv = [(ntv[0][0]+1, x) for x in ntv[0][1].content if 'content' in x.__dict__] + ntv[1:]

        return "".join([f"{x[0]} : {[y.token if 'content' in y.__dict__ else y for y in x[1]]}" for x in li])

    def getListView(self, level):
        """
        Prints a simple list version of the tree for output. Calls itself recursively

        Args:
            level: The current level of the tree.
        """

        li = []
        li.append(f"{level+1} : {[x if 'content' not in x.__dict__ else x.token for x in self.content]}")

        for x in self.content:
            if "content" in x.__dict__:
                li.extend(x.getListView(level+1))

        if level == 0:
            return "".join(li)
        return li

Methods

def getListView(self, level)

Prints a simple list version of the tree for output. Calls itself recursively

Args

level
The current level of the tree.
Expand source code
def getListView(self, level):
    """
    Prints a simple list version of the tree for output. Calls itself recursively

    Args:
        level: The current level of the tree.
    """

    li = []
    li.append(f"{level+1} : {[x if 'content' not in x.__dict__ else x.token for x in self.content]}")

    for x in self.content:
        if "content" in x.__dict__:
            li.extend(x.getListView(level+1))

    if level == 0:
        return "".join(li)
    return li
def print_ParseTree(self, file=None)

Prints the ParseTree in depth first order

Args

file
The file to be written to (Defaults to Stdout).
_prefix
A string indicating the spacing from the left side of the screen.
_last
A boolean that indicates if a self is the last in it's immediate surroundings.
Expand source code
def print_ParseTree(self, file=None, _prefix="", _last=True):
    """
    Prints the ParseTree in depth first order

    Args:
        file: The file to be written to (Defaults to Stdout).
        _prefix: A string indicating the spacing from the left side of the screen.
        _last: A boolean that indicates if a self is the last in it's immediate surroundings.
    """
    print(f"{_prefix}{'`-- ' if _last else '|-- '}{self.token}", file=file)
    _prefix += "    " if _last else "|   "
    for i, child in enumerate(self.content):
        _last = i == len(self.content)-1
        if 'content' in child.__dict__:
            child.print_ParseTree(file, _prefix, _last)
        else:
            print(f"{_prefix}{'`-- ' if _last else '|-- '}{child}", file=file)
class Parser

Definition for the Parser object, works off of rply. Contains rules for parsing a gimple IR.

Initializes the parser and tells it the allowed tokens

Expand source code
class Parser():
    """
    Definition for the Parser object, works off of rply. Contains rules for parsing a gimple IR.
    """

    def __init__(self):
        """
        Initializes the parser and tells it the allowed tokens

        """

        self.pg = ParserGenerator(
            ['PROGRAM','VAR_NAME','OPEN_PAREN','CLOSE_PAREN','OPEN_BRACK','CLOSE_BRACK','FUNCTION_DEF','TYPE','COMMA','PARAMATERS','PARAMETERS','CONTENT','D_NUM','SEMICOLON','LINE','EQUALS','STRING','CHAR','MINUS','PLUS','NEGATE','NOT','NULL','RETURN','IF','GOTO','LESS_THAN','GREATER_THAN','ELSE','COLON','KEWORD','CONDITION','FUNC_CALL','FUNC_INPUT','COMP','EQUAL_TO','LEQ','GEQ','NOT_EQUAL_TO','OP','DIVIDE','TIMES','MODULUS','BW_AND','BW_OR','LEFT_SHIFT','RIGHT_SHIFT','XOR','INT','DIG','FLOAT'] ,
        )
        #initialzie head and current node
        self.Head = None
        self.ls = []


    def parse(self):
        """
        The list of BNF functions and their behavior for the gimple IR.
        """

        @self.pg.production('program : function_def ')
        def program___function_def_(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('program : function_def program ')
        def program___function_def_program_(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('program :  ')
        def program____(p):
            newNode = ParseTree("PROGRAM",p)
            self.Head = newNode
            return newNode

        @self.pg.production('function_def : VAR_NAME OPEN_PAREN parameters CLOSE_PAREN OPEN_BRACK content CLOSE_BRACK ')
        def function_def___VAR_NAME_OPEN_PAREN_parameters_CLOSE_PAREN_OPEN_BRACK_content_CLOSE_BRACK_(p):

            newNode = ParseTree("FUNCTION_DEF",p)
            self.Head = newNode
            #first, convert parameters to a string form
            #also, get the string representation of VAR_NAME

            tokens = []
            tokens += [x.value for x in p[2].content if isinstance(x,Token)]
            tokenSets = [x for x in p[2].content if isinstance(x,ParseTree)]
            while tokenSets != []:
                for i in tokenSets:
                    tokens += [x.value for x in i.content if isinstance(x,Token)]
                    tokenSets = [x for x in i.content if isinstance(x,ParseTree)]


            functioName = p[0].value
            params = " ".join(tokens)
            IRNodeToReturn = irl.IRFunctionDecl(functioName,params)
            self.ls.append(IRNodeToReturn)
            return newNode

        @self.pg.production('parameters : TYPE VAR_NAME COMMA parameters ')
        def parameters___TYPE_VAR_NAME_COMMA_parameters_(p):
            newNode = ParseTree("PARAMATERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('parameters : TYPE VAR_NAME ')
        def parameters___TYPE_VAR_NAME_(p):
            newNode = ParseTree("PARAMETERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('parameters : ')
        def parameters___(p):
            newNode = ParseTree("PARAMETERS",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : line ')
        def content___line_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : content content ')
        def content___content_content_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : ')
        def content___(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('content : OPEN_BRACK content CLOSE_BRACK ')
        def content___OPEN_BRACK_content_CLOSE_BRACK_(p):
            newNode = ParseTree("CONTENT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('line : TYPE D_NUM SEMICOLON ')
        def line___TYPE_D_NUM_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            typ = p[0]
            name = p[1]
            IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
            self.ls.append(IRNodeToReturn)

            return newNode

        @self.pg.production('line : TYPE VAR_NAME SEMICOLON ')
        def line___TYPE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #needs modifiers, type, and varname
            #modifiers is none
            typ = p[0]
            name = p[1]
            IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
            self.ls.append(IRNodeToReturn)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig op dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_op_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].content[0].value
            rhs = p[4].content[0].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].content[0].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS STRING SEMICOLON ')
        def line___VAR_NAME_EQUALS_STRING_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS CHAR SEMICOLON ')
        def line___VAR_NAME_EQUALS_CHAR_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_op_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].value
            rhs = p[4].content[0].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS dig op VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_dig_op_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].content[0].value
            rhs = p[4].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_VAR_NAME_op_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = p[2].value
            rhs = p[4].value
            op = p[3].content[0].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS MINUS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_MINUS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS MINUS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_MINUS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS PLUS dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_PLUS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : VAR_NAME EQUALS PLUS VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_PLUS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = 0
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NEGATE dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_NEGATE_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NOT dig SEMICOLON ')
        def line___VAR_NAME_EQUALS_NOT_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].content[0].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NOT VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_NOT_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode

            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NEGATE VAR_NAME SEMICOLON ')
        def line___VAR_NAME_EQUALS_NEGATE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            IRNodeToBeReturned = irl.IRArth(None,None,None)
            varName = p[0].value
            lhs = ""
            rhs = p[3].value
            op = p[2].value

            IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS NULL SEMICOLON ')
        def line___VAR_NAME_EQUALS_NULL_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)

            return newNode

        @self.pg.production('line : D_NUM EQUALS VAR_NAME SEMICOLON ')
        def line___D_NUM_EQUALS_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS dig SEMICOLON ')
        def line___D_NUM_EQUALS_dig_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].content[0].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS STRING SEMICOLON ')
        def line___D_NUM_EQUALS_STRING_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : D_NUM EQUALS CHAR SEMICOLON ')
        def line___D_NUM_EQUALS_CHAR_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[0].value
            rhs = p[2].value
            NodeToBeReturned = irl.IRAssignment(lhs,rhs)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : RETURN D_NUM SEMICOLON ')
        def line___RETURN_D_NUM_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #just needs value, should be p[1]
            value = p[1].value
            NodeToBeReturned = irl.IRReturn(value)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('line : func_call SEMICOLON ')
        def line___func_call_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            func_name = p[0].content[0].value
            contentList = p[0].content[2]
            params = []
            while contentList != []:
                # print("SJSD")
                params.append(contentList.content[0].value)
                if(len(contentList.content) == 3):
                    contentList = contentList.content[2]
                else:
                    contentList =[]
            #NEED TO IDENTIF WHAT IR NODE THIS BECOMES, WE HAVE THE PARAMS AND THE NAME
            return newNode

        @self.pg.production('line : VAR_NAME EQUALS func_call SEMICOLON ')
        def line___VAR_NAME_EQUALS_func_call_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            func_name = p[2].content[0].value
            contentList = p[2].content[2]
            params = []
            lhs = p[0].value
            while contentList != []:
                params.append(contentList.content[0].value)
                if(len(contentList.content) == 3):
                    contentList = contentList.content[2]
                else:
                    contentList =[]
            IRNodeToBeReturned = irl.IRFunctionAssign(None,None,None)
            IRNodeToBeReturned.LineFromFile(lhs,func_name,params)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : IF OPEN_PAREN condition CLOSE_PAREN GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ELSE GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
        def line___IF_OPEN_PAREN_condition_CLOSE_PAREN_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_ELSE_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            lhs = p[2].content[0].value
            rhs = p[2].content[2].value
            compOp = p[2].content[1].content[0].value
            succ = p[6].value.split(".")[1]
            fail = p[12].value.split(".")[1]
            IRNodeToBeReturned = irl.IRIf(None,None,None,None)
            IRNodeToBeReturned.fileInit(lhs,rhs,compOp,succ,fail)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : LESS_THAN D_NUM GREATER_THAN COLON ')
        def line___LESS_THAN_D_NUM_GREATER_THAN_COLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            #name of the label
            nameLabel = p[1].value
            IRNodeToBeReturned = irl.IRJump(nameLabel)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
        def line___GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            name = "".join([p[1].value, p[2].value, p[3].value])
            IRNodeToBeReturned = irl.IRGoTo(name)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : GOTO VAR_NAME SEMICOLON ')
        def line___GOTO_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            name = p[1].value
            IRNodeToBeReturned = irl.IRGoTo(name)
            self.ls.append(IRNodeToBeReturned)
            return newNode

        @self.pg.production('line : VAR_NAME COLON ')
        def line___VAR_NAME_COLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            nameLabel = p[0].value
            IRNodeToBeReturned = irl.IRJump(nameLabel)
            self.ls.append(IRNodeToBeReturned)

            return newNode

        @self.pg.production('line : KEWORD TYPE VAR_NAME SEMICOLON ')
        def line___KEWORD_TYPE_VAR_NAME_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            return newNode

        @self.pg.production('line : RETURN SEMICOLON ')
        def line___RETURN_SEMICOLON_(p):
            newNode = ParseTree("LINE",p)
            self.Head = newNode
            value = ""
            NodeToBeReturned = irl.IRReturn(value)
            self.ls.append(NodeToBeReturned)
            return newNode

        @self.pg.production('condition : VAR_NAME comp VAR_NAME ')
        def condition___VAR_NAME_comp_VAR_NAME_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : VAR_NAME comp dig ')
        def condition___VAR_NAME_comp_dig_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : dig comp dig ')
        def condition___dig_comp_dig_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('condition : dig comp VAR_NAME ')
        def condition___dig_comp_VAR_NAME_(p):
            newNode = ParseTree("CONDITION",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_call : VAR_NAME OPEN_PAREN func_input CLOSE_PAREN ')
        def func_call___VAR_NAME_OPEN_PAREN_func_input_CLOSE_PAREN_(p):
            newNode = ParseTree("FUNC_CALL",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : ')
        def func_input___(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : STRING COMMA func_input ')
        def func_input___STRING_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : CHAR COMMA func_input ')
        def func_input___CHAR_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : dig COMMA func_input ')
        def func_input___dig_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : VAR_NAME COMMA func_input ')
        def func_input___VAR_NAME_COMMA_func_input_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : STRING  ')
        def func_input___STRING__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : CHAR  ')
        def func_input___CHAR__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : dig  ')
        def func_input___dig__(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('func_input : VAR_NAME ')
        def func_input___VAR_NAME_(p):
            newNode = ParseTree("FUNC_INPUT",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : LESS_THAN ')
        def comp___LESS_THAN_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : GREATER_THAN ')
        def comp___GREATER_THAN_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : EQUAL_TO ')
        def comp___EQUAL_TO_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : LEQ ')
        def comp___LEQ_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : GEQ ')
        def comp___GEQ_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('comp : NOT_EQUAL_TO ')
        def comp___NOT_EQUAL_TO_(p):
            newNode = ParseTree("COMP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : PLUS ')
        def op___PLUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : MINUS ')
        def op___MINUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : DIVIDE ')
        def op___DIVIDE_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : TIMES ')
        def op___TIMES_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : MODULUS ')
        def op___MODULUS_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : BW_AND ')
        def op___BW_AND_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : BW_OR ')
        def op___BW_OR_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : NEGATE ')
        def op___NEGATE_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : LEFT_SHIFT ')
        def op___LEFT_SHIFT_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : RIGHT_SHIFT ')
        def op___RIGHT_SHIFT_(p):
            newNode = ParseTree("OP",p)
            self.Head = newNode
            return newNode

        @self.pg.production('op : XOR ')
        def op___XOR_(p):
            newNode = ParseTree("",p)
            self.Head = newNode
            return newNode

        @self.pg.production('dig : INT ')
        def dig___INT_(p):
            newNode = ParseTree("DIG",p)
            self.Head = newNode
            return newNode

        @self.pg.production('dig : FLOAT ')
        def dig___FLOAT_(p):
            newNode = ParseTree("DIG",p)
            self.Head = newNode
            return newNode


        @self.pg.error
        def error_handle(token):
            """
            Boilerplate error handling function

            Args:
                token: The token that caused an error.
            """
            return ValueError(token)

    #boilerplate function
    def get_parser(self):
        """
        Retrieves the built version of the parser.

        Returns:
            The built parser.
        """
        return self.pg.build()

    #retrieve the trees head
    def getTree(self):
        """
        Getter for the head of the tree.

        Returns:
            The head of the tree.
        """

        return self.Head

    def print_error(self):
        """
        Prints parser error message. This function ultimately iterates through the ParseTree that was returned after the parser found an error. ParseTree's consist of tokens as well as other ParseTree's so we need to iterate to find the first token and then print its source position.
        """
        # TODO: add some more in-depth error processing to print
        # out a more detailed description of what went wrong, and possibly some suggestions
        # at to why there was a parse/syntax error. (i.e. suggest a missing semicolon)

        head = self.getTree()
        token = 0 # token hasn't been found yet, so we set value to 0

        while True and head:
            # Iterate through list of elements
            for i in head.content:

                # Could be a Token
                if(type(i) == type(Token("sample", "sample"))):

                    # Found a Token
                    token = i
                    break

            # Check again (to break out of while loop and not iterate again)
            if (type(token) == type(Token("sample", "sample"))):
                break
            else:
                # Set head to last element.
                # If this code executes then I can assume that the
                # last element is an ParseTree.
                head = head.content[len(head.content)-1]

        if token:
            print(f"ParsingError: Last token  \'{token.value}\' parsed successfully at, {token.source_pos}\n")
        else:
            # Never found a token to report, need to exit
            print("ParsingError: No ParseTree obtained\n")
            exit()

Methods

def getTree(self)

Getter for the head of the tree.

Returns

The head of the tree.

Expand source code
def getTree(self):
    """
    Getter for the head of the tree.

    Returns:
        The head of the tree.
    """

    return self.Head
def get_parser(self)

Retrieves the built version of the parser.

Returns

The built parser.

Expand source code
def get_parser(self):
    """
    Retrieves the built version of the parser.

    Returns:
        The built parser.
    """
    return self.pg.build()
def parse(self)

The list of BNF functions and their behavior for the gimple IR.

Expand source code
def parse(self):
    """
    The list of BNF functions and their behavior for the gimple IR.
    """

    @self.pg.production('program : function_def ')
    def program___function_def_(p):
        newNode = ParseTree("PROGRAM",p)
        self.Head = newNode
        return newNode

    @self.pg.production('program : function_def program ')
    def program___function_def_program_(p):
        newNode = ParseTree("PROGRAM",p)
        self.Head = newNode
        return newNode

    @self.pg.production('program :  ')
    def program____(p):
        newNode = ParseTree("PROGRAM",p)
        self.Head = newNode
        return newNode

    @self.pg.production('function_def : VAR_NAME OPEN_PAREN parameters CLOSE_PAREN OPEN_BRACK content CLOSE_BRACK ')
    def function_def___VAR_NAME_OPEN_PAREN_parameters_CLOSE_PAREN_OPEN_BRACK_content_CLOSE_BRACK_(p):

        newNode = ParseTree("FUNCTION_DEF",p)
        self.Head = newNode
        #first, convert parameters to a string form
        #also, get the string representation of VAR_NAME

        tokens = []
        tokens += [x.value for x in p[2].content if isinstance(x,Token)]
        tokenSets = [x for x in p[2].content if isinstance(x,ParseTree)]
        while tokenSets != []:
            for i in tokenSets:
                tokens += [x.value for x in i.content if isinstance(x,Token)]
                tokenSets = [x for x in i.content if isinstance(x,ParseTree)]


        functioName = p[0].value
        params = " ".join(tokens)
        IRNodeToReturn = irl.IRFunctionDecl(functioName,params)
        self.ls.append(IRNodeToReturn)
        return newNode

    @self.pg.production('parameters : TYPE VAR_NAME COMMA parameters ')
    def parameters___TYPE_VAR_NAME_COMMA_parameters_(p):
        newNode = ParseTree("PARAMATERS",p)
        self.Head = newNode
        return newNode

    @self.pg.production('parameters : TYPE VAR_NAME ')
    def parameters___TYPE_VAR_NAME_(p):
        newNode = ParseTree("PARAMETERS",p)
        self.Head = newNode
        return newNode

    @self.pg.production('parameters : ')
    def parameters___(p):
        newNode = ParseTree("PARAMETERS",p)
        self.Head = newNode
        return newNode

    @self.pg.production('content : line ')
    def content___line_(p):
        newNode = ParseTree("CONTENT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('content : content content ')
    def content___content_content_(p):
        newNode = ParseTree("CONTENT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('content : ')
    def content___(p):
        newNode = ParseTree("CONTENT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('content : OPEN_BRACK content CLOSE_BRACK ')
    def content___OPEN_BRACK_content_CLOSE_BRACK_(p):
        newNode = ParseTree("CONTENT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('line : TYPE D_NUM SEMICOLON ')
    def line___TYPE_D_NUM_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        typ = p[0]
        name = p[1]
        IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
        self.ls.append(IRNodeToReturn)

        return newNode

    @self.pg.production('line : TYPE VAR_NAME SEMICOLON ')
    def line___TYPE_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        #needs modifiers, type, and varname
        #modifiers is none
        typ = p[0]
        name = p[1]
        IRNodeToReturn = irl.IRVariableInit("",typ.value, name.value)
        self.ls.append(IRNodeToReturn)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS dig op dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_dig_op_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = p[2].content[0].value
        rhs = p[4].content[0].value
        op = p[3].content[0].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].content[0].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS STRING SEMICOLON ')
    def line___VAR_NAME_EQUALS_STRING_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS CHAR SEMICOLON ')
    def line___VAR_NAME_EQUALS_CHAR_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_VAR_NAME_op_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = p[2].value
        rhs = p[4].content[0].value
        op = p[3].content[0].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS dig op VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_dig_op_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = p[2].content[0].value
        rhs = p[4].value
        op = p[3].content[0].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS VAR_NAME op VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_VAR_NAME_op_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = p[2].value
        rhs = p[4].value
        op = p[3].content[0].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS MINUS dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_MINUS_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = 0
        rhs = p[3].content[0].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS MINUS VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_MINUS_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode

        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = 0
        rhs = p[3].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS PLUS dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_PLUS_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode

        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = 0
        rhs = p[3].content[0].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : VAR_NAME EQUALS PLUS VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_PLUS_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = 0
        rhs = p[3].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS NEGATE dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_NEGATE_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = ""
        rhs = p[3].content[0].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS NOT dig SEMICOLON ')
    def line___VAR_NAME_EQUALS_NOT_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode

        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = ""
        rhs = p[3].content[0].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS NOT VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_NOT_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode

        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = ""
        rhs = p[3].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS NEGATE VAR_NAME SEMICOLON ')
    def line___VAR_NAME_EQUALS_NEGATE_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        IRNodeToBeReturned = irl.IRArth(None,None,None)
        varName = p[0].value
        lhs = ""
        rhs = p[3].value
        op = p[2].value

        IRNodeToBeReturned.fileInit(lhs,op,rhs,varName)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS NULL SEMICOLON ')
    def line___VAR_NAME_EQUALS_NULL_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)

        return newNode

    @self.pg.production('line : D_NUM EQUALS VAR_NAME SEMICOLON ')
    def line___D_NUM_EQUALS_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : D_NUM EQUALS dig SEMICOLON ')
    def line___D_NUM_EQUALS_dig_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].content[0].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : D_NUM EQUALS STRING SEMICOLON ')
    def line___D_NUM_EQUALS_STRING_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : D_NUM EQUALS CHAR SEMICOLON ')
    def line___D_NUM_EQUALS_CHAR_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[0].value
        rhs = p[2].value
        NodeToBeReturned = irl.IRAssignment(lhs,rhs)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : RETURN D_NUM SEMICOLON ')
    def line___RETURN_D_NUM_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        #just needs value, should be p[1]
        value = p[1].value
        NodeToBeReturned = irl.IRReturn(value)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('line : func_call SEMICOLON ')
    def line___func_call_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        func_name = p[0].content[0].value
        contentList = p[0].content[2]
        params = []
        while contentList != []:
            # print("SJSD")
            params.append(contentList.content[0].value)
            if(len(contentList.content) == 3):
                contentList = contentList.content[2]
            else:
                contentList =[]
        #NEED TO IDENTIF WHAT IR NODE THIS BECOMES, WE HAVE THE PARAMS AND THE NAME
        return newNode

    @self.pg.production('line : VAR_NAME EQUALS func_call SEMICOLON ')
    def line___VAR_NAME_EQUALS_func_call_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        func_name = p[2].content[0].value
        contentList = p[2].content[2]
        params = []
        lhs = p[0].value
        while contentList != []:
            params.append(contentList.content[0].value)
            if(len(contentList.content) == 3):
                contentList = contentList.content[2]
            else:
                contentList =[]
        IRNodeToBeReturned = irl.IRFunctionAssign(None,None,None)
        IRNodeToBeReturned.LineFromFile(lhs,func_name,params)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : IF OPEN_PAREN condition CLOSE_PAREN GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ELSE GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
    def line___IF_OPEN_PAREN_condition_CLOSE_PAREN_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_ELSE_GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        lhs = p[2].content[0].value
        rhs = p[2].content[2].value
        compOp = p[2].content[1].content[0].value
        succ = p[6].value.split(".")[1]
        fail = p[12].value.split(".")[1]
        IRNodeToBeReturned = irl.IRIf(None,None,None,None)
        IRNodeToBeReturned.fileInit(lhs,rhs,compOp,succ,fail)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : LESS_THAN D_NUM GREATER_THAN COLON ')
    def line___LESS_THAN_D_NUM_GREATER_THAN_COLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        #name of the label
        nameLabel = p[1].value
        IRNodeToBeReturned = irl.IRJump(nameLabel)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : GOTO LESS_THAN D_NUM GREATER_THAN SEMICOLON ')
    def line___GOTO_LESS_THAN_D_NUM_GREATER_THAN_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        name = "".join([p[1].value, p[2].value, p[3].value])
        IRNodeToBeReturned = irl.IRGoTo(name)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : GOTO VAR_NAME SEMICOLON ')
    def line___GOTO_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        name = p[1].value
        IRNodeToBeReturned = irl.IRGoTo(name)
        self.ls.append(IRNodeToBeReturned)
        return newNode

    @self.pg.production('line : VAR_NAME COLON ')
    def line___VAR_NAME_COLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        nameLabel = p[0].value
        IRNodeToBeReturned = irl.IRJump(nameLabel)
        self.ls.append(IRNodeToBeReturned)

        return newNode

    @self.pg.production('line : KEWORD TYPE VAR_NAME SEMICOLON ')
    def line___KEWORD_TYPE_VAR_NAME_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        return newNode

    @self.pg.production('line : RETURN SEMICOLON ')
    def line___RETURN_SEMICOLON_(p):
        newNode = ParseTree("LINE",p)
        self.Head = newNode
        value = ""
        NodeToBeReturned = irl.IRReturn(value)
        self.ls.append(NodeToBeReturned)
        return newNode

    @self.pg.production('condition : VAR_NAME comp VAR_NAME ')
    def condition___VAR_NAME_comp_VAR_NAME_(p):
        newNode = ParseTree("CONDITION",p)
        self.Head = newNode
        return newNode

    @self.pg.production('condition : VAR_NAME comp dig ')
    def condition___VAR_NAME_comp_dig_(p):
        newNode = ParseTree("CONDITION",p)
        self.Head = newNode
        return newNode

    @self.pg.production('condition : dig comp dig ')
    def condition___dig_comp_dig_(p):
        newNode = ParseTree("CONDITION",p)
        self.Head = newNode
        return newNode

    @self.pg.production('condition : dig comp VAR_NAME ')
    def condition___dig_comp_VAR_NAME_(p):
        newNode = ParseTree("CONDITION",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_call : VAR_NAME OPEN_PAREN func_input CLOSE_PAREN ')
    def func_call___VAR_NAME_OPEN_PAREN_func_input_CLOSE_PAREN_(p):
        newNode = ParseTree("FUNC_CALL",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : ')
    def func_input___(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : STRING COMMA func_input ')
    def func_input___STRING_COMMA_func_input_(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : CHAR COMMA func_input ')
    def func_input___CHAR_COMMA_func_input_(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : dig COMMA func_input ')
    def func_input___dig_COMMA_func_input_(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : VAR_NAME COMMA func_input ')
    def func_input___VAR_NAME_COMMA_func_input_(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : STRING  ')
    def func_input___STRING__(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : CHAR  ')
    def func_input___CHAR__(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : dig  ')
    def func_input___dig__(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('func_input : VAR_NAME ')
    def func_input___VAR_NAME_(p):
        newNode = ParseTree("FUNC_INPUT",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : LESS_THAN ')
    def comp___LESS_THAN_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : GREATER_THAN ')
    def comp___GREATER_THAN_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : EQUAL_TO ')
    def comp___EQUAL_TO_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : LEQ ')
    def comp___LEQ_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : GEQ ')
    def comp___GEQ_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('comp : NOT_EQUAL_TO ')
    def comp___NOT_EQUAL_TO_(p):
        newNode = ParseTree("COMP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : PLUS ')
    def op___PLUS_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : MINUS ')
    def op___MINUS_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : DIVIDE ')
    def op___DIVIDE_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : TIMES ')
    def op___TIMES_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : MODULUS ')
    def op___MODULUS_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : BW_AND ')
    def op___BW_AND_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : BW_OR ')
    def op___BW_OR_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : NEGATE ')
    def op___NEGATE_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : LEFT_SHIFT ')
    def op___LEFT_SHIFT_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : RIGHT_SHIFT ')
    def op___RIGHT_SHIFT_(p):
        newNode = ParseTree("OP",p)
        self.Head = newNode
        return newNode

    @self.pg.production('op : XOR ')
    def op___XOR_(p):
        newNode = ParseTree("",p)
        self.Head = newNode
        return newNode

    @self.pg.production('dig : INT ')
    def dig___INT_(p):
        newNode = ParseTree("DIG",p)
        self.Head = newNode
        return newNode

    @self.pg.production('dig : FLOAT ')
    def dig___FLOAT_(p):
        newNode = ParseTree("DIG",p)
        self.Head = newNode
        return newNode


    @self.pg.error
    def error_handle(token):
        """
        Boilerplate error handling function

        Args:
            token: The token that caused an error.
        """
        return ValueError(token)
def print_error(self)

Prints parser error message. This function ultimately iterates through the ParseTree that was returned after the parser found an error. ParseTree's consist of tokens as well as other ParseTree's so we need to iterate to find the first token and then print its source position.

Expand source code
def print_error(self):
    """
    Prints parser error message. This function ultimately iterates through the ParseTree that was returned after the parser found an error. ParseTree's consist of tokens as well as other ParseTree's so we need to iterate to find the first token and then print its source position.
    """
    # TODO: add some more in-depth error processing to print
    # out a more detailed description of what went wrong, and possibly some suggestions
    # at to why there was a parse/syntax error. (i.e. suggest a missing semicolon)

    head = self.getTree()
    token = 0 # token hasn't been found yet, so we set value to 0

    while True and head:
        # Iterate through list of elements
        for i in head.content:

            # Could be a Token
            if(type(i) == type(Token("sample", "sample"))):

                # Found a Token
                token = i
                break

        # Check again (to break out of while loop and not iterate again)
        if (type(token) == type(Token("sample", "sample"))):
            break
        else:
            # Set head to last element.
            # If this code executes then I can assume that the
            # last element is an ParseTree.
            head = head.content[len(head.content)-1]

    if token:
        print(f"ParsingError: Last token  \'{token.value}\' parsed successfully at, {token.source_pos}\n")
    else:
        # Never found a token to report, need to exit
        print("ParsingError: No ParseTree obtained\n")
        exit()
class import_ir (filename)

This function initializes the object that imports the IR, it takes in the filename of the file being imported.

Args

filename
The filename of the IR
Expand source code
class import_ir():
    def __init__(self, filename):
        """
        This function initializes the object that imports the IR, it takes in the filename of the file being imported.

        Args:
            filename: The filename of the IR

        """
        self.IR = []
        with open(filename,"r") as fd:
            self.data = fd.read()
            self.tokens = None

    def tokenize(self):
        """
        This will tokenize the IR that has been read in.

        """

        text_input = self.data.strip()
        lexer = IR_Lexer().get_lexer()
        tokens = lexer.lex(text_input)
        self.tokens = tokens

    def parse(self):
        """
        This function parses the IR after it has been tokenized, and returns the list of lines in the IR as IRNodes

        Returns:
            A list of the IRNodes that make up this IR file
        """

        pg = Parser()
        pg.parse()
        parser = pg.get_parser()
        parser.parse(self.tokens)

        head = pg.getTree()
        # here, sort the list of IRNodes that have been generated by the parser,
        # since the bottom up nature of the parse means it will parse function_definitions after lines
        finalLs = []
        tempLs = []
        for i in pg.ls:
            if(isinstance(i,irl.IRFunctionDecl)):
                tempLs.insert(0,i)
                tempLs.insert(1,irl.IRBracket(True))
                finalLs += tempLs
                finalLs.append(irl.IRBracket(False))
                tempLs = []
            else:
                tempLs.append(i)
        for i in finalLs:
            toAdd = irl.IRLine(None)
            toAdd.treeList = [i]
            self.IR.append(toAdd)
        return finalLs

    def __str__(self):
        return "\n".join([str(x) for x in finalLs])

Methods

def parse(self)

This function parses the IR after it has been tokenized, and returns the list of lines in the IR as IRNodes

Returns

A list of the IRNodes that make up this IR file
 
Expand source code
def parse(self):
    """
    This function parses the IR after it has been tokenized, and returns the list of lines in the IR as IRNodes

    Returns:
        A list of the IRNodes that make up this IR file
    """

    pg = Parser()
    pg.parse()
    parser = pg.get_parser()
    parser.parse(self.tokens)

    head = pg.getTree()
    # here, sort the list of IRNodes that have been generated by the parser,
    # since the bottom up nature of the parse means it will parse function_definitions after lines
    finalLs = []
    tempLs = []
    for i in pg.ls:
        if(isinstance(i,irl.IRFunctionDecl)):
            tempLs.insert(0,i)
            tempLs.insert(1,irl.IRBracket(True))
            finalLs += tempLs
            finalLs.append(irl.IRBracket(False))
            tempLs = []
        else:
            tempLs.append(i)
    for i in finalLs:
        toAdd = irl.IRLine(None)
        toAdd.treeList = [i]
        self.IR.append(toAdd)
    return finalLs
def tokenize(self)

This will tokenize the IR that has been read in.

Expand source code
def tokenize(self):
    """
    This will tokenize the IR that has been read in.

    """

    text_input = self.data.strip()
    lexer = IR_Lexer().get_lexer()
    tokens = lexer.lex(text_input)
    self.tokens = tokens