使用PLY解析逻辑表达式

时间:2016-11-22 05:21:52

标签: python parsing ply

我正在尝试解析包含'暗示'的逻辑表达式。 '和' '或'和“否定”#39;使用诸如(Q(a)=>R(b))之类的括号,使用PLY,其中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编写正确的语法规则,如果有人可以帮助我,这将是非常有帮助的

1 个答案:

答案 0 :(得分:0)

我不记得在哪里使用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')