好的,我们来详细展开讲解 第四步:定义"句子结构"(语法规则 / Parser Rules)。这是整个语法文件的核心,决定了如何将词法规则产生的 Token 流组织成有意义的语法结构。
1. 语法规则的核心概念
什么是语法规则?
语法规则定义了 Token 之间的组合关系,描述了语言的句子结构。它指定了哪些 Token 序列是合法的,以及它们的层次关系。
简单比喻:如果词法规则是"认字",那么语法规则就是"组词造句"——将单词按照语法规则组合成正确的句子。
语法规则的基本结构
ruleName : alternative1 | alternative2 | ... ;- ruleName:规则名称,必须小写字母开头
- ::分隔符
- alternative:备选分支,用
|分隔 - ;:结束符
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
;标签的好处:
- 生成独立的上下文类(
MultiplyContext,AddContext等) - 在 Visitor/Listener 中便于区分不同情况
- 提高代码的可读性和类型安全性
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 的核心,它负责:
- ✅ 定义语言结构:描述合法的句子模式
- ✅ 建立层次关系:通过规则嵌套创建解析树
- ✅ 处理优先级:通过左递归实现自然的运算符优先级
- ✅ 提供处理入口:为 Visitor/Listener 模式提供结构化的访问点
关键要点:
- 命名规范:语法规则小写开头,词法规则大写开头
- 优先级设计:使用直接左递归,低优先级规则在前
- 标签使用:为备选分支添加标签,便于后续处理
- 模块化设计:将复杂规则分解为简单的子规则
掌握了语法规则,你就完成了 G4 文件最主要的部分。下一步我们将学习如何完善语法文件的其余部分。
本文由 jxxxy 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。