You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

下划线被识别为空格是否正常?词法分析器需设置选项吗?

这确实是个容易踩的坑!咱们一步步理清楚:

问题本质:这不正常

你明明定义了空格规则,但解析器把下划线当空格处理且不报错,这肯定不符合预期。问题根源出在词法分析器(Lexer)阶段——因为空白符的识别、跳过逻辑是Lexer负责的,语法分析器(Parser)只会处理Lexer输出的Token流,如果Lexer把下划线当成空白符跳过了,Parser根本看不到这个字符,自然不会报错。

必须在Lexer里调整配置

答案是肯定的,你需要修改Lexer的规则,明确区分「合法空白符」和「下划线」:

  • 首先检查你的Lexer规则,是不是不小心把下划线包含在了空白符的匹配正则里(比如写成了[\s_]+这种错误格式)
  • 如果下划线不是你的语法里的合法字符,要给Lexer添加规则:匹配下划线时直接抛出词法错误,而不是跳过
  • 如果下划线是合法标识符的一部分(比如变量名里允许下划线),那也要单独定义标识符的规则,避免和空白混淆

附你的简化示例与修正思路

原简化语法(可能存在的问题)

grammar MyLang;

program : statement+;
statement : ID ';' ;
ID : [a-zA-Z]+ ;
WS : [ \t\n\r]+ -> skip; // 这里如果写成[\s_]+就会把下划线当空白跳过

本应被拒绝的错误示例

my_var; // 下划线被当成空白,解析成my var; 反而通过了

修正后的Lexer规则(参考Bart的解答)

grammar MyLang;

program : statement+;
statement : ID ';' ;
ID : [a-zA-Z]+ ;
WS : [ \t\n\r]+ -> skip; // 只匹配合法空白符
ILLEGAL_UNDERSCORE : '_' -> channel(HIDDEN), throw; // 捕获下划线并抛出错误

关于JUnit测试的补充

你后来发现的问题很关键:之前的JUnit测试只检查Parser的语法错误,但下划线被Lexer提前当成空白跳过了,根本到不了Parser阶段,所以测试没检测出问题。你需要调整测试逻辑:

  • 不仅验证合法输入的解析结果,还要验证包含下划线的非法输入是否会抛出词法错误
  • 可以通过监听Lexer的错误信息,或者直接捕获词法分析阶段的异常来断言

内容的提问来源于stack exchange,提问作者YaFred

火山引擎 最新活动