// SysY 子集语法
grammar SysY;

//----词法规则（优先级从高到低）----//
//keywords
Void    : 'void';
Int     : 'int';
Float   : 'float';
Const   : 'const';
If      : 'if';
Else    : 'else';
While   : 'while';
Break   : 'break';
Continue: 'continue';
Return  : 'return';

//Two-character operator (long preferred)
LeOp    : '<=';
GeOp    : '>=';
EqOp    : '==';
NeOp    : '!=';
AndOp   : '&&';
OrOp    : '||';

//single character operators
AddOp   : '+';
SubOp   : '-';
MulOp   : '*';
DivOp   : '/';
QuoOp   : '%';
NotOp   : '!';
LOp     : '<';
GOp     : '>';
Assign  : '=';

//Separator
Semi    : ';';
Comma   : ',';
L_PAREN : '(';
R_PAREN : ')';
L_BRACK : '[';
R_BRACK : ']';
L_BRACE : '{';
R_BRACE : '}';

// 16进制float first
HEX_FLOAT
    : '0' [xX](
        // 形式1: 0x1.921fb6p+1  (有小数点和指数)
          HEX_DIGIT* '.' HEX_DIGIT+ [pP] [+-]? DECIMAL_DIGIT+
        | // 形式2: 0x1p+1  (没有小数点，只有指数)
          HEX_DIGIT+ [pP] [+-]? DECIMAL_DIGIT+
        | // 形式3: 0x.AP-3  (小数点开头)
          '.' HEX_DIGIT+ [pP] [+-]? DECIMAL_DIGIT+
    )
    ;
fragment HEX_DIGIT: [0-9a-fA-F];
fragment DECIMAL_DIGIT: [0-9];

// 10进制float
DEC_FLOAT
    : [0-9]+ '.' [0-9]* EXP? //1.2/1./1.2e10/...
    | '.' [0-9]+ EXP?  //.1/.1e2
    | [0-9]+ EXP  //1e2/1e-2
    ;
fragment EXP: [eE] [+-]? [0-9]+;

HEX_INT: '0' [xX] [0-9a-fA-F]+; //16进制
OCTAL_INT: '0' [0-7]*; //8进制
DECIMAL_INT: [1-9][0-9]*; //10进制
ZERO: '0'; //单独0
  
// 标识符
Ident
    : [a-zA-Z_][a-zA-Z_0-9]*
    ;

// 注释和空白
WS
    : [ \t\r\n]+ -> skip
    ;

COMMENT
    : '//' ~[\r\n]* -> skip
    ;

BLOCK_COMMENT
    : '/*' .*? '*/' -> skip
    ;

//----语法规则----//
compUnit
    : (funcDef|decl)+ EOF
    ;

decl
    : varDecl
    | constDecl
    ;

constDecl
    : Const bType constDef (Comma constDef)* Semi
    ;

bType
    : Int
    | Float
    ;

constDef
    : Ident (L_BRACK constExp R_BRACK)* Assign constInitVal
    ;

constInitVal
    : constExp
    | L_BRACE (constInitVal (Comma constInitVal)*)? R_BRACE
    ;

varDecl
    : bType varDef (Comma varDef)* Semi
    ;

varDef
    : Ident (L_BRACK constExp R_BRACK)* (Assign initVal)?
    ;

initVal
    : exp
    | L_BRACE (initVal (Comma initVal)*)? R_BRACE
    ;

funcDef
    : funcType Ident L_PAREN (funcFParams)? R_PAREN block
    ;

funcType
    : Void
    | Int
    | Float
    ;

funcFParams
    : funcFParam (Comma funcFParam)*
    ;

funcFParam
    : bType Ident (L_BRACK R_BRACK (L_BRACK exp R_BRACK)*)?
    ;

block
    : L_BRACE (blockItem)* R_BRACE
    ;

blockItem
    : decl
    | stmt
    ;

stmt
    : lVal 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
    ;

exp
    : addExp
    ;

cond
    : lOrExp
    ;

lVal
    : Ident (L_BRACK exp R_BRACK)*
    ;

primaryExp
    : L_PAREN exp R_PAREN
    | lVal
    | HEX_FLOAT
    | DEC_FLOAT
    | HEX_INT
    | OCTAL_INT
    | DECIMAL_INT
    | ZERO
    ;

unaryExp
    : primaryExp
    | Ident L_PAREN (funcRParams)? R_PAREN
    | unaryOp unaryExp
    ;

unaryOp
    : AddOp
    | SubOp
    | NotOp
    ;

funcRParams
    : exp (Comma exp)*
    ;

mulExp
    : unaryExp
    | mulExp (MulOp|DivOp|QuoOp) unaryExp
    ;

addExp
    : mulExp
    | addExp (AddOp|SubOp) mulExp
    ;

relExp
    : addExp
    | relExp (LOp|GOp|LeOp|GeOp) addExp
    ;

eqExp
    : relExp
    | eqExp (EqOp|NeOp) relExp
    ;

lAndExp
    : eqExp
    | lAndExp AndOp eqExp
    ;

lOrExp
    : lAndExp
    | lOrExp OrOp lAndExp
    ;

constExp
    : addExp
    ;
