【问题标题】:PEGjs: Fallback (backtrack?) to string if floating point rule failPEGjs:如果浮点规则失败,则回退(回溯?)到字符串
【发布时间】:2013-04-18 11:29:59
【问题描述】:

我有一个atom 规则,它首先尝试将所有内容解析为数字或带引号的字符串,如果失败,则将其视为字符串。

除了这个非常特殊的字符串的特殊情况之外,一切都解析得很好:

DUD 123abc

解析失败并出现Expected " ", "." or [0-9] but "a" found. 错误。

我的期望:它应该成功解析并返回字符串“123abc”作为字符串原子。您可以在下面的语法内容中看到我的几次不成功的尝试。

感谢任何帮助/提示/指针/建议!


您可以在online PEG.js version 上尝试语法。我正在使用节点 v0.8.23 和 pegjs 0.7.0

正确解析的数字:

  • `123
  • `0
  • `0.
  • `1.
  • `.23
  • `0.23
  • `1.23
  • `0.000
  • .

我希望123abc被解析为字符串,这可能吗?


这是我的整个语法文件:

start = lines:line+ { return lines; }

// --------------------- LINE STRUCTURE
line = command:command eol { return command; }

command = action:atom args:(sep atom)*
{
  var i = 0, len = 0;

  for (var i = 0, len = args.length; i < len; i++) {
    // discard parsed separator tokens
    args[i] = args[i][1];
  }

  return [action, args];
}

sep = ' '+
eol = "\r" / "\n" / "\r\n"

atom = num:number { return num; }
     / str:string_quoted { return str; }
     / str:string { return str; }

// --------------------- COMMANDS

// TODO:

// --------------------- STRINGS
string = chars:([^" \r\n]+) { return chars.join(''); }

string_quoted = '"' chars:quoted_chars* '"' { return chars.join(''); }
quoted_chars = '\\"' { return '"'; }
             / char:[^"\r\n] { return char; }

// --------------------- NUMBERS
number = integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)?
{
  if (fraction && fraction.length) {
    fraction = fraction[0] + fraction[1].join('');
  } else {
    fraction = '';
  }

  integral = integral instanceof Array ?
    integral[0] + integral[1].join('') :
    '0';

  return parseFloat(integral + fraction);
}
        / ("." / "0.") fraction:[0-9]+
{
  return parseFloat("0." + fraction.join(''));
}

/*
float = integral:integer? fraction:fraction { return integral + fraction; }

fraction = '.' digits:[0-9]* { return parseFloat('0.' + digits.join('')); }

integer = digits:('0' / [1-9][0-9]*)
{
  if (digits === '0') return 0;
  return parseInt(digits[0] + digits[1].join(''), 10);
}

*/

【问题讨论】:

    标签: node.js grammar peg pegjs


    【解决方案1】:

    通过添加!([0-9\.]+[^0-9\.]) 解决了这个问题,这是number 规则的前瞻。

    我知道atom 规则会匹配,所以它的有效作用是使number 规则更快失败。希望这可以帮助将来有歧义的人。

    所以现在数字规则变成了:

    number = !([0-9\.]+[^0-9\.]) integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)?

    【讨论】:

    • 我认为检查 number 后面的字符是否是数字分隔符(不是字母数字)也可以,而且更便宜。
    • @Apalala 啊,这是个好主意。如果您将其添加为答案,会投票赞成。
    • Grako 中,我在每个字母数字标记之后添加了一个(可选的)自动检查字母数字。当流显示“IDENTIFICATION”时,它会避免匹配“ID”。到目前为止,我还没有关闭它。
    【解决方案2】:

    我认为检查number 后面的字符是否是数字分隔符(不是字母数字)也可以,而且成本更低。

    number = integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)? !([0-9A-Za-z]) 
    

    【讨论】:

      猜你喜欢
      • 2023-03-26
      • 2015-05-28
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 2023-01-26
      • 2022-01-12
      相关资源
      最近更新 更多