diff --git a/scripts/run_test.sh b/scripts/run_test.sh new file mode 100755 index 0000000..f495d67 --- /dev/null +++ b/scripts/run_test.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# 项目根目录 +PROJECT_ROOT="/home/wu/nudt-compiler-cpp" + +# 输出目录 +TEST_RESULT_DIR="$PROJECT_ROOT/test/test_result" + +# 编译g4文件生成C++代码 +echo "=== 编译ANTLR grammar文件 ===" +java -jar "$PROJECT_ROOT/third_party/antlr-4.13.2-complete.jar" \ + -Dlanguage=Cpp \ + -visitor \ + -no-listener \ + -Xexact-output-dir \ + -o "$PROJECT_ROOT/build/generated/antlr4" \ + "$PROJECT_ROOT/src/antlr4/SysY.g4" + +if [ $? -ne 0 ]; then + echo "错误:ANTLR编译失败" + exit 1 +fi + +# 构建项目 +echo "=== 构建项目 ===" +cmake -S "$PROJECT_ROOT" -B "$PROJECT_ROOT/build" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCOMPILER_PARSE_ONLY=ON + +if [ $? -ne 0 ]; then + echo "错误:CMake配置失败" + exit 1 +fi + +cmake --build "$PROJECT_ROOT/build" -j "$(nproc)" + +if [ $? -ne 0 ]; then + echo "错误:项目构建失败" + exit 1 +fi + +# 遍历测试用例 +echo "=== 运行测试用例 ===" +find "$PROJECT_ROOT/test/test_case" -name "*.sy" | while read -r test_file; do + # 计算相对路径 + relative_path=$(realpath --relative-to="$PROJECT_ROOT/test/test_case" "$test_file") + # 计算输出文件路径 + output_file="$TEST_RESULT_DIR/$relative_path.tree" + # 创建输出目录 + mkdir -p "$(dirname "$output_file")" + + # 运行编译器 + echo "处理:$relative_path" + "$PROJECT_ROOT/build/bin/compiler" --emit-parse-tree "$test_file" > "$output_file" + + if [ $? -ne 0 ]; then + echo "警告:处理 $relative_path 时出错" + fi +done + +echo "=== 测试完成 ===" +echo "结果保存在:$TEST_RESULT_DIR" \ No newline at end of file diff --git a/src/antlr4/SysY.g4 b/src/antlr4/SysY.g4 index 263aeef..3b06827 100644 --- a/src/antlr4/SysY.g4 +++ b/src/antlr4/SysY.g4 @@ -1,68 +1,65 @@ -// SysY 子集语法:支持形如 -// int main() { int a = 1; int b = 2; return a + b; } -// 的最小返回表达式编译。 - -// 后续需要自行添加 - grammar SysY; -/*===-------------------------------------------===*/ -/* Lexer rules */ -/*===-------------------------------------------===*/ - -INT: 'int'; -RETURN: 'return'; - -ASSIGN: '='; -ADD: '+'; +compUnit + : (funcDef | decl)+ EOF + ; -LPAREN: '('; -RPAREN: ')'; -LBRACE: '{'; -RBRACE: '}'; -SEMICOLON: ';'; +decl + : constDecl + | varDecl + ; -ID: [a-zA-Z_][a-zA-Z_0-9]*; -ILITERAL: [0-9]+; +constDecl + : Const bType constDef (Comma constDef)* Semi + ; -WS: [ \t\r\n] -> skip; -LINECOMMENT: '//' ~[\r\n]* -> skip; -BLOCKCOMMENT: '/*' .*? '*/' -> skip; +bType + : Int + | Float + ; -/*===-------------------------------------------===*/ -/* Syntax rules */ -/*===-------------------------------------------===*/ +constDef + : Ident (L_BRAKT constExp R_BRAKT)* Assign constInitVal + ; -compUnit - : funcDef EOF +constInitVal + : constExp + | L_BRACE (constInitVal (Comma constInitVal)*)? R_BRACE ; -decl - : btype varDef SEMICOLON +varDecl + : bType varDef (Comma varDef)* Semi ; -btype - : INT +funcDef + : funcType Ident L_PAREN (funcFParams)? R_PAREN block ; varDef - : lValue (ASSIGN initValue)? + : Ident (L_BRAKT constExp R_BRAKT)* (Assign initVal)? ; -initValue +initVal : exp + | L_BRACE (initVal (Comma initVal)*)? R_BRACE ; -funcDef - : funcType ID LPAREN RPAREN blockStmt +funcType + : Void + | Int + | Float ; -funcType - : INT +funcFParams + : funcFParam (Comma funcFParam)* ; -blockStmt - : LBRACE blockItem* RBRACE +funcFParam + : bType Ident (L_BRAKT R_BRAKT (L_BRAKT exp R_BRAKT)*)? + ; + +block + : L_BRACE (blockItem)* R_BRACE ; blockItem @@ -71,28 +68,182 @@ blockItem ; stmt - : returnStmt + : lVar Assign exp Semi + | (exp)? Semi + | block + | If L_PAREN cond R_PAREN stmt (Else stmt)? + | While L_PAREN cond R_PAREN stmt + | Break Semi + | Continue Semi + | Return (exp)? Semi ; -returnStmt - : RETURN exp SEMICOLON +exp + : addExp ; -exp - : LPAREN exp RPAREN # parenExp - | var # varExp - | number # numberExp - | exp ADD exp # additiveExp +cond + : lOrExp ; -var - : ID +lVar + : Ident (L_BRAKT exp R_BRAKT)* ; -lValue - : ID +primaryExp + : L_PAREN exp R_PAREN + | lVar + | number ; number - : ILITERAL + : IntConst + | FloatConst + ; + +unaryExp + : primaryExp + | Ident L_PAREN (funcRParams)? R_PAREN + | unaryOp unaryExp + ; + +unaryOp : AddOp | '!'; + +funcRParams + : exp (Comma exp)* + ; + +mulExp + : unaryExp (MulOp unaryExp)* + ; + +addExp + : mulExp (AddOp mulExp)* + ; + +relExp + : addExp (RelOp addExp)* + ; + +eqExp + : relExp (EqOp relExp)* + ; + +lAndExp + : eqExp ('&&' eqExp)* + ; + +lOrExp + : lAndExp ('||' lAndExp)* + ; + +constExp + : addExp + ; + +Void : 'void'; +Int : 'int'; +Float : 'float'; +Const : 'const'; +If : 'if'; +Else : 'else'; +While : 'while'; +Break : 'break'; +Continue: 'continue'; +Return : 'return'; + +Comma : ','; +Semi : ';'; +L_PAREN : '('; +R_PAREN : ')'; +L_BRAKT : '['; +R_BRAKT : ']'; +L_BRACE : '{'; +R_BRACE : '}'; +Assign : '='; + +MulOp : '*' | '/' | '%'; +AddOp : '+' | '-'; +RelOp : '<' | '>' | '<=' | '>='; +EqOp : '==' | '!='; + +Ident + : [a-zA-Z_][a-zA-Z_0-9]* + ; + +IntConst + : DecInt + | OctInt + | HexInt + ; + +fragment DecInt + : NonZeroD Digit* + ; + +fragment OctInt + : '0' OctDigit* + ; + +fragment HexInt + : HexPre HexDigit+ + ; + +FloatConst + : DecFloat + | HexFloat + ; + +fragment DecFloat + : Fraction Exponent? + | DiSeq Exponent + ; + +fragment HexFloat + : HexPre (HexFraction | HexDiSeq) BiExponent + ; + +fragment Fraction + : DiSeq? '.' DiSeq + | DiSeq '.' + ; + +fragment Exponent + : [eE] ('+' | '-')? DiSeq + ; + +fragment DiSeq + : Digit+ + ; + +fragment HexFraction + : HexDiSeq? '.' HexDiSeq + | HexDiSeq '.' + ; + +fragment BiExponent + : [pP] ('+' | '-')? DiSeq + ; + +fragment HexDiSeq + : HexDigit+ + ; + +fragment NonZeroD: [1-9]; +fragment Digit : [0-9]; +fragment OctDigit: [0-7]; +fragment HexPre : '0' [xX]; +fragment HexDigit: [0-9A-Fa-f]; + + +WS + : [ \t\r\n]+ -> skip + ; + +COMMENT + : '//' ~[\r\n]* -> skip + ; + +BLOCK_COMMENT + : '/*' .*? '*/' -> skip ;