forked from ph7n2ofui/SysyCompiler_Arm
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
3.4 KiB
169 lines
3.4 KiB
grammar SysY;
|
|
|
|
/*===-------------------------------------------===*/
|
|
/* Lexer rules */
|
|
/*===-------------------------------------------===*/
|
|
|
|
// fragments
|
|
|
|
// keywords
|
|
CONST: 'const';
|
|
INT: 'int';
|
|
FLOAT: 'float';
|
|
VOID: 'void';
|
|
IF: 'if';
|
|
ELSE: 'else';
|
|
WHILE: 'while';
|
|
BREAK: 'break';
|
|
CONTINUE: 'continue';
|
|
RETURN: 'return';
|
|
|
|
// operators
|
|
ASSIGN: '=';
|
|
ADD: '+';
|
|
SUB: '-';
|
|
MUL: '*';
|
|
DIV: '/';
|
|
MODULO: '%';
|
|
LT: '<';
|
|
GT: '>';
|
|
LE: '<=';
|
|
GE: '>=';
|
|
EQ: '==';
|
|
NE: '!=';
|
|
AND: '&&';
|
|
OR: '||';
|
|
NOT: '!';
|
|
|
|
// punctuations
|
|
LPAREN: '(';
|
|
RPAREN: ')';
|
|
LBRACKET: '[';
|
|
RBRACKET: ']';
|
|
LBRACE: '{';
|
|
RBRACE: '}';
|
|
COMMA: ',';
|
|
SEMICOLON: ';';
|
|
|
|
// identifier
|
|
fragment ALPHA: [a-zA-Z];
|
|
fragment ALPHANUM: [a-zA-Z0-9];
|
|
fragment NONDIGIT: [a-zA-Z_];
|
|
ID: NONDIGIT (ALPHANUM | '_')*;
|
|
|
|
// literals
|
|
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
|
|
| HexDigit+ BinExponent;
|
|
|
|
ILITERAL:
|
|
NonZeroDecDigit DecDigit*
|
|
| OctPrefix OctDigit*
|
|
| HexPrefix HexDigit+;
|
|
|
|
FLITERAL: DecFloat | HexFloat;
|
|
|
|
// string
|
|
fragment ESC: '\\"' | '\\\\';
|
|
STRING: '"' (ESC | .)*? '"';
|
|
|
|
// white space and comments
|
|
WS: [ \t\r\n] -> skip;
|
|
LINECOMMENT: '//' .*? '\r'? '\n' -> skip;
|
|
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
|
|
/*===-------------------------------------------===*/
|
|
/* Syntax rules */
|
|
/*===-------------------------------------------===*/
|
|
|
|
module: (decl | func)+;
|
|
|
|
// constDecl and varDecl shares the same syntax structure, except that constDecl must have constant
|
|
// initial values. We combine these two syntax rules, and ensure the constraint above at the
|
|
// semantic check phase.
|
|
decl: CONST? btype varDef (COMMA varDef)* SEMICOLON;
|
|
|
|
btype: INT | FLOAT;
|
|
|
|
varDef: lValue (ASSIGN initValue)?;
|
|
|
|
initValue:
|
|
exp # scalarInitValue
|
|
| LBRACE (initValue (COMMA initValue)*)? # arrayInitValue;
|
|
|
|
func: funcType ID LPAREN funcFParams? RPAREN blockStmt;
|
|
|
|
funcType: VOID | INT | FLOAT;
|
|
|
|
funcFParams: funcFParam (COMMA funcFParam)*;
|
|
|
|
funcFParam:
|
|
btype ID (LBRACKET RBRACKET (LBRACKET exp RBRACKET)*)?;
|
|
|
|
blockStmt: LBRACE blockItem* RBRACE;
|
|
|
|
blockItem: decl | stmt;
|
|
|
|
stmt:
|
|
assignStmt
|
|
| expStmt
|
|
| ifStmt
|
|
| whileStmt
|
|
| breakStmt
|
|
| continueStmt
|
|
| returnStmt
|
|
| blockStmt
|
|
| emptyStmt;
|
|
|
|
assignStmt: lValue ASSIGN exp SEMICOLON;
|
|
|
|
expStmt: exp SEMICOLON;
|
|
|
|
ifStmt: IF LPAREN exp RPAREN stmt (ELSE stmt)?;
|
|
|
|
whileStmt: WHILE LPAREN exp RPAREN stmt;
|
|
|
|
breakStmt: BREAK SEMICOLON;
|
|
|
|
continueStmt: CONTINUE SEMICOLON;
|
|
|
|
returnStmt: RETURN exp? SEMICOLON;
|
|
|
|
emptyStmt: SEMICOLON;
|
|
|
|
exp:
|
|
LPAREN exp RPAREN # parenExp
|
|
| lValue # lValueExp
|
|
| number # numberExp
|
|
| string # stringExp
|
|
| call # callExp
|
|
| (ADD | SUB | NOT) exp # unaryExp
|
|
| exp (MUL | DIV | MODULO) exp # multiplicativeExp
|
|
| exp (ADD | SUB) exp # additiveExp
|
|
| exp (LT | GT | LE | GE) exp # relationExp
|
|
| exp (EQ | NE) exp # equalExp
|
|
| exp AND exp # andExp
|
|
| exp OR exp # orExp;
|
|
|
|
call: ID LPAREN funcRParams? RPAREN;
|
|
|
|
lValue: ID (LBRACKET exp RBRACKET)*;
|
|
|
|
number: ILITERAL | FLITERAL;
|
|
|
|
string: STRING;
|
|
|
|
funcRParams: exp (COMMA exp)*;
|