summaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorDavid Beazley <dave@dabeaz.com>2009-01-13 13:23:40 +0000
committerDavid Beazley <dave@dabeaz.com>2009-01-13 13:23:40 +0000
commitbc4321d25db0b37f5e6264c58827d69264aa0260 (patch)
tree69c2c7c7b654c71d7824829cc0cd3f115b9c70a3 /example
parente65cd063f1c8881c9589a9726e0cde76533b55c0 (diff)
downloadply-bc4321d25db0b37f5e6264c58827d69264aa0260.tar.gz
Significant cleanup. Refactoring of yacc internals
Diffstat (limited to 'example')
-rw-r--r--example/BASIC/basiclog.py79
-rw-r--r--example/BASIC/basparse.py4
-rw-r--r--example/calc/calc.py6
-rw-r--r--example/calcdebug/calc.py113
-rw-r--r--example/closurecalc/calc.py6
-rw-r--r--example/optcalc/README2
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.