Python 使用pyparsing检测无效语法

Python 使用pyparsing检测无效语法,python,pyparsing,Python,Pyparsing,我有一个计算逻辑表达式的简单语法 “单一”条件属于以下类型: keyword = value keyword != value 然后,我想允许用括号分组的逻辑组合, e、 g 但不是左/右关联性重要的逻辑组合 并迷惑用户。因此,以下情况将被禁止: cond1 & cond2 | cond3 如果我理解正确,后一个要求会阻止我使用operatorRecessence(), 无论如何,我想从一个较低的层次来理解它 以下语法将我带到我想要的地方: from pyparsing import

我有一个计算逻辑表达式的简单语法

“单一”条件属于以下类型:

keyword = value
keyword != value
然后,我想允许用括号分组的逻辑组合, e、 g

但不是左/右关联性重要的逻辑组合 并迷惑用户。因此,以下情况将被禁止:

cond1 & cond2 | cond3
如果我理解正确,后一个要求会阻止我使用
operatorRecessence()
, 无论如何,我想从一个较低的层次来理解它

以下语法将我带到我想要的地方:

from pyparsing import Word, alphas, nums, oneOf, Literal, Group, Suppress, \
                        Forward, ZeroOrMore, ParseException, StringEnd
comparison_op_list = ['=', '!=']
logical_op_list = ['&', '|']
# Pyparsing expression for single conditions
keyword = Word(alphas + nums + '_.:-')
comparison_op = oneOf(comparison_op_list)
value = Word(alphas + nums + '_.:-;')
single_condition = keyword + comparison_op + value
# Pyparsing expression for combined condition
lpar = Literal( '(' )
rpar = Literal( ')' )
logical_op = oneOf(logical_op_list)
combined_expr = Forward()
atom = single_condition | ( Suppress(lpar) + combined_expr + Suppress(rpar) )
combined_expr << Group(atom) + ZeroOrMore( logical_op + combined_expr )

# Examples
test_strings = [
    'keyword = value',
    'keyword1 = value1 & keyword2 = value2',
    'a=a & (b=b|c=c) & (d=d & (e=e|f=f))',
    'a=a & ((b=b|(c=c))) & (((d=d) & (e=e|f=f)))',
    'test1=A & test2=B | test3 = C'  # Parses fine, but later rejected in python code
]
for s in test_strings:
    print
    print s
    print combined_expr.parseString(s)
由此,我可以在常规python中处理有效的输入。 问题是,一些无效语法也会被正确读取:

invalid_strings = [
    'a b = c',  # Rightfully rejected 
    'word1 = word2 != word3', # Read as 'word1 = word2'
    'keyword = value_with_*illegal*_characters' # Read as 'keyword = value_with_'
]
for s in invalid_strings:
    try:
        result = combined_expr.parseString(s)
    except ParseException:
        result = None
    print
    print s
    print result
输出:

keyword = value
[['keyword', '=', 'value']]

keyword1 = value1 & keyword2 = value2
[['keyword1', '=', 'value1'], '&', ['keyword2', '=', 'value2']]

a=a & (b=b|c=c) & (d=d & (e=e|f=f))
[['a', '=', 'a'], '&', [['b', '=', 'b'], '|', ['c', '=', 'c']], '&', [['d', '=', 'd'], '&', [['e', '=', 'e'], '|', ['f', '=', 'f']]]]

a=a & ((b=b|(c=c))) & (((d=d) & (e=e|f=f)))
[['a', '=', 'a'], '&', [[['b', '=', 'b'], '|', [['c', '=', 'c']]]], '&', [[[['d', '=', 'd']], '&', [['e', '=', 'e'], '|', ['f', '=', 'f']]]]]

test1=A & test2=B | test3 = C
[['test1', '=', 'A'], '&', ['test2', '=', 'B'], '|', ['test3', '=', 'C']]
a b = c
None

word1 = word2 != word3
[['word1', '=', 'word2']]

keyword = value_with_*illegal*_characters
[['keyword', '=', 'value_with_']]
对于上面没有逻辑组合的例子,我可能 使用StringEnd要求字符串紧跟在表达式之后。 但当条件与逻辑运算符(?)组合时,这将不起作用 是否有一种方法要求输入表达式的所有部分都被识别为 是语法的一部分,还是这超出了pyparsing的范围和任务
e、 g.帘布层

如果包含
parseAll=True
arg,则可以在成功解析后强制parseString在额外字符上失败。另外,您应该能够调用
combined\u expr.runTests(test\u strings)
来测试您的示例。谢谢@PaulMcGuire,这解决了我的问题。如果你把它作为答案贴出来,我会接受的。
a b = c
None

word1 = word2 != word3
[['word1', '=', 'word2']]

keyword = value_with_*illegal*_characters
[['keyword', '=', 'value_with_']]