Принимается только первое правило парсера (с использованием слоя с python) - PullRequest
0 голосов
/ 27 мая 2020

Я пытаюсь создать Лексер и Парсер для проекта, я уже сделал Лексер, и теперь я пытаюсь сделать парсер

Лексер:


reserved = {
    'if' : 'IF',
    'else' : 'ELSE',
    'while' : 'WHILE',
    'do'    : 'DO',
    'for'   : 'FOR',
    'main'  : 'MAIN',
    'int'   : 'INT_ID',
    'float' : 'FLOAT_ID',
    'char'  : 'CHAR_ID'
 }
tokens = ['CHAR', 'FLOAT','INTEGER', 'PLUS', 'MINUS', 'MUL', 'DIV','OPEN_PAR', 'CLOSE_PAR','OPEN_BRACKETS','CLOSE_BRACKETS','ASSIGNMENT', 'EQUALS', 'NOT_EQUALS', 'EQUAL_OR_GREATER_THAN', 
        'EQUAL_OR_LESS_THAN', 'LESS_THAN', 'GREATER_THAN', 'COMMA', 'SEMI_COLON','IDENTIFIER','NEWLINE','COMMENT_EOL',"COMMENT_DELIMITED"] + list(reserved.values())



t_PLUS    = r'\+'
t_MINUS   = r'-'
t_MUL   = r'\*'
t_DIV  = r'/'
t_OPEN_PAR  = r'\('
t_CLOSE_PAR  = r'\)'
t_OPEN_BRACKETS  = r'\{'
t_CLOSE_BRACKETS  = r'\}'
t_ASSIGNMENT  = r'\='
t_EQUALS  = r'\=\='
t_NOT_EQUALS  = r'\!\='
t_EQUAL_OR_GREATER_THAN  = r'\>\='
t_EQUAL_OR_LESS_THAN  = r'\<\='
t_LESS_THAN = r'\<'
t_GREATER_THAN = r'\>'
t_COMMA = r'\,'
t_SEMI_COLON = r'\;'

def t_COMMENT_EOL(t):
    r'\/{2}.*\n'
    return t

def t_COMMENT_DELIMITED(t):
    r'\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/'
    return t

def t_CHAR(t):
    r'\'[a-zA-Z]\'' 
    return t

def t_FLOAT(t):
    r'[-]?[0-9]*\.{1}[0-9]+'
    t.value = float(t.value)    
    return t

def t_INTEGER(t):
    r'\d+'
    t.value = int(t.value)    
    return t


def t_IDENTIFIER(t):
    #  r'(^[a-zA-Z0-9]*\_{1}[0-9]*$)*'
     r'[a-zA-Z0-9\_]+'
     t.type = reserved.get(t.value,'IDENTIFIER')    # Check for reserved words
     return t


def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)


t_ignore  = ' \t'

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

lexer = lex.lex()

Парсер (Некоторые правила еще не созданы):


 # Get the token map from the lexer.  This is required.
from lexer import tokens


#valorvariaveis
def p_float(p):
    'float : FLOAT'
    p[0] = p[1]

def p_integer(p):
    'int : INTEGER'
    p[0] = p[1]

def p_char(p):
    'char : CHAR'
    p[0] = p[1]

def p_id(p):
    'id : IDENTIFIER'
    p[0] = p[1]
#fim valorvariaveis


#decl_var
def p_decl_var(p):
    'decl_var : type id SEMI_COLON'
    p[0] = p[1]


#tipovariaveis
def p_INT_ID(p):
    'type : INT_ID'
    p[0] = p[1]
def p_FLOAT_ID(p):
    'type : FLOAT_ID'
    p[0] = p[1]
def p_CHAR_ID(p):
    'type : CHAR_ID'
    p[0] = p[1]


#program
def p_program(p):
    'program : INT_ID MAIN OPEN_PAR CLOSE_PAR'
#block
def p_block(p):
    'block : OPEN_BRACKETS decl_var command CLOSE_BRACKETS'
    p[0] = p[1]


#command
def p_command_basic_command(p):
    'command : basic_command'
    p[0] = p[1] 

def p_command_iteration(p):
    'command : iteration'
    p[0] = p[1] 
