解析表达式语法:检测下一个令牌?

时间:2014-08-04 22:20:31

标签: parsing pegjs

我用PEG.js开始使用PEG。

有些东西我无法理解......我确信它很简单,但它让我头疼,试图理解这个概念。 ..

考虑这个双规则语法:

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规则的正则表达式比.*更具体,但是为什么必须这样,我可以解决这个问题?解析器不够聪明,无法向前看,并且可以看到#34;进入"即将到来,以及"。"最后?

我如何实现我想要的目标?这可能是"自下而上"和#34;自上而下"语法?

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

2 个答案:

答案 0 :(得分:1)

我非常确定"他们是镜像"是正确的 - 第一条规则将吃掉所有的输入。没有这个规则就试试吧。

此外,您应该有另一个允许任意空格的规则。我在网上发现了这个......

_
  = [ \r\n\t]*

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

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

答案 1 :(得分: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返回一个多维数组

和Fabrice