aboutsummaryrefslogtreecommitdiff
path: root/docs/SYNTAX.md
blob: ecf7c6d9380e2872fd8e9dd8f3f8a030b991eafd (plain) (blame)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Syntax: A Casual and Formal Look

...

## A Formal Look

We now shall take a look at a more formal description of Puck's syntax. Syntax rules are described in extended Backus–Naur form (EBNF) - but most rules surrounding whitespace, and scope, and line breaks, are modified to how they would appear after a lexing step (whitespace is removed, line breaks are normalized, scope is switched to use `{` and `}`).

### Identifiers
```
IDENT  ::= LETTER (LETTER | DIGIT | '_')*
LETTER ::= 'A'..'Z' | 'a'..'z' | '\x80'..'\xff' # todo
DIGIT  ::= '0'..'9'
```

### Literals
```
INT_LIT ::= '-'? (DEC_LIT | HEX_LIT | OCT_LIT | BIN_LIT)
BIN_LIT ::= '0b' BIN_DIGIT ('_'? BIN_DIGIT)*
OCT_LIT ::= '0o' OCT_DIGIT ('_'? OCT_DIGIT)*
HEX_LIT ::= '0x' HEX_DIGIT ('_'? HEX_DIGIT)*
DEC_LIT ::= DIGIT ('_'? DIGIT)*
BIN_DIGIT ::= '0'..'1'
OCT_DIGIT ::= '0'..'7'
HEX_DIGIT ::= DIGIT | 'A'..'F' | 'a'..'f'
```

### Operators
```
OPERATOR ::= 'and' | 'or' | 'not' | 'xor' | 'shl' | 'shr' | # todo: more?
             'div' | 'mod' | 'rem' | 'is' | 'isnot' | OPR+
OPR ::= '=' | '+' | '-' | '*' | '/' | '<' | '>' | # todo: more?
        '@' | '$' | '~' | '&' | '%' | '|' |
        '!' | '?' | '^' | '.' | ':' | '\\'
```

### Chars, Strings, and Comments
```
CHAR    ::= '\'' (PRINT - '\'' | '\\\'')* '\''
STRING  ::= SINGLE_LINE_STRING | MULTI_LINE_STRING
COMMENT ::= SINGLE_LINE_COMMENT | MULTI_LINE_COMMENT | EXPRESSION_COMMENT
SINGLE_LINE_STRING  ::= '"' (PRINT - '"' | '\\"')* '"'
MULTI_LINE_STRING   ::= '"""' (PRINT | '\n' | '\r')* '"""'
SINGLE_LINE_COMMENT ::= '#' PRINT*
MULTI_LINE_COMMENT  ::= '#[' (PRINT | '\n' | '\r' | MULTI_LINE_COMMENT)* ']#'
EXPRESSION_COMMENT  ::= '#;' SINGLE_STMT
PRINT ::= LETTER | DIGIT | OPR |
          '"' | '#' | "'" | '(' | ')' | # notably the dual of OPR
          ',' | ';' | '[' | ']' | '_' |
          '`' | '{' | '}' | ' ' | '\t'
```

### Values
```
VALUE ::= INT_LIT | STRING | CHAR |
LIST_DECL   ::= '[' (EXPR (',' EXPR)*)? ']'
ARRAY_DECL  ::= '[' (EXPR (',' EXPR)*)? ']'
TUPLE_DECL  ::= '(' (IDENT '=')? EXPR (',' (IDENT '=')? EXPR)* ')'
STRUCT_DECL ::= '{' IDENT '=' EXPR (',' IDENT '=' EXPR)* '}'
# note: no union or enum. should struct exist? only in a structural system.
```

### Variables
```
DECL       ::= LET_DECL | VAR_DECL | CONST_DECL
LET_DECL   ::= 'let' GROUP (':' TYPE_DESC)? '=' EXPR
VAR_DECL   ::= 'var' GROUP (':' TYPE_DESC)? ('=' EXPR)?
CONST_DECL ::= 'pub'? 'const' GROUP (':' TYPE_DESC)? '=' EXPR
GROUP      ::= ('(' IDENT (',' IDENT)* ')') | IDENT
```

## Types and Functions
```
FUNC_DECL ::= SIGNATURE '=' (EXPR | STMT)
SIGNATURE ::= 'pub'? ('pure' | 'yeet' | IDENT)? 'func' IDENT
              ('(' (PARAMETER (',' PARAMETER)?)? ')')?
              (':' TYPE_DESC)?
