繁体   English   中英

用PEG.js解析完整的数学表达式

[英]Parsing complete mathematical expressions with PEG.js

我正在尝试扩展PEG.js的示例语法,用于解析我的在线BASIC解释器实验的所有4个运算符的数学表达式:

http://www.dantonag.it/basicjs/basicjs.html

但并非所有表达式都被正确解析。

这是我的PEG语法:

expression = additive

additive = left:multiplicative atag:("+" / "-") right:additive { return {tag: atag, left:left, right:right}; } / multiplicative

multiplicative = left:primary atag:("*" / "/") right:multiplicative { return {tag: atag, left:left, right:right}; } / primary

primary = number / "(" additive:additive ")" { return additive; }

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

它解析正确的表达式,如2 * 3 + 1(给出7),但不是像2-1-1这样的表达式,它给出2而不是0。

你能帮我改进和调试吗?

提前致谢。

编辑 :我已经在语法中添加了“数字”规则。 是的,我的语法为输出提供了一个类似于解析树的递归结构。

Matt的答案是正确的,但关于如何在pegjs中实现左关联性:

expression = additive

additive
  = first:multiplicative rest:(("+" / "-") multiplicative)+ {
    return rest.reduce(function(memo, curr) {
      return {atag: curr[0], left: memo, right: curr[1]};
    }, first);
  }
  / multiplicative

multiplicative
  = first:primary rest:(("*" / "/") primary)+ {
    return rest.reduce(function(memo, curr) {
      return {atag: curr[0], left: memo, right: curr[1]};
    }, first);
  }
  / primary

primary
  = number
  / "(" additive:additive ")" { return additive; }

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

javascript.pegjs示例Matt链接使用类似的方法。 关键是处理与列表具有相同优先级的操作字符串,这允许您使用正确的关联性构建树。

第一:你的语法缺少number规则。 另外,我确信你知道,在你的例子中运行你的语法(在添加number )不会给2,而是像解析树那样。 您是否介意更新问题以解决这两个问题?


问题:看起来你已经陷入了联想。 当两个具有相同优先级的运算符竞争操作数时,关联性发挥作用。 在你的例子中, -正在与-竞争 - 很明显它将具有与它自身相同的优先级 - 但是关联性对于打破+-之间以及*/之间的关系也很重要。

我假设2*3+1被正确解析,因为两个运算符具有不同的优先级,这意味着关联性没有发挥作用,并且您的语法正确地实现了优先级(尽管您应该注意2+3*1是更标准的示例表示乘法具有比加法更高的优先级,因为简单的从左到右解析2*3+1会得到与解析器相同的结果。

我假设你想要-左联想,但在你的语法中它似乎是正确联想的,基于这个例子:

  • 输入:

     1-2-3 
  • 输出(解析为1-(2-3) ):

     { "tag": "-", "left": "1", "right": { "tag": "-", "left": "2", "right": "3" } } 

左关联树看起来像这样(从(1-2)-3 ):

{
   "tag": "-",
   "left": {
      "tag": "-",
      "left": "1",
      "right": "2"
   },
   "right": "3"
}

您应该注意,您的其他运算符也似乎是右关联而不是左 - 。

解决方案:我真的不知道peg.js是如何工作的,但一些快速的谷歌搜索出现了这个

基于语法的运算符优先级和关联性解决方案通常非常讨厌(请参阅Python语法以获取证据),因此您可能需要查看[自上而下]运算符优先级解析以获得更灵活和更具表现力的替代方案。 Douglas Crockford,Vaughn Pratt和Annika Aasa在这个主题上有一些很好的文章。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM