在 LPeg 中匹配具有特定结尾的字符串
Matching a string with a specific end in LPeg
我正在尝试捕获包含 a 和 b 的组合但始终以 b 结尾的字符串。换句话说:
local patt = S'ab'^0 * P'b'
匹配 aaab
和 bbabb
但不匹配 aaa
或 bba
。然而,以上内容与任何内容都不匹配。这是因为 S'ab'^0
贪婪匹配了最后的 b
吗?我是这么认为的,除了可能诉诸 lpeg.Cmt
之外想不出任何替代方案,这似乎有点矫枉过正。但也许不是,有人知道如何匹配这样的模式吗?我看到 this question 但解决方案的问题在于它会在第一个结束标记处停止(即 'cat' 那里, 'b' 在这里)并且在我的情况下我需要接受中间'b's.
P.S。
我实际上想做的是匹配最外层规则是函数调用的表达式。
例如
func();
func(x)(y);
func_arr[z]();
全部匹配但
exp;
func()[1];
4 + 5;
没有。我的其余语法有效,我很确定这归结为同一个问题,但为了完整起见,我正在使用的语法看起来像:
top_expr = V'primary_expr' * V'postfix_op'^0 * V'func_call_op' * P';';
postfix_op = V'func_call_op' + V'index_op';
同样,V'postfix_op'^0
吃掉了我最后期待的 func_call_op
。
是的,没有回溯,所以你已经正确地发现了问题。我认为解决方案是列出有效的 postfix_op
表达式;我会将 V'func_call_op' + V'index_op'
更改为 V'func_call_op'^0 * V'index_op'
并将最后的 V'func_call_op'
更改为 V'func_call_op'^1
以允许最后调用多个函数。
更新:如评论中所建议,a/b
问题的解决方案是 (P'b'^0 * P'a')^0 * P'b'^1
。
这个怎么样?
local final = P'b' * P(-1)
local patt = (S'ab' - final)^0 * final
模式final
是我们在字符串末尾所需要的。
模式 patt
与集合 'ab' 匹配,除非 它后面跟着最终序列。然后它断言我们有最终序列。这阻止了最后的 'b' 被吃掉。
这并不能保证我们得到任何 a(但问题中的模式也不会)。
抱歉,我的回答来得太晚了,但我认为值得给这个问题一个更正确的答案。
据我了解,您只需要 非盲 贪婪匹配。但不幸的是,LPeg 的“官方文档”只告诉我们如何使用 LPeg 进行 blind 贪婪匹配(或重复)。但是这种模式可以用解析表达式文法来描述。对于规则 S,如果你想匹配尽可能多的 E1,然后是 E2,你需要写
S <- E1 S / E2
a/b
问题的解决方案变为
S <- [ab] S / 'b'
您可能希望通过在第一个选项中插入一些 a 来优化规则
S <- [ab] 'a'* S / 'b'
这将大大减少递归。至于你真正的问题,这是我的答案:
top_expr <- primary_expr p_and_f ';'
p_and_f <- postfix_op p_and_f / func_call_op
postfix_op <- func_call_op / index_op
我正在尝试捕获包含 a 和 b 的组合但始终以 b 结尾的字符串。换句话说:
local patt = S'ab'^0 * P'b'
匹配 aaab
和 bbabb
但不匹配 aaa
或 bba
。然而,以上内容与任何内容都不匹配。这是因为 S'ab'^0
贪婪匹配了最后的 b
吗?我是这么认为的,除了可能诉诸 lpeg.Cmt
之外想不出任何替代方案,这似乎有点矫枉过正。但也许不是,有人知道如何匹配这样的模式吗?我看到 this question 但解决方案的问题在于它会在第一个结束标记处停止(即 'cat' 那里, 'b' 在这里)并且在我的情况下我需要接受中间'b's.
P.S。 我实际上想做的是匹配最外层规则是函数调用的表达式。 例如
func();
func(x)(y);
func_arr[z]();
全部匹配但
exp;
func()[1];
4 + 5;
没有。我的其余语法有效,我很确定这归结为同一个问题,但为了完整起见,我正在使用的语法看起来像:
top_expr = V'primary_expr' * V'postfix_op'^0 * V'func_call_op' * P';';
postfix_op = V'func_call_op' + V'index_op';
同样,V'postfix_op'^0
吃掉了我最后期待的 func_call_op
。
是的,没有回溯,所以你已经正确地发现了问题。我认为解决方案是列出有效的 postfix_op
表达式;我会将 V'func_call_op' + V'index_op'
更改为 V'func_call_op'^0 * V'index_op'
并将最后的 V'func_call_op'
更改为 V'func_call_op'^1
以允许最后调用多个函数。
更新:如评论中所建议,a/b
问题的解决方案是 (P'b'^0 * P'a')^0 * P'b'^1
。
这个怎么样?
local final = P'b' * P(-1)
local patt = (S'ab' - final)^0 * final
模式final
是我们在字符串末尾所需要的。
模式 patt
与集合 'ab' 匹配,除非 它后面跟着最终序列。然后它断言我们有最终序列。这阻止了最后的 'b' 被吃掉。
这并不能保证我们得到任何 a(但问题中的模式也不会)。
抱歉,我的回答来得太晚了,但我认为值得给这个问题一个更正确的答案。
据我了解,您只需要 非盲 贪婪匹配。但不幸的是,LPeg 的“官方文档”只告诉我们如何使用 LPeg 进行 blind 贪婪匹配(或重复)。但是这种模式可以用解析表达式文法来描述。对于规则 S,如果你想匹配尽可能多的 E1,然后是 E2,你需要写
S <- E1 S / E2
a/b
问题的解决方案变为
S <- [ab] S / 'b'
您可能希望通过在第一个选项中插入一些 a 来优化规则
S <- [ab] 'a'* S / 'b'
这将大大减少递归。至于你真正的问题,这是我的答案:
top_expr <- primary_expr p_and_f ';'
p_and_f <- postfix_op p_and_f / func_call_op
postfix_op <- func_call_op / index_op