diff options
author | David Beazley <dave@dabeaz.com> | 2006-11-21 15:09:46 +0000 |
---|---|---|
committer | David Beazley <dave@dabeaz.com> | 2006-11-21 15:09:46 +0000 |
commit | 80c8c2d0a6e63745ff099b33ad2848b6fb17285a (patch) | |
tree | 36d223fc55a5649dc85a4f8a3fa9d17cb130c6c3 /test | |
download | ply-80c8c2d0a6e63745ff099b33ad2848b6fb17285a.tar.gz |
initial checkin
Diffstat (limited to 'test')
108 files changed, 2830 insertions, 0 deletions
diff --git a/test/README b/test/README new file mode 100644 index 0000000..aac12b0 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ +This directory mostly contains tests for various types of error +conditions. To run: + + $ python testlex.py . + $ python testyacc.py . + +The tests can also be run using the Python unittest module. + + $ python rununit.py + +The script 'cleanup.sh' cleans up this directory to its original state. diff --git a/test/calclex.py b/test/calclex.py new file mode 100644 index 0000000..2550734 --- /dev/null +++ b/test/calclex.py @@ -0,0 +1,49 @@ +# ----------------------------------------------------------------------------- +# calclex.py +# ----------------------------------------------------------------------------- +import sys + +sys.path.append("..") +import ply.lex as lex + +tokens = ( + 'NAME','NUMBER', + 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', + 'LPAREN','RPAREN', + ) + +# Tokens + +t_PLUS = r'\+' +t_MINUS = r'-' +t_TIMES = r'\*' +t_DIVIDE = r'/' +t_EQUALS = r'=' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +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", t.value + t.value = 0 + return t + +t_ignore = " \t" + +def t_newline(t): + r'\n+' + t.lineno += t.value.count("\n") + +def t_error(t): + print "Illegal character '%s'" % t.value[0] + t.lexer.skip(1) + +# Build the lexer +lex.lex() + + + diff --git a/test/cleanup.sh b/test/cleanup.sh new file mode 100755 index 0000000..d7d99b6 --- /dev/null +++ b/test/cleanup.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -f *~ *.pyc *.dif *.out + diff --git a/test/lex_doc1.exp b/test/lex_doc1.exp new file mode 100644 index 0000000..5b63c1e --- /dev/null +++ b/test/lex_doc1.exp @@ -0,0 +1 @@ +./lex_doc1.py:18: No regular expression defined for rule 't_NUMBER' diff --git a/test/lex_doc1.py b/test/lex_doc1.py new file mode 100644 index 0000000..3951b5c --- /dev/null +++ b/test/lex_doc1.py @@ -0,0 +1,30 @@ +# lex_token.py +# +# Missing documentation string + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(t): + pass + +def t_error(t): + pass + + +import sys +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_dup1.exp b/test/lex_dup1.exp new file mode 100644 index 0000000..2098a40 --- /dev/null +++ b/test/lex_dup1.exp @@ -0,0 +1,2 @@ +./lex_dup1.py:20: Rule t_NUMBER redefined. Previously defined on line 18 +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_dup1.py b/test/lex_dup1.py new file mode 100644 index 0000000..68f8092 --- /dev/null +++ b/test/lex_dup1.py @@ -0,0 +1,29 @@ +# lex_token.py +# +# Duplicated rule specifiers + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_NUMBER = r'\d+' + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_dup2.exp b/test/lex_dup2.exp new file mode 100644 index 0000000..d327cfe --- /dev/null +++ b/test/lex_dup2.exp @@ -0,0 +1,2 @@ +./lex_dup2.py:22: Rule t_NUMBER redefined. Previously defined on line 18 +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_dup2.py b/test/lex_dup2.py new file mode 100644 index 0000000..f4d346e --- /dev/null +++ b/test/lex_dup2.py @@ -0,0 +1,33 @@ +# lex_token.py +# +# Duplicated rule specifiers + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +def t_NUMBER(t): + r'\d+' + pass + +def t_NUMBER(t): + r'\d+' + pass + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_dup3.exp b/test/lex_dup3.exp new file mode 100644 index 0000000..ec0680c --- /dev/null +++ b/test/lex_dup3.exp @@ -0,0 +1,2 @@ +./lex_dup3.py:20: Rule t_NUMBER redefined. Previously defined on line 18 +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_dup3.py b/test/lex_dup3.py new file mode 100644 index 0000000..e17b520 --- /dev/null +++ b/test/lex_dup3.py @@ -0,0 +1,31 @@ +# lex_token.py +# +# Duplicated rule specifiers + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_NUMBER(t): + r'\d+' + pass + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_empty.exp b/test/lex_empty.exp new file mode 100644 index 0000000..af38602 --- /dev/null +++ b/test/lex_empty.exp @@ -0,0 +1 @@ +SyntaxError: lex: no rules of the form t_rulename are defined. diff --git a/test/lex_empty.py b/test/lex_empty.py new file mode 100644 index 0000000..96625f7 --- /dev/null +++ b/test/lex_empty.py @@ -0,0 +1,20 @@ +# lex_token.py +# +# No rules defined + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_error1.exp b/test/lex_error1.exp new file mode 100644 index 0000000..baa19e5 --- /dev/null +++ b/test/lex_error1.exp @@ -0,0 +1 @@ +lex: Warning. no t_error rule is defined. diff --git a/test/lex_error1.py b/test/lex_error1.py new file mode 100644 index 0000000..a99d9be --- /dev/null +++ b/test/lex_error1.py @@ -0,0 +1,24 @@ +# lex_token.py +# +# Missing t_error() rule + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_error2.exp b/test/lex_error2.exp new file mode 100644 index 0000000..fb1b55c --- /dev/null +++ b/test/lex_error2.exp @@ -0,0 +1 @@ +SyntaxError: lex: Rule 't_error' must be defined as a function diff --git a/test/lex_error2.py b/test/lex_error2.py new file mode 100644 index 0000000..a59c8d4 --- /dev/null +++ b/test/lex_error2.py @@ -0,0 +1,26 @@ +# lex_token.py +# +# t_error defined, but not function + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_error = "foo" + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_error3.exp b/test/lex_error3.exp new file mode 100644 index 0000000..1b482bf --- /dev/null +++ b/test/lex_error3.exp @@ -0,0 +1,2 @@ +./lex_error3.py:20: Rule 't_error' requires an argument. +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_error3.py b/test/lex_error3.py new file mode 100644 index 0000000..584600f --- /dev/null +++ b/test/lex_error3.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# t_error defined as function, but with wrong # args + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_error4.exp b/test/lex_error4.exp new file mode 100644 index 0000000..98505a2 --- /dev/null +++ b/test/lex_error4.exp @@ -0,0 +1,2 @@ +./lex_error4.py:20: Rule 't_error' has too many arguments. +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_error4.py b/test/lex_error4.py new file mode 100644 index 0000000..d05de74 --- /dev/null +++ b/test/lex_error4.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# t_error defined as function, but too many args + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t,s): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_hedit.exp b/test/lex_hedit.exp new file mode 100644 index 0000000..7b27dcb --- /dev/null +++ b/test/lex_hedit.exp @@ -0,0 +1,3 @@ +(H_EDIT_DESCRIPTOR,'abc',1,0) +(H_EDIT_DESCRIPTOR,'abcdefghij',1,6) +(H_EDIT_DESCRIPTOR,'xy',1,20) diff --git a/test/lex_hedit.py b/test/lex_hedit.py new file mode 100644 index 0000000..0f87423 --- /dev/null +++ b/test/lex_hedit.py @@ -0,0 +1,47 @@ +# ----------------------------------------------------------------------------- +# hedit.py +# +# Paring of Fortran H Edit descriptions (Contributed by Pearu Peterson) +# +# These tokens can't be easily tokenized because they are of the following +# form: +# +# nHc1...cn +# +# where n is a positive integer and c1 ... cn are characters. +# +# This example shows how to modify the state of the lexer to parse +# such tokens +# ----------------------------------------------------------------------------- +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = ( + 'H_EDIT_DESCRIPTOR', + ) + +# Tokens +t_ignore = " \t\n" + +def t_H_EDIT_DESCRIPTOR(t): + r"\d+H.*" # This grabs all of the remaining text + i = t.value.index('H') + n = eval(t.value[:i]) + + # Adjust the tokenizing position + t.lexer.lexpos -= len(t.value) - (i+1+n) + t.value = t.value[i+1:i+1+n] + return t + +def t_error(t): + print "Illegal character '%s'" % t.value[0] + t.lexer.skip(1) + +# Build the lexer +lex.lex() +lex.runmain(data="3Habc 10Habcdefghij 2Hxy") + + + diff --git a/test/lex_ignore.exp b/test/lex_ignore.exp new file mode 100644 index 0000000..85e2961 --- /dev/null +++ b/test/lex_ignore.exp @@ -0,0 +1,7 @@ +./lex_ignore.py:20: Rule 't_ignore' must be defined as a string. +Traceback (most recent call last): + File "./lex_ignore.py", line 29, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_ignore.py b/test/lex_ignore.py new file mode 100644 index 0000000..94b0266 --- /dev/null +++ b/test/lex_ignore.py @@ -0,0 +1,31 @@ +# lex_token.py +# +# Improperly specific ignore declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_ignore(t): + ' \t' + pass + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_nowarn.exp b/test/lex_nowarn.exp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/lex_nowarn.exp diff --git a/test/lex_nowarn.py b/test/lex_nowarn.py new file mode 100644 index 0000000..d60d31c --- /dev/null +++ b/test/lex_nowarn.py @@ -0,0 +1,30 @@ +# lex_token.py +# +# Missing t_error() rule + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + "NUMBER", + ] + +states = (('foo','exclusive'),) + +t_ignore = ' \t' +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_foo_NUMBER = r'\d+' + +sys.tracebacklimit = 0 + +lex.lex(nowarn=1) + + diff --git a/test/lex_re1.exp b/test/lex_re1.exp new file mode 100644 index 0000000..b9e621c --- /dev/null +++ b/test/lex_re1.exp @@ -0,0 +1,7 @@ +lex: Invalid regular expression for rule 't_NUMBER'. unbalanced parenthesis +Traceback (most recent call last): + File "./lex_re1.py", line 25, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_re1.py b/test/lex_re1.py new file mode 100644 index 0000000..9e544fe --- /dev/null +++ b/test/lex_re1.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# Bad regular expression in a string + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'(\d+' + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_re2.exp b/test/lex_re2.exp new file mode 100644 index 0000000..7ba89b4 --- /dev/null +++ b/test/lex_re2.exp @@ -0,0 +1,7 @@ +lex: Regular expression for rule 't_PLUS' matches empty string. +Traceback (most recent call last): + File "./lex_re2.py", line 25, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_re2.py b/test/lex_re2.py new file mode 100644 index 0000000..522b415 --- /dev/null +++ b/test/lex_re2.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# Regular expression rule matches empty string + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+?' +t_MINUS = r'-' +t_NUMBER = r'(\d+)' + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_re3.exp b/test/lex_re3.exp new file mode 100644 index 0000000..7cdcae4 --- /dev/null +++ b/test/lex_re3.exp @@ -0,0 +1,8 @@ +lex: Invalid regular expression for rule 't_POUND'. unbalanced parenthesis +lex: Make sure '#' in rule 't_POUND' is escaped with '\#'. +Traceback (most recent call last): + File "./lex_re3.py", line 27, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_re3.py b/test/lex_re3.py new file mode 100644 index 0000000..099e156 --- /dev/null +++ b/test/lex_re3.py @@ -0,0 +1,29 @@ +# lex_token.py +# +# Regular expression rule matches empty string + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + "POUND", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'(\d+)' +t_POUND = r'#' + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_rule1.exp b/test/lex_rule1.exp new file mode 100644 index 0000000..0c23ca2 --- /dev/null +++ b/test/lex_rule1.exp @@ -0,0 +1,2 @@ +lex: t_NUMBER not defined as a function or string +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_rule1.py b/test/lex_rule1.py new file mode 100644 index 0000000..e49a15b --- /dev/null +++ b/test/lex_rule1.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# Rule defined as some other type + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = 1 + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_state1.exp b/test/lex_state1.exp new file mode 100644 index 0000000..8b58050 --- /dev/null +++ b/test/lex_state1.exp @@ -0,0 +1,7 @@ +lex: states must be defined as a tuple or list. +Traceback (most recent call last): + File "./lex_state1.py", line 38, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state1.py b/test/lex_state1.py new file mode 100644 index 0000000..7eb2976 --- /dev/null +++ b/test/lex_state1.py @@ -0,0 +1,40 @@ +# lex_state1.py +# +# Bad state declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = 'comment' + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state2.exp b/test/lex_state2.exp new file mode 100644 index 0000000..11c33a7 --- /dev/null +++ b/test/lex_state2.exp @@ -0,0 +1,8 @@ +lex: invalid state specifier 'comment'. Must be a tuple (statename,'exclusive|inclusive') +lex: invalid state specifier 'example'. Must be a tuple (statename,'exclusive|inclusive') +Traceback (most recent call last): + File "./lex_state2.py", line 38, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state2.py b/test/lex_state2.py new file mode 100644 index 0000000..b76b0db --- /dev/null +++ b/test/lex_state2.py @@ -0,0 +1,40 @@ +# lex_state2.py +# +# Bad state declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +states = ('comment','example') + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state3.exp b/test/lex_state3.exp new file mode 100644 index 0000000..2c3442c --- /dev/null +++ b/test/lex_state3.exp @@ -0,0 +1,8 @@ +lex: state name 1 must be a string +lex: No rules defined for state 'example' +Traceback (most recent call last): + File "./lex_state3.py", line 40, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state3.py b/test/lex_state3.py new file mode 100644 index 0000000..fb4ce6c --- /dev/null +++ b/test/lex_state3.py @@ -0,0 +1,42 @@ +# lex_state2.py +# +# Bad state declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = ((comment, 'inclusive'), + ('example', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state4.exp b/test/lex_state4.exp new file mode 100644 index 0000000..7497a47 --- /dev/null +++ b/test/lex_state4.exp @@ -0,0 +1,7 @@ +lex: state type for state comment must be 'inclusive' or 'exclusive' +Traceback (most recent call last): + File "./lex_state4.py", line 39, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state4.py b/test/lex_state4.py new file mode 100644 index 0000000..0993aa9 --- /dev/null +++ b/test/lex_state4.py @@ -0,0 +1,41 @@ +# lex_state2.py +# +# Bad state declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = (('comment', 'exclsive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state5.exp b/test/lex_state5.exp new file mode 100644 index 0000000..e9e43e8 --- /dev/null +++ b/test/lex_state5.exp @@ -0,0 +1,7 @@ +lex: state 'comment' already defined. +Traceback (most recent call last): + File "./lex_state5.py", line 40, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state5.py b/test/lex_state5.py new file mode 100644 index 0000000..c3c1cbf --- /dev/null +++ b/test/lex_state5.py @@ -0,0 +1,42 @@ +# lex_state2.py +# +# Bad state declaration + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = (('comment', 'exclusive'), + ('comment', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state_noerror.exp b/test/lex_state_noerror.exp new file mode 100644 index 0000000..e14149f --- /dev/null +++ b/test/lex_state_noerror.exp @@ -0,0 +1 @@ +lex: Warning. no error rule is defined for exclusive state 'comment' diff --git a/test/lex_state_noerror.py b/test/lex_state_noerror.py new file mode 100644 index 0000000..853b157 --- /dev/null +++ b/test/lex_state_noerror.py @@ -0,0 +1,41 @@ +# lex_state2.py +# +# Declaration of a state for which no rules are defined + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = (('comment', 'exclusive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state_norule.exp b/test/lex_state_norule.exp new file mode 100644 index 0000000..a8ff4ca --- /dev/null +++ b/test/lex_state_norule.exp @@ -0,0 +1,7 @@ +lex: No rules defined for state 'example' +Traceback (most recent call last): + File "./lex_state_norule.py", line 40, in ? + lex.lex() + File "../ply/lex.py", line 758, in lex + raise SyntaxError,"lex: Unable to build lexer." +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_state_norule.py b/test/lex_state_norule.py new file mode 100644 index 0000000..e48a319 --- /dev/null +++ b/test/lex_state_norule.py @@ -0,0 +1,42 @@ +# lex_state2.py +# +# Declaration of a state for which no rules are defined + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = (('comment', 'exclusive'), + ('example', 'exclusive')) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +import sys + +lex.lex() + + diff --git a/test/lex_state_try.exp b/test/lex_state_try.exp new file mode 100644 index 0000000..65f2e38 --- /dev/null +++ b/test/lex_state_try.exp @@ -0,0 +1,7 @@ +(NUMBER,'3',1,0) +(PLUS,'+',1,2) +(NUMBER,'4',1,4) +Entering comment state +comment body LexToken(comment_body_part,'This is a comment */',1,9) +(PLUS,'+',1,30) +(NUMBER,'10',1,32) diff --git a/test/lex_state_try.py b/test/lex_state_try.py new file mode 100644 index 0000000..a16403e --- /dev/null +++ b/test/lex_state_try.py @@ -0,0 +1,48 @@ +# lex_state2.py +# +# Declaration of a state for which no rules are defined + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +comment = 1 +states = (('comment', 'exclusive'),) + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +t_ignore = " \t" + +# Comments +def t_comment(t): + r'/\*' + t.lexer.begin('comment') + print "Entering comment state" + +def t_comment_body_part(t): + r'(.|\n)*\*/' + print "comment body", t + t.lexer.begin('INITIAL') + +def t_error(t): + pass + +t_comment_error = t_error +t_comment_ignore = t_ignore + +import sys + +lex.lex() + +data = "3 + 4 /* This is a comment */ + 10" + +lex.runmain(data=data) diff --git a/test/lex_token1.exp b/test/lex_token1.exp new file mode 100644 index 0000000..3792831 --- /dev/null +++ b/test/lex_token1.exp @@ -0,0 +1 @@ +SyntaxError: lex: module does not define 'tokens' diff --git a/test/lex_token1.py b/test/lex_token1.py new file mode 100644 index 0000000..380c31c --- /dev/null +++ b/test/lex_token1.py @@ -0,0 +1,21 @@ +# lex_token.py +# +# Tests for absence of tokens variable + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_token2.exp b/test/lex_token2.exp new file mode 100644 index 0000000..3f98fe5 --- /dev/null +++ b/test/lex_token2.exp @@ -0,0 +1 @@ +SyntaxError: lex: tokens must be a list or tuple. diff --git a/test/lex_token2.py b/test/lex_token2.py new file mode 100644 index 0000000..87db8a0 --- /dev/null +++ b/test/lex_token2.py @@ -0,0 +1,23 @@ +# lex_token.py +# +# Tests for tokens of wrong type + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = "PLUS MINUS NUMBER" + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_token3.exp b/test/lex_token3.exp new file mode 100644 index 0000000..d991d3c --- /dev/null +++ b/test/lex_token3.exp @@ -0,0 +1,2 @@ +lex: Rule 't_MINUS' defined for an unspecified token MINUS. +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_token3.py b/test/lex_token3.py new file mode 100644 index 0000000..27ce947 --- /dev/null +++ b/test/lex_token3.py @@ -0,0 +1,27 @@ +# lex_token.py +# +# tokens is right type, but is missing a token for one rule + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_token4.exp b/test/lex_token4.exp new file mode 100644 index 0000000..3dd88e0 --- /dev/null +++ b/test/lex_token4.exp @@ -0,0 +1,2 @@ +lex: Bad token name '-' +SyntaxError: lex: Unable to build lexer. diff --git a/test/lex_token4.py b/test/lex_token4.py new file mode 100644 index 0000000..612ff13 --- /dev/null +++ b/test/lex_token4.py @@ -0,0 +1,28 @@ +# lex_token.py +# +# Bad token name + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "-", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() + + diff --git a/test/lex_token5.exp b/test/lex_token5.exp new file mode 100644 index 0000000..2f03889 --- /dev/null +++ b/test/lex_token5.exp @@ -0,0 +1 @@ +ply.lex.LexError: ./lex_token5.py:19: Rule 't_NUMBER' returned an unknown token type 'NUM' diff --git a/test/lex_token5.py b/test/lex_token5.py new file mode 100644 index 0000000..77fabde --- /dev/null +++ b/test/lex_token5.py @@ -0,0 +1,33 @@ +# lex_token.py +# +# Return a bad token name + +import sys +sys.path.insert(0,"..") + +import ply.lex as lex + +tokens = [ + "PLUS", + "MINUS", + "NUMBER", + ] + +t_PLUS = r'\+' +t_MINUS = r'-' + +def t_NUMBER(t): + r'\d+' + t.type = "NUM" + return t + +def t_error(t): + pass + +sys.tracebacklimit = 0 + +lex.lex() +lex.input("1234") +t = lex.token() + + diff --git a/test/rununit.py b/test/rununit.py new file mode 100644 index 0000000..d6b36fd --- /dev/null +++ b/test/rununit.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +'''Script to run all tests using python "unittest" module''' + +__author__ = "Miki Tebeka <miki.tebeka@zoran.com>" + +from unittest import TestCase, main, makeSuite, TestSuite +from os import popen, environ, remove +from glob import glob +from sys import executable, argv +from os.path import isfile, basename, splitext + +# Add path to lex.py and yacc.py +environ["PYTHONPATH"] = ".." + +class PLYTest(TestCase): + '''General test case for PLY test''' + def _runtest(self, filename): + '''Run a single test file an compare result''' + exp_file = filename.replace(".py", ".exp") + self.failUnless(isfile(exp_file), "can't find %s" % exp_file) + pipe = popen("%s %s 2>&1" % (executable, filename)) + out = pipe.read().strip() + self.failUnlessEqual(out, open(exp_file).read().strip()) + + +class LexText(PLYTest): + '''Testing Lex''' + pass + +class YaccTest(PLYTest): + '''Testing Yacc''' + + def tearDown(self): + '''Cleanup parsetab.py[c] file''' + for ext in (".py", ".pyc"): + fname = "parsetab%s" % ext + if isfile(fname): + remove(fname) + +def add_test(klass, filename): + '''Add a test to TestCase class''' + def t(self): + self._runtest(filename) + # Test name is test_FILENAME without the ./ and without the .py + setattr(klass, "test_%s" % (splitext(basename(filename))[0]), t) + +# Add lex tests +for file in glob("./lex_*.py"): + add_test(LexText, file) +lex_suite = makeSuite(LexText, "test_") + +# Add yacc tests +for file in glob("./yacc_*.py"): + add_test(YaccTest, file) +yacc_suite = makeSuite(YaccTest, "test_") + +# All tests suite +test_suite = TestSuite((lex_suite, yacc_suite)) + +if __name__ == "__main__": + main() + diff --git a/test/testlex.py b/test/testlex.py new file mode 100755 index 0000000..2dae47a --- /dev/null +++ b/test/testlex.py @@ -0,0 +1,57 @@ +#!/usr/local/bin +# ---------------------------------------------------------------------- +# testlex.py +# +# Run tests for the lexing module +# ---------------------------------------------------------------------- + +import sys,os,glob + +if len(sys.argv) < 2: + print "Usage: python testlex.py directory" + raise SystemExit + +dirname = None +make = 0 + +for o in sys.argv[1:]: + if o == '-make': + make = 1 + else: + dirname = o + break + +if not dirname: + print "Usage: python testlex.py [-make] directory" + raise SystemExit + +f = glob.glob("%s/%s" % (dirname,"lex_*.py")) + +print "**** Running tests for lex ****" + +for t in f: + name = t[:-3] + print "Testing %-32s" % name, + if make: + if not os.path.exists("%s.exp" % name): + os.system("python %s.py >%s.exp 2>&1" % (name,name)) + passed = 1 + else: + os.system("python %s.py >%s.out 2>&1" % (name,name)) + a = os.system("diff %s.out %s.exp >%s.dif" % (name,name,name)) + if a == 0: + passed = 1 + else: + passed = 0 + + if passed: + print "Passed" + else: + print "Failed. See %s.dif" % name + + + + + + + diff --git a/test/testyacc.py b/test/testyacc.py new file mode 100644 index 0000000..f976ff5 --- /dev/null +++ b/test/testyacc.py @@ -0,0 +1,58 @@ +#!/usr/local/bin +# ---------------------------------------------------------------------- +# testyacc.py +# +# Run tests for the yacc module +# ---------------------------------------------------------------------- + +import sys,os,glob + +if len(sys.argv) < 2: + print "Usage: python testyacc.py directory" + raise SystemExit + +dirname = None +make = 0 + +for o in sys.argv[1:]: + if o == '-make': + make = 1 + else: + dirname = o + break + +if not dirname: + print "Usage: python testyacc.py [-make] directory" + raise SystemExit + +f = glob.glob("%s/%s" % (dirname,"yacc_*.py")) + +print "**** Running tests for yacc ****" + +for t in f: + name = t[:-3] + print "Testing %-32s" % name, + os.system("rm -f %s/parsetab.*" % dirname) + if make: + if not os.path.exists("%s.exp" % name): + os.system("python %s.py >%s.exp 2>&1" % (name,name)) + passed = 1 + else: + os.system("python %s.py >%s.out 2>&1" % (name,name)) + a = os.system("diff %s.out %s.exp >%s.dif" % (name,name,name)) + if a == 0: + passed = 1 + else: + passed = 0 + + if passed: + print "Passed" + else: + print "Failed. See %s.dif" % name + + + + + + + diff --git a/test/yacc_badargs.exp b/test/yacc_badargs.exp new file mode 100644 index 0000000..e994676 --- /dev/null +++ b/test/yacc_badargs.exp @@ -0,0 +1,3 @@ +./yacc_badargs.py:23: Rule 'p_statement_assign' has too many arguments. +./yacc_badargs.py:27: Rule 'p_statement_expr' requires an argument. +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_badargs.py b/test/yacc_badargs.py new file mode 100644 index 0000000..810e529 --- /dev/null +++ b/test/yacc_badargs.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_badargs.py +# +# Rules with wrong # args +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t,s): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_badprec.exp b/test/yacc_badprec.exp new file mode 100644 index 0000000..f4f574b --- /dev/null +++ b/test/yacc_badprec.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: precedence must be a list or tuple. diff --git a/test/yacc_badprec.py b/test/yacc_badprec.py new file mode 100644 index 0000000..8f64652 --- /dev/null +++ b/test/yacc_badprec.py @@ -0,0 +1,65 @@ +# ----------------------------------------------------------------------------- +# yacc_badprec.py +# +# Bad precedence specifier +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = "blah" + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_badprec2.exp b/test/yacc_badprec2.exp new file mode 100644 index 0000000..8fac075 --- /dev/null +++ b/test/yacc_badprec2.exp @@ -0,0 +1,3 @@ +yacc: Invalid precedence table. +yacc: Generating LALR parsing table... +yacc: 8 shift/reduce conflicts diff --git a/test/yacc_badprec2.py b/test/yacc_badprec2.py new file mode 100644 index 0000000..206bda7 --- /dev/null +++ b/test/yacc_badprec2.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_badprec2.py +# +# Bad precedence +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + 42, + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_badrule.exp b/test/yacc_badrule.exp new file mode 100644 index 0000000..a87bf7d --- /dev/null +++ b/test/yacc_badrule.exp @@ -0,0 +1,5 @@ +./yacc_badrule.py:25: Syntax error. Expected ':' +./yacc_badrule.py:29: Syntax error in rule 'statement' +./yacc_badrule.py:34: Syntax error. Expected ':' +./yacc_badrule.py:43: Syntax error. Expected ':' +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_badrule.py b/test/yacc_badrule.py new file mode 100644 index 0000000..f5fef8a --- /dev/null +++ b/test/yacc_badrule.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_badrule.py +# +# Syntax problems in the rule strings +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression: MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_badtok.exp b/test/yacc_badtok.exp new file mode 100644 index 0000000..ccdc0e7 --- /dev/null +++ b/test/yacc_badtok.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: tokens must be a list or tuple. diff --git a/test/yacc_badtok.py b/test/yacc_badtok.py new file mode 100644 index 0000000..4f2af51 --- /dev/null +++ b/test/yacc_badtok.py @@ -0,0 +1,70 @@ +# ----------------------------------------------------------------------------- +# yacc_badtok.py +# +# A grammar, but tokens is a bad datatype +# ----------------------------------------------------------------------------- + +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +tokens = "Hello" + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_dup.exp b/test/yacc_dup.exp new file mode 100644 index 0000000..fdfb210 --- /dev/null +++ b/test/yacc_dup.exp @@ -0,0 +1,4 @@ +./yacc_dup.py:28: Function p_statement redefined. Previously defined on line 24 +yacc: Warning. Token 'EQUALS' defined, but not used. +yacc: Warning. There is 1 unused token. +yacc: Generating LALR parsing table... diff --git a/test/yacc_dup.py b/test/yacc_dup.py new file mode 100644 index 0000000..e0b683d --- /dev/null +++ b/test/yacc_dup.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_dup.py +# +# Duplicated rule name +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_error1.exp b/test/yacc_error1.exp new file mode 100644 index 0000000..13bed04 --- /dev/null +++ b/test/yacc_error1.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: ./yacc_error1.py:62: p_error() requires 1 argument. diff --git a/test/yacc_error1.py b/test/yacc_error1.py new file mode 100644 index 0000000..2768fc1 --- /dev/null +++ b/test/yacc_error1.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_error1.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t,s): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_error2.exp b/test/yacc_error2.exp new file mode 100644 index 0000000..4a7628d --- /dev/null +++ b/test/yacc_error2.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: ./yacc_error2.py:62: p_error() requires 1 argument. diff --git a/test/yacc_error2.py b/test/yacc_error2.py new file mode 100644 index 0000000..8f3a052 --- /dev/null +++ b/test/yacc_error2.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_error1.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_error3.exp b/test/yacc_error3.exp new file mode 100644 index 0000000..7fca2fe --- /dev/null +++ b/test/yacc_error3.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: 'p_error' defined, but is not a function or method. diff --git a/test/yacc_error3.py b/test/yacc_error3.py new file mode 100644 index 0000000..b387de5 --- /dev/null +++ b/test/yacc_error3.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_error1.py +# +# Bad p_error() function +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +p_error = "blah" + +yacc.yacc() + + + + diff --git a/test/yacc_inf.exp b/test/yacc_inf.exp new file mode 100644 index 0000000..88cfa4a --- /dev/null +++ b/test/yacc_inf.exp @@ -0,0 +1,5 @@ +yacc: Warning. Token 'NUMBER' defined, but not used. +yacc: Warning. There is 1 unused token. +yacc: Infinite recursion detected for symbol 'statement'. +yacc: Infinite recursion detected for symbol 'expression'. +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_inf.py b/test/yacc_inf.py new file mode 100644 index 0000000..9b9aef7 --- /dev/null +++ b/test/yacc_inf.py @@ -0,0 +1,57 @@ +# ----------------------------------------------------------------------------- +# yacc_inf.py +# +# Infinite recursion +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_missing1.exp b/test/yacc_missing1.exp new file mode 100644 index 0000000..de63d4f --- /dev/null +++ b/test/yacc_missing1.exp @@ -0,0 +1,2 @@ +./yacc_missing1.py:25: Symbol 'location' used, but not defined as a token or a rule. +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_missing1.py b/test/yacc_missing1.py new file mode 100644 index 0000000..fbc54d8 --- /dev/null +++ b/test/yacc_missing1.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_missing1.py +# +# Grammar with a missing rule +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : location EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_nodoc.exp b/test/yacc_nodoc.exp new file mode 100644 index 0000000..889ccfc --- /dev/null +++ b/test/yacc_nodoc.exp @@ -0,0 +1,2 @@ +./yacc_nodoc.py:28: No documentation string specified in function 'p_statement_expr' +yacc: Generating LALR parsing table... diff --git a/test/yacc_nodoc.py b/test/yacc_nodoc.py new file mode 100644 index 0000000..4c5ab20 --- /dev/null +++ b/test/yacc_nodoc.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_nodoc.py +# +# Rule with a missing doc-string +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_noerror.exp b/test/yacc_noerror.exp new file mode 100644 index 0000000..658f907 --- /dev/null +++ b/test/yacc_noerror.exp @@ -0,0 +1,2 @@ +yacc: Generating LALR parsing table... +yacc: Warning. no p_error() function is defined. diff --git a/test/yacc_noerror.py b/test/yacc_noerror.py new file mode 100644 index 0000000..9c11838 --- /dev/null +++ b/test/yacc_noerror.py @@ -0,0 +1,67 @@ +# ----------------------------------------------------------------------------- +# yacc_noerror.py +# +# No p_error() rule defined. +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + + +yacc.yacc() + + + + diff --git a/test/yacc_nop.exp b/test/yacc_nop.exp new file mode 100644 index 0000000..515fff7 --- /dev/null +++ b/test/yacc_nop.exp @@ -0,0 +1,2 @@ +./yacc_nop.py:28: Warning. Possible grammar rule 'statement_expr' defined without p_ prefix. +yacc: Generating LALR parsing table... diff --git a/test/yacc_nop.py b/test/yacc_nop.py new file mode 100644 index 0000000..c0b431d --- /dev/null +++ b/test/yacc_nop.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_nop.py +# +# Possible grammar rule defined without p_ prefix +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_notfunc.exp b/test/yacc_notfunc.exp new file mode 100644 index 0000000..f73bc93 --- /dev/null +++ b/test/yacc_notfunc.exp @@ -0,0 +1,4 @@ +yacc: Warning. 'p_statement_assign' not defined as a function +yacc: Warning. Token 'EQUALS' defined, but not used. +yacc: Warning. There is 1 unused token. +yacc: Generating LALR parsing table... diff --git a/test/yacc_notfunc.py b/test/yacc_notfunc.py new file mode 100644 index 0000000..8389355 --- /dev/null +++ b/test/yacc_notfunc.py @@ -0,0 +1,67 @@ +# ----------------------------------------------------------------------------- +# yacc_notfunc.py +# +# p_rule not defined as a function +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +p_statement_assign = "Blah" + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_notok.exp b/test/yacc_notok.exp new file mode 100644 index 0000000..d2399fe --- /dev/null +++ b/test/yacc_notok.exp @@ -0,0 +1 @@ +ply.yacc.YaccError: module does not define a list 'tokens' diff --git a/test/yacc_notok.py b/test/yacc_notok.py new file mode 100644 index 0000000..e566a1b --- /dev/null +++ b/test/yacc_notok.py @@ -0,0 +1,68 @@ +# ----------------------------------------------------------------------------- +# yacc_notok.py +# +# A grammar, but we forgot to import the tokens list +# ----------------------------------------------------------------------------- + +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_rr.exp b/test/yacc_rr.exp new file mode 100644 index 0000000..f73cefd --- /dev/null +++ b/test/yacc_rr.exp @@ -0,0 +1,2 @@ +yacc: Generating LALR parsing table... +yacc: 1 reduce/reduce conflict diff --git a/test/yacc_rr.py b/test/yacc_rr.py new file mode 100644 index 0000000..bb8cba2 --- /dev/null +++ b/test/yacc_rr.py @@ -0,0 +1,73 @@ +# ----------------------------------------------------------------------------- +# yacc_rr.py +# +# A grammar with a reduce/reduce conflict +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_assign_2(t): + 'statement : NAME EQUALS NUMBER' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_simple.exp b/test/yacc_simple.exp new file mode 100644 index 0000000..3836031 --- /dev/null +++ b/test/yacc_simple.exp @@ -0,0 +1 @@ +yacc: Generating LALR parsing table... diff --git a/test/yacc_simple.py b/test/yacc_simple.py new file mode 100644 index 0000000..b5dc9f3 --- /dev/null +++ b/test/yacc_simple.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_simple.py +# +# A simple, properly specifier grammar +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_sr.exp b/test/yacc_sr.exp new file mode 100644 index 0000000..1b76450 --- /dev/null +++ b/test/yacc_sr.exp @@ -0,0 +1,2 @@ +yacc: Generating LALR parsing table... +yacc: 20 shift/reduce conflicts diff --git a/test/yacc_sr.py b/test/yacc_sr.py new file mode 100644 index 0000000..e2f03ec --- /dev/null +++ b/test/yacc_sr.py @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +# yacc_sr.py +# +# A grammar with shift-reduce conflicts +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_term1.exp b/test/yacc_term1.exp new file mode 100644 index 0000000..40f9bdf --- /dev/null +++ b/test/yacc_term1.exp @@ -0,0 +1,2 @@ +./yacc_term1.py:25: Illegal rule name 'NUMBER'. Already defined as a token. +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_term1.py b/test/yacc_term1.py new file mode 100644 index 0000000..bbc52da --- /dev/null +++ b/test/yacc_term1.py @@ -0,0 +1,69 @@ +# ----------------------------------------------------------------------------- +# yacc_term1.py +# +# Terminal used on the left-hand-side +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'NUMBER : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_unused.exp b/test/yacc_unused.exp new file mode 100644 index 0000000..6caafd2 --- /dev/null +++ b/test/yacc_unused.exp @@ -0,0 +1,4 @@ +./yacc_unused.py:63: Symbol 'COMMA' used, but not defined as a token or a rule. +yacc: Symbol 'COMMA' is unreachable. +yacc: Symbol 'exprlist' is unreachable. +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_unused.py b/test/yacc_unused.py new file mode 100644 index 0000000..3a61f99 --- /dev/null +++ b/test/yacc_unused.py @@ -0,0 +1,78 @@ +# ----------------------------------------------------------------------------- +# yacc_unused.py +# +# A grammar with an unused rule +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules +precedence = ( + ('left','PLUS','MINUS'), + ('left','TIMES','DIVIDE'), + ('right','UMINUS'), + ) + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_expr_list(t): + 'exprlist : exprlist COMMA expression' + pass + +def p_expr_list_2(t): + 'exprlist : expression' + pass + + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + diff --git a/test/yacc_uprec.exp b/test/yacc_uprec.exp new file mode 100644 index 0000000..eb9a398 --- /dev/null +++ b/test/yacc_uprec.exp @@ -0,0 +1,2 @@ +./yacc_uprec.py:38: Nothing known about the precedence of 'UMINUS' +ply.yacc.YaccError: Unable to construct parser. diff --git a/test/yacc_uprec.py b/test/yacc_uprec.py new file mode 100644 index 0000000..0e8711e --- /dev/null +++ b/test/yacc_uprec.py @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +# yacc_uprec.py +# +# A grammar with a bad %prec specifier +# ----------------------------------------------------------------------------- +import sys +sys.tracebacklimit = 0 + +sys.path.insert(0,"..") +import ply.yacc as yacc + +from calclex import tokens + +# Parsing rules + +# dictionary of names +names = { } + +def p_statement_assign(t): + 'statement : NAME EQUALS expression' + names[t[1]] = t[3] + +def p_statement_expr(t): + 'statement : expression' + print t[1] + +def p_expression_binop(t): + '''expression : expression PLUS expression + | expression MINUS expression + | expression TIMES expression + | expression DIVIDE expression''' + if t[2] == '+' : t[0] = t[1] + t[3] + elif t[2] == '-': t[0] = t[1] - t[3] + elif t[2] == '*': t[0] = t[1] * t[3] + elif t[3] == '/': t[0] = t[1] / t[3] + +def p_expression_uminus(t): + 'expression : MINUS expression %prec UMINUS' + t[0] = -t[2] + +def p_expression_group(t): + 'expression : LPAREN expression RPAREN' + t[0] = t[2] + +def p_expression_number(t): + 'expression : NUMBER' + t[0] = t[1] + +def p_expression_name(t): + 'expression : NAME' + try: + t[0] = names[t[1]] + except LookupError: + print "Undefined name '%s'" % t[1] + t[0] = 0 + +def p_error(t): + print "Syntax error at '%s'" % t.value + +yacc.yacc() + + + + |