0

我从 PEG 开始PEG.js

有些事情我无法理解......我确信它很简单,但它让我在试图理解这个概念时感到头疼......

考虑这个两规则语法:

name
  = name:.* {return name.join("")}

put
  = "put " a:name " into " b:name "." {put(a,b)}

我希望能够通过这个解析器“将 foo 放入 bar”。并导致put("foo","bar")评估。

但是 PEG.js 给了我错误Expected " into " or any character but end of input found.

name如果规则的正则表达式比规则更具体,我想我可以解决这个问题,.*但为什么必须这样?解析器不能足够聪明地向前看并看到“ into”即将出现,以及“。” 在最后?

我怎样才能实现我正在寻找的东西?这可能是“自下而上”和“自上而下”语法之间的区别吗?

编辑:正则表达式按/put (.*) into (.*)/g我想要的方式工作——如果我通过它"put foo into bar",它会给我$1="foo"and $2="bar"。我只是在问我是否可以使用 PEGjs 或 Jison 获得相同的功能(在决定令牌边界的位置之前考虑整个字符串)。

4

2 回答 2

1

我相当确定“themirror”是正确的——第一条规则会吃掉所有的输入。试试没有那个规则。

此外,您应该有另一条规则来允许任意空格。我在网上找到了这个...

_
  = [ \r\n\t]*

下划线将匹配任意数量的空白字符。然后你可以重写你的规则...

put
   = "put" _ a:name _ "into" _  b:name _  "." {put(a,b)}
于 2014-08-05T11:30:54.917 回答
0

对不起,我的英语不好。

第一条规则.*尝试读取每个字符,因此到达文件末尾。

您可以使名称规则更具体(任何字符,但不是 SPACE 或 DOT):

name = [^ .]+

这个有效......但不适用于内部有空格的名称。

put = "put " a:name " into " b:name "." {put(a,b);}

name = c:[^ .]+ {return c.join("");}

对于 Node.js

var PEG = require('pegjs');
var text = 'put foo into bar.';
var parser = PEG.buildParser('{function put(a,b){ console.log(a,b); }}put = "put " a:name " into " b:name "." {put(a,b);}\nname = c:[^ .]+ {return c.join("");}');
parser.parse(text);

对于名称中的空格,我没有很好的解决方案,但请尝试以下方法:

nameBeforeInto = (!" into ".)+

nameBeforeDot = [^.]+

put = "put " nameBeforeInto " into " nameBeforeDot "."

nameBeforeInto 返回一个多维数组

法布里斯

于 2014-10-11T02:32:56.207 回答