mirror of
https://github.com/Noratrieb/dilaria.git
synced 2026-01-14 17:35:03 +01:00
started lexer
This commit is contained in:
parent
3eeafb574c
commit
0f7999cc0f
4 changed files with 295 additions and 0 deletions
142
README.md
Normal file
142
README.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
_ is a small embeddable scripting language
|
||||
|
||||
_ is inspired by Javascript, Lox, Lua, Python, Rust and more
|
||||
|
||||
# Reference
|
||||
|
||||
## Overview
|
||||
|
||||
Declaring variables using `let`
|
||||
|
||||
```
|
||||
let hello = 4
|
||||
```
|
||||
|
||||
Semicolons are not needed
|
||||
|
||||
```
|
||||
let test = 5
|
||||
let another = 4
|
||||
```
|
||||
|
||||
The language has strings, numbers, arrays, objects and null and booleans
|
||||
|
||||
```
|
||||
let string = "hallo"
|
||||
let number = 4
|
||||
let array = []
|
||||
let object = {}
|
||||
let _null = null
|
||||
let bool = true
|
||||
```
|
||||
|
||||
You access properties on objects using `.`
|
||||
|
||||
```
|
||||
let obj = {}
|
||||
obj.hi = "hi!"
|
||||
```
|
||||
|
||||
Functions are first class
|
||||
|
||||
```
|
||||
let obj = {}
|
||||
obj.hello = helloFn
|
||||
obj.hello()
|
||||
```
|
||||
|
||||
Functions are declared using `fn`
|
||||
|
||||
```
|
||||
fn greet(name) {
|
||||
return "hello, " + name
|
||||
}
|
||||
```
|
||||
|
||||
Comments using `#`
|
||||
```
|
||||
# hi!
|
||||
```
|
||||
|
||||
There are many native functions, that can easily be customized and added/removed by the host
|
||||
|
||||
```
|
||||
# rocket game
|
||||
turnRocketLeft(29)
|
||||
turnRocketRight(32)
|
||||
|
||||
# chat bot
|
||||
message.respond("hi")
|
||||
|
||||
# dangerous http requests
|
||||
fn callback(html) {
|
||||
print(html)
|
||||
}
|
||||
fetch("https://github.com/Nilstrieb", callback);
|
||||
```
|
||||
|
||||
Basic arithmetic and boolean logic is available
|
||||
|
||||
```
|
||||
let a = 5
|
||||
let b = 5
|
||||
print(a + b / b * b - a % b)
|
||||
print(true and false or false or true and false)
|
||||
```
|
||||
|
||||
Loops and conditionals
|
||||
|
||||
```
|
||||
let x = true
|
||||
if x {
|
||||
print("true!")
|
||||
} else {
|
||||
print("false :(")
|
||||
}
|
||||
|
||||
loop {
|
||||
while 1 > 5 {
|
||||
print("yeet")
|
||||
break
|
||||
}
|
||||
# no for loops for now, but will be added (probably like python)
|
||||
}
|
||||
```
|
||||
|
||||
_ is dynamically and *strongly* typed
|
||||
|
||||
## Detail
|
||||
|
||||
### Reserved Keywords
|
||||
|
||||
#### Statements
|
||||
`fn`
|
||||
`let`
|
||||
`if`
|
||||
`else`
|
||||
`loop`
|
||||
`while`
|
||||
`for`
|
||||
|
||||
#### Values
|
||||
`true`
|
||||
`false`
|
||||
`null`
|
||||
|
||||
#### Operators
|
||||
`not`
|
||||
`and`
|
||||
`or`
|
||||
|
||||
### Operators
|
||||
`==`
|
||||
`>=`
|
||||
`>`
|
||||
`<=`
|
||||
`<`
|
||||
`!=`
|
||||
`+`
|
||||
`-`
|
||||
`*`
|
||||
`/`
|
||||
`%`
|
||||
145
src/lex.rs
Normal file
145
src/lex.rs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::iter::Peekable;
|
||||
use std::str::CharIndices;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
|
||||
struct Span(usize);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Token<'code> {
|
||||
span: Span,
|
||||
kind: TokenType<'code>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TokenType<'code> {
|
||||
// keywords
|
||||
Let,
|
||||
Fn,
|
||||
If,
|
||||
Else,
|
||||
Loop,
|
||||
While,
|
||||
For,
|
||||
True,
|
||||
False,
|
||||
Null,
|
||||
And,
|
||||
Or,
|
||||
Not,
|
||||
// literals
|
||||
String(&'code str),
|
||||
Number(f64),
|
||||
// ident
|
||||
Ident(&'code str),
|
||||
// punctuation
|
||||
/// +
|
||||
Plus,
|
||||
/// -
|
||||
Minus,
|
||||
/// *
|
||||
Asterisk,
|
||||
/// /
|
||||
Slash,
|
||||
/// %
|
||||
Percent,
|
||||
/// {
|
||||
BraceO,
|
||||
/// }
|
||||
BraceC,
|
||||
/// [
|
||||
BracketO,
|
||||
/// ]
|
||||
BracketC,
|
||||
/// (
|
||||
ParenO,
|
||||
/// )
|
||||
ParenC,
|
||||
/// .
|
||||
Dot,
|
||||
/// ,
|
||||
Comma,
|
||||
// =
|
||||
Equal,
|
||||
/// ==
|
||||
EqualEqual,
|
||||
/// !=
|
||||
BangEqual,
|
||||
/// >
|
||||
GreaterThan,
|
||||
/// <
|
||||
LessThan,
|
||||
/// >=
|
||||
GreaterThanEqual,
|
||||
/// <=
|
||||
LessThanEqual,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Lexer<'code> {
|
||||
code: Peekable<CharIndices<'code>>,
|
||||
state: LexState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum LexState {
|
||||
Init,
|
||||
StrLit(usize),
|
||||
NumLit(usize),
|
||||
Ident(usize),
|
||||
Equal(usize),
|
||||
Bang(usize),
|
||||
GreaterThan(usize),
|
||||
LessThan(usize),
|
||||
}
|
||||
|
||||
impl<'code> Lexer<'code> {
|
||||
pub fn lex(code: &'code str) -> Self {
|
||||
Self {
|
||||
code: code.char_indices().peekable(),
|
||||
state: LexState::Init,
|
||||
}
|
||||
}
|
||||
|
||||
fn expect(&mut self, expected: char) -> bool {
|
||||
self.code
|
||||
.peek()
|
||||
.map(|(_, char)| *char == expected)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'code> Iterator for Lexer<'code> {
|
||||
type Item = Result<Token<'code>, LexError>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.state {
|
||||
LexState::Init => match self.code.next() {
|
||||
_ => {}
|
||||
},
|
||||
LexState::StrLit(_) => {}
|
||||
LexState::NumLit(_) => {}
|
||||
LexState::Ident(_) => {}
|
||||
LexState::Equal(_) => {}
|
||||
LexState::Bang(start) => {
|
||||
return if self.expect('=') {
|
||||
let _ = self.code.next();
|
||||
Some(Ok(Token {
|
||||
span: Span(start),
|
||||
kind: TokenType::BangEqual,
|
||||
}))
|
||||
} else {
|
||||
Some(Err(LexError))
|
||||
}
|
||||
}
|
||||
LexState::GreaterThan(_) => {}
|
||||
LexState::LessThan(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LexError;
|
||||
8
src/lib.rs
Normal file
8
src/lib.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
mod lex;
|
||||
mod parse;
|
||||
|
||||
pub fn run_program(program: &str) {
|
||||
let lexer = lex::Lexer::lex(program);
|
||||
let tokens: Result<Vec<_>, _> = lexer.collect();
|
||||
println!("{:#?}", tokens);
|
||||
}
|
||||
0
src/parse.rs
Normal file
0
src/parse.rs
Normal file
Loading…
Add table
Add a link
Reference in a new issue