Anrlr4 语法规则
in 默认分类 with 0 comment

好的,我们来详细展开讲解 第四步:定义"句子结构"(语法规则 / Parser Rules)。这是整个语法文件的核心,决定了如何将词法规则产生的 Token 流组织成有意义的语法结构。

1. 语法规则的核心概念

什么是语法规则?

语法规则定义了 Token 之间的组合关系,描述了语言的句子结构。它指定了哪些 Token 序列是合法的,以及它们的层次关系。

简单比喻:如果词法规则是"认字",那么语法规则就是"组词造句"——将单词按照语法规则组合成正确的句子。

语法规则的基本结构

ruleName : alternative1 | alternative2 | ... ;

2. 语法规则的命名规范

大小写约定

类型命名规范示例
语法规则首字母小写,驼峰式expression, ifStatement, variableDeclaration
词法规则首字母大写,驼峰式INT, Identifier, StringLiteral

常用命名模式

// 1. 起始规则:通常命名为开始符号
program : statement+ EOF;

// 2. 语句规则:描述完整的语句
statement : expressionStatement
          | whileStatement
          | ifStatement
          | returnStatement;

// 3. 表达式规则:描述可计算的单元
expression : additiveExpression;

// 4. 原子规则:描述基本单元
primaryExpression : literal | identifier | parenthesizedExpression;

3. 语法规则的基本元素

3.1 Token 引用

直接引用词法规则中定义的 Token:

// 引用具体的Token
assignment : IDENTIFIER '=' expression ';';
ifStatement : 'if' '(' expression ')' statement;

// 混合引用
expression : INT | IDENTIFIER | STRING;

3.2 规则引用

引用其他语法规则:

statement : expressionStatement
          | ifStatement
          | whileStatement;

expressionStatement : expression ';';
ifStatement : 'if' '(' expression ')' statement;
whileStatement : 'while' '(' expression ')' statement;

3.3 序列(Sequence)

按顺序排列的元素:

// 固定序列
variableDeclaration : type IDENTIFIER ';';

// 复杂序列
functionCall : IDENTIFIER '(' (expression (',' expression)*)? ')';

3.4 分组(Grouping)

用括号分组:

// 分组用于明确优先级
expression : logicalOrExpression ('&&' logicalOrExpression)*;
logicalOrExpression : logicalAndExpression ('||' logicalAndExpression)*;

4. 量词(Quantifiers)详解

4.1 可选(Optional)?

// 可选元素
variableDeclaration : type IDENTIFIER ('=' expression)? ';';
ifElseStatement : 'if' '(' expression ')' statement ('else' statement)?;

4.2 零次或多次(Zero or more)*

// 重复零次或多次
argumentList : (expression (',' expression)*)?;
statementList : statement*;

4.3 一次或多次(One or more)+

// 重复一次或多次
program : statement+;
parameterList : parameter (',' parameter)*;

4.4 精确次数 {n}, {n,}, {n,m}

// 精确次数控制
ipAddress : OCTET '.' OCTET '.' OCTET '.' OCTET;
OCTET : [0-9]{1,3};  // 1到3个数字

5. 选择运算符(|)和备选分支

5.1 基本选择

// 简单的或关系
type : 'int' | 'float' | 'string' | 'boolean';
additiveOperator : '+' | '-';

5.2 复杂选择

statement : variableDeclaration ';'
          | expression ';'
          | ifStatement
          | whileStatement
          | returnStatement
          | blockStatement;

5.3 带标签的备选分支

使用 # 为分支添加标签,便于后续处理:

expression
    : expression '*' expression   # Multiply
    | expression '/' expression   # Divide
    | expression '+' expression   # Add
    | expression '-' expression   # Subtract
    | INT                        # IntLiteral
    | IDENTIFIER                 # Variable
    | '(' expression ')'         # Parenthesized
    ;

标签的好处


6. 递归规则设计

6.1 左递归(Left Recursion)

