Skip to content

Commit

Permalink
Added test for module sort order
Browse files Browse the repository at this point in the history
This test uses a grammar split into several modules, where the
line number of rules are the same in more than one module. This
will cause ParserReflect.get_pfunctions to try to sort tuples
on module items, which are unsortable in Python 3.
  • Loading branch information
moses-palmer committed Jul 16, 2015
1 parent dbf1226 commit 2e1d1c6
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 0 deletions.
9 changes: 9 additions & 0 deletions test/pkg_test6/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Tests proper sorting of modules in yacc.ParserReflect.get_pfunctions

# Here for testing purposes
import sys
if '..' not in sys.path:
sys.path.insert(0, '..')

from .parsing.calcparse import parser

Empty file.
48 changes: 48 additions & 0 deletions test/pkg_test6/parsing/calclex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -----------------------------------------------------------------------------
# calclex.py
# -----------------------------------------------------------------------------

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 %s" % t.value)
t.value = 0
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 os.path
lexer = lex.lex(optimize=True, outputdir=os.path.dirname(__file__))



33 changes: 33 additions & 0 deletions test/pkg_test6/parsing/calcparse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -----------------------------------------------------------------------------
# yacc_simple.py
#
# A simple, properly specifier grammar
# -----------------------------------------------------------------------------

from .calclex import tokens
from ply import yacc

# Parsing rules
precedence = (
('left','PLUS','MINUS'),
('left','TIMES','DIVIDE'),
('right','UMINUS'),
)

# dictionary of names
names = { }

from .statement import *

from .expression import *

def p_error(t):
print("Syntax error at '%s'" % t.value)

import os.path
parser = yacc.yacc(outputdir=os.path.dirname(__file__))





31 changes: 31 additions & 0 deletions test/pkg_test6/parsing/expression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This file contains definitions of expression grammar

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[2] == '/': 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
9 changes: 9 additions & 0 deletions test/pkg_test6/parsing/statement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This file contains definitions of statement grammar

def p_statement_assign(t):
'statement : NAME EQUALS expression'
names[t[1]] = t[3]

def p_statement_expr(t):
'statement : expression'
t[0] = t[1]
8 changes: 8 additions & 0 deletions test/testyacc.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,4 +441,12 @@ def test_pkg_test5(self):
r = parser.parse('3+4+5')
self.assertEqual(r, 12)

def test_pkg_test6(self):
from pkg_test6 import parser
self.assertTrue(os.path.exists('pkg_test6/parsing/parsetab.py'))
self.assertTrue(os.path.exists('pkg_test6/parsing/lextab.py'))
self.assertTrue(os.path.exists('pkg_test6/parsing/parser.out'))
r = parser.parse('3+4+5')
self.assertEqual(r, 12)

unittest.main()

0 comments on commit 2e1d1c6

Please sign in to comment.