aboutsummaryrefslogtreecommitdiff
path: root/docs/SYNTAX.md
blob: a1c8bfbf956fb48e8e6bbdeaaa2e926b1708903f (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
142
143
144
145
146
147
148
149
150
# Syntax: A Casual and Formal Look

## Reserved Keywords

The following keywords are reserved:
- variables: `let` `var` `const`
- control flow: `if` `elif` `else`
- pattern matching: `match` `of`
- loops: `loop` `while` `for` `in`
- blocks: `block` `break` `continue` `return`
- functions: `func` `mut` `static` `varargs`
- modules: `pub` `mod` `use` `as`
- error handling: `try` `catch` `finally`
- metaprogramming: `macro` `quote` `when`
- types: `type` `distinct` `ref`
- types: `struct` `tuple` `union` `enum` `interface`
- reserved:
  - `impl` `object` `class` `concept` `auto` `empty` `effect` `case` `nil`
  - `suspend` `resume` `spawn` `pool` `thread` `closure`
  - `cyclic` `acyclic` `sink` `move` `destroy` `copy` `trace` `deepcopy`

## A Formal Grammar

We now shall take a look at a more formal description of Puck's syntax. Syntax rules are described in [extended Backus–Naur form](https://en.wikipedia.org/wiki/Extended_Backus–Naur_form) (EBNF): however, most rules surrounding whitespace, and scope, and line breaks, are modified to how they would appear after a lexing step.

### Identifiers
```
Ident  ::= (Letter | '_') (Letter | Digit | '_')*
Letter ::= 'A'..'Z' | 'a'..'z' | '\x80'..'\xff' # todo
Digit  ::= '0'..'9'
```

### Literals
```
Int ::= '-'? (DecLit | HexLit | OctLit | BinLit)
Float ::= '-'? DecLit '.' DecLit
BinLit ::= '0b' BinDigit ('_'? BinDigit)*
OctLit ::= '0o' OctDigit ('_'? OctDigit)*
HexLit ::= '0x' HexDigit ('_'? HexDigit)*
DecLit ::= Digit ('_'? Digit)*
BinDigit ::= '0'..'1'
OctDigit ::= '0'..'7'
HexDigit ::= Digit | 'A'..'F' | 'a'..'f'
```

### 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 | Float | String | Char | Array | Tuple | Struct
Array  ::= '[' (Expr (',' Expr)*)? ']'
Tuple  ::= '(' (Ident ':')? Expr (',' (Ident ':')? Expr)* ')'
Struct ::= '{' Ident ':' Expr (',' Ident ':' Expr)* '}'
```

### Variables
```
Decl  ::= Let | Var | Const | Func | Type
Let   ::= 'let' Pattern Annotation? '=' Expr
Var   ::= 'var' Pattern Annotation? ('=' Expr)?
Const ::= 'pub'? 'const' Pattern Annotation? '=' Expr
Pattern ::= Char | String | Number | Float | Ident | '(' Pattern (',' Pattern)* ')'
            Ident '(' Pattern (',' Pattern)* ')'
```

### Declarations
```
Func  ::= 'pub'? 'func' Ident Generics? Parameters? Annotation? '=' Body
Macro ::= 'pub'? 'macro' Ident Generics? Parameters? Annotation? '=' Body
Generics   ::= '[' Ident Annotation? (',' Ident Annotation?)* ']'
Parameters ::= '(' Ident Annotation? (',' Ident Annotation?)* ')'
Annotation ::= ':' Type
```

### Types
```
TypeDecl ::= 'pub'? 'type' Ident Generics? '=' Type
Type ::= StructType | TupleType | EnumType | UnionType | Interface |
         (('distinct' | 'ref' | 'ptr' | 'mut' | 'static') (Type | ('[' Type ']'))?)
StructType ::= 'struct' ('[' Ident ':' Type (',' Ident ':' Type)* ']')?
UnionType  ::= 'union'  ('[' Ident ':' Type (',' Ident ':' Type)* ']')?
TupleType  ::= 'tuple' ('[' (Ident ':')? Type (',' (Ident ':')? Type)* ']')?
EnumType   ::= 'enum'  ('[' Ident ('=' Expr)? (',' Ident ('=' Expr)?)* ']')?
Interface ::= 'interface' ('[' Signature (',' Signature)* ']')?
Signature ::= Ident Generics? ('(' Type (',' Type)* ')')? Annotation?
```

## Control Flow
```
If    ::= 'if' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)?
When  ::= 'when' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)?
Try   ::= 'try' ':' Body
          ('except' Ident ('as' Ident)? (',' Ident ('as' Ident)?)*) ':' Body)*
          ('finally' ':' Body)?
Match ::= 'match' Expr ('of' Pattern (',' Pattern)* ('where' Expr)? ':' Body)+
Block ::= 'block' Ident? ':' Body
Block ::= 'static' ':' Body
Loop  ::= 'loop' ':' Body
While ::= 'while' Expr ':' Body
For   ::= 'for' Pattern 'in' Expr Body
```

## Modules
```
Mod ::= 'pub'? 'mod' Ident ':' Body
Use ::= 'use' Ident ('/' Ident)* ('/' ('[' Ident (',' Ident)* ']'))?
```

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

## Calls and Expressions
```
Call ::= Ident ('[' Call (',' Call)* ']')? ('(' (Ident '=')? Call (',' (Ident '=')? Call)* ')')? |
         Ident Call (',' Call)* |
         Call Operator Call? |
         Call ':' Body
Expr ::= Let | Var | Const | Func | Type | Mod | Use | Block | Static |
         For | While | Loop | If | When | Try | Match | Call
Body ::= Expr | ('{' Expr (';' Expr)* '}')
```

---

References:
- https://www.joshwcomeau.com/javascript/statements-vs-expressions/
- https://pgrandinetti.github.io/compilers/
- https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html
- https://nim-lang.github.io/Nim/manual.html