First, add token definition for english words
t_plustext = r'plus'
Add those new tokens to tokens
tokens = (
'NAME','NUMBER', 'times', 'divided_by', 'plus', 'minus', 'plustext', ....
)
Finally, use those new token in you grammar this way :
def p_expression_binop(p):
'''expression : expression '+' expression
| expression plustext expression
'''
UPDATE : here is a working subset of the grammar
#!/usr/bin/python
from __future__ import print_function
import sys
import ply.lex as lex
import ply.yacc as yacc
# ------- Calculator tokenizing rules
tokens = (
'NUMBER', 'times', 'divided_by', 'plus', 'minus', 'plustext',
'one', 'two', 'three',
)
literals = ['=','+','-','*','/', '(',')']
t_ignore = " \t\n"
t_plustext = r'plus'
t_plus = r'\+'
t_minus = r'-'
t_times = r'\*'
t_divided_by = r'/'
t_one = 'one'
t_two = 'two'
t_three = 'three'
def t_NUMBER(t):
r'\d+'
try:
t.value = int(t.value)
except ValueError:
print("Integer value too large %d", t.value)
t.value = 0
return t
precedence = (
('left','+','-','plustext'),
('left','times','divided_by'),
('left','*','/'),
)
def p_statement_expr(p):
'statement : expression'
p[0] = p[1]
print(p[1])
def p_expression_binop(p):
'''expression : expression '+' expression
| expression plustext 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]
elif p[2] == 'plus': p[0] = p[1] + p[3]
def p_statement_lit(p):
'''expression : NUMBER
| TXTNUMBER
'''
p[0] = p[1]
def p_txtnumber(p):
'''TXTNUMBER : one
| two
| three
'''
p[0] = w2n(p[1])
def w2n(s):
if s == 'one': return 1
elif s == 'two': return 2
elif s == 'three': return 3
assert(False)
# See http://stackoverflow.com/questions/493174/is-there-a-way-to-convert-number-words-to-integers-python for a complete implementation
def process(data):
lex.lex()
yacc.yacc()
#yacc.parse(data, debug=1, tracking=True)
yacc.parse(data)
if __name__ == "__main__":
data = open(sys.argv[1]).read()
process(data)