如何扩展默认的 PEG.js 算术示例以允许多个表达式而不是单个表达式?

问题描述

作为解析器的一部分,我想添加算术和布尔表达式。我想在 https://pegjs.org/online 处采用认的 PEG.js 示例,但问题是该解析器是递归的,您不能编写两行或更多行:

例如这是有效的 JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
    <Meta charset="UTF-8">
    <Meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="./style.css">
    <Meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <main>
        <div class="img">
            <div class="title title-dark">MEN STARVE FOR HOnor</div>
        </div>
        <div class="title">MEN STARVE FOR HOnor</div>

    </main>
</body>
<script src="./index.js"></script>
</html>

如您所见,有 3 个表达式,行尾不会终止它们。但是对于 PEG.js,它们需要被显式编码,所以表达式可以终止。

你会如何去创建这样的无限表达式,终止并转到下一个表达式?

解决方法

您可以为多个表达式添加如下所示的 Start 规则。

Start
  = head:Expression tail:("\n" Expression)* {
    return [head].concat(tail.map(function(element) {
      return element[1];
    }));
  }

Expression
  = head:Term tail:(_ ("+" / "-") _ Term)* {
      return tail.reduce(function(result,element) {
        if (element[1] === "+") { return result + element[3]; }
        if (element[1] === "-") { return result - element[3]; }
      },head);
    }

Term
  = head:Factor tail:(_ ("*" / "/") _ Factor)* {
      return tail.reduce(function(result,element) {
        if (element[1] === "*") { return result * element[3]; }
        if (element[1] === "/") { return result / element[3]; }
      },head);
    }

Factor
  = "(" _ expr:Expression _ ")" { return expr; }
  / Integer

Integer "integer"
  = _ [0-9]+ { return parseInt(text(),10); }

_ "whitespace"
  = [ \t\n\r]*