我想使用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)
,它将引发异常(“无可重复”)。
答案 0 :(得分:1)
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解析器中修复。