prog8/il65/antlr/il65.g4

208 lines
4.9 KiB
Plaintext
Raw Normal View History

2018-08-08 23:54:43 +00:00
/*
2018-08-10 21:56:30 +00:00
IL65 combined lexer and parser grammar
NOTES:
- whitespace is ignored. (tabs/spaces)
2018-08-11 12:06:43 +00:00
- every position can be empty, be a comment, or contain ONE statement.
2018-08-10 21:56:30 +00:00
2018-08-08 23:54:43 +00:00
*/
grammar il65;
2018-08-11 12:06:43 +00:00
LINECOMMENT : [\r\n][ \t]* COMMENT -> channel(HIDDEN);
2018-08-10 21:56:30 +00:00
COMMENT : ';' ~[\r\n]* -> channel(HIDDEN) ;
2018-08-09 22:26:41 +00:00
WS : [ \t] -> skip ;
2018-08-10 21:56:30 +00:00
EOL : [\r\n]+ ;
2018-08-08 23:54:43 +00:00
NAME : [a-zA-Z_][a-zA-Z0-9_]* ;
2018-08-09 22:26:41 +00:00
DEC_INTEGER : ('0'..'9') | (('1'..'9')('0'..'9')+);
HEX_INTEGER : '$' (('a'..'f') | ('A'..'F') | ('0'..'9'))+ ;
BIN_INTEGER : '%' ('0' | '1')+ ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
FLOAT_NUMBER : FNUMBER (('E'|'e') ('+' | '-')? FNUMBER)? ; // sign comes later from unary expression
fragment FNUMBER : ('0' .. '9') + ('.' ('0' .. '9') +)? ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
fragment STRING_ESCAPE_SEQ : '\\' . | '\\' EOL;
STRING :
'"' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f"] )* '"'
{
// get rid of the enclosing quotes
String s = getText();
setText(s.substring(1, s.length() - 1));
}
2018-08-08 23:54:43 +00:00
;
2018-08-10 21:56:30 +00:00
INLINEASMBLOCK :
'{{' .+? '}}'
{
// get rid of the enclosing double braces
String s = getText();
setText(s.substring(2, s.length() - 2));
}
;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
2018-08-11 12:06:43 +00:00
module : (modulestatement | EOL)* EOF ;
2018-08-10 21:56:30 +00:00
modulestatement: directive | block ;
2018-08-14 12:33:36 +00:00
block: '~' identifier integerliteral? statement_block EOL ;
2018-08-09 22:26:41 +00:00
statement :
2018-08-08 23:54:43 +00:00
directive
2018-08-10 00:58:41 +00:00
| varinitializer
| vardecl
2018-08-09 22:26:41 +00:00
| constdecl
| memoryvardecl
2018-08-08 23:54:43 +00:00
| assignment
| augassignment
2018-08-10 21:56:30 +00:00
| unconditionaljump
| postincrdecr
2018-08-14 00:22:59 +00:00
| functioncall_stmt
2018-08-14 12:33:36 +00:00
| if_stmt
2018-09-02 16:32:48 +00:00
| branch_stmt
2018-08-12 23:30:33 +00:00
| subroutine
2018-08-10 21:56:30 +00:00
| inlineasm
2018-08-12 15:16:36 +00:00
| labeldef
| returnstmt
2018-08-16 13:09:24 +00:00
// @todo forloop, whileloop, repeatloop
2018-08-08 23:54:43 +00:00
;
2018-08-12 15:16:36 +00:00
labeldef : identifier ':' ;
2018-08-10 21:56:30 +00:00
2018-08-13 02:12:42 +00:00
unconditionaljump : 'goto' (integerliteral | identifier | scoped_identifier) ;
2018-08-08 23:54:43 +00:00
2018-08-10 21:56:30 +00:00
directive :
2018-08-16 21:10:28 +00:00
directivename=('%output' | '%launcher' | '%zeropage' | '%address' | '%import' |
2018-08-13 08:51:05 +00:00
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option')
2018-08-10 21:56:30 +00:00
(directivearg? | directivearg (',' directivearg)*)
;
2018-08-08 23:54:43 +00:00
2018-08-10 21:56:30 +00:00
directivearg : stringliteral | identifier | integerliteral ;
2018-08-08 23:54:43 +00:00
2018-08-10 00:58:41 +00:00
vardecl: datatype arrayspec? identifier ;
2018-08-08 23:54:43 +00:00
2018-08-10 00:58:41 +00:00
varinitializer : datatype arrayspec? identifier '=' expression ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
constdecl: 'const' varinitializer ;
memoryvardecl: 'memory' varinitializer;
datatype: 'byte' | 'word' | 'float' | 'str' | 'str_p' | 'str_s' | 'str_ps' ;
arrayspec: '[' expression (',' expression)? ']' ;
assignment : assign_target '=' expression ;
2018-08-08 23:54:43 +00:00
augassignment :
2018-09-02 09:54:42 +00:00
assign_target operator=('+=' | '-=' | '/=' | '*=' | '**=' | '&=' | '|=' | '^=') expression
2018-08-08 23:54:43 +00:00
;
2018-08-09 22:26:41 +00:00
assign_target:
register
2018-08-10 00:58:41 +00:00
| identifier
| scoped_identifier
2018-08-09 22:26:41 +00:00
;
2018-08-08 23:54:43 +00:00
2018-08-10 21:56:30 +00:00
postincrdecr : assign_target operator = ('++' | '--') ;
2018-08-08 23:54:43 +00:00
expression :
2018-08-10 21:56:30 +00:00
'(' expression ')'
| expression arrayspec
| functioncall
2018-08-11 17:15:39 +00:00
| prefix = ('+'|'-'|'~') expression
2018-08-10 21:56:30 +00:00
| left = expression bop = '**' right = expression
| left = expression bop = ('*' | '/' ) right = expression
2018-08-10 21:56:30 +00:00
| left = expression bop = ('+' | '-' ) right = expression
| left = expression bop = ('<' | '>' | '<=' | '>=') right = expression
| left = expression bop = ('==' | '!=') right = expression
| left = expression bop = '&' right = expression
| left = expression bop = '^' right = expression
| left = expression bop = '|' right = expression
2018-08-16 21:10:28 +00:00
| rangefrom = expression 'to' rangeto = expression // create separate rule once for-loops are here?
2018-08-10 21:56:30 +00:00
| left = expression bop = 'and' right = expression
| left = expression bop = 'or' right = expression
| left = expression bop = 'xor' right = expression
2018-08-11 17:15:39 +00:00
| prefix = 'not' expression
2018-08-08 23:54:43 +00:00
| literalvalue
| register
2018-08-10 00:58:41 +00:00
| identifier
| scoped_identifier
2018-08-08 23:54:43 +00:00
;
2018-08-10 21:56:30 +00:00
functioncall :
2018-08-13 02:12:42 +00:00
(identifier | scoped_identifier) '(' expression_list? ')'
;
2018-08-14 00:22:59 +00:00
functioncall_stmt :
(identifier | scoped_identifier) '(' expression_list? ')'
;
2018-08-12 15:16:36 +00:00
expression_list :
expression (',' expression)*
2018-08-08 23:54:43 +00:00
;
2018-08-12 15:16:36 +00:00
returnstmt : 'return' expression_list? ;
2018-08-10 00:58:41 +00:00
identifier : NAME ;
2018-08-08 23:54:43 +00:00
2018-08-10 00:58:41 +00:00
scoped_identifier : NAME ('.' NAME)+ ;
2018-08-08 23:54:43 +00:00
2018-09-02 16:32:48 +00:00
register : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ;
statusflag : 'Pc' | 'Pz' | 'Pn' | 'Pv' ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
integerliteral : DEC_INTEGER | HEX_INTEGER | BIN_INTEGER ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
booleanliteral : 'true' | 'false' ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
arrayliteral : '[' expression (',' expression)* ']' ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
stringliteral : STRING ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
floatliteral : FLOAT_NUMBER ;
2018-08-08 23:54:43 +00:00
2018-08-09 22:26:41 +00:00
literalvalue :
integerliteral
| booleanliteral
| arrayliteral
| stringliteral
| floatliteral
2018-08-08 23:54:43 +00:00
;
2018-08-10 21:56:30 +00:00
inlineasm : '%asm' INLINEASMBLOCK;
2018-08-12 23:30:33 +00:00
subroutine :
2018-08-14 12:33:36 +00:00
'sub' identifier '(' sub_params? ')' '->' '(' sub_returns? ')' (sub_address | (statement_block EOL))
2018-08-13 02:12:42 +00:00
;
2018-08-14 12:33:36 +00:00
statement_block :
2018-08-13 02:12:42 +00:00
'{' EOL
2018-08-12 23:30:33 +00:00
(statement | EOL) *
2018-08-14 12:33:36 +00:00
'}'
2018-08-12 23:30:33 +00:00
;
2018-08-13 02:12:42 +00:00
sub_address : '=' integerliteral ;
2018-08-12 23:30:33 +00:00
sub_params : sub_param (',' sub_param)* ;
2018-09-02 16:32:48 +00:00
sub_param: identifier ':' (register | statusflag);
2018-08-12 23:30:33 +00:00
sub_returns : '?' | ( sub_return (',' sub_return)* ) ;
2018-09-02 16:32:48 +00:00
sub_return: (register | statusflag) '?'? ;
2018-08-14 12:33:36 +00:00
if_stmt : 'if' '(' expression ')' EOL? (statement | statement_block) EOL? else_part? EOL ; // statement is constrained later
else_part : 'else' EOL? (statement | statement_block) ; // statement is constrained later
2018-09-02 16:32:48 +00:00
branch_stmt : branchcondition EOL? (statement | statement_block) EOL? else_part? EOL ;
branchcondition: 'if_cs' | 'if_cc' | 'if_eq' | 'if_ne' | 'if_pl' | 'if_mi' | 'if_vs' | 'if_vc' ;