diff --git a/src/antlr4/SysY.g4 b/src/antlr4/SysY.g4 index 263aeef..cc41169 100644 --- a/src/antlr4/SysY.g4 +++ b/src/antlr4/SysY.g4 @@ -1,8 +1,4 @@ -// SysY 子集语法:支持形如 -// int main() { int a = 1; int b = 2; return a + b; } -// 的最小返回表达式编译。 - -// 后续需要自行添加 +// SysY 语法:支持完整的 SysY 子集 grammar SysY; @@ -11,19 +7,45 @@ grammar SysY; /*===-------------------------------------------===*/ INT: 'int'; +VOID: 'void'; +FLOAT: 'float'; RETURN: 'return'; +CONST: 'const'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; ASSIGN: '='; ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +MOD: '%'; + +LT: '<'; +LE: '<='; +GT: '>'; +GE: '>='; +EQ: '=='; +NEQ: '!='; + +AND: '&&'; +OR: '||'; +NOT: '!'; LPAREN: '('; RPAREN: ')'; LBRACE: '{'; RBRACE: '}'; +LBRACK: '['; +RBRACK: ']'; SEMICOLON: ';'; +COMMA: ','; ID: [a-zA-Z_][a-zA-Z_0-9]*; ILITERAL: [0-9]+; +FLITERAL: [0-9]+('.'[0-9]+)?([eE][+-]?[0-9]+)?; WS: [ \t\r\n] -> skip; LINECOMMENT: '//' ~[\r\n]* -> skip; @@ -34,15 +56,29 @@ BLOCKCOMMENT: '/*' .*? '*/' -> skip; /*===-------------------------------------------===*/ compUnit - : funcDef EOF + : (decl | funcDef)* EOF ; decl - : btype varDef SEMICOLON + : constDecl + | varDecl + ; + +constDecl + : CONST btype constDef (COMMA constDef)* SEMICOLON + ; + +constDef + : lValue ASSIGN initValue + ; + +varDecl + : btype varDef (COMMA varDef)* SEMICOLON ; btype : INT + | FLOAT ; varDef @@ -51,14 +87,29 @@ varDef initValue : exp + | arrayInit + ; + +arrayInit + : LBRACE (initValue (COMMA initValue)*)? RBRACE ; funcDef - : funcType ID LPAREN RPAREN blockStmt + : funcType ID LPAREN (funcFParams)? RPAREN blockStmt ; funcType : INT + | VOID + | FLOAT + ; + +funcFParams + : funcFParam (COMMA funcFParam)* + ; + +funcFParam + : btype ID (LBRACK (exp)? RBRACK)* ; blockStmt @@ -72,27 +123,78 @@ blockItem stmt : returnStmt + | assignStmt + | ifStmt + | whileStmt + | breakStmt + | continueStmt + | exprStmt + | blockStmt + ; + +continueStmt + : 'continue' SEMICOLON ; returnStmt - : RETURN exp SEMICOLON + : RETURN (exp)? SEMICOLON + ; + +assignStmt + : lValue ASSIGN exp SEMICOLON + ; + +ifStmt + : IF LPAREN cond RPAREN stmt (ELSE stmt)? + ; + +whileStmt + : WHILE LPAREN cond RPAREN stmt + ; + +breakStmt + : BREAK SEMICOLON + ; + +exprStmt + : exp SEMICOLON + ; + +cond + : exp ; exp : LPAREN exp RPAREN # parenExp | var # varExp | number # numberExp + | ID LPAREN (exp (COMMA exp)*)? RPAREN # funcCallExp + | SUB exp # unaryMinusExp + | NOT exp # unaryNotExp + | exp MUL exp # multiplicativeExp + | exp DIV exp # multiplicativeExp + | exp MOD exp # multiplicativeExp | exp ADD exp # additiveExp + | exp SUB exp # additiveExp + | exp LT exp # relationalExp + | exp LE exp # relationalExp + | exp GT exp # relationalExp + | exp GE exp # relationalExp + | exp EQ exp # equalityExp + | exp NEQ exp # equalityExp + | exp AND exp # logicalAndExp + | exp OR exp # logicalOrExp ; var - : ID + : ID (LBRACK exp RBRACK)* ; lValue - : ID + : ID (LBRACK exp RBRACK)* ; number : ILITERAL + | FLITERAL ; diff --git a/test_all.sh b/test_all.sh new file mode 100755 index 0000000..ea338b6 --- /dev/null +++ b/test_all.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# 测试所有 .sy 文件的解析 +# 确定脚本所在目录 +SCRIPT_DIR="$(dirname "$(realpath "$0")")" +TEST_DIR="$SCRIPT_DIR/nudt-compiler-cpp/test/test_case" +COMPILER="$SCRIPT_DIR/nudt-compiler-cpp/build/bin/compiler" + +# 遍历所有 .sy 文件 +find "$TEST_DIR" -name "*.sy" | sort | while read -r file; do + echo "Testing $file..." + "$COMPILER" --emit-parse-tree "$file" + if [ $? -eq 0 ]; then + echo "✓ $file: SUCCESS" + else + echo "✗ $file: FAILED" + fi + echo "" +done