【问题标题】:PEG Grammar to match a space separated or comma separated listPEG 语法以匹配空格分隔或逗号分隔的列表
【发布时间】:2022-01-04 00:56:16
【问题描述】:

我正在尝试制作一个简单的 PEG (pegjs) 语法来解析空格分隔的列表或逗号分隔的数字列表,但我显然缺少一些基本的东西。也就是说,我想匹配“1 2 3”或“1,2,3”之类的字符串,而不是“1 2,3”的混合表达式。

我尝试的语法是(可以在https://pegjs.org/online 运行):

start = seq

seq = num (" " n:num {return n})*
    / num ("," n:num {return n})*


num = a:$[0-9]+ {return parseInt(a, 10)}

EOL = !.

但是,这个语法只会解析一个空格分隔的列表。如果我将其修改为:

start = seq

seq = num (" " n:num {return n})* EOL
    / num ("," n:num {return n})* EOL


num = a:$[0-9]+ {return parseInt(a, 10)}

EOL = !.

它将解析空格分隔或逗号分隔的列表。但是,我觉得我不需要在每个表达式的末尾添加 EOL ......我认为,当给定一个逗号分隔的列表时,pegjs 会尝试将它与空格分隔的列表匹配,失败, 然后匹配逗号分隔的列表规则。

我错过了什么?

【问题讨论】:

    标签: javascript parsing peg pegjs


    【解决方案1】:

    替代num (" " n:num {return n})* 将成功匹配单个num,后面没有空格,因为* 表示“0 次或多次重复”,这意味着0 次重复计数。一旦备选方案成功,即使后续解析失败,也不会尝试该集合中的其他备选方案。所以这基本上使第二种选择无关紧要。

    当您将 EOL 标记添加到备选方案时,您会阻止第一个备选方案成功,除非它匹配到末尾。在这种情况下,尝试下一个替代方案。但是,正如你所说,它有点难看。

    这是一种可能性。通过分解初始的num 并将重复运算符更改为+(它将不匹配空输入),如果num 之后的第一个字符不是空格,我会强制第一个替代方法失败。然后将尝试第二种选择;只有当这也失败时才会应用可选运算符。

    seq = num ( (" " n:num {return n})+
              / ("," n:num {return n})+
              )?
    

    我使用 pegjs 在线工具对其进行了简要测试。如果你使用它,你可能会想要做一些事情来扁平化生成的数字列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      相关资源
      最近更新 更多