【发布时间】:2018-04-19 22:52:13
【问题描述】:
我遇到了一个问题,我需要将非常简单的句子解析为 BNF 解析。我能够轻松地标记标记并使用简单的句子。但是,有几种情况可以应用 reduce 规则,或者发生转变,并且可能发生另一个 reduce。例如:
杰瑞德追着汤姆和杰瑞吃饭。
我有一条规则将名词连词减少为名词短语,还有另一条规则将句子连词减少为复合句。在“Jerry”,它似乎自动假定句子是名词动词名词短语的形式,而不是句子连词,并且在遇到“ate”时抛出错误,因为 NP VP NP VP 没有重写规则.
我怎样才能改变这个,如果连词右边的词是一个句子,它就会把它解析为 S CONJ S,但如果不是,那么它就会被解析为 NP VP NP?
编辑:为澄清起见,这是我当前的代码:
import ply.yacc as yacc
from lexer import tokens
precedence = (('left', 'Vi'),('left', 'N'))
def p_S(p):
"""S : NP VP"""
p[0] = '[S ' + p[1] + ' ' + p[2] + ' ]'
def p_VP(p):
"""VP : VP Conj VP"""
p[0] = '[VP ' + p[1] + ' ' + p[2] + ' ' + p[3] + ' ]'
def p_Vi(p):
"""VP : Vi"""
p[0] = '[VP [VI ' + p[1] + ' ] ]'
def p_Vt(p):
"""VP : Vt NP"""
p[0] = '[VP [Vt ' + p[1] + ' ] ' + p[2] + ' ]'
def p_Vd(p):
"""VP : Vd NP NP"""
p[0] = '[VP [VT ' + p[1] + ' ] ' + p[2] + ' ' + p[3] + ' ]'
def p_NP(p):
"""NP : NP Conj NP
| N"""
if len(p) == 4:
p[0] = '[NP ' + p[1] + ' [Conj ' + p[2] + ' ] ' + p[3] + ' ]'
else:
p[0] = '[N ' + p[1] + ' ]'
def p_error(p):
print("Syntax Error in input!\n")
parser = yacc.yacc()
while True:
try:
s = input('calc > ')
if not s: continue
result = parser.parse(s)
if result is not None: print(result + '\n')
except EOFError:
print("Please try again")
【问题讨论】: