如何为leex和yecc编写可匹配JavaScript正则字面量的正则表达式?
问题解答
这个需求完全可以实现,leex、yecc类的编译工具完全支持该场景,你遇到的问题核心是两个:一是对JS正则字面量的语法规则理解有误,二是没有结合语法上下文做词法状态切换。
核心错误纠正
你之前的规则中错误将圆括号内的正斜杠判定为非结束标记,实际上JS正则语法里只有两种情况的正斜杠不会作为正则字面量的结束符:
- 被反斜杠转义的正斜杠
\/ - 包裹在字符类
[]内部的正斜杠
圆括号本身不会改变正斜杠的语义,括号内未转义、不在字符类里的正斜杠依然会被判定为正则结束标记,这是你之前复杂规则失效的主要原因。
正确的正则字面量匹配规则
leex层面可以用如下规则匹配正则字面量的主体部分:
RegexLiteral = "/(" (\\.) | (\[ ([^\\\]]|\\.)* \]) | [^/\\] )* "/[gimsuy]*"
匹配逻辑分层解释:
- 优先匹配转义序列
\\.:所有反斜杠引导的字符直接跳过,不做结束判定 - 其次匹配字符类块
\[ ([^\\\]]|\\.)* \]:从[开始到未转义的]结束,整块内部的正斜杠全部忽略 - 最后匹配普通非正斜杠、非反斜杠的字符
- 末尾匹配可选的正则标记位(g、i、m、s、u、y)
必须补充的上下文状态联动
仅靠词法规则无法100%正确识别正则字面量,因为JS中/同时是除法运算符,你需要借助yecc的语法上下文给leex传递状态:
- 当语法解析处于「期望接收表达式」的场景时(比如上一个token是左括号、运算符、逗号、冒号、语句起始标记等),将leex切换到正则匹配状态,此时遇到
/优先识别为正则字面量的开头 - 其他场景下遇到
/识别为除法运算符或者/=复合运算符
leex本身支持自定义起始状态(Start Conditions),完全可以实现和语法解析器的状态联动,不存在工具能力限制。
内容的提问来源于stack exchange,提问作者Noah
相关产品推荐
相关产品推荐