ANTLR4 支持直接左递归,这是定义运算符优先级最自然的方式:

expression
    : expression '*' expression   # Multiply
    | expression '+' expression   # Add  
    | INT                        # Primary
    ;

6.2 右递归(Right Recursion)

用于左结合的操作:

// 右递归示例(不推荐用于算术表达式)
expression
    : INT restExpression?
    ;

restExpression
    : ('*' | '+') expression
    ;

6.3 递归的最佳实践

// 清晰的优先级层次(从低到高)
expression
    : logicalOrExpression
    ;

logicalOrExpression
    : logicalAndExpression ('||' logicalAndExpression)*
    ;

logicalAndExpression  
    : equalityExpression ('&&' equalityExpression)*
    ;

equalityExpression
    : relationalExpression (('==' | '!=') relationalExpression)*
    ;

relationalExpression
    : additiveExpression (('<' | '>' | '<=' | '>=') additiveExpression)*
    ;

additiveExpression
    : multiplicativeExpression (('+' | '-') multiplicativeExpression)*
    ;

multiplicativeExpression
    : primaryExpression (('*' | '/' | '%') primaryExpression)*
    ;

primaryExpression
    : INT
    | IDENTIFIER  
    | '(' expression ')'
    ;

7. 语法规则指令和动作

7.1 返回值声明

expression returns [int value]
    : e=expression {$value = $e.value;}
    ;

7.2 参数传递

expression[Map<String, Integer> vars] returns [int value]
    : IDENTIFIER {$value = $vars.get($IDENTIFIER.text);}
    ;

7.3 局部变量

expression returns [int value]
    @init { int temp = 0; }
    : ...
    ;

8. 完整的语法规则示例

8.1 简单计算器语法

grammar Calculator;

// === 词法规则 ===
INT     : [0-9]+;
PLUS    : '+';
MINUS   : '-';
MUL     : '*';
DIV     : '/';
LPAREN  : '(';
RPAREN  : ')';
WS      : [ \t\r\n]+ -> skip;

// === 语法规则 ===
program : expression+ EOF;

expression
    : expression (MUL | DIV) expression   # MulDiv
    | expression (PLUS | MINUS) expression # AddSub
    | INT                                  # Int
    | LPAREN expression RPAREN             # Parens
    ;

8.2 简单编程语言语法

grammar SimpleLang;

// === 词法规则 ===
IF : 'if';
ELSE : 'else';
WHILE : 'while';
RETURN : 'return';
INT_TYPE : 'int';
IDENTIFIER : [a-zA-Z_][a-zA-Z_0-9]*;
INT : [0-9]+;
ASSIGN : '=';
PLUS : '+';
MINUS : '-';
MUL : '*';
DIV : '/';
LPAREN : '(';
RPAREN : ')';
LBRACE : '{';
RBRACE : '}';
SEMI : ';';
WS : [ \t\r\n]+ -> skip;

// === 语法规则 ===
program : statement+ EOF;

statement
    : variableDeclaration   # VarDecl
    | assignment            # Assign  
    | ifStatement           # If
    | whileStatement        # While
    | expression SEMI       # ExprStmt
    | block                 # BlockStmt
    ;

variableDeclaration : INT_TYPE IDENTIFIER ('=' expression)? SEMI;
assignment : IDENTIFIER ASSIGN expression SEMI;

ifStatement : IF LPAREN expression RPAREN statement (ELSE statement)?;
whileStatement : WHILE LPAREN expression RPAREN statement;

expression
    : expression (MUL | DIV) expression   # MulDiv
    | expression (PLUS | MINUS) expression # AddSub
    | INT                                  # IntLiteral
    | IDENTIFIER                           # Variable
    | LPAREN expression RPAREN            # Parenthesized
    ;

block : LBRACE statement* RBRACE;

9. 常见模式和最佳实践

9.1 表达式优先级模式

// 标准优先级模式(从低到高)
expression
    : logicalOrExpression
    ;

