解析 Peg.JS 中的段落
Parsing Paragraphs in Peg.JS
我正在尝试学习 peg.js 并想解析简单的 "blocks" 文本,但我正在努力解决如何在不从我的语法中得到 "possible infinite loop" 错误的情况下对顺序行进行分组。
目标:
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。
我知道我可以在初始化程序块中编写一个全局函数并跟踪最后一个元素并使其与上下文相关,但我觉得这并没有像我应该的那样真正使用语法。
你知道那些周你为某事挣扎了一天左右然后最终放弃,放下你的骄傲和 post 一个问题堆栈溢出......然后十分钟后找出回答?是的!那是我的一周。我认为写出问题的过程会让你以不同的方式思考问题,你的突触会再次启动或发生其他事情......
无论如何,这是解决方案:http://peg.arcanis.fr/4f4NdP/2/
post真理的语法:
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"
}
]
}
我正在尝试学习 peg.js 并想解析简单的 "blocks" 文本,但我正在努力解决如何在不从我的语法中得到 "possible infinite loop" 错误的情况下对顺序行进行分组。
目标:
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。
我知道我可以在初始化程序块中编写一个全局函数并跟踪最后一个元素并使其与上下文相关,但我觉得这并没有像我应该的那样真正使用语法。
你知道那些周你为某事挣扎了一天左右然后最终放弃,放下你的骄傲和 post 一个问题堆栈溢出......然后十分钟后找出回答?是的!那是我的一周。我认为写出问题的过程会让你以不同的方式思考问题,你的突触会再次启动或发生其他事情......
无论如何,这是解决方案:http://peg.arcanis.fr/4f4NdP/2/
post真理的语法:
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"
}
]
}