summaryrefslogtreecommitdiff
path: root/src/parser/grammar.peggy
blob: 1d1f142cf30cef95262279f06251614f32c15046 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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]