def p_command(p):
    'command : IF OPEN_PAR expr_relacional CLOSE_PAR command OPEN_BRACKETS ELSE command CLOSE_BRACKETS'
    p[0] = p[1] 




#basic_command
def p_basic_command_assignment(p):
    'basic_command : assignment'
    p[0] = p[1] 
def p_basic_command_block(p):
    'basic_command : block'
    p[0] = p[1] 



#iteration
def p_iteration_WHILE(p):
    'iteration : WHILE OPEN_PAR expr_relacional CLOSE_PAR command'
    #FALTA FAZER AQUIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
    p[0] = p[1] 
def p_iteration_DO(p):
    'iteration : DO command WHILE OPEN_PAR expr_relacional CLOSE_PAR SEMI_COLON'
    #FALTA FAZER AQUIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
    p[0] = p[1] 



#atribuicao
def p_assignment(p):
    'assignment : id ASSIGNMENT expression_arit SEMI_COLON'
    p[0] = p[1] 



#oprelacional
def p_op_relacional_GREATER_THAN(p):
    'op_relacional : GREATER_THAN'
    p[0] = p[1] 
def p_op_relacional_LESS_THAN(p):
    'op_relacional : LESS_THAN'
    p[0] = p[1] 
def p_op_relacional_EQUAL_OR_LESS_THAN(p):
    'op_relacional : EQUAL_OR_LESS_THAN'
    p[0] = p[1] 
def p_op_relacional_EQUAL_OR_GREATER_THAN(p):
    'op_relacional : EQUAL_OR_GREATER_THAN'
    p[0] = p[1] 



#expr_relacional
def p_expr_relacional(p):
    'expr_relacional : expression_arit op_relacional expression_arit'
    print("oioioi")
    if p[2] == '>=':
        if p[1] >= p[3]:
            p[0]=True
        else:
            p[0]=False
    elif p[2] == '<=':
        if p[1] <= p[3]:
            p[0]=True
        else:
            p[0]=False
    elif p[2] == '<':
        if p[1] < p[3]:
            p[0]=True
        else:
            p[0]=False
    elif p[2] == '>':
        if p[1] > p[3]:
            p[0]=True
        else:
            p[0]=False



#expression_arit
def p_expression_arit_plus(p):
    'expression_arit : expression_arit PLUS term'
    p[0] = p[1] + p[3]

def p_expression_arit_minus(p):
    'expression_arit : expression_arit MINUS term'
    p[0] = p[1]- p[3]

def p_expression_arit(p):
    'expression_arit : term'
    p[0] = p[1]
#fim expression_arit




#term
def p_term_mul(p):
    'term : term MUL factor'
    p[0] = p[1] * p[3]

def p_term_div(p):
    'term : term DIV factor'
    p[0] = p[1] / p[3]

def p_term_factor(p):
    'term : factor'
    p[0] = p[1]
#fim term



#fator
def p_factor_expr(p):
    'factor : OPEN_PAR expression_arit CLOSE_PAR'
    p[0] = p[2]


def p_factor_integer(p):
    'factor : int'
    p[0] = p[1]

def p_factor_float(p):
    'factor : float'
    p[0] = p[1]

def p_factor_id(p):
    'factor : id'
    p[0] = p[1]

def p_factor_char(p):
    'factor : char'
    p[0] = p[1]


# Error rule for syntax errors
def p_error(p):
    print("Syntax error in input!")

# Build the parser
parser = yacc.yacc()

while True:
    try:
        s = input('calc > ')
    except EOFError:
        break
    if not s: continue
    result = parser.parse(s)
    print(result)

Что происходит, так это то, что единственное принимаемое правило - первое (плавающее), все остальные недостижимы, и я не знаю, почему

calc > 1.0
1.0
calc > 1
Syntax error in input!
None
calc >

Вы видите введенное «1.0», и анализатор не выдает ошибок сообщения, но когда я пытаюсь ввести целое число, например «1», он выдает ошибку.

Но есть правило для чисел типа INTEGER

1 Ответ

0 голосов
/ 27 мая 2020

Ply всегда начинает синтаксический анализ с первого правила в вашем файле, если вы не укажете другое. См. Подробное руководство .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...