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);