Beispiel #1
0
 def __init__(self, list_tokens):
     self.list_tokens = list_tokens
     self.index = -1
     self.flag_do = 0
     self.symbol_table = SymbolTable()  # Semantic
     self.pct = Pct()
     self.scope = 0  # Semantic
Beispiel #2
0
 def __init__(self, tokenizer):
     """ Constructs parser object. """
     self.xml_data = []  # For xml export.
     self.symbol_table = SymbolTable(
     )  # Create symbol table for class scope.
     self.tokenizer = tokenizer  # Tokenizer.
     self.token = None  # Current token.
     self.compile_class()
Beispiel #3
0
def run(id_):
    dir_ = "tests/test%d/" % id_

    options = {
        "input": dir_ + "test.txt",
        "tokens": "tokens.txt",
        "tables": "tables.txt"
    }

    print("\n[*] Running test %d" % id_)

    symbol_table = SymbolTable(options)

    automata = Automata(options, symbol_table)
    automata.run()

    symbol_table.save()

    show_result("Tokens", dir_, options["tokens"])
    show_result("Tables", dir_, options["tables"])
def main():

    for argument in sys.argv[1:]:
        parser = Parser(argument)
        code = Code()
        symbol_table = SymbolTable()
        with open(argument, 'r') as hack_program:
            hack_program = cleanup_commands(parser, hack_program)
            init_labels(symbol_table, parser, hack_program)
            base = os.path.basename(argument)
            file_name = os.path.splitext(base)[0]
            process_translation(symbol_table, code, parser, hack_program, file_name)
            print("*** Assembly Completed ***")
Beispiel #5
0
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("prop", help="Propositional statement")
    arg_parser.add_argument("--tokens", "-t", action="store_true")
    arg_parser.add_argument("--ast", "-a", action="store_true")
    arg_parser.add_argument("--symbols", "-s", action="store_true")
    arg_parser.add_argument("--truthtable", "-tt", nargs='?', const=1, type=int)
    args = arg_parser.parse_args()

    if not args.prop:
        args.prop = " "

    error_collector = ErrorCollector(args.prop)
    symbol_table = SymbolTable()

    tokenizer = Tokenizer(error_collector, symbol_table)

    parser = Parser(tokenizer, error_collector)
    ast = parser.parse()
    
    # Para hacer debug jeje
    if args.symbols:
        symbol_table.show_symbols()

    if error_collector.has_errors():
        error_collector.show_errors()
        return

    if args.tokens:
        tokenizer.show_tokens()

    if args.ast:
        print(ast)
        
    if args.truthtable:
        tt = TruthTable(ast, symbol_table, args.truthtable)
        tt.show()
