0

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

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

例如,我希望能够将其解析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')

可能的?

4

1 回答 1

4

仔细考虑之后,我认为您尝试定义的语言是模棱两可的,但有多种方法可以解决这个问题。

你要这个:

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

给你这个:

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

您已经暗示您希望空格充当运算符。但是为什么它不是上下文中的运算符'c :'呢?什么时候是,什么时候不是运营商的规则是什么?

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

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

我能想到三个更好的选择:

  1. 要求每个操作数都是以空格分隔的单词列表。
  2. 在操作数中间允许空格。
  3. 使用默认的空白处理,并允许在任何运算符的每一侧使用多个术语。

其中任何一个都非常容易解析,并为您提供了一个非常易于使用的解析树。我可能会选择#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']]]
于 2013-01-18T22:01:06.250 回答