我想使用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)我不清楚为什么这里需要skipws=False,或者手动正则表达式...如果我忽略了(?i),它会抛出一个异常('nothing to repeat')。
发布于 2019-09-16 00:53:21
因此,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解析器中已修复此问题。
https://stackoverflow.com/questions/57944531
复制相似问题