【问题标题】:Matching a string with a specific end in LPeg在 LPeg 中匹配具有特定结尾的字符串
【发布时间】:2021-10-25 21:46:10
【问题描述】:

我正在尝试用 a 和 b 的组合捕获一个字符串,但总是以 b 结尾。换句话说:

local patt = S'ab'^0 * P'b'

匹配 aaabbbabb 但不匹配 aaabba。但是,以上内容不匹配任何内容。这是因为S'ab'^0 是贪婪的并且匹配最终的b?我认为是这样,除了可能诉诸lpeg.Cmt 之外,我想不出任何替代方案,这似乎有点矫枉过正。但也许不是,有人知道如何匹配这样的模式吗?我看到了this question,但解决方案的问题在于它会停在第一个结束标记处(即那里的“猫”,这里的“b”),就我而言,我需要接受中间的“b”。

附: 我实际上想要做的是匹配一个最外层规则是函数调用的表达式。 例如

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

【问题讨论】:

    标签: lua lpeg


    【解决方案1】:

    是的,没有回溯,因此您已正确识别问题。我认为解决方案是列出有效的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 以允许最后进行多个函数调用。

    更新:正如 cmets 中所建议的,a/b 问题的解决方案将是 (P'b'^0 * P'a')^0 * P'b'^1

    【讨论】:

    • 很好,我想应该有这样的东西,谢谢!
    • 顺便说一句,我的编辑被拒绝了,但最后一位应该是V'func_call_op'^1,因为我至少需要匹配其中一个。在答案中包含 a/b 解析器也很好,这将是:(P'b'^0 * P'a')^0 * P'b'^1
    • 确实;在答案中都修复了。
    【解决方案2】:

    这个怎么样?

    local final = P'b' * P(-1)
    local patt =  (S'ab' - final)^0 * final
    

    final 是我们在字符串末尾需要的模式。

    模式patt 匹配集合'ab'除非它后面是最终序列。然后它断言我们有最终的序列。这会阻止最后的“b”被吃掉。

    这并不能保证我们得到任何 a(但问题中的模式也没有)。

    【讨论】:

      【解决方案3】:

      对不起,我的回答来得太晚了,但我认为值得给这个问题一个更正确的答案。

      据我了解,您只需要 非盲 贪婪匹配。但不幸的是,LPeg 的“官方文档”只告诉我们如何使用 LPeg 进行 blind 贪婪匹配(或重复)。但是这种模式可以用解析表达式语法来描述。对于规则 S,如果你想匹配尽可能多的 E1,然后是 E2,你需要写

      S 1 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
      

      【讨论】:

        猜你喜欢
        • 2022-01-06
        相关资源
        最近更新 更多