grammar SysY;

// ======================
// Parser Rules
// ======================

compUnit
    : (decl | funcDef)+
    ;

decl
    : constDecl
    | varDecl
    ;

constDecl
    : 'const' bType constDef (',' constDef)* ';'
    ;

bType
    : 'int'
    | 'float'
    ;

constDef
    : Ident ('[' constExp ']')* '=' constInitVal
    ;

constInitVal
    : constExp
    | '{' (constInitVal (',' constInitVal)*)? '}'
    ;

varDecl
    : bType varDef (',' varDef)* ';'
    ;

varDef
    : Ident ('[' constExp ']')*
    | Ident ('[' constExp ']')* '=' initVal
    ;

initVal
    : exp
    | '{' (initVal (',' initVal)*)? '}'
    ;

funcDef
    : funcType Ident '(' funcFParams? ')' block
    ;

funcType
    : 'void'
    | 'int'
    | 'float'
    ;

funcFParams
    : funcFParam (',' funcFParam)*
    ;

funcFParam
    : bType Ident ('[' ']' ('[' exp ']')*)?
    ;

block
    : '{' blockItem* '}'
    ;

blockItem
    : decl
    | stmt
    ;

stmt
    : lVal '=' exp ';'
    | exp? ';'
    | block
    | 'if' '(' cond ')' stmt ('else' stmt)?
    | 'while' '(' cond ')' stmt
    | 'break' ';'
    | 'continue' ';'
    | 'return' exp? ';'
    ;

exp
    : addExp
    ;

cond
    : lOrExp
    ;

lVal
    : Ident ('[' exp ']')*
    ;

primaryExp
    : '(' exp ')'
    | lVal
    | number
    ;

number
    : 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
    ;