首页 > 解决方案 > Pegjs 预期 [0-9.] 或输入结束但找到“a”

问题描述

我想string starts with number使用 pegjs 处理。当我用1abcd输入时,它会抛出Expected [0-9.] or end of input but "a" found.. 预期输出为{ item: '1abcd', case: '=' }。我需要什么改变?


var parser = peg.generate(`
  start
    = number:NUMBER  { return { case: "=", item: number } } 
    / string:STRING  { return { case: "=", item: string.join("") } }

    NUMBER
    = number:[0-9\.]+ { return parseFloat(number.join("")); }
    / number:[0-9]+   { return parseInt(number.join(""), 10); }

    STRING = string:[^*]+ { return string; }
`);

console.log(parser.parse("123"))
console.log(parser.parse("123.45"))
console.log(parser.parse("abcd"))
console.log(parser.parse("abcd-efgh"))
console.log(parser.parse("1abcd"))

输出如下:

{case: "=", item: 123}
{case: "=", item: 123.45}
{case: "=", item: "abcd"}
{case: "=", item: "abcd-efgh"}

沙盒:https ://codesandbox.io/s/javascript-testing-sandbox-forked-5vekz?file=/src/index.js

标签: javascriptregexpegjs

解决方案


由于NUMBER匹配第一个字符,因此您需要STRING在返回成功匹配之前使用负前瞻。这样,如果STRING遇到一个字符,则NUMBER规则将失败,并且start将使用第二个替代字符。

这是一个示例,尽管正如@thinkgruen 所写,您可能还想尝试不那么松散地解析浮点数。

start
    = number:NUMBER  { return { case: "=", item: number } } 
    / string:STRING  { return { case: "=", item: string.join("") } }

NUMBER
    = number:[0-9\.]+ (!STRING) { return parseFloat(number.join("")); }
    / number:[0-9]+   (!STRING) { return parseInt(number.join(""), 10); }

STRING = string:[^*]+ { return string; }

推荐阅读