些細なことだと思うことを解決するのに苦労しています。PLY の calc の例を修正して、いくつかの関数呼び出しと、1 つ以上の式 (式は名前、数値、またはリテラル) を受け入れることができる引数リストを含めました。問題は、私の実装が非決定論的であることです。複数行の引数が正しく、そうでない場合もあります。
たとえば、実行中に次のように入力しています。
currentDoc(2,5)
時々実行すると、次のようになります。
calc > currentDoc(2,5)
p_expression_number
p_expression_number
p_expression_function
its in there: [2, 5]
また、プログラムを実行すると、これが生成されます(これは避けたいです):
calc > currentDoc(2,5)
Syntax error at ','
p_expression_number
どちらの場合も、パーサーは正しいルール (p_expression_number) に入りますが、間違ったものを選択することもあります。半分の時間は、(コンマを無視して) 式に縮小され、次の引数であるコンマが理解できないと不平を言うように見えます。それ以外の時は大丈夫です。
これを解決するにはどうすればよいですか? 私はいくつかのことを試しましたが、例を調べましたが、わかりません。
これが私のコードです:
tokens = ( 'NAME','NUMBER', 'EQUALS', 'COMMA', 'DOT', 'LITERAL', 'LPAREN','RPAREN', )
t_EQUALS = r'='
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_COMMA = r','
t_DOT = r'.'
t_LITERAL = r'(\'[^\']*\'|"[^"]*")'
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
functions = {
'currentDoc',
}
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
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)
import ply.lex as lex
lex.lex()
names = {}
def p_statement_assign(t):
'statement : NAME EQUALS expression'
print("p_statement_assign")
names[t[1]] = t[3]
def p_statement_expr(t):
'statement : expression'
print("p_statement_expr")
print(t[1])
def p_parameters(t):
'''
parameters : expression
| parameters COMMA expression
'''
if len(t) == 2:
t[0] = [t[1]]
else:
t[0] = t[1]
t[0].append(t[3])
def p_expression_function(t):
'''
statement : NAME LPAREN parameters RPAREN
statement : NAME DOT NAME LPAREN parameters RPAREN
'''
print("p_expression_function")
if t[2] is ".":
print('tis dot')
if t[1] in functions:
print("its in there:", t[3])
else:
print("Function '%s' not defined" % t[1])
def p_expression_literal(t):
'expression : LITERAL'
print("p_literal")
t[0] = t[1][1:-1]
def p_expression_number(t):
'expression : NUMBER'
print("p_expression_number")
t[0] = t[1]
def p_expression_name(t):
'expression : NAME'
print("p_expression_name")
try:
t[0] = names[t[1]]
except LookupError:
print("Undefined name '%s'" % t[1])
t[0] = 0
def p_error(t):
if t:
print("Syntax error at '%s'" % t.value)
import ply.yacc as yacc
yacc.yacc()
while 1:
try: s = input('calc > ')
except EOFError:
break
yacc.parse(s)