meowlang/parser/Meow.g4
2022-02-12 02:29:25 +01:00

277 lines
5.4 KiB
ANTLR

grammar Meow;
file
: importStatement* declaration* EOF
;
importStatement
: ImportKeyword importpath=StringLiteral (AsKeyword importname=Identifier)? ';'
;
declaration
: function ';'?
| constraintDeclaration ';'?
| structDeclaration ';'?
| enumDeclaration ';'?
| tupleDeclaration ';'?
| typeAlias ';'?
;
structDeclaration
: StructKeyword name=Identifier (genericParameters constraint*)? structType
;
enumDeclaration
: EnumKeyword name=Identifier (genericParameters constraint*)? enumType
;
tupleDeclaration
: TupleKeyword name=Identifier (genericParameters constraint*)? tupleType
;
typeAlias
: TypeKeyword name=Identifier genericParameters? '=' typeReference
;
constraintDeclaration
: ConstraintKeyword name=Identifier types+=Identifier+ '{' constraintRule* '}'
;
constraintRule
: embedConstraintRule
| functionConstraintRule
;
embedConstraintRule
: ConstraintKeyword name=Identifier types+=typeReference+ ';'
;
functionConstraintRule
: name=Identifier constraintFunctionParameters functionReturn? ';'
;
constraintFunctionParameters
: '(' (typeReference (',' typeReference)*)? ')'
;
function
: attribute* pub=PubKeyword? FnKeyword name=Identifier functionParameters functionReturn? functionBody
| attribute* pub=PubKeyword? FnKeyword name=Identifier genericParameters functionParameters functionReturn? constraint* functionBody
;
attribute
: '[' name=Identifier ('(' (attributeValue (',' attributeValue)*)? ')')? ']'
;
attributeValue
: literal
| id=Identifier
;
literal
: stringLiteral
| numericLiteral
| boolLiteral
| characterLiteral
;
stringLiteral: val=StringLiteral;
numericLiteral: val=NumericLiteral;
boolLiteral: val=BoolLiteral;
characterLiteral: val=CharacterLiteral;
genericParameters
: '<' (name+=Identifier (',' name+=Identifier)*) '>'
;
functionParameters
: '(' (functionParameter (',' functionParameter)*)? ')'
;
functionParameter
: typeReference name=Identifier
;
functionReturn
: '->' (typeReference (',' typeReference)*)
;
constraint
: WhereKeyword name=Identifier typenames+=Identifier+
;
functionBody
: '{' statement* expression? '}'
;
typeReference
: nonPointerTypeReference pointer='*'?
;
nonPointerTypeReference
: typeName
| arrayType
| tupleType
| StructKeyword structType
| EnumKeyword enumType
;
typeName
: (importName=Identifier ':')? name+=Identifier ('<' genericType+=typeName (',' genericType+=typeName)* '>')? ('@' name+=Identifier)*
;
arrayType
: '[' typeReference (';' length=NumericLiteral)? ']'
;
tupleType
: '(' typeReference (',' typeReference)* ')'
;
structType
: '{' structMember* '}'
;
structMember
: typeReference name=Identifier ';'
;
enumType
: '{' enumMember (',' enumMember)* ','? '}'
;
enumMember
: name=Identifier ('(' typeReference ')')?
;
statement
: breakStatement
| continueStatement
| returnStatement
| loopStatement
| expressionStatement
;
breakStatement
: BreakKeyword label=Identifier? ';'
;
continueStatement
: ContinueKeyword label=Identifier? ';'
;
returnStatement
: ReturnKeyword expression? ';'
;
loopStatement
: LoopKeyword '{' statement* '}'
| LoopKeyword condition=expression '{' statement* '}'
| LoopKeyword init=expression? ';' condition=expression? ';' increment=expression? '{' statement* '}'
;
expressionStatement
: expression ';'
;
/*
todo: use C operator precedence: https://en.cppreference.com/w/c/language/operator_precedence
binary operators:
== != > >= < <=
||
&&
+ -
* / %
&
|
^
<<
>>
unary operators:
+
-
~
!
assignment:
=
+=
-=
/=
*=
%=
&=
|=
^=
<<=
>>=
*/
expression
: addExpression
;
addExpression
: multExpression ((op='+'|op='-') multExpression)*
;
multExpression
: terminalExpression ((op='*'|op='/'|op='%') terminalExpression)*
;
terminalExpression
: literal
| structConstructor
| arrayConstructor
| enumConstructor
| functionCall
| ifExpression
| switchExpression
| blockExpression
| parenthesisExpression
;
///////////////////////////
ImportKeyword: 'import';
AsKeyword: 'as';
PubKeyword: 'pub';
FnKeyword: 'fn';
WhereKeyword: 'where';
ConstraintKeyword: 'constraint';
StructKeyword: 'struct';
EnumKeyword: 'enum';
TupleKeyword: 'tuple';
TypeKeyword: 'type';
BreakKeyword: 'break';
ContinueKeyword: 'continue';
ReturnKeyword: 'return';
LoopKeyword: 'loop';
// start with letters (upper or lower case) followed by any alphanumeric symbol
Identifier: [a-zA-Z_][a-zA-Z_0-9]*;
NumericLiteral: DecimalNumberLiteral /*| HexadecimalNumberLiteral | OctalNumberLiteral | BinaryNumberLiteral*/;
fragment DecimalNumberLiteral: DecimalNumberPart ('.' DecimalNumberPart)? | '.' DecimalNumberPart;
fragment DecimalNumberPart: [0-9] [0-9_]*;
BoolLiteral: 'true' | 'false' ;
CharacterLiteral: '\'' (CharacterEscape | ~['\\]) '\'';
fragment CharacterEscape: '\\\'' | '\\\\';
StringLiteral: '"' (StringEscape | ~[\\"])*? '"';
fragment StringEscape: '\\"' | '\\\\';
// comments and white space -> ignored
BLOCK_COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
LINE_COMMENT: '//' ~[\n]* -> channel(HIDDEN);
WS: [ \t\r\n\f]+ -> channel(HIDDEN);