CompilerSysY/Sysy.g4
2023-05-05 16:11:44 +08:00

150 lines
2.9 KiB
ANTLR

grammar Sysy;
program: compUnit;
compUnit: (funcDef | decl)+;
decl: constDecl | varDecl;
constDecl: 'const' bType constDef (',' constDef)* ';';
bType: 'int';
constDef: IDENT ('[' constExp ']')* '=' constInitVal;
constInitVal:
constExp
| ('{' (constInitVal (',' constInitVal)*)? '}');
varDecl: bType varDef (',' varDef)* ';';
varDef: IDENT ('[' constExp ']')* ('=' initVal)?;
initVal: exp | ('{' (initVal (',' initVal)*)? '}');
funcDef: funcType IDENT '(' (funcFParams)? ')' block;
funcType: 'void' | 'int';
funcFParams: funcFParam (',' funcFParam)*;
funcFParam: bType IDENT ('[' ']' ('[' exp ']')*)?;
block: '{' (blockItem)* '}';
blockItem: decl | stmt;
stmt:
lVal '=' exp ';' # assignStmt
| (exp)? ';' # expStmt
| block # blockStmt
| 'if' '(' cond ')' stmt ('else' stmt)? # ifStmt
| 'while' '(' cond ')' stmt # whileStmt
| 'break' ';' # breakStmt
| 'continue' ';' # continueStmt
| 'return' (exp)? ';' # returnStmt;
exp: addExp;
cond: lOrExp;
lVal: IDENT ('[' exp ']')*;
primaryExp: ('(' exp ')') | lVal | number;
number: intConst;
intConst: DECIMAL_CONST | OCTAL_CONST | HEXADECIMAL_CONST;
unaryExp:
primaryExp
| IDENT '(' (funcRParams)? ')'
| unaryOp unaryExp;
unaryOp: '+' | '-' | '!'; // 注:'!'仅出现在条件表达式中
funcRParams: funcRParam (',' funcRParam)*;
funcRParam: exp | StringLiteral;
mulExp:
unaryExp
| mulExp ('*' | '/' | '%') unaryExp;
// ANTLR4 has support for direct left recursion
// Though it is not a good idea, when the expression is too long, stack will explode
addExp: mulExp | addExp ('+' | '-') mulExp;
relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp;
eqExp: relExp | eqExp ('==' | '!=') relExp;
lAndExp: eqExp ('&&' eqExp)*;
lOrExp: lAndExp ('||' lAndExp)*;
constExp: addExp; // 注:使用的 Ident 必须是常量
// -------- Terminals ---------
CONST: 'const';
COMMA: ',';
SEMICOLON: ';';
INT: 'int';
LBRACKET: '[';
RBRACKET: ']';
ASSIGN: '=';
LBRACE: '{';
RBRACE: '}';
LPAREN: '(';
RPAREN: ')';
VOID: 'void';
IF: 'if';
ELSE: 'else';
WHILE: 'while';
BREAK: 'break';
CONTINUE: 'continue';
RETURN: 'return';
ADD: '+';
SUB: '-';
NOT: '!';
MUL: '*';
DIV: '/';
MOD: '%';
LT: '<';
GT: '>';
LE: '<=';
GE: '>=';
EQ: '==';
NE: '!=';
AND: '&&';
OR: '||';
DQUOTE: '"';
IDENT: [_a-zA-Z] | [_a-zA-Z] [_a-zA-Z0-9]+;
DECIMAL_CONST: [1-9] | [1-9] [0-9]+;
OCTAL_CONST: '0' | ('0' [0-7]+);
HEXADECIMAL_CONST: ('0x' | '0X') [a-fA-F0-9]+;
WS: [ \r\n\t]+ -> skip;
SINGLELINE_COMMENT: '//' ~ [\r\n]* -> skip;
MULTILINE_COMMENT: '/*' .*? '*/' -> skip;
fragment EscapeSequence:
'\\' ['"?abfnrtv\\]
| '\\' [0-7] [0-7]? [0-7]?
| '\\x' [0-9a-fA-F]+; // https://github.com/antlr/grammars-v4/blob/master/c/C.g4
fragment SChar:
~["\\\r\n]
| EscapeSequence
| '\\\n' // Added line
| '\\\r\n'; // Added line
StringLiteral: DQUOTE (SChar+)? DQUOTE;
// https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md