Javascript 使用JISON匹配但忽略嵌套括号
我正在为模板系统编写语法。我在构建过程中遇到了一个障碍,我不太明白如何解决这个问题。我简化了测试用例,以便更好地强调我正在做的事情 示例字符串:Javascript 使用JISON匹配但忽略嵌套括号,javascript,parsing,jison,Javascript,Parsing,Jison,我正在为模板系统编写语法。我在构建过程中遇到了一个障碍,我不太明白如何解决这个问题。我简化了测试用例,以便更好地强调我正在做的事情 示例字符串: (foo)-有效 (foo())-失败应为'parenEnd',获得'parenterior' foo(foo)条 foo(foo(function(){console.log('stuff');}))条 foo(foo.bar.baz(“东西”))条 规则是,在插入语中,任何内容都可以是任何字符。我不需要验证,也不需要确保它们匹配正确的格式。另一
-有效(foo)
-失败(foo())
应为'parenEnd',获得'parenterior'
foo(foo)条
foo(foo(function(){console.log('stuff');}))条
foo(foo.bar.baz(“东西”))条
(
和)
,否则lexer无法知道一个插入语句的开始和另一个结束,例如(foo())(bar)
。为了跟踪这一点,我使用了一个paren
start条件,每当在paren语句中点击一个paren时,该条件就会增加一个值,并且在关闭paren时将其删除
问题是它根本不起作用。罪魁祸首是它似乎从未达到我的“
规则,而我却达到了”(“
规则很好。它们在语法上看起来是一样的,为什么一个有效,另一个无效
文法
%lex
%x paren
%%
\s+ /* skip whitespace */
<INITIAL>"(" { this.begin("paren"); parenCount = 1; return "parenStart"; };
<paren>"(" { console.log("parenStart", parenCount); parenCount++; return "parenInterior"; };
<paren>")" { console.log("parenEnd", parenCount); parenCount--; if (parenCount === 0) { this.popState(); return "parenEnd"; } else { return "parenInterior"; } };
<paren>[^\)\(]+ { console.log(this); return "parenInterior"; };
<<EOF>> return 'EOF';
. return 'INVALID';
/lex
%start expressions
%% /* language grammar */
expressions
: parenStart parenInterior parenEnd { return $1 + $2 + $3; }
;
%%
parenCount = 0;
%lex
%x帕伦
%%
\s+/*跳过空格*/
({this.begin(“paren”);parenCount=1;返回“parenStart”;};
({console.log(“parenStart”,parenCount);parenCount++;返回“parenInterior”;};
“{console.log(“parenEnd”,parenCount);parenCount--;if(parenCount==0){this.popState();return“parenEnd”;}否则{return“parenterior”;};
[^\)\(]+{console.log(this);返回“parenterior”;};
返回“EOF”;
。返回“无效”;
/莱克斯
%起始表达式
%%/*语言语法*/
表达
:parenStart parenterior parenEnd{返回$1+$2+$3;}
;
%%
parenCount=0;
我相信你的问题在于你的语法不接受一系列标记。如果我将你的语法改为这个,那么我会得到一些可以处理你在问题中显示的字符串的东西:
%lex
%x paren
%%
\s+ /* skip whitespace */
<INITIAL>"(" { this.begin("paren"); parenCount = 1; return "parenStart"; };
<paren>"(" { console.log("parenStart", parenCount); parenCount++; return "parenInterior"; };
<paren>")" { console.log("parenEnd", parenCount); parenCount--; if (parenCount === 0) { this.popState(); return "parenEnd"; } else { return "parenInterior"; } };
<paren>[^\)\(]+ { console.log(this); return "parenInterior"; };
<<EOF>> return 'EOF';
. return 'WHATEVER';
/lex
%start expressions
%% /* language grammar */
expressions
: whateverSeq parenStart parenInteriorSeq parenEnd whateverSeq EOF { return $1 + $2 + $3 + $4 + $5; }
;
parenInteriorSeq
: parenInterior
| parenInteriorSeq parenInterior -> $1.concat($2)
;
whateverSeq
: -> "" // Empty sequence.
| whatevers // One or more WHATEVER tokens.
;
whatevers
: whatever
| whateverSeq WHATEVER -> $1.concat($2)
;
%%
parenCount = 0;
%lex
%x帕伦
%%
\s+/*跳过空格*/
({this.begin(“paren”);parenCount=1;返回“parenStart”;};
({console.log(“parenStart”,parenCount);parenCount++;返回“parenInterior”;};
“{console.log(“parenEnd”,parenCount);parenCount--;if(parenCount==0){this.popState();return“parenEnd”;}否则{return“parenterior”;};
[^\)\(]+{console.log(this);返回“parenterior”;};
返回“EOF”;
.返回“无论什么”;
/莱克斯
%起始表达式
%%/*语言语法*/
表达
:whateverSeq parenStart parenInteriorSeq Parenen和whateverSeq EOF{返回$1+$2+$3+$4+$5;}
;
帕累尼蒂罗塞克
:第九层
|parenInteriorSeq parenInterior->1.concat(2美元)
;
whateverSeq
:->=“//空序列。
|whatevers//一个或多个任意标记。
;
无论如何
:随便
|whateverSeq无论什么->1美元。concat($2)
;
%%
parenCount=0;
那么嵌套括号就没有问题了
显著变化:
无效的
替换为WHATEVER
。添加规则以在开始和结束处具有一系列的WHATEVER
标记。这允许使用类似的blah(foo)blah
parenInterior
替换为parenInteriorSeq
,这样可以在括号内有parenInterior
标记序列。这是必要的,因为在类似(foo())
的字符串中,foo
是一个标记,下一个(
是另一个标记,下一个)
是另一个令牌。因此您必须接受令牌列表我不知道更多关于吉森的信息,从阅读本文中我可以了解到,所以我可能错了。当你说“失败
期望'parenEnd',得到'parenterior'
”,它怎么知道会发生什么?它是否期望输出是parenStart
,parenterior
,parenEnd
,就像在表达式中一样?如果我没有读错的话,的实际输出(foo())
将是parenStart
,parenterior
,parenterior
,parenterior
,parennd
。因此,在第三次输出之前,它的行为与预期一致,这是parenterior
预期的时间。我很确定你是正确的,但我如何更正它?早些时候,我尝试了parenteriors:parenteriors parenterior | parenterior
规则,但一开始它就阻塞了。这有什么意义吗?你可以在上在线测试语法,如果有帮助的话,可以复制并粘贴我的规则。我想路易斯的答案是我们能得到的最接近的答案,而这个问题没有更多的明确性。你说“规则是在括号内,任何内容都可以,任何字符都可以。”,你说括号必须匹配,但我认为你没有提供更多信息。例如,带有两对非嵌套括号的字符串,如()()
,或者根本没有括号,在这个答案下会失败;这可能不是您想要的。此外,如果您想确保花括号也成对排列,同时避免字符串,例如({}
,整数值变量paren
是不够的。您需要用堆栈(或数组)替换它一组括号符号,每一个都可以是(
或{
。当你遇到一个打开的括号时,将其推到堆栈中;当你得到一个关闭的括号时,从堆栈中弹出一个,并确保它与你刚才看到的括号匹配