114 lines
2.4 KiB
ANTLR
114 lines
2.4 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
|
|
|
|
addExp: mulExp | addExp ('+' | '-') mulExp;
|
|
|
|
relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp;
|
|
|
|
eqExp: relExp | eqExp ('==' | '!=') relExp;
|
|
|
|
lAndExp: eqExp | lAndExp '&&' eqExp;
|
|
|
|
lOrExp: lAndExp | lOrExp '||' lAndExp;
|
|
|
|
constExp: addExp; // 注:使用的 Ident 必须是常量
|
|
|
|
// -------- Terminals ---------
|
|
|
|
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: '"' (SChar+)? '"';
|
|
// https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md |