Beispiel #6
0
class SyntacticAnalyzer(object):
    def __init__(self, list_tokens):
        self.list_tokens = list_tokens
        self.index = -1
        self.flag_do = 0
        self.symbol_table = SymbolTable()  # Semantic
        self.pct = Pct()
        self.scope = 0  # Semantic

    def program(self):
        if self.next_token().token == 'program':
            self.symbol_table.begin_scope()  # Semantic
            if self.next_token().tokenType == 'Identificador':
                self.symbol_table.add_symbol(self.get_token().token,
                                             'program')  # Semantic
                if self.next_token().token == ';':
                    self.variable_declaration()
                    self.subprograms_declarations()
                    self.composed_commands()
                    if self.next_token().token == '.':
                        self.symbol_table.end_scope()  # Semantic
                        print('sucesso')
                    else:
                        self.syntax_error('.')
                else:
                    print(self.get_token().token)
                    self.syntax_error(';')
            else:
                self.syntax_error('Identificador')
        else:
            self.syntax_error('program')

    ''' Help Functions '''

    def previous_token(self):
        if (self.index - 1) > 0:
            return self.list_tokens[self.index - 1]
        else:
            sys.exit("out range")

    def next_token(self):
        if (self.index + 1) < len(self.list_tokens):
            self.index += 1
            return self.list_tokens[self.index]
        else:
            sys.exit("out range")

    def syntax_error(self, expected):
        ct = self.get_token()
        sys.exit(
            'Syntax error, "{}" expected but "{}" found in line {}'.format(
                expected, ct.token, ct.line))

    def get_token(self):
        return self.list_tokens[self.index]

    ''' SyntacticAnalyzer Functions '''

    def variable_declaration(self):
        if self.next_token().token == 'var':
            self.list_var_declarations(True)
        else:
            self.index -= 1

    ''' 
        flag indica a primeira chamada da função, pois
        a partir da segunda chamada não existe erro de 
        identificador.
    '''

    def list_var_declarations(self, flag=False):
        if self.list_identifiers():
            if self.next_token().token == ':':
                self.type()
                if self.next_token().token == ';':
                    self.list_var_declarations()
                else:
                    self.syntax_error(';')
            else:
                self.syntax_error(':')
        elif flag:
            self.syntax_error('Identificador')

    def list_identifiers(self):
        if self.next_token().tokenType == 'Identificador':
            self.verify_scope(self.get_token())  # Semantic
            self.list_identifiers_()
            return True
        else:
            self.index -= 1
            return False

    def list_identifiers_(self):
        if self.next_token().token == ',':
            if self.next_token().tokenType == 'Identificador':
                self.verify_scope(self.get_token())  # Semantic
                self.list_identifiers_()
            else:
                self.syntax_error('Identificador')
        else:
            self.index -= 1

    def type(self):
        if self.next_token().token in ['integer', 'boolean', 'real']:
            self.symbol_table.set_type(self.get_token().token)  # Semantic
            return
        else:
            self.syntax_error('Tipo')

    # Fim da análise de variáveis #

    def subprograms_declarations(self):
        self.subprograms_declarations_()

    def subprograms_declarations_(self):
        if self.subprogram_declaration():
            if self.next_token().token == ';':
                self.subprograms_declarations_()
            else:
                self.syntax_error(';')

    def subprogram_declaration(self):
        if self.next_token().token == 'procedure':
            if self.next_token().tokenType == 'Identificador':
                self.symbol_table.add_symbol(self.get_token().token,
                                             'procedure')  # Semantic
                self.symbol_table.begin_scope()  # Semantic
                self.arguments()
                if self.next_token().token == ';':
                    self.variable_declaration()
                    self.subprograms_declarations()
                    self.composed_commands()
                    return True
                else:
                    self.syntax_error(';')
            else:
                self.syntax_error('Identificador')
        else:
            self.index -= 1

    def arguments(self):
        if self.next_token().token == '(':
            self.list_parameters()
            if self.next_token().token == ')':
                pass
            else:
                self.syntax_error(')')
        else:
            self.index -= 1

    def list_parameters(self):
        self.list_identifiers()
        if self.next_token().token == ':':
            self.type()
            self.list_parameters__()
        else:
            self.syntax_error(':')

    def list_parameters__(self):
        if self.next_token(
        ).token == ';':  # ainda existe mais parâmetros para ser verificado
            self.list_identifiers()
            if self.next_token().token == ':':
                self.type()
                self.list_parameters__()
            else:
                self.syntax_error(':')
        else:
            self.index -= 1
        '''
            se não for ';' significa que terminou a verificação de parâmetros e o próximo
            caractere da lista tem que ser ')' 
        '''

    def composed_commands(self):
        if self.next_token().token == 'begin':
            self.scope += 1  # Semantic
            self.options_commands()
            if self.next_token().token == 'end':
                self.scope -= 1  # Semantic
                if not self.scope:  # Semantic
                    self.symbol_table.end_scope()  # Semantic
                return True
            else:
                self.syntax_error('end')
        else:
            self.index -= 1
            return False

    def options_commands(self):
        self.list_commands()

    def list_commands(self):
        self.command()
        self.list_commands_()

    def list_commands_(self):
        if self.next_token().token == ';':
            self.command()
            self.list_commands_()
        else:
            self.index -= 1

    def command(self):
        if self.variable():
            temp_typeId = self.symbol_table.search_symbol(
                self.get_token().token).type  # Semantic [type_control]
            if self.next_token().token == ':=':
                self.expression()
                self.verify_typesId(temp_typeId,
                                    self.pct.pop())  # Semantic [type_control]
                return
            else:
                self.syntax_error(':=')
        elif self.activation_procedure():
            pass
        elif self.composed_commands():
            pass
        else:
            temp = self.next_token()
            if temp.token == 'if':
                self.expression()
                if self.next_token().token == 'then':
                    self.command()
                    self.part_else()
                    return
                else:
                    self.syntax_error('then')
            elif temp.token == 'while':
                self.expression()
                if self.next_token().token == 'do':
                    self.command()
                    return
                elif self.get_token().token == 'end':
                    self.index -= 1
                    return
                else:
                    self.syntax_error('do')
            elif temp.token == 'do':
                self.list_commands()
            else:
                self.index -= 1
                return False

    def part_else(self):
        self.index += 1
        if self.next_token().token == 'else':
            self.command()
        else:
            self.index -= 1

    def variable(self):
        if self.next_token().tokenType == 'Identificador':
            self.verify_scope(self.get_token())  # Semantic
            return True
        else:
            self.index -= 1
            return False

    def activation_procedure(self):
        if self.next_token().tokenType == 'Identificador':
            if self.next_token().token == '(':
                self.list_expressions()
                if self.next_token().token == ')':
                    return True
                else:
                    self.syntax_error(')')
            else:
                self.index -= 1
                return True
        else:
            self.index -= 1
            return False

    def list_expressions(self):
        self.expression()
        self.list_expressions_()

    def list_expressions_(self):
        if self.next_token().token == ';':
            self.expression()
            self.list_expressions_()
        else:
            self.index -= 1

    def expression(self):
        if self.simple_expression():
            if self.op_relational():
                self.simple_expression()
                ''' Semantic [type_control] '''
                if not self.pct.type_checking_relational():
                    sys.exit(
                        'Error linha {}! Incompatibilidade de tipos: Comparacoes realizadas entre tipos que nao seja integer ou real'
                        .format(self.get_token().line))

        else:
            self.syntax_error('Expressao')

    def simple_expression(self):
        if self.term():
            self.simple_expression_()
            return True
        elif self.signal():
            self.term()
            self.simple_expression_()
            return True
        else:
            return False

    def simple_expression_(self):
        if self.op_additive():
            op = self.get_token().token  # Semantic [type_control]
            self.term()
            self.simple_expression_()
            ''' Semantic [type_control] '''
            if op == 'or':
                if not self.pct.type_checking_logical():
                    sys.exit(
                        'Error linha {}! Incompatibilidade de tipos: Op logicas com outros tipos'
                        .format(self.get_token().line))
            else:
                if not self.pct.type_checking_arithmetic():
                    sys.exit(
                        'Error linha {}! Incompatibilidade de tipos: Op aritimeticas com outros tipos'
                        .format(self.get_token().line))

    def term(self):
        if self.factor():
            self.term_()
            return True
        else:
            return False

    def term_(self):
        if self.op_multi():
            op = self.get_token().token  # Semantic [type_control]
            self.factor()
            self.term_()
            ''' Semantic [type_control] '''
            if op == 'and':
                if not self.pct.type_checking_logical():
                    sys.exit(
                        'Error linha {}! Incompatibilidade de tipos: Op logicas com outros tipos'
                        .format(self.get_token().line))
            else:
                if not self.pct.type_checking_arithmetic():
                    sys.exit(
                        'Error linha {}! Incompatibilidade de tipos: Op aritimeticas com outros tipos'
                        .format(self.get_token().line))

    def factor(self):
        temp = self.next_token()
        if temp.tokenType == 'Identificador':
            self.verify_scope(self.get_token())  # Semantic
            self.pct.push(
                self.symbol_table.search_symbol(
                    self.get_token().token).type)  # Semantic [type_control]

            if self.next_token() == '(':
                self.list_expressions()
                if self.next_token().token == ')':
                    return True
                else:
                    self.syntax_error(')')
            else:
                self.index -= 1
                return True
        elif temp.tokenType == 'Numero inteiro':
            self.pct.push('integer')  # Semantic [type_control]
            return True
        elif temp.tokenType == 'Numero real':
            self.pct.push('real')  # Semantic [type_control]
            return True
        elif temp.token in ['true', 'false']:
            self.pct.push('boolean')  # Semantic [type_control]
            return True
        elif temp.token == '(':
            self.expression()
            if self.next_token().token == ')':
                return True
            else:
                self.syntax_error(')')
        elif temp.token == 'not':
            self.factor()
            return True
        else:
            self.index -= 1
            return False

    def signal(self):
        if self.next_token().token in "+-":
            return True
        else:
            self.index -= 1
            return False

    def op_relational(self):
        if self.next_token().tokenType == 'Operador relacional':
            return True
        else:
            self.index -= 1
            return False

    def op_additive(self):
        if self.next_token().tokenType == 'Operador aditivo':
            return True
        else:
            self.index -= 1
            return False

    def op_multi(self):
        if self.next_token().tokenType == 'Operador multiplicativo':
            return True
        else:
            self.index -= 1
            return False

    ''' Semantic '''

    def verify_typesId(self, type_id, pct_top):
        line = self.get_token().line
        if type_id == 'integer' and pct_top == 'real':
            sys.exit(
                'Erro linha {}! Incompatibilade de tipos: Atribuindo um valor real a uma variável inteira'
                .format(line))
        if type_id in ['integer', 'real'] == pct_top == 'boolean':
            sys.exit(
                'Erro linha {}! Incompatibilade de tipos: Atribuindo um valor booleano a uma variável {}'
                .format(line, type_id))
        if type_id == 'boolean' and pct_top in ['integer', 'real']:
            sys.exit(
                'Erro linha {}! Incompatibilade de tipos: Atribuindo um valor {} em uma variavel boolean'
                .format(line, pct_top))

        self.pct.pop()

    def verify_scope(self, symbol):
        if self.scope:
            symbol_temp = self.symbol_table.search_symbol(symbol.token)
            if not symbol_temp:
                sys.exit('Erro linha {}! Simbolo {} nao declarado'.format(
                    symbol.line, symbol.token))
            elif symbol_temp.type == 'program':
                sys.exit(
                    'ERRO! O nome do programa nao pode ser usado em comandos e expressoes'
                )
        else:
            if not self.symbol_table.add_symbol(symbol.token, '?'):
                sys.exit(
                    "Erro linha {}! Simbolo {} ja foi declarado no mesmo escopo"
                    .format(symbol.line, symbol.token))
