使用 PLY 解析逻辑表达式
Parsing logical expression using PLY
我正在尝试使用 PLY where Q(a)和 R(b) 是谓词,始终以大写字母开头,变量 'a' 和 'b' 将是单个小写字母字符。
每个运算符及其操作数都用括号括起来。我试图解析的其他一些逻辑表达式示例是 ((D(q,w) & E(r,s)) => F(t)), (((G(a)=>H(b))=>I(c))=>J(d)), (~(~(~P(a))))
.
下面是我写的代码
import ply.lex as lex
import ply.yacc as yacc
tokens = [
'LPAREN',
'RPAREN',
'PREDICATE',
'AND',
'OR',
'IMPLIES',
'NEGATION'
]
t_PREDICATE = r'[A-Z][a-z]*\(([A-Za-z,]+)\)'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_AND = r'\&'
t_OR = r'\|'
t_IMPLIES = r'\=>'
t_NEGATION = r'\~'
t_ignore = r' '
def t_error(t):
print("Illegeal characters")
t.lexer.skip(1)
lexer = lex.lex()
def p_expression_negation(p):
'''
expression : LPAREN NEGATION PREDICATE RPAREN
'''
p[0] = (p[2], p[3])
print(p[0])
def p_expression_single(p):
'''
expression : PREDICATE
'''
p[0] = p[1]
print(p[0])
def p_expression(p):
'''
expression : LPAREN term IMPLIES term RPAREN
| LPAREN term AND term RPAREN
| LPAREN term OR term RPAREN
'''
p[0] = (p[3], p[2], p[4])
print(p[0])
def p_term_negation(p):
'''
term : LPAREN NEGATION PREDICATE RPAREN
'''
p[0] = (p[2], p[3])
return p[0]
def p_term_single(p):
'''
term : PREDICATE
'''
p[0] = (p[1])
return p[0]
def p_term_multiple(p):
'''
term : LPAREN PREDICATE IMPLIES PREDICATE RPAREN
| LPAREN PREDICATE AND PREDICATE RPAREN
| LPAREN PREDICATE OR PREDICATE RPAREN
'''
p[0] = (p[3], p[2], p[4])
return p[0]
def p_error(p):
print("Syntax error in input!")
parser = yacc.yacc()
while True:
try:
s = input('Enter the input')
except EOFError:
break
parser.parse(s, lexer=lexer)
但是这个程序对于 (((G(a)=>H(b))=>I(c))=>J(d)), (~(~(~P(a))))
等逻辑表达式失败,因为这些表达式以超过 2 个 '(' 开头,我无法修改我的代码以适应在表达式开头打开括号的情况可以是 1 到 n。
我想我应该使用递归,但这对我来说也是失败的。
这是我第一个使用 PLY 的程序,所以无法为 yacc 编写正确的语法规则,如果有人可以帮助我,那将是很大的帮助
我不记得在哪里使用 term
但这对我有用。
编辑:
之前的版本并不理想,因为 Q(a)=>R(b)
被视为正确的表达式。
当前版本将 Q(a)=>R(b)
视为不正确的表达式。
import ply.lex as lex
import ply.yacc as yacc
tokens = [
'LPAREN',
'RPAREN',
'PREDICATE',
'AND',
'OR',
'IMPLIES',
'NEGATION'
]
t_PREDICATE = r'[A-Z][a-z]*\(([A-Za-z,]+)\)'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_AND = r'\&'
t_OR = r'\|'
t_IMPLIES = r'\=>'
t_NEGATION = r'\~'
t_ignore = r' '
def t_error(t):
print("Illegeal characters")
t.lexer.skip(1)
lexer = lex.lex()
def p_expression_normal(p):
'''
expression : LPAREN PREDICATE RPAREN
'''
p[0] = ('()', p[2])
print(p[0])
def p_expression_negation(p):
'''
expression : LPAREN NEGATION PREDICATE RPAREN
| LPAREN NEGATION expression RPAREN
'''
p[0] = ('()', p[2], p[3])
print(p[0])
def p_expression_operation(p):
'''
expression : LPAREN expression IMPLIES expression RPAREN
| LPAREN expression AND expression RPAREN
| LPAREN expression OR expression RPAREN
| LPAREN PREDICATE IMPLIES expression RPAREN
| LPAREN PREDICATE AND expression RPAREN
| LPAREN PREDICATE OR expression RPAREN
| LPAREN expression IMPLIES PREDICATE RPAREN
| LPAREN expression AND PREDICATE RPAREN
| LPAREN expression OR PREDICATE RPAREN
| LPAREN PREDICATE IMPLIES PREDICATE RPAREN
| LPAREN PREDICATE AND PREDICATE RPAREN
| LPAREN PREDICATE OR PREDICATE RPAREN
'''
p[0] = ('()', p[3], p[2], p[4])
print(p[0])
def p_error(p):
print("Syntax error in input!")
parser = yacc.yacc()
#while True:
# try:
# s = input('Enter the input: ')
# except EOFError:
# break
# parser.parse(s, lexer=lexer)
test = [
'(Q(a))', # OK
'Q(a)', # wrong
'(Q(a)=>R(b))', # OK
'Q(a)=>R(b)', # wrong
'(((G(a)=>H(b))=>I(c))=>J(d))', # OK
'((G(a)=>H(b))=>I(c))=>J(d)', # wrong
'(~(~(~P(a))))', # OK
'~(~(~P(a)))', # wrong
'((D(q,w) & E(r,s)) => F(t))', # OK
'(D(q,w) & E(r,s)) => F(t)', # wrong
]
for s in test:
print(s)
print()
parser.parse(s, lexer=lexer)
print('\n------\n')
我正在尝试使用 PLY where Q(a)和 R(b) 是谓词,始终以大写字母开头,变量 'a' 和 'b' 将是单个小写字母字符。
每个运算符及其操作数都用括号括起来。我试图解析的其他一些逻辑表达式示例是 ((D(q,w) & E(r,s)) => F(t)), (((G(a)=>H(b))=>I(c))=>J(d)), (~(~(~P(a))))
.
下面是我写的代码
import ply.lex as lex
import ply.yacc as yacc
tokens = [
'LPAREN',
'RPAREN',
'PREDICATE',
'AND',
'OR',
'IMPLIES',
'NEGATION'
]
t_PREDICATE = r'[A-Z][a-z]*\(([A-Za-z,]+)\)'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_AND = r'\&'
t_OR = r'\|'
t_IMPLIES = r'\=>'
t_NEGATION = r'\~'
t_ignore = r' '
def t_error(t):
print("Illegeal characters")
t.lexer.skip(1)
lexer = lex.lex()
def p_expression_negation(p):
'''
expression : LPAREN NEGATION PREDICATE RPAREN
'''
p[0] = (p[2], p[3])
print(p[0])
def p_expression_single(p):
'''
expression : PREDICATE
'''
p[0] = p[1]
print(p[0])
def p_expression(p):
'''
expression : LPAREN term IMPLIES term RPAREN
| LPAREN term AND term RPAREN
| LPAREN term OR term RPAREN
'''
p[0] = (p[3], p[2], p[4])
print(p[0])
def p_term_negation(p):
'''
term : LPAREN NEGATION PREDICATE RPAREN
'''
p[0] = (p[2], p[3])
return p[0]
def p_term_single(p):
'''
term : PREDICATE
'''
p[0] = (p[1])
return p[0]
def p_term_multiple(p):
'''
term : LPAREN PREDICATE IMPLIES PREDICATE RPAREN
| LPAREN PREDICATE AND PREDICATE RPAREN
| LPAREN PREDICATE OR PREDICATE RPAREN
'''
p[0] = (p[3], p[2], p[4])
return p[0]
def p_error(p):
print("Syntax error in input!")
parser = yacc.yacc()
while True:
try:
s = input('Enter the input')
except EOFError:
break
parser.parse(s, lexer=lexer)
但是这个程序对于 (((G(a)=>H(b))=>I(c))=>J(d)), (~(~(~P(a))))
等逻辑表达式失败,因为这些表达式以超过 2 个 '(' 开头,我无法修改我的代码以适应在表达式开头打开括号的情况可以是 1 到 n。
我想我应该使用递归,但这对我来说也是失败的。
这是我第一个使用 PLY 的程序,所以无法为 yacc 编写正确的语法规则,如果有人可以帮助我,那将是很大的帮助
我不记得在哪里使用 term
但这对我有用。
编辑:
之前的版本并不理想,因为 Q(a)=>R(b)
被视为正确的表达式。
当前版本将 Q(a)=>R(b)
视为不正确的表达式。
import ply.lex as lex
import ply.yacc as yacc
tokens = [
'LPAREN',
'RPAREN',
'PREDICATE',
'AND',
'OR',
'IMPLIES',
'NEGATION'
]
t_PREDICATE = r'[A-Z][a-z]*\(([A-Za-z,]+)\)'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_AND = r'\&'
t_OR = r'\|'
t_IMPLIES = r'\=>'
t_NEGATION = r'\~'
t_ignore = r' '
def t_error(t):
print("Illegeal characters")
t.lexer.skip(1)
lexer = lex.lex()
def p_expression_normal(p):
'''
expression : LPAREN PREDICATE RPAREN
'''
p[0] = ('()', p[2])
print(p[0])
def p_expression_negation(p):
'''
expression : LPAREN NEGATION PREDICATE RPAREN
| LPAREN NEGATION expression RPAREN
'''
p[0] = ('()', p[2], p[3])
print(p[0])
def p_expression_operation(p):
'''
expression : LPAREN expression IMPLIES expression RPAREN
| LPAREN expression AND expression RPAREN
| LPAREN expression OR expression RPAREN
| LPAREN PREDICATE IMPLIES expression RPAREN
| LPAREN PREDICATE AND expression RPAREN
| LPAREN PREDICATE OR expression RPAREN
| LPAREN expression IMPLIES PREDICATE RPAREN
| LPAREN expression AND PREDICATE RPAREN
| LPAREN expression OR PREDICATE RPAREN
| LPAREN PREDICATE IMPLIES PREDICATE RPAREN
| LPAREN PREDICATE AND PREDICATE RPAREN
| LPAREN PREDICATE OR PREDICATE RPAREN
'''
p[0] = ('()', p[3], p[2], p[4])
print(p[0])
def p_error(p):
print("Syntax error in input!")
parser = yacc.yacc()
#while True:
# try:
# s = input('Enter the input: ')
# except EOFError:
# break
# parser.parse(s, lexer=lexer)
test = [
'(Q(a))', # OK
'Q(a)', # wrong
'(Q(a)=>R(b))', # OK
'Q(a)=>R(b)', # wrong
'(((G(a)=>H(b))=>I(c))=>J(d))', # OK
'((G(a)=>H(b))=>I(c))=>J(d)', # wrong
'(~(~(~P(a))))', # OK
'~(~(~P(a)))', # wrong
'((D(q,w) & E(r,s)) => F(t))', # OK
'(D(q,w) & E(r,s)) => F(t)', # wrong
]
for s in test:
print(s)
print()
parser.parse(s, lexer=lexer)
print('\n------\n')