diff options
author | David Beazley <dave@dabeaz.com> | 2009-01-13 13:23:40 +0000 |
---|---|---|
committer | David Beazley <dave@dabeaz.com> | 2009-01-13 13:23:40 +0000 |
commit | bc4321d25db0b37f5e6264c58827d69264aa0260 (patch) | |
tree | 69c2c7c7b654c71d7824829cc0cd3f115b9c70a3 /example | |
parent | e65cd063f1c8881c9589a9726e0cde76533b55c0 (diff) | |
download | ply-bc4321d25db0b37f5e6264c58827d69264aa0260.tar.gz |
Significant cleanup. Refactoring of yacc internals
Diffstat (limited to 'example')
-rw-r--r-- | example/BASIC/basiclog.py | 79 | ||||
-rw-r--r-- | example/BASIC/basparse.py | 4 | ||||
-rw-r--r-- | example/calc/calc.py | 6 | ||||
-rw-r--r-- | example/calcdebug/calc.py | 113 | ||||
-rw-r--r-- | example/closurecalc/calc.py | 6 | ||||
-rw-r--r-- | example/optcalc/README | 2 |
6 files changed, 197 insertions, 13 deletions
diff --git a/example/BASIC/basiclog.py b/example/BASIC/basiclog.py new file mode 100644 index 0000000..ccfd7b9 --- /dev/null +++ b/example/BASIC/basiclog.py @@ -0,0 +1,79 @@ +# An implementation of Dartmouth BASIC (1964) +# + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +import logging +logging.basicConfig( + level = logging.INFO, + filename = "parselog.txt", + filemode = "w" +) +log = logging.getLogger() + +import basiclex +import basparse +import basinterp + +# If a filename has been specified, we try to run it. +# If a runtime error occurs, we bail out and enter +# interactive mode below +if len(sys.argv) == 2: + data = open(sys.argv[1]).read() + prog = basparse.parse(data,debug=log) + if not prog: raise SystemExit + b = basinterp.BasicInterpreter(prog) + try: + b.run() + raise SystemExit + except RuntimeError: + pass + +else: + b = basinterp.BasicInterpreter({}) + +# Interactive mode. This incrementally adds/deletes statements +# from the program stored in the BasicInterpreter object. In +# addition, special commands 'NEW','LIST',and 'RUN' are added. +# Specifying a line number with no code deletes that line from +# the program. + +while 1: + try: + line = raw_input("[BASIC] ") + except EOFError: + raise SystemExit + if not line: continue + line += "\n" + prog = basparse.parse(line,debug=log) + if not prog: continue + + keys = list(prog) + if keys[0] > 0: + b.add_statements(prog) + else: + stat = prog[keys[0]] + if stat[0] == 'RUN': + try: + b.run() + except RuntimeError: + pass + elif stat[0] == 'LIST': + b.list() + elif stat[0] == 'BLANK': + b.del_line(stat[1]) + elif stat[0] == 'NEW': + b.new() + + + + + + + + + diff --git a/example/BASIC/basparse.py b/example/BASIC/basparse.py index d773715..ccdeb16 100644 --- a/example/BASIC/basparse.py +++ b/example/BASIC/basparse.py @@ -403,9 +403,9 @@ def p_error(p): bparser = yacc.yacc() -def parse(data): +def parse(data,debug=0): bparser.error = 0 - p = bparser.parse(data) + p = bparser.parse(data,debug=debug) if bparser.error: return None return p diff --git a/example/calc/calc.py b/example/calc/calc.py index 2e36c7d..b923780 100644 --- a/example/calc/calc.py +++ b/example/calc/calc.py @@ -23,11 +23,7 @@ t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' def t_NUMBER(t): r'\d+' - try: - t.value = int(t.value) - except ValueError: - print("Integer value too large %s" % t.value) - t.value = 0 + t.value = int(t.value) return t t_ignore = " \t" diff --git a/example/calcdebug/calc.py b/example/calcdebug/calc.py new file mode 100644 index 0000000..6732f9f --- /dev/null +++ b/example/calcdebug/calc.py @@ -0,0 +1,113 @@ +# ----------------------------------------------------------------------------- +# calc.py +# +# This example shows how to run the parser in a debugging mode +# with output routed to a logging object. +# ----------------------------------------------------------------------------- + +import sys +sys.path.insert(0,"../..") + +if sys.version_info[0] >= 3: + raw_input = input + +tokens = ( + 'NAME','NUMBER', + ) + +literals = ['=','+','-','*','/', '(',')'] + +# Tokens + +t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' + +def t_NUMBER(t): + r'\d+' + t.value = int(t.value) + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Build the lexer +import ply.lex as lex +lex.lex() + +# Parsing rules + +precedence = ( + ('left','+','-'), + ('left','*','/'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(p): + 'statement : NAME "=" expression' + names[p[1]] = p[3] + +def p_statement_expr(p): + 'statement : expression' + print(p[1]) + +def p_expression_binop(p): + '''expression : expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression''' + if p[2] == '+' : p[0] = p[1] + p[3] + elif p[2] == '-': p[0] = p[1] - p[3] + elif p[2] == '*': p[0] = p[1] * p[3] + elif p[2] == '/': p[0] = p[1] / p[3] + +def p_expression_uminus(p): + "expression : '-' expression %prec UMINUS" + p[0] = -p[2] + +def p_expression_group(p): + "expression : '(' expression ')'" + 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): + if p: + print("Syntax error at '%s'" % p.value) + else: + print("Syntax error at EOF") + +import ply.yacc as yacc +yacc.yacc() + +import logging +logging.basicConfig( + level=logging.INFO, + filename="parselog.txt" +) + +while 1: + try: + s = raw_input('calc > ') + except EOFError: + break + if not s: continue + yacc.parse(s,debug=logging.getLogger()) diff --git a/example/closurecalc/calc.py b/example/closurecalc/calc.py index a1d5845..6598f58 100644 --- a/example/closurecalc/calc.py +++ b/example/closurecalc/calc.py @@ -36,11 +36,7 @@ def make_calculator(): def t_NUMBER(t): r'\d+' - try: - t.value = int(t.value) - except ValueError: - print("Integer value too large %s" % t.value) - t.value = 0 + t.value = int(t.value) return t def t_newline(t): diff --git a/example/optcalc/README b/example/optcalc/README index 6d196f0..53dd5fc 100644 --- a/example/optcalc/README +++ b/example/optcalc/README @@ -5,5 +5,5 @@ To run: - Then run 'python -OO calc.py' -If working corretly, the second version should run the +If working correctly, the second version should run the same way. |