ANTLR MiniLexer词法规则下关键字被识别为标识符问题求助
问题原因与解决方法
核心错误:混淆了词法分析器(Lexer)和语法分析器(Parser)的职责
你当前的写法把所有语法结构规则全部写在了Lexer定义中,这是完全不符合ANTLR的设计逻辑的:
- Lexer的作用仅为将输入字符流切割为独立的最小词法单元(Token),比如关键字、标识符、运算符、常量、分隔符等,它不处理多Token组合的语法结构
- 类似
Program: 'program' Identifier Body、Decl_list: Decl ';' (Decl ';')?这类描述多Token组合规则的语法定义,应该放在Parser规则中,而非Lexer中
其他关联错误
- 关键字优先级不足:你没有将
program、integer这类关键字单独定义为独立的Token,且放在Identifier规则之前。ANTLR的词法规则按书写顺序匹配,优先级从高到低,所有符合标识符规则的关键字都会被优先识别为Identifier,导致无法触发关键字匹配 fragment规则使用错误:被fragment修饰的规则只能被其他词法规则引用,不能作为语法结构的组成部分,你给Ident_list加了fragment修饰属于错误用法- 字符转义错误:规则中出现的
>、"这类HTML实体字符需要替换为实际的语法字符>、"等
修复步骤
- 拆分词法和语法规则:分别创建
MiniLexer.g4(仅存词法规则)和MiniParser.g4(仅存语法规则) - 在
MiniLexer.g4中先单独定义所有关键字Token,优先级高于Identifier:
// MiniLexer.g4 示例 lexer grammar MiniLexer; // 关键字定义(必须放在Identifier之前) PROGRAM: 'program'; DECLARE: 'declare'; BEGIN: 'begin'; END: 'end'; INTEGER: 'integer'; DECIMAL: 'decimal'; IF: 'if'; THEN: 'then'; ELSE: 'else'; WHILE: 'while'; DO: 'do'; READ: 'read'; WRITE: 'write'; NOT: 'not'; OR: 'or'; MOD: 'mod'; AND: 'and'; // 运算符、分隔符定义 ASSIGN: ':='; EQ: '='; GT: '>'; GE: '>='; LT: '<'; LE: '<='; NEQ: '<>'; PLUS: '+'; MINUS: '-'; MUL: '*'; DIV: '/'; LPAREN: '('; RPAREN: ')'; SEMICOLON: ';'; COMMA: ','; // 原有词法规则 COMENTARIO: '%' ~[\n\r]* '\r'? '\n' -> skip; WS : [ \t\r\n] -> skip; Constant: [0-9]+; Literal: '"' ~["]* '"'; Identifier: [a-zA-Z][a-zA-Z0-9]*;
- 在
MiniParser.g4中定义所有语法结构规则,关联已定义的Lexer:
// MiniParser.g4 示例 parser grammar MiniParser; options { tokenVocab=MiniLexer; } program: PROGRAM Identifier body; body: (DECLARE decl_list) BEGIN stmt_list END; decl_list: decl SEMICOLON (decl SEMICOLON)*; decl: type ident_list; ident_list: Identifier (COMMA Identifier)*; type: INTEGER | DECIMAL; stmt_list: Stmt SEMICOLON (Stmt SEMICOLON)*; Stmt: Assign_stmt | If_stmt | While_stmt| Read_stmt | Write_stmt; Assign_stmt: Identifier ASSIGN Simple_expr; // 其余原有语法规则同理迁移到此处,替换对应的Token名称即可
- 修正语法规则中的逻辑错误,比如原
Simple_expr规则里的歧义写法、多余的可选标记等
内容的提问来源于stack exchange,提问作者Maurício Mathias
相关产品推荐
相关产品推荐