Beispiel #7
0
class Parser(object):
    def __init__(self, tokenizer):
        """ Constructs parser object. """
        self.xml_data = []  # For xml export.
        self.symbol_table = SymbolTable(
        )  # Create symbol table for class scope.
        self.tokenizer = tokenizer  # Tokenizer.
        self.token = None  # Current token.
        self.compile_class()

    def check_for_value(self, value):
        """ Check if current token has expected value. """
        self.token = self.tokenizer.advance()
        if self.token.value != value:
            raise Exception(
                "Error: Excpected value => '{0}' but got => '{1}'".format(
                    value, self.token.value))

        if self.token.value in XML_REPLACE.keys():
            self.xml_data.append("<{0}> {1} </{0}>".format(
                self.token.type, XML_REPLACE[self.token.value]))
        else:
            self.xml_data.append(self.token.__str__())

    def check_for_identifier(self):
        """ Check if current token is valid identifier. """
        self.token = self.tokenizer.advance()
        if self.token.type != "identifier" or (not re.match(
                R_IDENTIFIER, self.token.value)):
            raise Exception("Error: Identifier name not valid => '{0}'".format(
                self.token.value))
        self.xml_data.append(self.token.__str__())

    def check_for_type(self):
        """ Check if current token has valid type. """
        self.token = self.tokenizer.advance()
        if self.token.value not in list(TYPES) + CLASSES:
            raise Exception("Error: Not valid type => '{0}'".format(
                self.token.value))
        self.xml_data.append(self.token.__str__())

    def check_for_operator(self):
        """ Check if current token is operator. """
        self.token = self.tokenizer.advance()
        if self.token.value not in OP:
            raise Exception("Error: Invalid operator => '{0}'".format(
                self.token.value))

        if self.token.value in XML_REPLACE.keys():
            self.xml_data.append("<{0}> {1} </{0}>".format(
                self.token.type, XML_REPLACE[self.token.value]))
        else:
            self.xml_data.append(self.token.__str__())

    def compile_class(self):
        """
            Compile class.
            -------------------------------------------------------------
            Rule => 'class' className '{' classVarDec* subroutineDec* '}'
            -------------------------------------------------------------
        """
        self.xml_data.append("<class>")  # Xml rep: <class>
        self.check_for_value('class')  # Xml rep:    <keyword> class </keyword>
        self.check_for_identifier(
        )  # Xml rep:    <identifier> className </identifier>

        CLASSES.append(self.token.value)  # Add class name to list of classes.

        self.check_for_value('{')  # Xml rep:    <symbol> { </symbol>

        while self.tokenizer.next().value != "}":
            self.token = self.tokenizer.advance()

            if self.token.value in ['static', 'field']:
                self.compile_class_var_dec(
                )  # Compile class variable declarations.

            elif self.token.value in ['constructor', 'function', 'method']:
                self.compile_subroutine_dec(
                )  # Compile class subroutine declarations.

        self.check_for_value("}")  # Xml rep:    <symbol> } </symbol>
        self.xml_data.append("</class>")  # Xml rep: </class>

    def compile_class_var_dec(self):
        """
            Compile class variable declarations.
            -------------------------------------------------------------
            Rule => ('static' | 'field') type varName (',', varName)* ';'
            -------------------------------------------------------------
        """
        self.xml_data.append("<classVarDec>")  # Xml rep: <classVarDec>
        variable = Variable()

        self.xml_data.append(self.token.__str__(
        ))  # Xml rep:    <keyword> ('static' | 'field') </keyword>
        variable.kind = self.token.value

        self.check_for_type()  # Xml rep:    <keyword> type </keyword>
        variable.type = self.token.value

        self.check_for_identifier(
        )  # Xml rep:    <identifier> varName </identifier>
        variable.name = self.token.value

        self.symbol_table.add(
            variable)  # Add variable to class scope symbol table.

        while self.tokenizer.next().value != ";":
            self.check_for_value(",")  # Xml rep:     <symbol> , </symbol>
            self.check_for_identifier(
            )  # Xml rep:     <identifier> varName </identifier>
            v = copy(variable)
            v.name = self.token.value
            self.symbol_table.add(
                v)  # Add variable to class scope symbol table.

        self.check_for_value(";")  # Xml rep:     <symbol> ; </symbol>
        self.xml_data.append("</classVarDec>")  # Xml rep: </classVarDec>

    def compile_subroutine_dec(self):
        """
            Compile class subroutine declarations.
            -------------------------------------------------------------------------------------------------------------------
            Rule => ('constructor' | 'function' | 'method') ('void' | type) subroutineName '(' parameterList ')' subroutineBody
            -------------------------------------------------------------------------------------------------------------------
        """
        self.xml_data.append("<subroutineDec>")  # Xml rep: <subroutineDec>
        self.xml_data.append(
            self.token.__str__()
        )  # Xml rep:     <keyword> ('constructor' | 'function' | 'method')) </keyword>
        self.check_for_type()  # Xml rep:     <keyword> type </keyword>
        self.check_for_identifier(
        )  # Xml rep:     <identifier> subroutineName </identifier>

        SUBROUTINES.append(
            self.token.value)  # Add subroutine name to subroutine list.

        self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
        self.compile_parameter_list()  # Compile parameter list.
        self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        self.compile_subroutine_body()  # Compile subroutine body.
        self.xml_data.append("</subroutineDec>")  # Xml rep: </subroutineDec>

    def compile_parameter_list(self):
        """
            Compile parameter list.
            ---------------------------------------------
            Rule => ((type varName) (',' type varName)*)?
            ---------------------------------------------
        """
        self.xml_data.append("<parameterList>")  # Xml rep: <parameterList>
        if self.tokenizer.next().value != ")":
            self.check_for_type()  # Xml rep:     <keyword> type </keyword>
            self.check_for_identifier(
            )  # Xml rep:     <identifier> varName </identifier>
            while self.tokenizer.next().value == ",":
                self.check_for_value(",")  # Xml rep:     <symbol> , </symbol>
                self.check_for_type()  # Xml rep:     <keyword> type </keyword>
                self.check_for_identifier(
                )  # Xml rep:     <identifier> varName </identifier>
        self.xml_data.append("</parameterList>")  # Xml rep: </parameterList>

    def compile_subroutine_body(self):
        """
            Compile subroutine body.
            ----------------------------------
            Rule => '{' varDec* statements '}'
            ----------------------------------
        """
        self.xml_data.append("<subroutineBody>")  # Xml rep: <subroutineBody>
        self.check_for_value("{")  # Xml rep:     <symbol> { </symbol>
        while self.tokenizer.next().value == "var":
            self.compile_var_dec()  # Compile variable declarations.
        self.compile_statements()  # Compile statements.

        self.check_for_value("}")  # Xml rep:     <symbol> } </symbol>
        self.xml_data.append("</subroutineBody>")  # Xml rep: </subroutineBody>

    def compile_var_dec(self):
        """
            Compile variable declarations.
            ----------------------------------------------
            Rule => 'var' type varName (',', varName)* ';'
            ----------------------------------------------
        """
        self.xml_data.append("<varDec>")  # Xml rep: <varDec>
        self.check_for_value("var")  # Xml rep:     <keyword> var </keyword>
        self.check_for_type()  # Xml rep:     <keyword> type </keyword>
        self.check_for_identifier(
        )  # Xml rep:     <identifier> varName </identifier>
        while self.tokenizer.next().value != ";":
            self.check_for_value(",")  # Xml rep:     <symbol> ; </symbol>
            self.check_for_identifier(
            )  # Xml rep:     <identifier> varName </identifier>
        self.check_for_value(";")  # Xml rep:     <symbol> ; </symbol>
        self.xml_data.append("</varDec>")  # Xml rep: </varDec>

    def compile_statements(self):
        """
            Compile statements.
            -----------------------------------------------------------------------------------
            Rule => letStatement | ifStatement | whileStatement | doStatement | returnStatement
            -----------------------------------------------------------------------------------
        """
        self.xml_data.append("<statements>")  # Xml rep: <statements>
        while self.tokenizer.next().value != "}":
            token = self.tokenizer.next().value
            if token == 'let':
                self.compile_let_statement()  # Compile let statement.
            elif token == 'while':
                self.compile_while_statement()  # Compile while statement.
            elif token == 'if':
                self.compile_if_statement()  # Compile if statement.
            elif token == 'do':
                self.compile_do_statement()  # Compile do statement.
            elif token == 'return':
                self.compile_return_statement()  # Compile return statement.
        self.xml_data.append("</statements>")  # Xml rep: </statements>

    def compile_let_statement(self):
        """
            Compile let statement.
            --------------------------------------------------------------
            Rule => 'let' varName ('[' expression ']')? '=' expression ';'
            --------------------------------------------------------------
        """
        self.xml_data.append("<letStatement>")  # Xml rep: <letStatement>
        self.check_for_value("let")  # Xml rep:     <keyword> let </keyword>
        self.check_for_identifier(
        )  # Xml rep:     <identifier> varName </identifier>
        var = self.symbol_table.find(self.token.value)
        if self.tokenizer.next().value == '[':
            self.check_for_value("[")  # Xml rep:     <symbol> [ </symbol>
            self.compile_expression("]")  # Compile expression.
            self.check_for_value("]")  # Xml rep:     <symbol> ] </symbol>
        self.check_for_value("=")  # Xml rep:     <symbol> = </symbol>
        self.compile_expression(";")  # Compile expression.
        self.check_for_value(";")  # Xml rep:     <symbol> ; </symbol>
        self.xml_data.append("</letStatement>")  # Xml rep: </letStatement>

    def compile_while_statement(self):
        """
            Compile while statement.
            -----------------------------------------------------
            Rule => 'while' '(' expression ')' '{' statements '}'
            -----------------------------------------------------
        """
        self.xml_data.append("<whileStatement>")  # Xml rep: <whileStatement>
        self.check_for_value(
            "while")  # Xml rep:     <keyword> while </keyword>
        self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
        self.compile_expression(")")  # Compile expression.
        self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        self.check_for_value("{")  # Xml rep:     <symbol> { </symbol>
        self.compile_statements()  # Compile statements.
        self.check_for_value("}")  # Xml rep:     <symbol> } </symbol>
        self.xml_data.append("</whileStatement>")  # Xml rep: </whileStatement>

    def compile_if_statement(self):
        """
            Compile if statement.
            -------------------------------------------------------------------------------
            Rule => 'if' '(' expression ')' '{' statements '}' ('else' '{' statements '}')?
            -------------------------------------------------------------------------------
        """
        self.xml_data.append("<ifStatement>")  # Xml rep: <ifStatement>
        self.check_for_value("if")  # Xml rep:     <keyword> if </keyword>
        self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
        self.compile_expression(")")  # Compile expression.
        self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        self.check_for_value("{")  # Xml rep:     <symbol> { </symbol>
        self.compile_statements()  # Compile statements.
        self.check_for_value("}")  # Xml rep:     <symbol> } </symbol>
        if self.tokenizer.next().value == 'else':
            self.check_for_value(
                'else')  # Xml rep:     <keyword> else </keyword>
            self.check_for_value('{')  # Xml rep:     <symbol> { </symbol>
            self.compile_statements()  # Compile statements.
            self.check_for_value('}')  # Xml rep:     <symbol> } </symbol>
        self.xml_data.append("</ifStatement>")  # Xml rep: </ifStatement>

    def compile_do_statement(self):
        """
            Compile do statement.
            -------------------------------
            Rule => 'do' subroutineCall ';'
            -------------------------------
        """
        self.xml_data.append("<doStatement>")  # Xml rep: <doStatement>
        self.check_for_value("do")  # Xml rep:     <keword> do </keyword>
        self.compile_subroutine_call()  # Compile subroutine call.
        self.check_for_value(";")  # Xml rep:     <symbol> ; </symbol>
        self.xml_data.append("</doStatement>")  # Xml rep: </doStatement>

    def compile_return_statement(self):
        """
            Compile return statement.
            --------------------------------
            Rule => 'return' expression? ';'
            --------------------------------
        """
        self.xml_data.append("<returnStatement>")  # Xml rep: <returnStatement>
        self.check_for_value(
            "return")  # Xml rep:     <keword> return </keyword>
        if self.tokenizer.next().value != ";":
            self.compile_expression(';')
        self.check_for_value(";")  # Xml rep:     <symbol> ; </symbol>
        self.xml_data.append(
            "</returnStatement>")  # Xml rep: </returnStatement>

    def compile_subroutine_call(self):
        """
            Compile subroutine call.
            ---------------------------------------------------------------------------------------------------------------
            Rule => subroutineName '(' expressionList ')' | (className | varName) '.' subroutineName '(' expressionList ')'
            ---------------------------------------------------------------------------------------------------------------
        """
        self.xml_data.append("<subroutineCall>")  # Xml rep: <subroutineCall>
        self.check_for_identifier(
        )  # Xml rep:     <identifier> subroutineName | (className | varName) </identifier>
        if self.tokenizer.next().value == ".":
            self.check_for_value(".")  # Xml rep:     <symbol> . </symbol>
            self.check_for_identifier(
            )  # Xml rep:     <identifier> subroutineName </identifier>
        self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
        self.compile_expression_list()  # Compile expression list.
        self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        self.xml_data.append("</subroutineCall>")  # Xml rep: </subroutineCall>

    def compile_expression(self, *end):
        """
            Compile expression.
            -----------------------
            Rule => term (op term)*
            -----------------------
        """
        self.xml_data.append("<expression>")  # Xml rep:<expression>
        self.compile_term()  # Compile term.
        while self.tokenizer.next().value not in end:
            self.check_for_operator(
            )  # Xml rep:     <symbol> operator </symbol>
            self.compile_term()  # Compile term.
        self.xml_data.append("</expression>")  # Xml rep: </expression>

    def compile_term(self):
        """
            Compile term.
            ----------------------------------------------------------------------------------
            Rule => integerConstant | stringConstant | keywordConstant | unaryOp term | 
                    varName |  varName'[' expression ']' | subroutineCall | '(' expression ')'
            ----------------------------------------------------------------------------------
        """
        self.xml_data.append("<term>")  # Xml rep: <term>
        if self.tokenizer.next().type in [
                "integerConstant", "stringConstant"
        ] or self.tokenizer.next().value in KEYWORD_CONSANTS:
            self.token = self.tokenizer.advance()
            self.xml_data.append(
                self.token.__str__()
            )  # Xml rep:     <integerConstant | stringConstant | keyword> value </integerConstant | stringConstant | keyword>
        elif self.tokenizer.next().value in UNARY_OP:
            self.token = self.tokenizer.advance()
            self.xml_data.append(self.token.__str__()
                                 )  # Xml rep:     <symbol> unaryOp </symbol>
            self.compile_term()  # Compile term.
        elif self.tokenizer.next().value == "(":
            self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
            self.compile_expression(")")  # Compile expression.
            self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        else:
            self.check_for_identifier(
            )  # Xml rep:     <identifier> varName </identifier>
            var = self.symbol_table.find(self.token.value)
            if self.tokenizer.next().value == "[":
                self.check_for_value("[")  # Xml rep:     <symbol> [ </symbol>
                self.compile_expression("]")  # Compile expression.
                self.check_for_value("]")  # Xml rep:     <symbol> ] </symbol>
            elif self.tokenizer.next().value == ".":
                self.check_for_value(".")  # Xml rep:     <symbol> . </symbol>
                self.check_for_identifier(
                )  # Xml rep:     <identifier> subroutineName </identifier>
                self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
                self.compile_expression_list()  # Compile expression list.
                self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
            elif self.tokenizer.next().value == "(":
                self.check_for_value("(")  # Xml rep:     <symbol> ( </symbol>
                self.compile_expression_list()  # Compile expression list.
                self.check_for_value(")")  # Xml rep:     <symbol> ) </symbol>
        self.xml_data.append("</term>")  # Xml rep: </term>

    def compile_expression_list(self):
        """
            Compile expression list.
            ---------------------------------------
            Rule => (expression (',' expression)*)?
            ---------------------------------------
        """
        self.xml_data.append("<expressionList>")  # Xml rep: <expressionList>
        if self.tokenizer.next().value != ")":
            self.compile_expression(",", ")")  # Compile expression.
            while self.tokenizer.next().value == ",":
                self.check_for_value(",")  # Xml rep:     <symbol> , </symbol>
                self.compile_expression(",", ")")
        self.xml_data.append("</expressionList>")  # Xml rep: </expressionList>

    def export_xml(self, file_name):
        """ Export code structure to file in xml format. """
        with open("xml-export/{0}.structure.xml".format(file_name),
                  "w") as xml_file:
            for line in self.xml_data:
                xml_file.write(line + "\n")
Beispiel #8
0
import readline

from src.lexer import Lexer
from src.parser import Parser
from src.values import Number
from src.interpreter import Interpreter, Context, BuiltInFunction
from src.symbol_table import SymbolTable

symb_table = SymbolTable()
symb_table.set('null', Number.null)
symb_table.set('false', Number.false)
symb_table.set('true', Number.true)
symb_table.set('math_pi', Number.math_PI)
symb_table.set('print', BuiltInFunction.print)
symb_table.set('print_ret', BuiltInFunction.print_ret)
symb_table.set('input', BuiltInFunction.input)
symb_table.set('input_int', BuiltInFunction.input_int)
symb_table.set('is_num', BuiltInFunction.is_number)
symb_table.set('is_str', BuiltInFunction.is_string)
symb_table.set('is_list', BuiltInFunction.is_list)
symb_table.set('is_fun', BuiltInFunction.is_function)
symb_table.set('append', BuiltInFunction.append)
symb_table.set('pop', BuiltInFunction.pop)
symb_table.set('extend', BuiltInFunction.extend)

if __name__ == "__main__":
    lex = Lexer()
    par = Parser()
    inter = Interpreter()
    ctx = Context('<program>')
    ctx.symbol_table = symb_table