Compare commits

...

1 Commits
master ... hyz

Author SHA1 Message Date
just 40c77fb717 Hyz branch
2 weeks ago

@ -0,0 +1,78 @@
#!/bin/bash
# ================================================
# SysY 编译器 Lab1 批量解析测试脚本
# 文件名scripts/test_parse.sh
# 适用环境Arch Linuxbash 原生支持,无需额外安装)
# 功能:
# - 遍历 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"

@ -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
;

@ -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
;

@ -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;
}

@ -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
;

@ -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
;

@ -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
;

@ -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
;

@ -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
;

@ -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
;

@ -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
;

@ -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
;

@ -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
;
Loading…
Cancel
Save