【问题标题】:Parsing logical expression using PLY使用 PLY 解析逻辑表达式
【发布时间】:2016-11-22 05:21:52
【问题描述】:

我正在尝试使用 PLY 解析包含 'implies' 'and' 'or' 和 'negation' 的逻辑表达式,其中 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 编写正确的语法规则,如果有人可以帮助我,那将是非常有帮助的

【问题讨论】:

    标签: python parsing ply


    【解决方案1】:

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

    【讨论】:

    • 我放了新版本。
    • 嘿伙计,我可以问你一些问题,因为我正在做类似的程序吗?谢谢! @furas
    猜你喜欢
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多