meowlang/parser/Meow.g4
Gwendolyn d6bdd08002 loooots of stuff
the typechecker project can collect all the top level types from a file, which is pretty cool I think
(except for pointers, those aren't implemented yet...)
2022-02-13 02:41:16 +01:00

413 lines
9.1 KiB
ANTLR

grammar Meow;
file
: importStatement* topLevelDeclaration* EOF
;
importStatement
: ImportKeyword importpath=StringLiteral (AsKeyword importname=Identifier)? ';'
;
topLevelDeclaration
: unterminatedTopLevelDeclaration ';'?
;
unterminatedTopLevelDeclaration
: function
| constraintDeclaration
| structDeclaration
| enumDeclaration
| tupleDeclaration
| typeAlias
| topLevelStatement
;
topLevelStatement
: constantDeclarationStatement
;
structDeclaration
: attribute* pub=PubKeyword? StructKeyword name=Identifier (genericParameters constraint*)? structType
;
enumDeclaration
: attribute* pub=PubKeyword? EnumKeyword name=Identifier (genericParameters constraint*)? enumType
;
tupleDeclaration
: attribute* pub=PubKeyword? TupleKeyword name=Identifier (genericParameters constraint*)? tupleType
;
typeAlias
: attribute* pub=PubKeyword? TypeKeyword name=Identifier genericParameters? '=' typeReference
;
constraintDeclaration
: attribute* pub=PubKeyword? 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? body=blockExpression
| attribute* pub=PubKeyword? FnKeyword name=Identifier genericParameters functionParameters functionReturn? constraint* body=blockExpression
;
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
: name=Identifier ':' typeReference
;
functionReturn
: ':' (typeReference (',' typeReference)*)
;
constraint
: WhereKeyword name=Identifier typenames+=Identifier+
;
typeReference
: nonPointerTypeReference pointer='*'?
;
nonPointerTypeReference
: typeName
| arrayType
| tupleType
| StructKeyword structType
| EnumKeyword enumType
;
typeName
: identifierName ('<' genericType+=typeName (',' genericType+=typeName)* '>')? ('@' name+=Identifier)*
;
identifierName
: (importName=Identifier ':')? name=Identifier
;
arrayType
: '[' typeReference (';' length=NumericLiteral)? ']'
;
tupleType
: '(' typeReference (',' typeReference)* ')'
;
structType
: '{' structMember+ '}'
;
structMember
: name=Identifier ':' typeReference ';'
;
enumType
: '{' enumMember (',' enumMember)* ','? '}'
;
enumMember
: name=Identifier ('(' typeReference ')')?
;
terminatedStatement
: statement ';'
| blockStatement
;
statement
: breakStatement
| continueStatement
| returnStatement
| expressionStatement
| variableDeclarationStatement
| constantDeclarationStatement
;
blockStatement
: ifExpression
| switchExpression
| blockExpression
| loopStatement
;
breakStatement
: BreakKeyword label=Identifier?
;
variableDeclarationStatement
: 'let' name+=Identifier (',' name+= Identifier)* '=' expression
;
constantDeclarationStatement
: 'const' Identifier (',' name+= Identifier)* '=' expression
;
continueStatement
: ContinueKeyword label=Identifier?
;
returnStatement
: ReturnKeyword expression?
;
loopStatement
: (label=Identifier ':')? LoopKeyword '{' terminatedStatement* '}'
| (label=Identifier ':')? LoopKeyword condition=expression '{' terminatedStatement* '}'
| (label=Identifier ':')? LoopKeyword (initExpression=expression|initDeclaration=variableDeclarationStatement)? forIndicator=';' condition=expression? ';' increment=expression? '{' terminatedStatement* '}'
;
expressionStatement
: expression
;
expression
: assignmentExpression
;
assignmentExpression
: pattern op=AssignmentOperator logicalOrExpression
| logicalOrExpression
;
pattern
: pointerDereferenceExpression (',' pointerDereferenceExpression)*
;
logicalOrExpression
: logicalXorExpression ('||' logicalXorExpression)*
;
logicalXorExpression
: logicalAndExpression ('^^' logicalAndExpression)*
;
logicalAndExpression
: bitwiseOrExpression ('&&' bitwiseOrExpression)*
;
bitwiseOrExpression
: bitwiseXorExpression ('|' bitwiseXorExpression)*
;
bitwiseXorExpression
: bitwiseAndExpression ('^' bitwiseAndExpression)*
;
bitwiseAndExpression
: equalityExpression ('&' equalityExpression)*
;
equalityExpression
: relationalExpression ((op+='=='|op+='!=') relationalExpression)*
;
relationalExpression
: shiftExpression ((op+='<'|op+='>'|op+='<='|op+='>=') shiftExpression)*
;
shiftExpression
: addExpression ((op+='<<'|op+='>' '>') addExpression)*
;
addExpression
: multExpression ((op+='+'|op+='-') multExpression)*
;
multExpression
: unaryExpression ((op+='*'|op+='/'|op+='%') unaryExpression)*
;
unaryExpression
: (op+='!'|op+='~'|op+='-'|op+='&')* pointerDereferenceExpression
;
pointerDereferenceExpression
: op+='*'* accessExpression
;
accessExpression
: terminalExpression accessExpression1?
;
accessExpression1
: '[' subscript=expression end=']' accessExpression1?
| '.' (name=Identifier|name=NumericLiteral) accessExpression1?
;
terminalExpression
: literalExpression
| nameExpression
| structConstructor
| arrayConstructor
| enumConstructor
| tupleConstructor
| functionCall
| ifExpression
| switchExpression
| blockExpression
| parenthesisExpression
;
literalExpression
: literal
;
nameExpression
: identifierName
;
structConstructor
: typeName? '{' structConstructorMember (',' structConstructorMember)* ','? '}'
;
structConstructorMember
: name=Identifier ':' expression
;
arrayConstructor
: (arrayType | typeName? '[' ']') '{' (expression (',' expression)* ','?)? '}'
;
enumConstructor
: typeName? '\'' name=Identifier
;
tupleConstructor
: '(' ')'
| '(' expression ',' ')'
| '(' expression (',' expression)+ ','? ')'
;
functionCall
: identifierName '(' (expression (',' expression)*)? ')'
;
ifExpression
: IfKeyword cond=expression then=blockExpression elseIfExpression* (ElseKeyword else=blockExpression)?
;
elseIfExpression
: ElseKeyword IfKeyword cond=expression then=blockExpression
;
switchExpression
: SwitchKeyword expression '{' (switchDefault ','?)? '}'
| SwitchKeyword expression '{' switchCase (',' switchCase)* (',' switchDefault ','?)? '}'
;
switchCase
: CaseKeyword literal ':' (expression|FallthroughKeyword)
;
switchDefault
: DefaultKeyword ':' expression
;
blockExpression
: '{' terminatedStatement* expression? '}'
;
parenthesisExpression
: '(' expression ')'
;
///////////////////////////
MeowKeyword: 'm' 'e'+ 'o'* 'w' -> channel(HIDDEN); // ignores all me+o*ws in the code
NyaKeyword: '-ny' 'a'+ -> channel(HIDDEN); // ignores all -nya+s in the code
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';
IfKeyword: 'if';
ElseKeyword: 'else';
SwitchKeyword: 'switch';
CaseKeyword: 'case';
FallthroughKeyword: 'fallthrough';
DefaultKeyword: 'default';
AssignmentOperator: '='|'+='|'-='|'*='|'/='|'%='|'&='|'|='|'^='|'<<='|'>>=';
// 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);