如何用RPLY编写语言的语法规则

2024-05-17 11:59:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一份大学工作写一种虚构的语言,语法规则应该描述以下示例: example of the language

我试着在我的解析器.py中编写这个:

class Parser():
    def __init__(self):
        self.pg = ParserGenerator(
            # Uma lista com todos os nomes de tokens aceitos pelo Parser
            ['INTEGER', 'WRITE', 'OPEN_PAREN', 'CLOSE_PAREN',
             'SEMI_COLON', 'SOMA', 'SUBTRACAO', 'MULT', 'DIV', 'MOD', 'LEFT_SHIFT',
             'RIGHT_SHIFT', '>>>', 'PROGRAM', 'IDENTIFIER', 'AND'],
             
             precedence=[
                 ('left', ['WRITE']),
                 ('left', ['SOMA', 'SUBTRACAO']),
                 ('left', ['MULT', 'DIV']),
                 ('left', ['MOD']),
                 ('left', ['LEFT_SHIFT', 'RIGHT_SHIFT']),
                 ('left', ['>>>', 'AND'])
             ],
             cache_id='myparser'
        )
        
    def parse(self):
        @self.pg.production('program : PROGRAM IDENTIFIER body')
        def main_program(p):
            return p[2]

        @self.pg.production('body : statement_full')
        def body_statement(p):
            return Program(p[0])

        @self.pg.production('body : statement_full body')
        def body_statement_program(p):
            if type(p[1]) is Program:
                body = p[1]
            else:
                body = Program(p[12])
            
            body.adiciona_statement(p[0])
            return p[1]

        @self.pg.production('statement_full : statement')
        @self.pg.production('statement_full : statement SEMI_COLON')  
        def statement_full(p):
            return p[0]
        
        @self.pg.production('statement : expression')
        def statement_expr(p):
            return p[0]

        @self.pg.production('statement : WRITE OPEN_PAREN expression CLOSE_PAREN SEMI_COLON')
        def write(p):
            return Write(p[2])

        #Função que define as regras das operações da linguagem
        @self.pg.production('expression : expression SOMA expression')
        @self.pg.production('expression : expression SUBTRACAO expression')
        @self.pg.production('expression : expression MULT expression')
        @self.pg.production('expression : expression DIV expression')
        @self.pg.production('expression : expression MOD expression')
        @self.pg.production('expression : expression LEFT_SHIFT expression')
        @self.pg.production('expression : expression RIGHT_SHIFT expression')
        @self.pg.production('expression : expression >>> expression')
        @self.pg.production('expression : expression AND expression')
        def operacoes(p):
            esquerda = p[0]
            direita = p[2]
            operator = p[1]

            if operator.gettokentype() == 'SOMA':
                return Soma(esquerda, direita)
            
            elif operator.gettokentype() == 'SUBTRACAO':
                return Subtracao(esquerda, direita)
            
            elif operator.gettokentype() == 'MULT':
                return Mult(esquerda, direita)
            
            elif operator.gettokentype() == 'DIV':
                return Div(esquerda, direita)
            
            elif operator.gettokentype() == 'MOD':
                return Mod(esquerda, direita)

            elif operator.gettokentype() == 'LEFT_SHIFT':
                return Left_Shift(esquerda, direita)
            
            elif operator.gettokentype() == 'RIGHT_SHIFT':
                return Right_Shift(esquerda, direita)

            elif operator.gettokentype() == '>>>':
                return Unsigned_Right_Shift(esquerda, direita)

            elif operator.gettokentype() == 'AND':
                return And(esquerda, direita)
            else:
                raise AssertionError('Opa, isso não é possível!')
        
        #Definição do único tipo aceitado em MINI: inteiro
        @self.pg.production('expression : INTEGER')
        def numero(p):
            return Integer(int(p[0].value))

        @self.pg.production('expression : OPEN_PAREN expression CLOSE_PAREN')
        def expression_parens(p):
            return p[1]

在我的ast.py中:

class Program():
    def __init__(self, st):
        self.statements = []
        self.statements.append(st)

    def adiciona_statement(self, statement):
        self.statements.insert(0, statement)

    def eval(self):
        result = None
        for s in self.statements:
            result = s.eval()
            return result
    
    def get_statement(self):
        return self.statements

class Integer():
    def __init__(self, valor):
        self.valor = valor

    def eval(self):
        return int(self.valor)
    
class OpBinarios():
    def __init__(self, esquerda, direita):
        self.esquerda = esquerda
        self.direita = direita

class Subtracao(OpBinarios):
    def eval(self):
        return self.esquerda.eval() - self.direita.eval()

class Soma(OpBinarios):
    def eval(self):
        return self.esquerda.eval() + self.direita.eval()

class Mult(OpBinarios):
    def eval(self):
        return self.esquerda.eval() * self.direita.eval()

class Div(OpBinarios):
    def eval(self):
        return int(self.esquerda.eval() / self.direita.eval())

class Mod(OpBinarios):
    def eval(self):
        return self.esquerda.eval() % self.direita.eval()

class Left_Shift(OpBinarios):
    def eval(self):
        return self.esquerda.eval() << self.direita.eval()

class Right_Shift(OpBinarios):
    def eval(self):
        return self.esquerda.eval() >> self.direita.eval()

class Unsigned_Right_Shift(OpBinarios):
    def eval(self):
        return (self.esquerda.eval() % 0x100000000) >> self.direita.eval()

class And(OpBinarios):
    def eval(self):
        return self.esquerda.eval() and self.direita.eval()

class Write():
    def __init__(self, valor):
        self.valor = valor
    
    def eval(self):
        print(self.valor.eval())

在mymain.py中,我有:

from analisador_lexico import Analisador_Lexico
from analisador_sintatico import Parser

text_input = """
program teste
write(3 / 2);
write(3 * 3);
"""

lexer = Analisador_Lexico().get_lexer()
tokens = lexer.lex(text_input)

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

但是当我编译时,控制台上只显示第一行(write(3/2);)('1'因为我的语言只有int)。我在语法规则上做错了什么

有些单词是葡萄牙语的,因为我是巴西人,只要照写的样子用就行了。如果我写错了什么,请为我的英语不好道歉


Tags: selfreturndefevalbodyoperatorclassproduction