PARAMETER ::= (IDENT (':' ('var' | 'static')? TYPE_DESC)?
```

```
TYPE_DECL   ::= 'pub'? 'type' IDENT '=' 'ref'? 'distinct'? TYPE_DESC
TYPE_DESC   ::= TUPLE_TYPE | STRUCT_TYPE | UNION_TYPE | ENUM_TYPE | INTERFACE | IDENT
TUPLE_TYPE  ::= 'tuple' '[' (IDENT ':')? TYPE_DESC (',' (IDENT ':')? TYPE_DESC)* ']'
STRUCT_TYPE ::= 'struct' '[' 'pub'? IDENT ':' TYPE_DESC' (',' 'pub'? IDENT ':' 'TYPE_DESC')* ']'
# note: pub in structs conflicts w/ a structural system
UNION_TYPE  ::= 'union'  '[' IDENT ':' TYPE_DESC' (',' IDENT ':' 'TYPE_DESC')* ']'
ENUM_TYPE   ::= 'enum' '[' IDENT ('=' EXPR)? (',' IDENT ('=' EXPR)?)* ']'
FUNC_TYPE   ::= 'func' ('(' (PARAMETER (',' PARAMETER)?)? ')')? (':' TYPE_DESC)?
INTERFACE   ::= 'interface' '[' SIGNATURE (',' SIGNATURE)* ('for' TYPE_DESC)? ']'
```

## Control Flow
```
IF_EXPR    ::= 'if' EXPR ':' EXPR ('elif' EXPR ':' EXPR)* 'else' ':' EXPR
IF_STMT    ::= 'if' EXPR ':' STMT ('elif' EXPR ':' STMT)* ('else' ':' STMT)?
WHEN_EXPR  ::= 'when' EXPR ':' EXPR ('else' ':' EXPR)?
WHEN_STMT  ::= 'when' EXPR ':' STMT ('else' ':' STMT)?
BLOCK_EXPR ::= 'block' IDENT? ':' EXPR
BLOCK_STMT ::= 'block' IDENT? ':' STMT
MATCH_EXPR ::= 'match' EXPR ':'
               ('case' EXPR ('where' EXPR)? (',' EXPR ('where' EXPR)?)* ':' EXPR)+
MATCH_STMT ::= 'match' EXPR ':'
               ('case' EXPR ('where' EXPR)? (',' EXPR ('where' EXPR)?)* ':' STMT)+
LOOP_STMT  ::= 'loop' ':' STMT
WHILE_STMT ::= 'while' EXPR ':' STMT
FOR_STMT   ::= 'for' GROUP 'in' EXPR ':' STMT
```

## Modules
```
IMPORT_STMT ::= 'import' IDENT? ('/' (IDENT | '[' (IDENT (',' IDENT)*)? ']'))*
EXPORT_STMT ::= 'export' IDENT? ('/' (IDENT | '[' (IDENT (',' IDENT)*)? ']'))*
MODULE_STMT ::= 'module' IDENT ':' STMT
```

## Macros
```
MACRO_FUNC  ::= IDENT '(' EXPR ')'
MACRO_BLOCK ::= IDENT ':' EXPR # todo
```

## Calls, Statements, and Expressions
```
OPERATION   ::= EXPR OPERATOR EXPR
PREFIX      ::= OPERATOR EXPR
SUFFIX      ::= EXPR OPERATOR
APPLICATION ::= IDENT EXPR | IDENT PARAMS? | (IDENT | APPLICATION) '.' IDENT PARAMS?
PARAMS      ::= '(' ((IDENT '=')? EXPR (',' (IDENT '=')? EXPR)*)? ')'
```

```
STMT        ::= SINGLE_STMT | STMT+
SINGLE_STMT ::= IF_STMT | WHEN_STMT | BLOCK_STMT | MATCH_STMT |
                LOOP_STMT | WHILE_STMT | FOR_STMT |
                IMPORT_STMT | EXPORT_STMT | MODULE_STMT |
                TYPE_DECL | FUNC_DECL | (EXPR ';')
EXPR        ::= IF_EXPR | WHEN_EXPR | BLOCK_EXPR | MATCH_EXPR |
                MACRO_FUNC | MACRO_BLOCK |
                VALUE | APPLICATION | (STMT EXPR)
```