Program = (Statement / _)* end:PROGRAM_END _? Statement = Definition / Expression Definition = EnumDefinition / InterfaceDefinition / FunctionDefinition Expression = BinaryExpression / UnaryExpression / Literal Literal = String / Integer / Float / StructInit / Identifier String = '"' chars:((![\\"]. / "\\\"")*) '"' { return chars.map(([_, match]) => match).join(""); } Integer = digits:[0-9]+ !'.' { return parseInt(digits.join(''), 10); } Float = digits:[0-9]+ '.' fractionalDigits:[0-9]+ { return parseFloat(digits.join('') + '.' + fractionalDigits.join('')); } StructInit = STRUCT_START _ SCOPE_START _ init:Declaration+ _ SCOPE_END Declaration = VarDeclaration / FunctionDefinition VarDeclaration = VAR_DEF _ name:CAMEL_CASE _ VAR_CONT _ Type _ val:(option:OptionMatch / "OF" _ expr:Expression)? OptionMatch = "WHO" _ "IS" _ "DATING" _ SCOPE_START _ (some:SomeMatch _ none:NoneMatch) / (none:NoneMatch _ some:SomeMatch) _ SCOPE_END SomeMatch = "Someone" LPAREN name:Identifier RPAREN _ "SO" _ expr:Expression NoneMatch = "Nobody" _ "SO" _ expr:Expression // recursion here after removing LPAREN - maybe move to prefix notation? BinaryExpression = LPAREN left:Expression _ op:BinaryOperation _ right:Expression BinaryOperation = ArithmeticOperation / ComparisonOperation / BooleanOperation ArithmeticOperation = "PLUS" / "MINUS" / "DIVIDED BY" / "REMAINDER" / "TIMES" / "TO THE POWER OF" / "MOVED A BIT RIGHT" / "MOVED A BIT LEFT" / "IS WITH" / "MASKED BY" ComparisonOperation = "LESS THAN" / "GREATER THAN" / "IS NOT EQUAL TO" / "IS EQUAL TO" / "LESS THAN OR EQUAL" / "GREATER THAN OR EQUAL" BooleanOperation = "OR" / "AND" UnaryExpression = PrefixOperation Expression / LPAREN Expression PostfixOperation PrefixOperation = "!" / "~" PostfixOperation = LBRACKET _? index:PositiveInteger _? RBRACKET EnumDefinition = ENUM_DEF _ name:PASCAL_CASE _ ENUM_CONT _ SCOPE_START _ options:EnumBody+ _ SCOPE_END EnumBody = name:Identifier "," InterfaceDefinition = INTERFACE_DEF _ name:PASCAL_CASE _ INTERFACE_CONT _ signatures:FunctionSignature* _ SCOPE_END FunctionDefinition = FunctionSignature _ SCOPE_START _ body:Expression* _ SCOPE_END FunctionSignature = FUNCTION_DEF _ name:CAMEL_CASE _ (FUNCTION_DEF_ARGS _ args:FunctionArgsList _)? FUNCTION_RETURN_TYPE _ result:Type FunctionArgsList = (type:Type _ name:CAMEL_CASE _? "," _?)? type:Type _ name:CAMEL_CASE Type = name:PASCAL_CASE (_ generic:Generic)? / TupleType / UnionType TupleType = tupleType:PASCAL_CASE _? LBRACKET _? tupleLength:PositiveInteger _? RBRACKET UnionType = firstType:PASCAL_CASE _ TYPE_UNION _ secondType:(UnionType / Type) Generic = LPAREN _? generic:((Type _? COMMA _?)* Type _?) RPAREN Identifier = !KEYWORD name:(PASCAL_CASE / CAMEL_CASE) { return { name }; } PASCAL_CASE = [A-Z](LETTER / DIGIT / SAFE_SYMBOL)+ CAMEL_CASE = [a-z](LETTER / DIGIT / SAFE_SYMBOL)+ PositiveInteger = [1-9][0-9]* KEYWORD = TYPE_UNION / FUNCTION_DEF / FUNCTION_DEF_ARGS / FUNCTION_RETURN_TYPE / INTERFACE_DEF / INTERFACE_CONT / ENUM_DEF / ENUM_CONT / STRUCT_START / SCOPE_START / SCOPE_END / PROGRAM_END / ArithmeticOperation / BinaryOperation / BooleanOperation TYPE_UNION = "OR" FUNCTION_DEF = "DISCOVER" _ "HOW" _ "TO" FUNCTION_DEF_ARGS = "WITH" FUNCTION_RETURN_TYPE = "GIVES" _ "YOU" INTERFACE_DEF = "STUFF" _ "OF" INTERFACE_CONT = "LOOKS" _ "LIKE" ENUM_DEF = "ONLY" _ "OPTIONS" _ "OF" ENUM_CONT = "ARE" STRUCT_START = "STUFF" _ "MADE" _ "OF" VAR_DEF = "EXPERTS" _ "CLAIM" VAR_CONT = "TO" _ "BE" SCOPE_START = "RUMOR" _ "HAS" _ "IT" SCOPE_END = "END" _ "OF" _ "STORY" PROGRAM_END = "PLEASE" _ "LIKE" _ "AND" _ "SUBSCRIBE" COMMA = "," LBRACKET = "[" RBRACKET = "]" LPAREN = "(" RPAREN = ")" _ = (" " / "\n" / "\t" / "\r\n")+ LETTER = [A-Za-z] SAFE_SYMBOL = "_" DIGIT = [0-9]