我用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来获得相同的功能(在决定令牌边界的位置之前考虑整个字符串)。
答案 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