logicalOrExpression
    : logicalAndExpression ('||' logicalAndExpression)*
    ;

logicalAndExpression
    : equalityExpression ('&&' equalityExpression)*  
    ;

equalityExpression
    : relationalExpression (('==' | '!=') relationalExpression)*
    ;

relationalExpression
    : additiveExpression (('<' | '>' | '<=' | '>=') additiveExpression)*
    ;

additiveExpression
    : multiplicativeExpression (('+' | '-') multiplicativeExpression)*
    ;

multiplicativeExpression
    : unaryExpression (('*' | '/' | '%') unaryExpression)*
    ;

unaryExpression
    : ('!' | '-') unaryExpression
    | primaryExpression
    ;

primaryExpression
    : literal
    | IDENTIFIER
    | LPAREN expression RPAREN
    ;

9.2 语句结构模式

program : (function | statement)* EOF;

function : TYPE IDENTIFIER LPAREN parameters? RPAREN block;

statement
    : variableDeclaration SEMI
    | expression SEMI
    | ifStatement
    | whileStatement
    | returnStatement SEMI
    | block
    ;

9.3 错误处理和恢复

// 容错设计
statement
    : variableDeclaration SEMI
    | expression SEMI
    | errorStatement  // 错误恢复
    ;

errorStatement
    : // 匹配错误模式,进行恢复
    ;

10. 调试和测试技巧

10.1 使用标签调试

expression
    : expression '*' expression   # Multiply {System.out.println("Multiply");}
    | expression '+' expression   # Add {System.out.println("Add");}
    | INT                        # Int {System.out.println("Int: " + $INT.text);}
    ;

10.2 测试语法规则

# 使用 ANTLR 测试工具
antlr4 YourGrammar.g4
javac YourGrammar*.java
grun YourGrammar program -tree input.txt
grun YourGrammar program -gui input.txt  # 图形化显示

10.3 常见错误模式

// ❌ 错误:间接左递归(ANTLR4不支持)
// expression : term | expression '+' term;
// term : expression '*' factor;

// ✅ 正确:直接左递归
expression
    : expression '+' term
    | term
    ;
term
    : term '*' factor  
    | factor
    ;

11. 完整示例:JSON 语法

grammar JSON;

// === 词法规则 ===
STRING : '"' (ESC | ~["\\])* '"';
fragment ESC : '\\' (["\\/bfnrt] | UNICODE);
fragment UNICODE : 'u' HEX HEX HEX HEX;
fragment HEX : [0-9a-fA-F];

NUMBER : '-'? INT ('.' [0-9]+)? EXP?;
fragment INT : '0' | [1-9] [0-9]*;
fragment EXP : [Ee] [+\-]? [0-9]+;

TRUE : 'true';
FALSE : 'false';  
NULL : 'null';

WS : [ \t\n\r]+ -> skip;

// === 语法规则 ===
json
    : object
    | array
    ;

object
    : '{' pair (',' pair)* '}'   # NonEmptyObject  
    | '{' '}'                    # EmptyObject
    ;

pair
    : STRING ':' value
    ;

array
    : '[' value (',' value)* ']' # NonEmptyArray
    | '[' ']'                    # EmptyArray
    ;

value
    : STRING  # StringValue
    | NUMBER  # NumberValue
    | object  # ObjectValue
    | array   # ArrayValue
    | TRUE    # TrueValue
    | FALSE   # FalseValue
    | NULL    # NullValue
    ;

总结

语法规则是 ANTLR4 的核心,它负责:

关键要点

  1. 命名规范:语法规则小写开头,词法规则大写开头
  2. 优先级设计:使用直接左递归,低优先级规则在前
  3. 标签使用:为备选分支添加标签,便于后续处理
  4. 模块化设计:将复杂规则分解为简单的子规则

掌握了语法规则,你就完成了 G4 文件最主要的部分。下一步我们将学习如何完善语法文件的其余部分。