Skip to content

Commit

Permalink
#4 [doc] added grammar and spec draft
Browse files Browse the repository at this point in the history
  • Loading branch information
vityaman committed Dec 10, 2023
1 parent 3d68b2d commit 84bb811
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,6 @@ cython_debug/

# Ruff
.ruff_cache

# ANTLR
.antlr/
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,13 @@
"editor.insertSpaces": true,
"editor.tabSize": 4,
},
"antlr4.format": {
"columnLimit": 80,
"tabWidth": 4,
"useTab": false,
"alignColons": "hanging",
"alignSemicolons": "hanging",
"breakBeforeParens": false,
"breakBeforeBraces": false,
},
}
130 changes: 130 additions & 0 deletions doc/lang/sleepy.g4
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
grammar sleepy;

WS
: [ \r\n\t]+ -> skip
;

program
: expression+ EOF
;

expression
: atomic
| lambda
| ifExpression
| variableDefinition
| application
;

atomic
: SYMBOL
| INTEGER
| STRING
;

application
: LCURL expression expression* RCURL
;

ifExpression
: LCURL IF expression expression expression RCURL
;

variableDefinition
: LCURL DEF SYMBOL expression RCURL
;

lambda
: LCURL LAMBDA LCURL lambdaParameter* RCURL expression+ RCURL
;

lambdaParameter
: SYMBOL SYMBOL
;

SYMBOL
: LETTER+
;

INTEGER
: ZERO
| SIGN? NON_ZERO_DIGIT DIGIT*
;

STRING
: QUOTE STRING_ATOM* QUOTE
;

STRING_ATOM
: [a-zA-Z0-9 .,!?]
;

SIGN
: MINUS
| PLUS
;

LETTER
: [a-z]
;

DIGIT
: ZERO
| NON_ZERO_DIGIT
;

NON_ZERO_DIGIT
: [1-9]
;

ZERO
: '0'
;

QUOTE
: '"'
;

LAMBDA
: 'lambda'
;

IF
: 'if'
;

DEF
: 'def'
;

LCURL
: '('
;

RCURL
: ')'
;

MINUS
: '-'
;

PLUS
: '+'
;

SPACE
: ' '
;

COMMA
: ','
;

DOT
: '.'
;

COMMENT_OUT
: ';'
;
244 changes: 244 additions & 0 deletions doc/lang/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
# Sleepy Language Specification

## Table of contents

- [Sleepy Language Specification](#sleepy-language-specification)
- [Table of contents](#table-of-contents)
- [Introduction](#introduction)
- [Syntax](#syntax)
- [Types](#types)
- [Bool](#bool)
- [Integer](#integer)
- [String](#string)
- [Lambda](#lambda)
- [Definitions](#definitions)
- [Intrinsics](#intrinsics)
- [Logical operators](#logical-operators)
- [Integer Comparisons](#integer-comparisons)
- [Input](#input)
- [Output](#output)
- [Examples](#examples)
- [Problem 1](#problem-1)
- [Problem 2](#problem-2)

## Introduction

## Syntax

Grammar expressed in ANTLR4 notation can be found
in [`sleepy.g4`](./sleepy.g4).

There are inline comments supported via `;` keyword.

## Types

This section explains all core types of
the Sleepy Language: Integer, String
and Lambda.

### Bool

```scheme
true
false
```

### Integer

Integer number. It is an immutable type.
Literal can be prefixed with a sign
'+' or '-'. Type is written as `int`.

Example of **valid** integer literals:

```scheme
123 0 9987658754345689098765
+123 1 -9987658754345689098765
-123 -1
```

Example of **invalid** integer literals:

```scheme
-0 01 -01231
+0 001 +01231
```

Usage:

```scheme
(eq (sum 2 2) 4)
(eq (sum 2 -2) 0)
(def a (sum a 1))
```

### String

String is a an immutable list of
characters. Type is written as
`string`.

Example of **valid** strings:

```scheme
"ITMO University."
"Sleepy 1.0.0 is coming!"
"" "a" "."
"Hello, World?!"
```

Example of **invalid** strings:

```scheme
"lalala
oqoqq"
"
"""
```

Usage:

```scheme
(print "Hello, CArch!")
```

### Lambda

Lamda is a function. It is a value,
so you can store it in your variable.
Closures are not supported yet or maybe
even would not ever due to feature
of calling itself, as it is hard to
come up with an idea how to capture
environment.

Lambda call itself to make a recusive call
using keyword `self`.

Last expression in labda body is
return expression.

Example of **valid** lambdas:

```scheme
(lambda (x int) (sum x 1))
(lambda (y int z int) (sum x y))
(lambda (x int)
(if (eq x 1)
1
(mul x (self (sum x -1)))))
```

## Definitions

Variable definition associates a
name with a specific value. Variables
are immutable and can be defined only
once. But they can be redefined.

Usage:

```scheme
(def x 1)
(def hello "Wake up, Sleepy")
(def is_even (lambda (n int)
(eq (rem n 2) 0)))
(def inc (lambda (n int) (sum n 1)))
```

## Intrinsics

Intrinsics special are functions
that are implemented via compiler.

### Logical operators

```scheme
(not false)
(or true false)
(and true true)
```

### Integer Comparisons

```scheme
(eq 4 4)
(lt 1 2)
```

### Input

```scheme
(def a (input))
```

### Output

```scheme
(print "Hello, World!")
```

## Examples

### Problem 1

If we list all the natural numbers
below 10 that are multiples of 3 or 5,
we get 3, 5, 6 and 9. The sum of these
multiples is 23.
Find the sum of all the multiples of 3
or 5 below 1000.

```scheme
(def result (
(lambda (number int)
(sum
(if (eq (rem number 3))
number
(if (eq (rem number 5)
number
0)))
(if (not (eq number 0))
(self (sum number -1))
0)))
(sum 1000 -1)))
```

### Problem 2

Each new term in the Fibonacci sequence is
generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms
will be: 1, 2, 3, 5, 8, 13, 21, 34, 55,
89, ...
By considering the terms in the Fibonacci
sequence whose values do not exceed four
million, find the sum of the even-valued
terms.

```scheme
(def fibb (lambda (n int)
(if (or (eq n 0) (eq n 1))
1
(sum
(self (sum n -1))
(self (sum n -2))))))
(def iseven (lambda (x int)
(eq (rem x 2) 0)))
(def sumfrom (lambda (n int)
(def current
(fibb n))
(def addition
(if (iseven current) current 0))
(def hasnext
(lt current 4000000000))
(def next
(if hasnext (self (sum n +1)) 0))
(sum next addition)))
(def x (input))
(def r (sumfrom x))
(print r)
```

0 comments on commit 84bb811

Please sign in to comment.