From 40c77fb71719015f367e8959e428ae00cac86b3e Mon Sep 17 00:00:00 2001 From: just <2931381969@qq.com> Date: Mon, 23 Mar 2026 20:48:13 +0800 Subject: [PATCH] Hyz branch --- scripts/test_parse.sh | 78 +++++++ src/antlr4/.history/SysY_20260318021417.g4 | 98 ++++++++ src/antlr4/.history/SysY_20260323191019.g4 | 98 ++++++++ src/antlr4/.history/SysY_20260323191026.g4 | 17 ++ src/antlr4/.history/SysY_20260323191030.g4 | 98 ++++++++ src/antlr4/.history/SysY_20260323191034.g4 | 187 +++++++++++++++ src/antlr4/.history/SysY_20260323193633.g4 | 229 ++++++++++++++++++ src/antlr4/.history/SysY_20260323193647.g4 | 229 ++++++++++++++++++ src/antlr4/.history/SysY_20260323193649.g4 | 229 ++++++++++++++++++ src/antlr4/.history/SysY_20260323193749.g4 | 229 ++++++++++++++++++ src/antlr4/.history/SysY_20260323194900.g4 | 260 +++++++++++++++++++++ src/antlr4/.history/SysY_20260323194903.g4 | 260 +++++++++++++++++++++ src/antlr4/SysY.g4 | 227 ++++++++++++++++++ 13 files changed, 2239 insertions(+) create mode 100755 scripts/test_parse.sh create mode 100644 src/antlr4/.history/SysY_20260318021417.g4 create mode 100644 src/antlr4/.history/SysY_20260323191019.g4 create mode 100644 src/antlr4/.history/SysY_20260323191026.g4 create mode 100644 src/antlr4/.history/SysY_20260323191030.g4 create mode 100644 src/antlr4/.history/SysY_20260323191034.g4 create mode 100644 src/antlr4/.history/SysY_20260323193633.g4 create mode 100644 src/antlr4/.history/SysY_20260323193647.g4 create mode 100644 src/antlr4/.history/SysY_20260323193649.g4 create mode 100644 src/antlr4/.history/SysY_20260323193749.g4 create mode 100644 src/antlr4/.history/SysY_20260323194900.g4 create mode 100644 src/antlr4/.history/SysY_20260323194903.g4 create mode 100644 src/antlr4/SysY.g4 diff --git a/scripts/test_parse.sh b/scripts/test_parse.sh new file mode 100755 index 0000000..750d9bf --- /dev/null +++ b/scripts/test_parse.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# ================================================ +# SysY 编译器 Lab1 批量解析测试脚本 +# 文件名:scripts/test_parse.sh +# 适用环境:Arch Linux(bash 原生支持,无需额外安装) +# 功能: +# - 遍历 test/test_case 下所有 .sy 文件(functional + performance) +# - 执行 --emit-parse-tree 检查是否能成功解析 +# - 输出简洁的 PASS/FAIL 结果 + 统计 +# - 错误文件会自动打印最后 10 行报错信息(方便调试) +# - 所有结果保存到 test/test_result/parse_test.log +# ================================================ + +set -u # 遇到未定义变量直接报错 + +# ================== 配置 ================== +COMPILER="./build/bin/compiler" +TEST_DIR="test/test_case" +LOG_FILE="test/test_result/parse_test.log" +MAX_ERROR_LINES=10 + +# 检查编译器是否存在 +if [[ ! -x "$COMPILER" ]]; then + echo "❌ 错误:找不到编译器 $COMPILER" + echo " 请先执行 Lab1 构建命令:" + echo " cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=ON" + echo " cmake --build build -j \"\$(nproc)\"" + exit 1 +fi + +# 创建日志目录(如果不存在) +mkdir -p "$(dirname "$LOG_FILE")" +> "$LOG_FILE" # 清空日志 + +echo "开始 Lab1 批量语法树测试..." | tee -a "$LOG_FILE" +echo "测试目录:$TEST_DIR" | tee -a "$LOG_FILE" +echo "编译器:$COMPILER" | tee -a "$LOG_FILE" +echo "========================================" | tee -a "$LOG_FILE" + +pass=0 +fail=0 +total=0 + +# 遍历所有 .sy 文件(支持子目录) +while IFS= read -r -d '' sy_file; do + ((total++)) + echo -n "[$total] 测试: $sy_file ... " | tee -a "$LOG_FILE" + + # 执行解析(把输出丢到 /dev/null,防止刷屏) + if "$COMPILER" --emit-parse-tree "$sy_file" > /dev/null 2>&1; then + echo "✅PASS" | tee -a "$LOG_FILE" + ((pass++)) + else + echo "FAIL" | tee -a "$LOG_FILE" + ((fail++)) + + # 打印错误信息到日志(最后几行) + echo " └── 错误详情(最后 $MAX_ERROR_LINES 行):" >> "$LOG_FILE" + "$COMPILER" --emit-parse-tree "$sy_file" 2>&1 | tail -n "$MAX_ERROR_LINES" >> "$LOG_FILE" + echo "" >> "$LOG_FILE" + fi +done < <(find "$TEST_DIR" -name "*.sy" -print0 | sort -z) + +# ================== 总结 ================== +echo "========================================" | tee -a "$LOG_FILE" +echo "测试完成!" | tee -a "$LOG_FILE" +echo "总文件数 : $total" | tee -a "$LOG_FILE" +echo "通过 : $pass" | tee -a "$LOG_FILE" +echo "失败 : $fail" | tee -a "$LOG_FILE" + +if [[ $fail -eq 0 ]]; then + echo "恭喜!Lab1 语法树构建全部通过!可以进入 Lab2 啦~" | tee -a "$LOG_FILE" +else + echo "有 $fail 个文件解析失败,请检查 SysY.g4 或报错日志" | tee -a "$LOG_FILE" + echo " 日志文件:$LOG_FILE" | tee -a "$LOG_FILE" +fi + +echo "========================================" | tee -a "$LOG_FILE" diff --git a/src/antlr4/.history/SysY_20260318021417.g4 b/src/antlr4/.history/SysY_20260318021417.g4 new file mode 100644 index 0000000..263aeef --- /dev/null +++ b/src/antlr4/.history/SysY_20260318021417.g4 @@ -0,0 +1,98 @@ +// SysY 子集语法:支持形如 +// int main() { int a = 1; int b = 2; return a + b; } +// 的最小返回表达式编译。 + +// 后续需要自行添加 + +grammar SysY; + +/*===-------------------------------------------===*/ +/* Lexer rules */ +/*===-------------------------------------------===*/ + +INT: 'int'; +RETURN: 'return'; + +ASSIGN: '='; +ADD: '+'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +SEMICOLON: ';'; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + +/*===-------------------------------------------===*/ +/* Syntax rules */ +/*===-------------------------------------------===*/ + +compUnit + : funcDef EOF + ; + +decl + : btype varDef SEMICOLON + ; + +btype + : INT + ; + +varDef + : lValue (ASSIGN initValue)? + ; + +initValue + : exp + ; + +funcDef + : funcType ID LPAREN RPAREN blockStmt + ; + +funcType + : INT + ; + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +stmt + : returnStmt + ; + +returnStmt + : RETURN exp SEMICOLON + ; + +exp + : LPAREN exp RPAREN # parenExp + | var # varExp + | number # numberExp + | exp ADD exp # additiveExp + ; + +var + : ID + ; + +lValue + : ID + ; + +number + : ILITERAL + ; diff --git a/src/antlr4/.history/SysY_20260323191019.g4 b/src/antlr4/.history/SysY_20260323191019.g4 new file mode 100644 index 0000000..263aeef --- /dev/null +++ b/src/antlr4/.history/SysY_20260323191019.g4 @@ -0,0 +1,98 @@ +// SysY 子集语法:支持形如 +// int main() { int a = 1; int b = 2; return a + b; } +// 的最小返回表达式编译。 + +// 后续需要自行添加 + +grammar SysY; + +/*===-------------------------------------------===*/ +/* Lexer rules */ +/*===-------------------------------------------===*/ + +INT: 'int'; +RETURN: 'return'; + +ASSIGN: '='; +ADD: '+'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +SEMICOLON: ';'; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + +/*===-------------------------------------------===*/ +/* Syntax rules */ +/*===-------------------------------------------===*/ + +compUnit + : funcDef EOF + ; + +decl + : btype varDef SEMICOLON + ; + +btype + : INT + ; + +varDef + : lValue (ASSIGN initValue)? + ; + +initValue + : exp + ; + +funcDef + : funcType ID LPAREN RPAREN blockStmt + ; + +funcType + : INT + ; + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +stmt + : returnStmt + ; + +returnStmt + : RETURN exp SEMICOLON + ; + +exp + : LPAREN exp RPAREN # parenExp + | var # varExp + | number # numberExp + | exp ADD exp # additiveExp + ; + +var + : ID + ; + +lValue + : ID + ; + +number + : ILITERAL + ; diff --git a/src/antlr4/.history/SysY_20260323191026.g4 b/src/antlr4/.history/SysY_20260323191026.g4 new file mode 100644 index 0000000..2292f21 --- /dev/null +++ b/src/antlr4/.history/SysY_20260323191026.g4 @@ -0,0 +1,17 @@ +int main() { + int a = 1, b = 2; + int c; + c = a + b * 3; + + if (c > 5) { + c = c - 1; + } else { + c = c + 1; + } + + while (c < 10) { + c = c + 1; + } + + return c; +} diff --git a/src/antlr4/.history/SysY_20260323191030.g4 b/src/antlr4/.history/SysY_20260323191030.g4 new file mode 100644 index 0000000..263aeef --- /dev/null +++ b/src/antlr4/.history/SysY_20260323191030.g4 @@ -0,0 +1,98 @@ +// SysY 子集语法:支持形如 +// int main() { int a = 1; int b = 2; return a + b; } +// 的最小返回表达式编译。 + +// 后续需要自行添加 + +grammar SysY; + +/*===-------------------------------------------===*/ +/* Lexer rules */ +/*===-------------------------------------------===*/ + +INT: 'int'; +RETURN: 'return'; + +ASSIGN: '='; +ADD: '+'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +SEMICOLON: ';'; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + +/*===-------------------------------------------===*/ +/* Syntax rules */ +/*===-------------------------------------------===*/ + +compUnit + : funcDef EOF + ; + +decl + : btype varDef SEMICOLON + ; + +btype + : INT + ; + +varDef + : lValue (ASSIGN initValue)? + ; + +initValue + : exp + ; + +funcDef + : funcType ID LPAREN RPAREN blockStmt + ; + +funcType + : INT + ; + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +stmt + : returnStmt + ; + +returnStmt + : RETURN exp SEMICOLON + ; + +exp + : LPAREN exp RPAREN # parenExp + | var # varExp + | number # numberExp + | exp ADD exp # additiveExp + ; + +var + : ID + ; + +lValue + : ID + ; + +number + : ILITERAL + ; diff --git a/src/antlr4/.history/SysY_20260323191034.g4 b/src/antlr4/.history/SysY_20260323191034.g4 new file mode 100644 index 0000000..bf80555 --- /dev/null +++ b/src/antlr4/.history/SysY_20260323191034.g4 @@ -0,0 +1,187 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +INT: 'int'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Syntax rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : btype varDefList SEMICOLON + ; + +btype + : INT + ; + +varDefList + : varDef (COMMA varDef)* + ; + +varDef + : ID (LBRACK number RBRACK)? (ASSIGN initValue)? + ; + +initValue + : exp + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcParams? RPAREN blockStmt + ; + +funcType + : INT + ; + +funcParams + : funcParam (COMMA funcParam)* + ; + +funcParam + : btype ID + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : returnStmt + | assignStmt + | expStmt + | blockStmt + | ifStmt + | whileStmt + ; + +returnStmt + : RETURN exp SEMICOLON + ; + +assignStmt + : lValue ASSIGN exp SEMICOLON + ; + +expStmt + : exp? SEMICOLON + ; + +ifStmt + : IF LPAREN exp RPAREN stmt (ELSE stmt)? + ; + +whileStmt + : WHILE LPAREN exp RPAREN stmt + ; + +/* ===== 表达式 ===== */ + +exp + : logicalExp + ; + +/* 逻辑(先简化成关系表达式) */ +logicalExp + : relationalExp + ; + +/* 比较 */ +relationalExp + : additiveExp ( (LT | GT | LE | GE | EQ | NEQ) additiveExp )* + ; + +/* 加减 */ +additiveExp + : multiplicativeExp ( (ADD | SUB) multiplicativeExp )* + ; + +/* 乘除 */ +multiplicativeExp + : unaryExp ( (MUL | DIV) unaryExp )* + ; + +/* 一元 */ +unaryExp + : primaryExp + | ADD unaryExp + | SUB unaryExp + ; + +/* 基本表达式 */ +primaryExp + : LPAREN exp RPAREN + | number + | lValue + | funcCall + ; + +/* 函数调用 */ +funcCall + : ID LPAREN (exp (COMMA exp)*)? RPAREN + ; + +/* ===== 基础 ===== */ + +lValue + : ID (LBRACK exp RBRACK)? + ; + +number + : ILITERAL + ; diff --git a/src/antlr4/.history/SysY_20260323193633.g4 b/src/antlr4/.history/SysY_20260323193633.g4 new file mode 100644 index 0000000..f150b72 --- /dev/null +++ b/src/antlr4/.history/SysY_20260323193633.g4 @@ -0,0 +1,229 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量要放在整数字面量前面 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDef (COMMA constDef)* SEMICOLON + ; + +varDecl + : btype varDef (COMMA varDef)* SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDef + : ID constExpArrayDims ASSIGN constInitVal + ; + +varDef + : ID arrayDims? (ASSIGN initVal)? + ; + +/* 变量定义时数组维度一般要求是 exp */ +arrayDims + : (LBRACK exp RBRACK)+ + ; + +/* const 定义也支持多维 */ +constExpArrayDims + : (LBRACK constExp RBRACK)+ + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcFParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : lVal ASSIGN exp SEMICOLON # assignStatement + | exp? SEMICOLON # expStatement + | blockStmt # blockStatement + | IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement + | WHILE LPAREN cond RPAREN stmt # whileStatement + | BREAK SEMICOLON # breakStatement + | CONTINUE SEMICOLON # continueStatement + | RETURN exp? SEMICOLON # returnStatement + ; + +/* ===== 表达式 ===== */ + +exp + : addExp + ; + +cond + : lOrExp + ; + +lVal + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | lVal + | number + ; + +number + : ILITERAL + | FLOATLITERAL + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | ID LPAREN funcRParams? RPAREN + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; diff --git a/src/antlr4/.history/SysY_20260323193647.g4 b/src/antlr4/.history/SysY_20260323193647.g4 new file mode 100644 index 0000000..f150b72 --- /dev/null +++ b/src/antlr4/.history/SysY_20260323193647.g4 @@ -0,0 +1,229 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量要放在整数字面量前面 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDef (COMMA constDef)* SEMICOLON + ; + +varDecl + : btype varDef (COMMA varDef)* SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDef + : ID constExpArrayDims ASSIGN constInitVal + ; + +varDef + : ID arrayDims? (ASSIGN initVal)? + ; + +/* 变量定义时数组维度一般要求是 exp */ +arrayDims + : (LBRACK exp RBRACK)+ + ; + +/* const 定义也支持多维 */ +constExpArrayDims + : (LBRACK constExp RBRACK)+ + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcFParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : lVal ASSIGN exp SEMICOLON # assignStatement + | exp? SEMICOLON # expStatement + | blockStmt # blockStatement + | IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement + | WHILE LPAREN cond RPAREN stmt # whileStatement + | BREAK SEMICOLON # breakStatement + | CONTINUE SEMICOLON # continueStatement + | RETURN exp? SEMICOLON # returnStatement + ; + +/* ===== 表达式 ===== */ + +exp + : addExp + ; + +cond + : lOrExp + ; + +lVal + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | lVal + | number + ; + +number + : ILITERAL + | FLOATLITERAL + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | ID LPAREN funcRParams? RPAREN + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; diff --git a/src/antlr4/.history/SysY_20260323193649.g4 b/src/antlr4/.history/SysY_20260323193649.g4 new file mode 100644 index 0000000..05af7ba --- /dev/null +++ b/src/antlr4/.history/SysY_20260323193649.g4 @@ -0,0 +1,229 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量要放在整数字面量前面 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDef (COMMA constDef)* SEMICOLON + ; + +varDecl + : btype varDef (COMMA varDef)* SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDef + : ID constExpArrayDims ASSIGN constInitVal + ; + +varDef + : ID arrayDims? (ASSIGN initVal)? + ; + +/* 变量定义时数组维度一般要求是 exp */ +arrayDims + : (LBRACK exp RBRACK)+ + ; + +/* const 定义也支持多维 */ +constExpArrayDims + : (LBRACK constExp RBRACK)+ + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcFParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : lVal ASSIGN exp SEMICOLON # assignStatement + | exp? SEMICOLON # expStatement + | blockStmt # blockStatement + | IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement + | WHILE LPAREN cond RPAREN stmt # whileStatement + | BREAK SEMICOLON # breakStatement + | CONTINUE SEMICOLON # continueStatement + | RETURN exp? SEMICOLON # returnStatement + ; + +/* ===== 表达式 ===== */ + +exp + : addExp + ; + +cond + : lOrExp + ; + +lVal + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | lVal + | number + ; + +number + : ILITERAL + | FLOATLITERAL + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | ID LPAREN funcRParams? RPAREN + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; diff --git a/src/antlr4/.history/SysY_20260323193749.g4 b/src/antlr4/.history/SysY_20260323193749.g4 new file mode 100644 index 0000000..05af7ba --- /dev/null +++ b/src/antlr4/.history/SysY_20260323193749.g4 @@ -0,0 +1,229 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量要放在整数字面量前面 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDef (COMMA constDef)* SEMICOLON + ; + +varDecl + : btype varDef (COMMA varDef)* SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDef + : ID constExpArrayDims ASSIGN constInitVal + ; + +varDef + : ID arrayDims? (ASSIGN initVal)? + ; + +/* 变量定义时数组维度一般要求是 exp */ +arrayDims + : (LBRACK exp RBRACK)+ + ; + +/* const 定义也支持多维 */ +constExpArrayDims + : (LBRACK constExp RBRACK)+ + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcFParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : lVal ASSIGN exp SEMICOLON # assignStatement + | exp? SEMICOLON # expStatement + | blockStmt # blockStatement + | IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement + | WHILE LPAREN cond RPAREN stmt # whileStatement + | BREAK SEMICOLON # breakStatement + | CONTINUE SEMICOLON # continueStatement + | RETURN exp? SEMICOLON # returnStatement + ; + +/* ===== 表达式 ===== */ + +exp + : addExp + ; + +cond + : lOrExp + ; + +lVal + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | lVal + | number + ; + +number + : ILITERAL + | FLOATLITERAL + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | ID LPAREN funcRParams? RPAREN + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; diff --git a/src/antlr4/.history/SysY_20260323194900.g4 b/src/antlr4/.history/SysY_20260323194900.g4 new file mode 100644 index 0000000..1b888be --- /dev/null +++ b/src/antlr4/.history/SysY_20260323194900.g4 @@ -0,0 +1,260 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量放在整数字面量前 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDefList SEMICOLON + ; + +varDecl + : btype varDefList SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDefList + : constDef (COMMA constDef)* + ; + +varDefList + : varDef (COMMA varDef)* + ; + +constDef + : ID (LBRACK constExp RBRACK)+ ASSIGN constInitVal + | ID ASSIGN constInitVal + ; + +varDef + : ID (LBRACK exp RBRACK)* (ASSIGN initVal)? + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcParams + : funcParam (COMMA funcParam)* + ; + +funcParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : returnStmt + | assignStmt + | expStmt + | blockStmt + | ifStmt + | whileStmt + | breakStmt + | continueStmt + ; + +returnStmt + : RETURN exp? SEMICOLON + ; + +assignStmt + : lValue ASSIGN exp SEMICOLON + ; + +expStmt + : exp? SEMICOLON + ; + +ifStmt + : IF LPAREN cond RPAREN stmt (ELSE stmt)? + ; + +whileStmt + : WHILE LPAREN cond RPAREN stmt + ; + +breakStmt + : BREAK SEMICOLON + ; + +continueStmt + : CONTINUE SEMICOLON + ; + +/* ===== 表达式 ===== */ + +exp + : lOrExp + ; + +cond + : lOrExp + ; + +lValue + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | number + | lValue + ; + +funcCall + : ID LPAREN funcRParams? RPAREN + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | funcCall + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; + +number + : ILITERAL + | FLOATLITERAL + ; diff --git a/src/antlr4/.history/SysY_20260323194903.g4 b/src/antlr4/.history/SysY_20260323194903.g4 new file mode 100644 index 0000000..1b888be --- /dev/null +++ b/src/antlr4/.history/SysY_20260323194903.g4 @@ -0,0 +1,260 @@ +grammar SysY; + +/*====================*/ +/* Lexer rules */ +/*====================*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +RETURN: 'return'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; + +ASSIGN: '='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; + +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +SEMICOLON: ';'; +COMMA: ','; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +/* 浮点字面量放在整数字面量前 */ +FLOATLITERAL + : [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)? + | '.' [0-9]+ ([eE] [+\-]? [0-9]+)? + | [0-9]+ [eE] [+\-]? [0-9]+ + ; + +ILITERAL: [0-9]+; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + + +/*====================*/ +/* Parser rules */ +/*====================*/ + +compUnit + : (decl | funcDef)* EOF + ; + +/* ===== 声明 ===== */ + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDefList SEMICOLON + ; + +varDecl + : btype varDefList SEMICOLON + ; + +btype + : INT + | FLOAT + ; + +constDefList + : constDef (COMMA constDef)* + ; + +varDefList + : varDef (COMMA varDef)* + ; + +constDef + : ID (LBRACK constExp RBRACK)+ ASSIGN constInitVal + | ID ASSIGN constInitVal + ; + +varDef + : ID (LBRACK exp RBRACK)* (ASSIGN initVal)? + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +/* ===== 函数 ===== */ + +funcDef + : funcType ID LPAREN funcParams? RPAREN blockStmt + ; + +funcType + : INT + | FLOAT + | VOID + ; + +funcParams + : funcParam (COMMA funcParam)* + ; + +funcParam + : btype ID + | btype ID LBRACK RBRACK (LBRACK exp RBRACK)* + ; + +/* ===== 语句块 ===== */ + +blockStmt + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +/* ===== 语句 ===== */ + +stmt + : returnStmt + | assignStmt + | expStmt + | blockStmt + | ifStmt + | whileStmt + | breakStmt + | continueStmt + ; + +returnStmt + : RETURN exp? SEMICOLON + ; + +assignStmt + : lValue ASSIGN exp SEMICOLON + ; + +expStmt + : exp? SEMICOLON + ; + +ifStmt + : IF LPAREN cond RPAREN stmt (ELSE stmt)? + ; + +whileStmt + : WHILE LPAREN cond RPAREN stmt + ; + +breakStmt + : BREAK SEMICOLON + ; + +continueStmt + : CONTINUE SEMICOLON + ; + +/* ===== 表达式 ===== */ + +exp + : lOrExp + ; + +cond + : lOrExp + ; + +lValue + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | number + | lValue + ; + +funcCall + : ID LPAREN funcRParams? RPAREN + ; + +funcRParams + : exp (COMMA exp)* + ; + +unaryExp + : primaryExp + | funcCall + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NEQ) relExp)* + ; + +lAndExp + : eqExp (AND eqExp)* + ; + +lOrExp + : lAndExp (OR lAndExp)* + ; + +constExp + : addExp + ; + +number + : ILITERAL + | FLOATLITERAL + ; diff --git a/src/antlr4/SysY.g4 b/src/antlr4/SysY.g4 new file mode 100644 index 0000000..d3633df --- /dev/null +++ b/src/antlr4/SysY.g4 @@ -0,0 +1,227 @@ +grammar SysY; + +/*===-------------------------------------------===*/ +/* Lexer rules */ +/*===-------------------------------------------===*/ + +CONST: 'const'; +INT: 'int'; +FLOAT: 'float'; +VOID: 'void'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +CONTINUE: 'continue'; +RETURN: 'return'; + +ASSIGN: '='; +EQ: '=='; +NE: '!='; +LT: '<'; +GT: '>'; +LE: '<='; +GE: '>='; + +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; +NOT: '!'; +LAND: '&&'; +LOR: '||'; + +LPAREN: '('; +RPAREN: ')'; +LBRACE: '{'; +RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; +COMMA: ','; +SEMICOLON: ';'; + +FLOAT_CONST + : DEC_FLOAT_CONST + | HEX_FLOAT_CONST + ; + +INT_CONST + : HEX_PREFIX HEX_DIGIT+ + | '0' [0-7]+ + | '0' + | [1-9] DIGIT* + ; + +ID: [a-zA-Z_][a-zA-Z_0-9]*; + +WS: [ \t\r\n] -> skip; +LINECOMMENT: '//' ~[\r\n]* -> skip; +BLOCKCOMMENT: '/*' .*? '*/' -> skip; + +fragment DEC_FLOAT_CONST + : DIGIT+ '.' DIGIT* EXP_PART? + | '.' DIGIT+ EXP_PART? + | DIGIT+ EXP_PART + ; + +fragment HEX_FLOAT_CONST + : HEX_PREFIX HEX_DIGIT+ '.' HEX_DIGIT* BIN_EXP_PART + | HEX_PREFIX '.' HEX_DIGIT+ BIN_EXP_PART + | HEX_PREFIX HEX_DIGIT+ BIN_EXP_PART + ; + +fragment EXP_PART: [eE] [+-]? DIGIT+; +fragment BIN_EXP_PART: [pP] [+-]? DIGIT+; +fragment HEX_PREFIX: '0' [xX]; +fragment HEX_DIGIT: [0-9a-fA-F]; +fragment DIGIT: [0-9]; + +/*===-------------------------------------------===*/ +/* Syntax rules */ +/*===-------------------------------------------===*/ + +compUnit + : (decl | funcDef)+ EOF + ; + +decl + : constDecl + | varDecl + ; + +constDecl + : CONST bType constDef (COMMA constDef)* SEMICOLON + ; + +varDecl + : bType varDef (COMMA varDef)* SEMICOLON + ; + +bType + : INT + | FLOAT + ; + +constDef + : ID (LBRACK constExp RBRACK)* ASSIGN constInitVal + ; + +constInitVal + : constExp + | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE + ; + +varDef + : ID (LBRACK constExp RBRACK)* (ASSIGN initVal)? + ; + +initVal + : exp + | LBRACE (initVal (COMMA initVal)*)? RBRACE + ; + +funcDef + : funcType ID LPAREN funcFParams? RPAREN block + ; + +funcType + : VOID + | INT + | FLOAT + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : bType ID (LBRACK RBRACK (LBRACK exp RBRACK)*)? + ; + +block + : LBRACE blockItem* RBRACE + ; + +blockItem + : decl + | stmt + ; + +stmt + : lVal ASSIGN exp SEMICOLON + | exp? SEMICOLON + | block + | IF LPAREN cond RPAREN stmt (ELSE stmt)? + | WHILE LPAREN cond RPAREN stmt + | BREAK SEMICOLON + | CONTINUE SEMICOLON + | RETURN exp? SEMICOLON + ; + +exp + : addExp + ; + +cond + : lOrExp + ; + +lVal + : ID (LBRACK exp RBRACK)* + ; + +primaryExp + : LPAREN exp RPAREN + | lVal + | number + ; + +number + : INT_CONST + | FLOAT_CONST + ; + +unaryExp + : primaryExp + | ID LPAREN funcRParams? RPAREN + | unaryOp unaryExp + ; + +unaryOp + : ADD + | SUB + | NOT + ; + +funcRParams + : exp (COMMA exp)* + ; + +mulExp + : unaryExp ((MUL | DIV | MOD) unaryExp)* + ; + +addExp + : mulExp ((ADD | SUB) mulExp)* + ; + +relExp + : addExp ((LT | GT | LE | GE) addExp)* + ; + +eqExp + : relExp ((EQ | NE) relExp)* + ; + +lAndExp + : eqExp (LAND eqExp)* + ; + +lOrExp + : lAndExp (LOR lAndExp)* + ; + +constExp + : addExp + ;