python - PLY thinks a mathematical expression is a syntax error after I implemented variables -
i've been playing around ply , after getting examples work decided should implement variables. working great mathematical expression not assigned variable seems throw syntax error (not python syntax error syntax error within language). example:
calc> = 5 name: number: 5 assigning variable 5 {'a': 5} calc> 6 + 1 number: 6 syntactic error: line: 1 position: 0 syntax error: 6 number: 1 {'a': 5}
i noticed put number grammar function above of variable assignments variables break , calculations work.
lexer:
#!/usr/bin/env python ### lexical analysis ### import ply.lex lex import colorama colorama.init() tokens = ( "number", "plus", "minus", "multiply", "divide", "lbracket", "rbracket", "name", "equals" ) t_plus = r"\+" t_minus = r"-" t_multiply = r"\*" t_divide = r"/" t_lbracket = r"\(" t_rbracket = r"\)" t_equals = r"=" t_ignore = "\t\r " def t_number(t): r"\d+" print "number:", t.value t.value = int(t.value) return t def t_name(t): r"[a-za-z]+\w*" print "name:", t.value return t def t_newline(t): r"\n+" t.lexer.lineno += len(t.value) def t_comment(t): r"\#.*" print "comment:", t.value def t_error(t): print colorama.fore.red + "lexical error: line:", t.lexer.lineno, "position:", t.lexer.lexpos, "invalid token:", t.value, colorama.fore.reset t.lexer.skip(len(t.value)) lexer = lex.lex()
parser:
import ply.yacc yacc langlex import tokens import colorama colorama.init() variables = {} def p_assignment(p): "assignment : name equals expression" print "assigning variable", p[1], "to", p[3] variables[p[1]] = p[3] def p_expression_plus(p): "expression : expression plus term" p[0] = p[1] + p[3] def p_expression_minus(p): "expression : expression minus term" p[0] = p[1] - p[3] def p_expression_term(p): "expression : term" p[0] = p[1] def p_expression_name(p): "expression : name" p[0] = variables[p[1]] def p_term_times(p): "term : term multiply factor" p[0] = p[1] * p[3] def p_term_div(p): "term : term divide factor" p[0] = p[1] / p[3] def p_term_factor(p): "term : factor" p[0] = p[1] def p_factor_expr(p): "factor : lbracket expression rbracket" p[0] = p[2] def p_factor_num(p): "factor : number" p[0] = p[1] def p_error(p): if(p): print colorama.fore.red + "syntactic error: line:", p.lexer.lineno, "position:", p.lexpos, "syntax error:", p.value, colorama.fore.reset else: print colorama.fore.red + "syntactic error: unknown syntax error" + colorama.fore.reset parser = yacc.yacc() while true: s = raw_input("calc> ") if not(s): continue result = parser.parse(s) if(result): print result print variables
in creating p_assignment
, have created new starting grammar symbol. docs:
the first rule defined in yacc specification determines starting grammar symbol. whenever starting rule reduced parser , no more input available, parsing stops , final value returned.
this means, grammer, allowed input sentences assignments:
$ python p_o.py generating lalr tables calc> a=1 name: number: 1 assigning variable 1 {'a': 1} calc> name: syntactic error: unknown syntax error {'a': 1} calc> 1 number: 1 syntactic error: line: 1 position: 0 syntax error: 1 {'a': 1}
so, need have starting grammar symbol that, path, resolves expression. chose add statement
non-terminal starting grammar symbol:
... def p_statement_assignment(p): "statement : assignment" pass def p_statement_expression(p): "statement : expression" p[0] = p[1] def p_assignment(p): "assignment : name equals expression" print "assigning variable", p[1], "to", p[3] variables[p[1]] = p[3] ...
$ python p_1.py generating lalr tables calc> a=1 name: number: 1 assigning variable 1 {'a': 1} calc> name: 1 {'a': 1} calc> 1 number: 1 1 {'a': 1} calc>
Comments
Post a Comment