Simple repl

trunk
Alona EM 2021-12-16 20:30:28 +00:00
parent 066e5d03e0
commit eb7a236720
6 changed files with 816 additions and 494 deletions

218
Cargo.lock generated
View File

@ -73,6 +73,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -88,6 +94,17 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "clipboard-win"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3db8340083d28acb43451166543b98c838299b7e0863621be53a338adceea0ed"
dependencies = [
"error-code",
"str-buf",
"winapi",
]
[[package]] [[package]]
name = "const-random" name = "const-random"
version = "0.1.13" version = "0.1.13"
@ -116,6 +133,23 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "debug2"
version = "0.1.0"
dependencies = [
"debug2-derive",
]
[[package]]
name = "debug2-derive"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]] [[package]]
name = "diff" name = "diff"
version = "0.1.12" version = "0.1.12"
@ -158,6 +192,33 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "error-code"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff"
dependencies = [
"libc",
"str-buf",
]
[[package]]
name = "fd-lock"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a16910e685088843d53132b04e0f10a571fdb193224fc589685b3ba1ce4cb03d"
dependencies = [
"cfg-if",
"libc",
"windows-sys",
]
[[package]] [[package]]
name = "fixedbitset" name = "fixedbitset"
version = "0.2.0" version = "0.2.0"
@ -186,9 +247,12 @@ name = "handball"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chumsky", "chumsky",
"debug2",
"lalrpop", "lalrpop",
"lalrpop-util", "lalrpop-util",
"logos", "logos",
"rustyline",
"rustyline-derive",
] ]
[[package]] [[package]]
@ -326,12 +390,43 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "new_debug_unreachable" name = "new_debug_unreachable"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nibble_vec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
dependencies = [
"smallvec",
]
[[package]]
name = "nix"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"memoffset",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -412,6 +507,16 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "radix_trie"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
dependencies = [
"endian-type",
"nibble_vec",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.10" version = "0.2.10"
@ -454,6 +559,40 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
[[package]]
name = "rustyline"
version = "9.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c38cfbd0a4d7df7aab7cf53732d5d43449d0300358fd15cd4e8c8468a956aca"
dependencies = [
"bitflags",
"cfg-if",
"clipboard-win",
"dirs-next",
"fd-lock",
"libc",
"log",
"memchr",
"nix",
"radix_trie",
"scopeguard",
"smallvec",
"unicode-segmentation",
"unicode-width",
"utf8parse",
"winapi",
]
[[package]]
name = "rustyline-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb35a55ab810b5c0fe31606fe9b47d1354e4dc519bec0a102655f78ea2b38057"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@ -472,6 +611,12 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "str-buf"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
[[package]] [[package]]
name = "string_cache" name = "string_cache"
version = "0.8.2" version = "0.8.2"
@ -496,6 +641,18 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]] [[package]]
name = "term" name = "term"
version = "0.7.0" version = "0.7.0"
@ -516,6 +673,18 @@ dependencies = [
"crunchy", "crunchy",
] ]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.2"
@ -528,6 +697,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
[[package]]
name = "utf8parse"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
@ -555,3 +730,46 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
[[package]]
name = "windows_i686_gnu"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
[[package]]
name = "windows_i686_msvc"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
[[package]]
name = "windows_x86_64_gnu"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
[[package]]
name = "windows_x86_64_msvc"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"

View File

@ -7,8 +7,11 @@ edition = "2021"
[dependencies] [dependencies]
chumsky = "0.6.0" chumsky = "0.6.0"
lalrpop-util = "0.19.6" lalrpop-util = { version = "0.19.6", features = ["lexer"] }
logos = "0.12.0" logos = "0.12.0"
debug2 = {path="../debug2"}
rustyline = "9.1.1"
rustyline-derive = "0.6.0"
[build-dependencies] [build-dependencies]
lalrpop = "0.19.6" lalrpop = "0.19.6"

View File

