## Grotsky Part 1: Syntax

#### Syntax Restrictions

• No use of semicolon ;
• Block statements delimited by begin and end
• Function definition using fn keyword
• Logic operators in plain english or, and, not
• Conditional statements use the following keywords: if, elif, else
• There is no switch statement
• Class definition with class keyword
• Arithmetic operations: *, /, -, +, ^
• Grouping with parentheses ()
• Native support for python-like lists and dictionaries: [], {}
• Support for enhanced for loop: for i, el in array
• Keywords and identifiers can only use alphabethic characters

• nil
• Integers
• Floats
• Booleans
• Strings
• Lists
• Dictionaries
• #### Example of functions and operations

```## Arithmethic
print(2^10 - 2323*3)
# Output: -5945
print(2^(12*3+400/-4+10*5/2))
# Output: 1.8189894035458565e-12

## Logic
print(true or false)
# Output: true (short circuit)
print(false and true)
# Output: false (short circuit)

## Conditionals
if 3 > 2 or (1 < 3 and 2 == 2) begin
print('Condition is true')
end
elif 3 == 4 begin
print('Condition 2 is true')
end
else begin
print('Conditions are false')
end

## Lists
for i in [1, 2, 3, 4] begin
print(i)
end

let lst = [1, 2, 3, 4]
lst[0] = -1
print(lst) # Output: [-1, 2, 3, 4]
print(lst[1:3]) # Output: [2, 3]

## Dictionaries
# (dictionaries and lists not allowed as keys)
let dct = {
"Key1": "Val1",
2: "Val2",
true: false
}
for key, val in dct begin
print(key, val)
end

## Functions
fn square(x)
begin
return x^2
end

fn operate(x, operation)
begin
return operation(x)
end

## Clojure
fn makeCounter()
begin
let n = 0
return fn() begin
n = n+1
return n
end
end

## Classes
class Counter
begin
init(start) begin
self.start = start
end
count() begin
self.start = self.start+1
return self.start
end
end

class CounterTwo
begin
count() begin
return super.count()*2
end
end
```

#### Syntax definition

Let's build a syntax definition in backus naur format that will be easy to parse with a recursive descent parser.
##### Expresions
```expression       assignment;
list             "[" arguments? "]";
dictionary       "{" dict_elements? "}";
dict_elements    keyval ("," keyval)*;
keyval           expression ":" expression;
assignment       (call ".")? IDENTIFIER "=" assignment | access;
access           logic_or ("[" slice "]")*;
logic_or         logic_and ("or" logic_and)*;
logic_and        equality ("and" equality)*;
equality         comparison (("!=" | "==") comparison)*;
addition         multiplication (("-" | "+") multiplication)*;
multiplication   power (("/" | "*") power)*;
power            unary ("^" unary)*;
unary            ("not" | "-") unary | call;
call             primary ("(" arguments? ")" | "." IDENTIFIER)*;
arguments        expression ("," expression)*;
slice            (":" expression)
| (":" expression ":" expression)
| (":" ":" expression)
| expression
| (expression ":")
| (expression ":" expression)
| (expression ":" ":" expression)
| (expression ":" expression ":" expression);
primary          NUMBER
| STRING
| "false"
| "true"
| "nil"
| IDENTIFIER
| "(" expression ")"
| fnAnon
| list
| dictionary;
fnAnon           "fn" "(" parameters? ")" block;
```
##### Statements
```program         declaration* EOF;
declaration     classDecl | funDecl | varDecl | statement;
classDecl       "class" IDENTIFIER ( "<" IDENTIFIER )? "begin" methodDecl* "end" NEWLINE;
methodDecl      "class"? function;
funDecl         "fn" function ;
function        IDENTIFIER "(" parameters? ")" block ;
parameters      IDENTIFIER ( "," IDENTIFIER )* ;
varDecl         "let" IDENTIFIER ("=" expression)? NEWLINE;
statement       forStmt
| ifStmt
| returnStmt
| whileStmt
| exprStmt
| block;
exprStmt        expression NEWLINE;
forStmt         "for"  (classicFor | newFor) statement;
classicFor      (varDecl | exprStmt | ",") expression? "," expression?;
newFor          IDENTIFIER ("," IDENTIFIER)? "in" expression;
ifStmt          "if" expression statement ("elif" expression statement)* ("else" statement)?;
returnStmt      "return" expression? NEWLINE;
whileStmt       "while" expression statement;
block           "begin" NEWLINE declaration* "end" NEWLINE;
```
That's it! The next step is to build a lexer and a parser.