def __init__(self, **kw): self.debug = kw.get('debug', 0) self.names = {} try: modname = os.path.split(os.path.splitext(__file__) [0])[1] + "_" + self.__class__.__name__ except: modname = "parser" + "_" + self.__class__.__name__ self.debugfile = modname + ".dbg" self.tabmodule = modname + "_" + "parsetab" # Build lexer/parser lex.lex(module=self, debug=self.debug) yacc.yacc(module=self, debug=self.debug, debugfile=self.debugfile, tabmodule=self.tabmodule)
def p_expression_group(p): 'expression : LPAREN expression RPAREN' p[0] = p[2] def p_expression_number(p): 'expression : NUMBER' p[0] = p[1] def p_expression_name(p): 'expression : NAME' try: p[0] = names[p[1]] except LookupError: print("Undefined name '%s'" % p[1]) p[0] = 0 def p_error(p): print("Syntax error at '%s'" % p.value) yacc.yacc() while True: try: s = input('calc > ') # use input() on Python 3 except EOFError: break yacc.parse(s)
'ASSIGN': "\n--> Declaraciones: 'DCL <variable> DEFAULT <variable|número>'.", 'CUANDO': "\n--> Casos:" "\n--> Sintaxis 1 para Casos: 'ENCASO <casos1> SINO { <acciones> } FINCASO'. Los <casos1> son: 'CUANDO <comparativo> ENTONS { <acciones> }'." "\n--> Sintaxis 2 para Casos: 'ENCASO <variable> <casos2> SINO { <acciones> } FINCASO'. Los <casos2> son: 'CUANDO <condición> <expresión> ENTONS { <acciones> }'.", 'MIENTRAS': "\n--> Repeticiones: 'REPITA <acciones> MIENTRAS <comparativo>'.", 'HASTA': "\n--> Desde: 'DESDE <variable> = <expresión> HASTA <expresión> HAGA <acciones> FINDESDE'." } func = cases.get(instruccion, "\n--> Nada") return func parser = yacc.yacc() ''' ------------------------------ ANALISIS SEMANTICO ------------------------------ ''' def run(p): global st global error global proc_called global gvariables global lvariables global proc_declarations_called global lineError if proc_called == True: variables = lvariables else:
if error_msg == last_error_msg or (last_error_msg and error_msg == default_msg): sys.exit() print error_msg last_error_msg = error_msg # Guardar a última mensagem de erro. Isto é feito uma # vez que o comportamento de yacc.errok() nem sempre é o esperado, e pode entrar # em ciclo ilustrando sempre a mesma mensagem de erro # Dos slides: # É conveniente que o parser não interrompa a acção quando encontra um erro # Ele deve levar a análise até ao fim e reportar todos os erros encontrados yacc.errok() # Tenta continuar apesar do erro que ocorreu return yacc.token() # Devolve o próximo token da stream def ln(p): ''' Devolve a linha em que se encontra ''' return p.lineno(0) # Útil para termos esta informação na árvore de sintaxe # abstracta para as mensagens de erro da análise semântica e de geração de código if __name__ == '__main__': # Build the parser parser = yacc.yacc() f = open(r'input') try: for line in f: result = parser.parse(line.strip()) finally: f.close()