@ -1,33 +1,12 @@
use crate::{Token, Tree, Val}; use crate::Tree;
grammar<'s>(); grammar<'s>();
pub(crate) Trees = Tree*; pub Tree: Tree = {
"(" "+" <Tree*> ")" => Tree::Add(<>),
Tree: Tree<'s> = { "(" "-" <Tree+> ")" => Tree::Sub(<>),
"(" <Trees> ")" => Tree::Branch(<>), "(" "*" <Tree*> ")" => Tree::Mul(<>),
Val => Tree::Leaf(<>) "(" "/" <Tree+> ")" => Tree::Div(<>),
r"[0-9]+(\.[0-9]+)?" => Tree::Val(<>.parse().unwrap()),
}
Val: Val<'s> = {
"@int" => Val::Int(<>),
"@float" => Val::Float(<>),
"@id" => Val::Ident(<>),
}
extern {
type Location = usize;
type Error = crate::LexError;
enum Token<'s> {
"(" => Token::Lparen,
")" => Token::Rparen,
"@id" => Token::Ident(<&'s str>),
"@int" => Token::Int(<i64>),
"@float" => Token::Float(<f64>),
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,130 +1,63 @@
use logos::Logos;
mod grammar; mod grammar;
#[derive(Logos, Debug, PartialEq)] use debug2::dbg;
enum LogosToken {
#[regex(r"[0-9]+", priority = 2)]
Int,
#[regex(r"[0-9]+(\\.[0-9]+)?")] #[derive(Debug, debug2::Debug, PartialEq)]
Float, pub enum Tree {
Val(f64),
#[regex(r"[A-Za-z0-9!$%&*+\-./:<=>?@^_~]+")] Add(Vec<Tree>),
Ident, Sub(Vec<Tree>),
Mul(Vec<Tree>),
#[error] Div(Vec<Tree>),
#[regex(r"[ \t\n\f]+", logos::skip)]
Error,
#[token(r"(")]
Lparen,
#[token(r")")]
Rparen,
}
#[derive(Debug)]
pub struct LexError;
type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
struct Lexer<'a>(logos::Lexer<'a, LogosToken>);
impl<'a> Lexer<'a> {
fn new(src: &'a str) -> Self {
Self(LogosToken::lexer(src))
}
} }
#[derive(Clone, Debug)] use rustyline::validate::{
pub enum Token<'s> { MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
Int(i64),
Float(f64),
Ident(&'s str),
Lparen,
Rparen,
}
impl<'a> Iterator for Lexer<'a> {
type Item = Spanned<Token<'a>, usize, LexError>;
fn next(&mut self) -> Option<Self::Item> {
let kind = self.0.next()?;
let span = self.0.span();
let text = self.0.slice();
let t = match kind {
LogosToken::Int => Token::Int(text.parse().unwrap()),
LogosToken::Float => Token::Float(text.parse().unwrap()),
LogosToken::Ident => Token::Ident(text),
LogosToken::Lparen => Token::Lparen,
LogosToken::Rparen => Token::Rparen,
LogosToken::Error => return Some(Err(LexError)),
}; };
use rustyline::{Editor, Result};
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
Some(Ok((span.start, t, span.end))) #[derive(Completer, Helper, Highlighter, Hinter)]
} struct InputValidator {
brackets: MatchingBracketValidator,
} }
#[derive(Clone, Debug)] impl Validator for InputValidator {
pub enum Tree<'s> { fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
Leaf(Val<'s>), self.brackets.validate(ctx)
Branch(Vec<Tree<'s>>),
}
#[derive(Clone, Debug)]
pub enum Val<'s> {
Int(i64),
Float(f64),
Ident(&'s str),
}
enum Func {}
enum RVal {
Func(Func),
Num(f64),
}
enum Op {
Push(RVal),
Call(u8),
Print,
}
fn comp_to(t: &Tree)
fn eval(t: &Tree<'_>) -> f64 {
match t {
Tree::Leaf(Val::Ident(_)) => panic!("Need number got {:?}", t),
Tree::Leaf(Val::Float(f)) => *f,
Tree::Leaf(Val::Int(i)) => *i as f64,
Tree::Branch(v) => {
if let Tree::Leaf(Val::Ident(f)) = v[0] {
match f {
"min" => v[1..].iter().map(eval).reduce(f64::min).unwrap(),
"max" => v[1..].iter().map(eval).reduce(f64::max).unwrap(),
"+" => v[1..].iter().map(eval).sum(),
"*" => v[1..].iter().map(eval).product(),
"/" => eval(&v[1]) / v[2..].iter().map(eval).product::<f64>(),
"-" => eval(&v[1]) - v[2..].iter().map(eval).sum::<f64>(),
_ => panic!("Unknown func {:?}", f),
}
} else {
panic!("Not a function")
}
}
} }
} }
fn main() { fn main() {
let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(); // let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap();
let tree = grammar::TreesParser::new().parse(Lexer::new(&src)); // let tree = grammar::TreeParser::new().parse(&src);
let t = dbg!(tree).unwrap(); // let t = dbg!(tree.unwrap());
dbg!(eval(&t[0])); // println!("{}", eval(&t));
let mut rl = Editor::new();
rl.set_helper(Some(InputValidator {
brackets: MatchingBracketValidator::new(),
}));
while let Ok(line) = rl.readline("> ") {
rl.add_history_entry(&line);
let tree = grammar::TreeParser::new().parse(&line).unwrap();
dbg!(&tree);
println!("< {}", eval(&tree))
}
}
fn eval(t: &Tree) -> f64 {
match t {
Tree::Val(v) => *v,
Tree::Add(vs) => vs.iter().map(eval).sum(),
Tree::Mul(vs) => vs.iter().map(eval).product(),
Tree::Sub(vs) => eval(&vs[0]) - vs[1..].iter().map(eval).sum::<f64>(),
Tree::Div(vs) => eval(&vs[0]) / vs[1..].iter().map(eval).product::<f64>(),
}
} }
#[cfg(test)] #[cfg(test)]
@ -132,15 +65,42 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn math_exprs() { fn simple_math_space() {
fn test(s: &str, v: f64) { let t = grammar::TreeParser::new()
let tree = grammar::TreesParser::new().parse(Lexer::new(s)).unwrap(); .parse("( + 1 2 ( / 2 3 4 5) )")
assert_eq!(tree.len(), 1); .unwrap();
assert_eq!(eval(&tree[0]), v); assert_eq!(
t,
Tree::Add(vec![
Tree::Val(1.0),
Tree::Val(2.0),
Tree::Div(vec![
Tree::Val(2.0),
Tree::Val(3.0),
Tree::Val(4.0),
Tree::Val(5.0),
])
])
);
} }
test("1", 1.0); #[test]
test("(+ 1 2)", 3.0); fn simple_math_dence() {
test("(+ 1 2 (/ 2 3 4 5))", 3.033333333333333); let t = grammar::TreeParser::new()
.parse("(+ 1 2 (/ 2 3 4 5))")
.unwrap();
assert_eq!(
t,
Tree::Add(vec![
Tree::Val(1.0),
Tree::Val(2.0),
Tree::Div(vec![
Tree::Val(2.0),
Tree::Val(3.0),
Tree::Val(4.0),
Tree::Val(5.0),
])
])
);
} }
} }