我正在尝试为javascript标识符编写解析器到目前为止,这是我所拥有的:
// All this rules have string as attribute.
identifier_ = identifier_start
>>
*(
identifier_part >> -(qi::char_(".") > identifier_part)
)
;
identifier_part = +(qi::alnum | qi::char_("_"));
identifier_start = qi::char_("a-zA-Z$_");
在我的测试中,这个解析器可以很好地处理"良好标识符"列表:
"x__",
"__xyz",
"_",
"$",
"foo4_.bar_3",
"$foo.bar",
"$foo",
"_foo_bar.foo",
"_foo____bar.foo"
但是我遇到了一个不好的标识符:foo$bar
。这应该是失败的,但它成功了!!该属性的值为"foo"
。
下面是foo$bar
的调试输出:
<identifier_>
<try>foo$bar</try>
<identifier_start>
<try>foo$bar</try>
<success>oo$bar</success>
<attributes>[[f]]</attributes>
</identifier_start>
<identifier_part>
<try>oo$bar</try>
<success>$bar</success>
<attributes>[[f, o, o]]</attributes>
</identifier_part>
<identifier_part>
<try>$bar</try>
<fail/>
</identifier_part>
<success>$bar</success>
<attributes>[[f, o, o]]</attributes>
</identifier_>
我想要的是解析器在解析foo$bar
时失败,而不是在解析$foobar
时失败。
我错过了什么?
您不要求解析器需要使用所有输入。
当一个规则在$
符号之前停止匹配时,它返回成功,因为没有人说它不能后跟$
符号。因此,您要断言它后面没有可能是标识符的一部分的字符:
identifier_ = identifier_start
>>
*(
identifier_part >> -(qi::char_(".") > identifier_part)
) >> !identifier_start
;
相关的指令是Qi存储库中的distinct
: http://www.boost.org/doc/libs/1_55_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/distinct.html