Anlr4——组成完整例子
in 默认分类 with 0 comment

好的!现在让我们将前面所有步骤整合成一个完整的、可运行的例子。我们将创建一个简单的计算器语言,支持变量、基本运算和函数调用。

完整示例:SimpleCalc 语言

文件结构

SimpleCalc/
├── src/
│   └── main/
│       └── antlr/
│           └── SimpleCalc.g4          # 语法定义文件
├── examples/
│   ├── example1.scalc                 # 示例程序1
│   └── example2.scalc                 # 示例程序2
└── README.md

第一步:语法文件骨架

文件:SimpleCalc.g4

/*
 * SimpleCalc 语言语法定义
 * 一个简单的计算器语言,支持变量、函数和基本运算
 */

// 第一步:grammar 声明
grammar SimpleCalc;

第二步:添加 @header 动作

grammar SimpleCalc;

// 第二步:@header 动作 - 定义包结构和导入
@header {
package com.example.simplecalc.parser;

import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
}

第三步:定义词法规则(Lexer Rules)

// 第三步:词法规则 - 定义语言的基本单词

// === 关键字 ===
VAR     : 'var' ;
FUNC    : 'func' ;
IF      : 'if' ;
ELSE    : 'else' ;
WHILE   : 'while' ;
RETURN  : 'return' ;
PRINT   : 'print' ;

// === 类型关键字 ===
INT_TYPE    : 'int' ;
FLOAT_TYPE  : 'float' ;
BOOL_TYPE   : 'bool' ;
STRING_TYPE : 'string' ;

