Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/447.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解析Javascript时,什么决定了斜杠的含义?_Javascript_Lexer - Fatal编程技术网

解析Javascript时,什么决定了斜杠的含义?

解析Javascript时,什么决定了斜杠的含义?,javascript,lexer,Javascript,Lexer,Javascript有一个很难解析的语法。正斜杠可以表示许多不同的内容:除法运算符、正则表达式文字、注释引入器或行注释引入器。最后两个很容易区分:如果斜杠后面跟一个星号,它将开始一个多行注释。如果斜杠后面跟着另一个斜杠,则它是一个行注释 但是除法和正则表达式文字的消歧规则让我不知所措。我在房间里找不到它。根据斜杠的含义,词汇语法被明确地分为两部分:InputElementDiv和InputElementRegExp。但并没有解释什么时候该用哪个 当然,可怕的分号插入规则使一切变得复杂 有没有人有

Javascript有一个很难解析的语法。正斜杠可以表示许多不同的内容:除法运算符、正则表达式文字、注释引入器或行注释引入器。最后两个很容易区分:如果斜杠后面跟一个星号,它将开始一个多行注释。如果斜杠后面跟着另一个斜杠,则它是一个行注释

但是除法和正则表达式文字的消歧规则让我不知所措。我在房间里找不到它。根据斜杠的含义,词汇语法被明确地分为两部分:InputElementDiv和InputElementRegExp。但并没有解释什么时候该用哪个

当然,可怕的分号插入规则使一切变得复杂

有没有人有一个清晰的代码示例,可以解释Javascript的词法?

参见第7节:

词汇语法有两个目标符号。InputElementDiv符号用于允许前导除法(/)或除法赋值(/=)运算符的语法上下文中。InputElementRegExp符号用于其他语法上下文

注意,不存在允许前导除法或除法赋值以及前导RegularExpressionLiteral的语法上下文。这不受分号插入的影响(见7.9);例如 以下:

a = b 
/hi/g.exec(c).map(d); 
如果行终止符后的第一个非空白、非注释字符是斜杠(/),并且语法上下文允许除法或除法赋值,则不会在行终止符处插入分号。也就是说,上面的示例在中进行了解释 与以下方法相同:

a = b / hi / g.exec(c).map(d); 
我同意,这很混乱,应该有一个顶级语法表达式而不是两个


编辑:

但并没有解释什么时候该用哪个


也许简单的答案就在眼前:试一个,然后再试另一个。由于不允许两者都使用,因此最多只能产生一个无错误的匹配。

您只能通过实现语法分析器来了解如何解释/。任何到达有效解析的lex路径都决定了如何解释字符。显然,这是他们曾考虑过解决的问题,但没有。 更多阅读:
如果前面的标记是

(,=:[!&|?{};

Rhino总是从lexer返回一个DIV令牌。

这实际上相当简单,但它需要让你的lexer比平常更聪明一点

除法运算符必须跟在表达式后面,而正则表达式文字不能跟在表达式后面,因此在所有其他情况下,可以安全地假设您正在查看正则表达式文字

如果操作正确,您已经必须将标点符号标识为多个字符串。因此,请查看前面的标记,并查看它是否为以下任何标记:

. ( , { } [ ; , < > <= >= == != === !== + - * % ++ --
<< >> >>> & | ^ ! ~ && || ? : = += -= *= %= <<= >>= >>>=
&= |= ^= / /=
如果您刚才使用的IdentifierName是其中之一,那么您将看到一个正则表达式文本;否则,它就是一个除法器

以上内容基于ECMAScript 5.1规范(已找到),不包括任何特定于浏览器的语言扩展。但如果您需要支持这些,那么这应该为确定您所处的环境类型提供简单的指导


当然,上面的大多数都是包含正则表达式文本的非常愚蠢的情况。例如,即使在语法上允许,也不能对正则表达式进行预增量。因此,大多数工具都可以简化实际应用程序的正则表达式上下文检查。JSLint检查前一个字符是否为
(,=:[!&|?{}的方法
可能就足够了。但是如果你在开发本应是JS词法分析工具的工具时走了这样一条捷径,那么你应该一定要注意。

我目前正在用JavaCC开发一个。这两件事让我对ECMAScript语法发疯。这个问题和答案对于正则表达式问题来说是非常宝贵的。在这个答案我想把我自己的发现放在一起

TL;DR在JavaCC中,使用和


非常重要的是Thom Blake所写的:

除法运算符必须跟在表达式和正则表达式之后 表达式文字不能跟在表达式后面,所以在所有其他情况下 您可以放心地假设您正在查看正则表达式文本

因此,您实际上需要了解它之前是否是一个表达式。这在解析器中是微不足道的,但在lexer中是非常困难的

Thom,在许多(但不幸的是,并非全部)的情况下,你可以理解它是“看”最后一个令牌的表达式。你必须考虑标点符号和关键字。

让我们从关键字开始。以下关键字不能在
标点符号或
之前(例如,您不能有
大小写/5
),因此,如果您在这些关键字之后看到
/
,您就有了
RegularExpressionLiteral

case
delete
do
else
in
instanceof
new
return
throw
typeof
void
if ('a')/a/g
接下来是标点符号。以下标点符号不能位于
除法标点符号之前(例如在
{/a..
中,符号
/
不能开始除法):

然后它也必须是一个
正则表达式文字
。如果这些斜杠之间没有空格(即
/…
),那么它必须作为
单行注释处理(

接下来,以下标点符号可能仅用于结束表达式:

]
因此,下面的
/
必须启动
除法器

不幸的是,我们还有以下几起案件模棱两可:

}
)
++
--
对于
}
您必须知道它们是否结束表达式,对于
++
--
-它们结束
后固定表达式
或启动
无固定表达式

]
}
)
++
--
{}/a/g
+{}/a/g
('a')/a/g
if ('a')/a/g