您如何正确混合textx跳过/不跳过?

时间:2019-09-15 13:24:16

标签: python textx

我想使用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),它将引发异常(“无可重复”)。

1 个答案:

答案 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解析器中修复。