具有pyparsing的operatorPrecedence的句法空格

时间:2013-01-18 21:02:35

标签: python parsing operator-precedence

是否可以使用一些空格作为分隔符?我的意思是......

给定一些python运算符优先级解析器,我希望将自然语言与运算符混合,用于记笔记的简写,即'caffeine : A1 antagonist -> caffeine : peripheral stimulant'具有解释'caffeine is an A1 antagonist implies that it is a peripheral stimulant'

e.g。我希望能够将此parse('a:b -> c : d e')解析为[[['a', ':', 'b'], '->', ['c', ':', ['d', 'e']]]]

有这样的东西

operands = delimitedList(Word(alphanums), delim=',') 
# delim=' ' obviously doesn't work

precedence = [
    (":", 2, opAssoc.LEFT),
    ("->", 2, opAssoc.LEFT),
    ]

parser = operatorPrecedence(operands, precedence)

def parse(s): return parser.parseString(s, parseAll=True)

print parse('a:b -> c : d e')

可能?

1 个答案:

答案 0 :(得分:4)

在考虑完之后,我认为您尝试定义的语言含糊不清,但有多种方法可以解决这个问题。

你想要这个:

parse('a:b -> c : d e')

给你这个:

[[['a', ':', 'b'], '->', ['c', ':', ['d', 'e']]]]

您暗示您希望空格充当运算符。但那么为什么它不是'c :'背景下的算子?它何时以及何时不是运营商的规则是什么?

或者您希望每个操作数都是以空格分隔的单词列表。但在这种情况下,为什么'a'代替['a']?每个操作数都是一个列表,或者它们都不是,对吧?它显然不依赖于位置,并且您没有指定任何其他规则。

有(至少)一个合理的规则适合您的想法:将单个元素列表的任何操作数折叠到该元素。但这是一个奇怪的规则 - 当你以后使用这个解析树用于你正在使用它的任何目的时,你必须通过编写处理单个单词的代码来有效地反转相同的规则,就像它是一个单词列表一样。所以...为什么这样做?

我可以想到三个更好的选择:

  1. 要求每个操作数都是以空格分隔的单词列表。
  2. 在操作数中间留出空格。
  3. 使用默认的空白处理,并在任何运算符的每一侧允许多个术语。
  4. 其中任何一个都很容易解析,并为您提供一个非常容易使用的解析树。我可能会选择#2,但由于我已经在上面的评论中解释了如何做到这一点,让我们在这里做#3:

    >>> operands = OneOrMore(Word(alphanums))
    >>> precedence = [
    ...     (":", 2, opAssoc.LEFT),
    ...     ("->", 2, opAssoc.LEFT),
    ...     ]
    >>> parser = operatorPrecedence(operands, precedence)
    >>> def parse(s): return parser.parseString(s, parseAll=True)
    >>> print(parse('a:b -> c : d e'))
    [[['a', ':', 'b'], '->', ['c', ':', 'd', 'e']]]
    >>> print(parse('caffeine : A1 antagonist -> caffeine : peripheral stimulant'))
    [[['caffeine', ':', 'A1', 'antagonist'], '->', ['caffeine', ':', 'peripheral', 'stimulant']]]