From 702ed9c1fd77a999c4b8a922ef11c8e7dcddee7f Mon Sep 17 00:00:00 2001 From: zjx Date: Thu, 19 Mar 2026 19:46:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(antlr4)=EF=BC=9A=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E6=A0=91=E6=9E=84=E5=BB=BA=E7=9A=84=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/antlr4/SysY.g4 | 209 +++++++++++++++++++++++++++++++++------------ 1 file changed, 156 insertions(+), 53 deletions(-) diff --git a/src/antlr4/SysY.g4 b/src/antlr4/SysY.g4 index 263aeef..38d82a3 100644 --- a/src/antlr4/SysY.g4 +++ b/src/antlr4/SysY.g4 @@ -1,68 +1,70 @@ -// SysY 子集语法:支持形如 -// int main() { int a = 1; int b = 2; return a + b; } -// 的最小返回表达式编译。 - -// 后续需要自行添加 - grammar SysY; -/*===-------------------------------------------===*/ -/* Lexer rules */ -/*===-------------------------------------------===*/ - -INT: 'int'; -RETURN: 'return'; - -ASSIGN: '='; -ADD: '+'; +// ====================== +// Parser Rules +// ====================== -LPAREN: '('; -RPAREN: ')'; -LBRACE: '{'; -RBRACE: '}'; -SEMICOLON: ';'; +compUnit + : (decl | funcDef)+ + ; -ID: [a-zA-Z_][a-zA-Z_0-9]*; -ILITERAL: [0-9]+; +decl + : constDecl + | varDecl + ; -WS: [ \t\r\n] -> skip; -LINECOMMENT: '//' ~[\r\n]* -> skip; -BLOCKCOMMENT: '/*' .*? '*/' -> skip; +constDecl + : 'const' bType constDef (',' constDef)* ';' + ; -/*===-------------------------------------------===*/ -/* Syntax rules */ -/*===-------------------------------------------===*/ +bType + : 'int' + | 'float' + ; -compUnit - : funcDef EOF +constDef + : Ident ('[' constExp ']')* '=' constInitVal ; -decl - : btype varDef SEMICOLON +constInitVal + : constExp + | '{' (constInitVal (',' constInitVal)*)? '}' ; -btype - : INT +varDecl + : bType varDef (',' varDef)* ';' ; varDef - : lValue (ASSIGN initValue)? + : Ident ('[' constExp ']')* + | Ident ('[' constExp ']')* '=' initVal ; -initValue +initVal : exp + | '{' (initVal (',' initVal)*)? '}' ; funcDef - : funcType ID LPAREN RPAREN blockStmt + : funcType Ident '(' funcFParams? ')' block ; funcType - : INT + : 'void' + | 'int' + | 'float' ; -blockStmt - : LBRACE blockItem* RBRACE +funcFParams + : funcFParam (',' funcFParam)* + ; + +funcFParam + : bType Ident ('[' ']' ('[' exp ']')*)? + ; + +block + : '{' blockItem* '}' ; blockItem @@ -71,28 +73,129 @@ blockItem ; stmt - : returnStmt + : lVal '=' exp ';' + | exp? ';' + | block + | 'if' '(' cond ')' stmt ('else' stmt)? + | 'while' '(' cond ')' stmt + | 'break' ';' + | 'continue' ';' + | 'return' exp? ';' ; -returnStmt - : RETURN exp SEMICOLON +exp + : addExp ; -exp - : LPAREN exp RPAREN # parenExp - | var # varExp - | number # numberExp - | exp ADD exp # additiveExp +cond + : lOrExp ; -var - : ID +lVal + : Ident ('[' exp ']')* ; -lValue - : ID +primaryExp + : '(' exp ')' + | lVal + | number ; number - : ILITERAL + : FloatConst + | IntConst + ; + +unaryExp + : primaryExp + | Ident '(' funcRParams? ')' + | unaryOp unaryExp + ; + +unaryOp + : '+' + | '-' + | '!' ; + +funcRParams + : exp (',' exp)* + ; + +mulExp + : unaryExp (('*' | '/' | '%') unaryExp)* + ; + +addExp + : mulExp (('+' | '-') mulExp)* + ; + +relExp + : addExp (('<' | '>' | '<=' | '>=') addExp)* + ; + +eqExp + : relExp (('==' | '!=') relExp)* + ; + +lAndExp + : eqExp ('&&' eqExp)* + ; + +lOrExp + : lAndExp ('||' lAndExp)* + ; + +constExp + : addExp + ; + +// ====================== +// Lexer Rules +// ====================== + +fragment DIGIT : [0-9] ; +fragment HEXDIGIT : [0-9a-fA-F] ; +fragment EXP : [eE][+-]? DIGIT+ ; +fragment PEXP : [pP][+-]? DIGIT+ ; + +// Float(含 hex float) +FloatConst + : ('0x' | '0X') + ( + HEXDIGIT+ '.' HEXDIGIT* + | '.' HEXDIGIT+ + | HEXDIGIT+ + ) + PEXP + | '.' DIGIT+ EXP? + | DIGIT+ '.' DIGIT* EXP? + | DIGIT+ EXP + ; + +// Int(完整三种) +IntConst + : '0' + | [1-9][0-9]* // decimal + | '0'[0-7]+ // octal + | ('0x' | '0X')[0-9a-fA-F]+ // hex + ; + +// ---------- 标识符 ---------- +Ident + : [a-zA-Z_][a-zA-Z0-9_]* + ; + +// ---------- 空白 ---------- +WS + : [ \t\r\n]+ -> skip + ; + +// ---------- 注释 ---------- +LINE_COMMENT + : '//' ~[\r\n]* -> skip + ; + +BLOCK_COMMENT + : '/*' .*? '*/' -> skip + ; \ No newline at end of file