如何使用百灵鸟ebnf解析字符串内的〜{expr}

时间:2018-07-13 14:21:51

标签: python regex parsing ebnf lark-parser

我正在尝试为dsl编写过时的语法,但是在使用此字符串插值语法时遇到了麻烦:

" abc " <- normal string
" xyz~{expression}abc " <- string with interpolation

因此~~从字符串切换到表达式,而}终止该表达式。我认为这很接近:

string : "\"" (string_interp|not_string_interp)* "\""
string_interp: "~{" expression "}"
not_string_interp: /([^~][^{])+/

但是正则表达式只能匹配偶数个字符,如果〜{跨越一个偶数边界,它将被忽略。

not_string_interp: /(.?|([^~][^{])+)/

这是我所能获得的,但似乎仍然是错误的。我可以提前使用吗?我还想保持%ignore WS的正常运行,因为它可以大大降低噪音,因此解决该问题的方法将是不错的选择!

谢谢

测试用例:

""
"a"
"~{1}"
" ~{1} "
"a bc~{1}c d"
"a b~{1}c d"

2 个答案:

答案 0 :(得分:2)

我认为这样做。遗憾的是,任何〜后跟{的字符都不会分割字符串,但是我以后可以重构它们。规则的优先级和正则表达式的贪婪使我迷惑。

/[^"~]+/不是〜或“(常规字符串)的任何内容

"~{" expression "}"正则表达式

/~(?!{)/句柄〜不带{。采用 ?!因为我们一定不能消耗下一个字符(它可以是“或另一个〜”)

from lark import Lark

print (Lark(r"""
    string: "\"" string_thing* "\""
    string_thing: /[^"~]+/
        | "~{" expression "}"
        | /~(?!{)/
    expression: /[^}]+/
""", start='string', ambiguity="explicit").parse(
# '"a"'
'"a~b{}c}d~{1}g"'
# '"~abc~"'
# '"~{1}~~{1}~~~{1}"'
).pretty())

答案 1 :(得分:1)

Here is a solution to your problem使用正向后方。

(?<=~{)[^}]+

它将查找表达式~{的开头,并捕获所有内容,直到右括号}