183 lines
4.3 KiB
ANTLR
183 lines
4.3 KiB
ANTLR
grammar SysY;
|
|
|
|
/*===-------------------------------------------===*/
|
|
/* Lexer rules */
|
|
/*===-------------------------------------------===*/
|
|
|
|
|
|
// keywords
|
|
CONST: 'const';
|
|
INT: 'int';
|
|
FLOAT: 'float';
|
|
VOID: 'void';
|
|
IF: 'if';
|
|
ELSE: 'else';
|
|
WHILE: 'while';
|
|
BREAK: 'break';
|
|
CONTINUE: 'continue';
|
|
RETURN: 'return';
|
|
|
|
// operators
|
|
ADD: '+';
|
|
SUB: '-';
|
|
MUL: '*';
|
|
DIV: '/';
|
|
MOD: '%';
|
|
|
|
// relational operators
|
|
EQ: '==';
|
|
NE: '!=';
|
|
LT: '<';
|
|
LE: '<=';
|
|
GT: '>';
|
|
GE: '>=';
|
|
|
|
// logical operators
|
|
AND: '&&';
|
|
OR: '||';
|
|
NOT: '!';
|
|
|
|
// assignment operators
|
|
ASSIGN: '=';
|
|
|
|
// punctuations
|
|
COMMA: ',';
|
|
SEMICOLON: ';';
|
|
LPAREN: '(';
|
|
RPAREN: ')';
|
|
LBRACE: '{';
|
|
RBRACE: '}';
|
|
LBRACK: '[';
|
|
RBRACK: ']';
|
|
|
|
// fragments
|
|
fragment DecDigit: [0-9];
|
|
fragment OctDigit: [0-7];
|
|
fragment HexDigit: [0-9a-fA-F];
|
|
fragment OctPrefix: '0';
|
|
fragment HexPrefix: '0' [xX];
|
|
fragment NonZeroDecDigit: [1-9];
|
|
fragment Sign: '+' | '-';
|
|
fragment DecFractional: DecDigit* '.' DecDigit+ | DecDigit+ '.';
|
|
fragment Exponent: [eE] Sign? DecDigit+;
|
|
fragment DecFloat: DecFractional Exponent? | DecDigit+ Exponent;
|
|
fragment HexFractional: HexDigit* '.' HexDigit+ | HexDigit+ '.';
|
|
fragment BinExponent: [pP] Sign? DecDigit+;
|
|
fragment HexFloat:
|
|
HexPrefix HexFractional BinExponent
|
|
| HexPrefix HexDigit+ BinExponent;
|
|
|
|
fragment ESC: '\\"' | '\\\\';
|
|
|
|
|
|
// identifier
|
|
fragment ALPHA: [a-zA-Z];
|
|
fragment ALPHANUM: [a-zA-Z0-9];
|
|
fragment NONDIGIT: [a-zA-Z_];
|
|
Ident: NONDIGIT (ALPHANUM | '_')*;
|
|
|
|
// IntConst -> ILITERAL
|
|
// FloatConst -> FLITERAL
|
|
// literals
|
|
ILITERAL:
|
|
NonZeroDecDigit DecDigit*
|
|
| OctPrefix OctDigit*
|
|
| HexPrefix HexDigit+;
|
|
|
|
// fliteral
|
|
FLITERAL: DecFloat | HexFloat;
|
|
|
|
// string
|
|
STRING: '"' (ESC | .)*? '"';
|
|
|
|
// white space and comments
|
|
WS: [\t\r\n ] -> skip;
|
|
LINECOMMENT: '//' .*? '\r'? '\n' -> skip;
|
|
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
|
|
/*===-------------------------------------------===*/
|
|
/* Syntax rules */
|
|
/*===-------------------------------------------===*/
|
|
|
|
// CompUnit: (CompUnit)? (decl |funcDef);
|
|
|
|
compUnit: (globalDecl |funcDef)+;
|
|
|
|
globalDecl: constDecl # globalConstDecl
|
|
| varDecl # globalVarDecl;
|
|
|
|
decl: constDecl | varDecl;
|
|
|
|
constDecl: CONST bType constDef (COMMA constDef)* SEMICOLON;
|
|
|
|
bType: INT | FLOAT;
|
|
|
|
constDef: Ident (LBRACK constExp RBRACK)* ASSIGN constInitVal;
|
|
|
|
constInitVal: constExp # constScalarInitValue
|
|
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE # constArrayInitValue;
|
|
|
|
varDecl: bType varDef (COMMA varDef)* SEMICOLON;
|
|
|
|
varDef: Ident (LBRACK constExp RBRACK)*
|
|
| Ident (LBRACK constExp RBRACK)* ASSIGN initVal;
|
|
|
|
initVal: exp # scalarInitValue
|
|
| LBRACE (initVal (COMMA initVal)*)? RBRACE # arrayInitValue;
|
|
|
|
funcType: VOID | INT | FLOAT;
|
|
|
|
funcDef: funcType Ident LPAREN funcFParams? RPAREN blockStmt;
|
|
|
|
funcFParams: funcFParam (COMMA funcFParam)*;
|
|
|
|
// 函数形参感觉定义有问题
|
|
// 应该是funcFParam: bType Ident ((LBRACK RBRACK)* (LBRACK exp RBRACK)*)?;
|
|
funcFParam: bType Ident (LBRACK RBRACK (LBRACK exp RBRACK)*)?;
|
|
|
|
blockStmt: LBRACE blockItem* RBRACE;
|
|
|
|
blockItem: decl | stmt;
|
|
|
|
stmt: lValue ASSIGN exp SEMICOLON #assignStmt
|
|
| exp? SEMICOLON #expStmt
|
|
| blockStmt #blkStmt
|
|
| IF LPAREN cond RPAREN stmt (ELSE stmt)? #ifStmt
|
|
| WHILE LPAREN cond RPAREN stmt #whileStmt
|
|
| BREAK SEMICOLON #breakStmt
|
|
| CONTINUE SEMICOLON #continueStmt
|
|
| RETURN exp? SEMICOLON #returnStmt;
|
|
|
|
exp: addExp;
|
|
cond: lOrExp;
|
|
lValue: Ident (LBRACK exp RBRACK)*;
|
|
|
|
// 为了方便测试 primaryExp 可以是一个string
|
|
primaryExp: LPAREN exp RPAREN
|
|
| lValue
|
|
| number
|
|
| string;
|
|
|
|
number: ILITERAL | FLITERAL;
|
|
call: Ident LPAREN (funcRParams)? RPAREN;
|
|
unaryExp: primaryExp
|
|
| call
|
|
| unaryOp unaryExp;
|
|
|
|
unaryOp: ADD|SUB|NOT;
|
|
funcRParams: exp (COMMA exp)*;
|
|
string: STRING;
|
|
mulExp: unaryExp ((MUL|DIV|MOD) unaryExp)*;
|
|
addExp: mulExp ((ADD|SUB) mulExp)*;
|
|
relExp: addExp ((LT|GT|LE|GE) addExp)*;
|
|
eqExp: relExp ((EQ|NE) relExp)*;
|
|
lAndExp: eqExp (AND eqExp)*;
|
|
lOrExp: lAndExp (OR lAndExp)*;
|
|
constExp: addExp;
|
|
// mulExp: unaryExp ((MUL|DIV|MOD) unaryExp)*;
|
|
// addExp: mulExp | addExp (ADD|SUB) mulExp;
|
|
// relExp: addExp | relExp (LT|GT|LE|GE) addExp;
|
|
// eqExp: relExp | eqExp (EQ|NE) relExp;
|
|
// lAndExp: eqExp | lAndExp AND eqExp;
|
|
// lOrExp: lAndExp | lOrExp OR lAndExp;
|
|
// constExp: addExp; |