// === 字面量 ===
fragment DIGIT   : [0-9] ;
fragment LETTER  : [a-zA-Z_] ;
fragment ESCAPE  : '\\' [btnfr"\\] ;  // 转义字符: \b, \t, \n, \f, \r, \", \\

INT_LITERAL     : DIGIT+ ;
FLOAT_LITERAL   : DIGIT+ '.' DIGIT* 
                | '.' DIGIT+ 
                ;
BOOL_LITERAL    : 'true' | 'false' ;
STRING_LITERAL  : '"' (ESCAPE | ~["\\])* '"' ;
NULL_LITERAL    : 'null' ;

// === 标识符 ===
IDENTIFIER  : LETTER (LETTER | DIGIT)* ;

// === 运算符 ===
// 赋值
ASSIGN : '=' ;

// 算术运算符
PLUS    : '+' ;
MINUS   : '-' ;
MUL     : '*' ;
DIV     : '/' ;
MOD     : '%' ;
POW     : '**' ;

// 比较运算符
EQ      : '==' ;
NEQ     : '!=' ;
LT      : '<' ;
GT      : '>' ;
LTE     : '<=' ;
GTE     : '>=' ;

// 逻辑运算符
AND     : '&&' ;
OR      : '||' ;
NOT     : '!' ;

// === 分隔符 ===
LPAREN      : '(' ;
RPAREN      : ')' ;
LBRACE      : '{' ;
RBRACE      : '}' ;
LBRACKET    : '[' ;
RBRACKET    : ']' ;
SEMI        : ';' ;
COMMA       : ',' ;
DOT         : '.' ;
COLON       : ':' ;
QUESTION    : '?' ;

// === 需要跳过的内容 ===
WS          : [ \t\r\n]+ -> skip ;  // 空白字符
LINE_COMMENT: '//' ~[\r\n]* -> skip ;  // 单行注释
BLOCK_COMMENT: '/*' .*? '*/' -> skip ;  // 多行注释

第四步:定义语法规则(Parser Rules)

// 第四步:语法规则 - 定义语言结构

// === 程序结构 ===
program : (functionDecl | statement)+ EOF ;

// === 函数声明 ===
functionDecl : FUNC IDENTIFIER LPAREN parameterList? RPAREN 
               (COLON type)? block ;

parameterList : parameter (COMMA parameter)* ;
parameter : IDENTIFIER COLON type ;
type : INT_TYPE | FLOAT_TYPE | BOOL_TYPE | STRING_TYPE ;

// === 语句(Statements)===
statement
    : variableDecl SEMI          # VariableDeclStmt
    | assignment SEMI           # AssignmentStmt
    | ifStatement               # IfStmt
    | whileStatement            # WhileStmt
    | returnStatement SEMI      # ReturnStmt
    | printStatement SEMI       # PrintStmt
    | expression SEMI           # ExpressionStmt
    | block                     # BlockStmt
    | SEMI                      # EmptyStmt
    ;

variableDecl : VAR IDENTIFIER (COLON type)? (ASSIGN expression)? ;
assignment : IDENTIFIER ASSIGN expression ;
returnStatement : RETURN expression? ;
printStatement : PRINT expression ;

// === 控制流语句 ===
ifStatement : IF LPAREN expression RPAREN statement (ELSE statement)? ;
whileStatement : WHILE LPAREN expression RPAREN statement ;
block : LBRACE statement* RBRACE ;

// === 表达式(Expressions)- 优先级处理 ===
// 第五步:处理递归和优先级
expression
    : assignmentExpression
    ;

assignmentExpression
    : IDENTIFIER ASSIGN assignmentExpression     # AssignmentExpr
    | conditionalExpression                       # ConditionalExpr
    ;

conditionalExpression
    : logicalOrExpression (QUESTION expression COLON conditionalExpression)? 
    ;

logicalOrExpression
    : logicalAndExpression (OR logicalAndExpression)*
    ;

logicalAndExpression
    : equalityExpression (AND equalityExpression)*
    ;

equalityExpression
    : relationalExpression ((EQ | NEQ) relationalExpression)*
    ;

relationalExpression
    : additiveExpression ((LT | GT | LTE | GTE) additiveExpression)*
    ;

additiveExpression
    : multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)*
    ;

multiplicativeExpression
    : powerExpression ((MUL | DIV | MOD) powerExpression)*
    ;

powerExpression
    : unaryExpression (POW unaryExpression)*
    ;

unaryExpression
    : (PLUS | MINUS | NOT) unaryExpression   # UnaryExpr
    | postfixExpression                       # PostfixExpr
    ;

postfixExpression
    : primaryExpression
    | postfixExpression LPAREN argumentList? RPAREN    # FunctionCall
    | postfixExpression LBRACKET expression RBRACKET    # ArrayAccess
    | postfixExpression DOT IDENTIFIER                 # MemberAccess
    ;

primaryExpression
    : literal                     # LiteralExpr
    | IDENTIFIER                  # VariableExpr
    | LPAREN expression RPAREN    # ParenthesizedExpr
    | arrayLiteral                # ArrayLiteralExpr
    ;

// === 字面量和数据结构 ===
literal
    : INT_LITERAL     # IntLiteral
    | FLOAT_LITERAL   # FloatLiteral
    | BOOL_LITERAL    # BoolLiteral
    | STRING_LITERAL  # StringLiteral
    | NULL_LITERAL    # NullLiteral
    ;

arrayLiteral : LBRACKET (expression (COMMA expression)*)? RBRACKET ;
argumentList : expression (COMMA expression)* ;

完整的 SimpleCalc.g4 文件

将以上所有部分组合起来:

/*
 * SimpleCalc 语言语法定义
 * 一个简单的计算器语言,支持变量、函数和基本运算
 */

// 第一步:grammar 声明
grammar SimpleCalc;

// 第二步:@header 动作
@header {
package com.example.simplecalc.parser;

import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
}

// 第三步:词法规则
VAR     : 'var' ;
FUNC    : 'func' ;
IF      : 'if' ;
ELSE    : 'else' ;
WHILE   : 'while' ;
RETURN  : 'return' ;
PRINT   : 'print' ;

INT_TYPE    : 'int' ;
FLOAT_TYPE  : 'float' ;
BOOL_TYPE   : 'bool' ;
STRING_TYPE : 'string' ;

fragment DIGIT   : [0-9] ;
fragment LETTER  : [a-zA-Z_] ;
fragment ESCAPE  : '\\' [btnfr"\\] ;

INT_LITERAL     : DIGIT+ ;
FLOAT_LITERAL   : DIGIT+ '.' DIGIT* | '.' DIGIT+ ;
BOOL_LITERAL    : 'true' | 'false' ;
STRING_LITERAL  : '"' (ESCAPE | ~["\\])* '"' ;
NULL_LITERAL    : 'null' ;

IDENTIFIER  : LETTER (LETTER | DIGIT)* ;

ASSIGN : '=' ;
PLUS    : '+' ; MINUS   : '-' ; MUL     : '*' ; DIV     : '/' ; MOD     : '%' ; POW     : '**' ;
EQ      : '==' ; NEQ     : '!=' ; LT      : '<' ; GT      : '>' ; LTE     : '<=' ; GTE     : '>=' ;
AND     : '&&' ; OR      : '||' ; NOT     : '!' ;

LPAREN : '(' ; RPAREN : ')' ; LBRACE : '{' ; RBRACE : '}' ;
LBRACKET : '[' ; RBRACKET : ']' ; SEMI : ';' ; COMMA : ',' ;
DOT : '.' ; COLON : ':' ; QUESTION : '?' ;

WS          : [ \t\r\n]+ -> skip ;
LINE_COMMENT: '//' ~[\r\n]* -> skip ;
BLOCK_COMMENT: '/*' .*? '*/' -> skip ;

// 第四步 + 第五步:语法规则与优先级处理
program : (functionDecl | statement)+ EOF ;

functionDecl : FUNC IDENTIFIER LPAREN parameterList? RPAREN (COLON type)? block ;
parameterList : parameter (COMMA parameter)* ;
parameter : IDENTIFIER COLON type ;
type : INT_TYPE | FLOAT_TYPE | BOOL_TYPE | STRING_TYPE ;

statement
    : variableDecl SEMI | assignment SEMI | ifStatement | whileStatement 
    | returnStatement SEMI | printStatement SEMI | expression SEMI 
    | block | SEMI
    ;

variableDecl : VAR IDENTIFIER (COLON type)? (ASSIGN expression)? ;
assignment : IDENTIFIER ASSIGN expression ;
returnStatement : RETURN expression? ;
printStatement : PRINT expression ;

ifStatement : IF LPAREN expression RPAREN statement (ELSE statement)? ;
whileStatement : WHILE LPAREN expression RPAREN statement ;
block : LBRACE statement* RBRACE ;

expression : assignmentExpression ;
assignmentExpression : IDENTIFIER ASSIGN assignmentExpression | conditionalExpression ;
conditionalExpression : logicalOrExpression (QUESTION expression COLON conditionalExpression)? ;
logicalOrExpression : logicalAndExpression (OR logicalAndExpression)* ;
logicalAndExpression : equalityExpression (AND equalityExpression)* ;
equalityExpression : relationalExpression ((EQ | NEQ) relationalExpression)* ;
relationalExpression : additiveExpression ((LT | GT | LTE | GTE) additiveExpression)* ;
additiveExpression : multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* ;
multiplicativeExpression : powerExpression ((MUL | DIV | MOD) powerExpression)* ;
powerExpression : unaryExpression (POW unaryExpression)* ;
unaryExpression : (PLUS | MINUS | NOT) unaryExpression | postfixExpression ;
postfixExpression : primaryExpression | postfixExpression LPAREN argumentList? RPAREN | postfixExpression LBRACKET expression RBRACKET | postfixExpression DOT IDENTIFIER ;
primaryExpression : literal | IDENTIFIER | LPAREN expression RPAREN | arrayLiteral ;

literal : INT_LITERAL | FLOAT_LITERAL | BOOL_LITERAL | STRING_LITERAL | NULL_LITERAL ;
arrayLiteral : LBRACKET (expression (COMMA expression)*)? RBRACKET ;
argumentList : expression (COMMA expression)* ;

示例程序

examples/example1.scalc:

// 简单计算器示例
var x = 10;
var y = 20;
var result = x * y + 5;

print(result);

// 条件语句
if (result > 100) {
    print("结果大于100");
} else {
    print("结果小于等于100");
}

// 循环示例
var i = 0;
while (i < 5) {
    print(i);
    i = i + 1;
}

examples/example2.scalc:

// 函数定义和调用示例
func factorial(n: int): int {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

func main() {
    var num = 5;
    var fact = factorial(num);
    print("阶乘结果: " + fact);
}

main();

编译和测试步骤

1. 生成解析器代码

antlr4 SimpleCalc.g4

2. 编译Java文件

javac -cp "antlr-4.9.3-complete.jar" SimpleCalc*.java

3. 测试语法解析

# 测试示例1
grun SimpleCalc program -tree examples/example1.scalc
grun SimpleCalc program -gui examples/example1.scalc

# 测试示例2  
grun SimpleCalc program -tree examples/example2.scalc

关键特性总结

这个完整的例子展示了:

第一步完成:正确的 grammar 声明

第二步完成:合理的包结构定义

第三步完成:完整的词法规则,包含:

第四步完成:层次化的语法规则,包含:

第五步完成:正确的优先级处理:

这个完整的语法文件可以直接用于生成功能完整的解析器,能够解析一个具有实用性的简单编程语言。