0

我正在尝试学习 peg.js 并想解析简单的文本“块”,但正在努力解决如何对连续行进行分组而不会从我的语法中得到“可能的无限循环”错误。

目标:

line 1

line 3
line 4

line 6

解析后会变成:

{
   "type": "root",
   "children": [
      { type: "para", content: "line 1" },
      { type: "para", content: "line 3\nline 4" },
      { type: "para", content: "line 6" },
   ]
}

换句话说:

  • 第一行是它自己的一段,因为它后面跟着一个空行
  • 第三行和第四行是一个段落,因为它们后面是一个空行
  • 第六行是一个段落,因为它是最后一行(一个或多个)

我可以编写一个匹配行和空行的语法(请参阅http://peg.arcanis.fr/4f4NdP/),但我所做的任何事情都是为了让多个连续行后跟一个空行(或 EOF)变成一个段落以递归错误结束。我觉得这是一个非常简单的 n00b 东西,我只是想念它,因为我以前没有使用过 PEG。

我知道我可以在初始化程序块中编写一个全局函数并跟踪最后一个元素并使其具有上下文关系,但我觉得这并没有像我应该使用的那样真正使用语法。

4

1 回答 1

3

你知道那些周你在某事上挣扎了一天左右,然后最终放弃,放下你的骄傲,发布一个问题到堆栈溢出……然后十分钟后找出答案?是的!那是我的一周。我认为写出问题的过程会让您以不同的方式思考问题,并且您的突触再次开始触发或其他什么...

无论如何,这是解决方案:http: //peg.arcanis.fr/4f4NdP/2/

后代语法:

start = head:Para tail:(newline Para)*
   {
      var t;

      t = tail.reduce(function(memo, element) {
         return memo.concat(element[1]);
      }, []);

      return {
         type: 'root',
         children: [ head ].concat(t),
      }
   }

Para = text:LineOfText+
   { return { type: 'para', content: text.join('\n') } }

LineOfText = text:$(char+) EOL
   { return text }

char = [^\n\r]
newline = '\n' / '\r' '\n'?
EOL = newline / !.

输入:

line 1

line 3
line 4

line 6

输出:

{
   "type": "root",
   "children": [
      {
         "type": "para",
         "content": "line 1"
      },
      {
         "type": "para",
         "content": "line 3
line 4"
      },
      {
         "type": "para",
         "content": "line 6"
      }
   ]
}
于 2017-06-23T13:50:36.407 回答