我想使用textx来解析"foo bar."
与"foo bar ."
不同(如果没有空格,则将'.'
绑定到最后一个单词,但仍单独解析'.'
)。
我本以为以下可以做到这一点:
from textx.metamodel import metamodel_from_str
mm = metamodel_from_str('''
Sentence[skipws]: words*=Word;
Word[noskipws]: ID '.' | ID | '.';
''')
但是它将以下内容解析为两个而不是三个“单词”:
>>> print(len(mm.model_from_str('''foo bar .''').words))
2
如果我改为这样做,它似乎可以正常工作:
from textx.metamodel import metamodel_from_str
mm = metamodel_from_str('''
Sentence[skipws]: (words=Word /(?i) */)*;
Word[noskipws]: ID '.' | ID | '.';
''', skipws=False)
我不清楚,为什么在这里需要skipps = False,还是手动正则表达式...,如果我不使用
(?i)
,它将引发异常(“无可重复”)。 最佳答案
skipws/noskipws
applies immediately,因此,Word
规则的第一个匹配项将在ID
之前看到前面的空格,因此ID '.'
将永远不会匹配。您必须占用这些空间。这是完成的方式:
mm = metamodel_from_str('''
Sentence[skipws]: words*=Word;
Word[noskipws]: /\s*/- (ID '.' | ID | '.');
''')
print(mm.model_from_str('foo bar.', debug=True).words)
-
之后的/\s*/
运算符是match suppression,这意味着我们不希望匹配的那一部分出现在我们的Word
中。最好使用debug=True
进行分析,以了解幕后发生的事情。更新2019-10-02:
OrderedChoice
中存在一个错误,该错误使skipws
在替代选择的情况下的工作方式引起混乱。从1.9.1版开始,它已在Arpeggio解析器中修复。