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"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -88,6 +94,17 @@ dependencies = [
"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]]
name = "const-random"
version = "0.1.13"
@ -116,6 +133,23 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "diff"
version = "0.1.12"
@ -158,6 +192,33 @@ dependencies = [
"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]]
name = "fixedbitset"
version = "0.2.0"
@ -186,9 +247,12 @@ name = "handball"
version = "0.1.0"
dependencies = [
"chumsky",
"debug2",
"lalrpop",
"lalrpop-util",
"logos",
"rustyline",
"rustyline-derive",
]
[[package]]
@ -326,12 +390,43 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "parking_lot"
version = "0.11.2"
@ -412,6 +507,16 @@ dependencies = [
"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]]
name = "redox_syscall"
version = "0.2.10"
@ -454,6 +559,40 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "scopeguard"
version = "1.1.0"
@ -472,6 +611,12 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "str-buf"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
[[package]]
name = "string_cache"
version = "0.8.2"
@ -496,6 +641,18 @@ dependencies = [
"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]]
name = "term"
version = "0.7.0"
@ -516,6 +673,18 @@ dependencies = [
"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]]
name = "unicode-xid"
version = "0.2.2"
@ -528,6 +697,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
[[package]]
name = "utf8parse"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
@ -555,3 +730,46 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]
chumsky = "0.6.0"
lalrpop-util = "0.19.6"
lalrpop-util = { version = "0.19.6", features = ["lexer"] }
logos = "0.12.0"
debug2 = {path="../debug2"}
rustyline = "9.1.1"
rustyline-derive = "0.6.0"
[build-dependencies]
lalrpop = "0.19.6"

View File

@ -1,33 +1,12 @@
use crate::{Token, Tree, Val};
use crate::Tree;
grammar<'s>();
pub(crate) Trees = Tree*;
Tree: Tree<'s> = {
"(" <Trees> ")" => Tree::Branch(<>),
Val => Tree::Leaf(<>)
pub Tree: Tree = {
"(" "+" <Tree*> ")" => Tree::Add(<>),
"(" "-" <Tree+> ")" => Tree::Sub(<>),
"(" "*" <Tree*> ")" => Tree::Mul(<>),
"(" "/" <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;
#[derive(Logos, Debug, PartialEq)]
enum LogosToken {
#[regex(r"[0-9]+", priority = 2)]
Int,
use debug2::dbg;
#[regex(r"[0-9]+(\\.[0-9]+)?")]
Float,
#[regex(r"[A-Za-z0-9!$%&*+\-./:<=>?@^_~]+")]
Ident,
#[error]
#[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(Debug, debug2::Debug, PartialEq)]
pub enum Tree {
Val(f64),
Add(Vec<Tree>),
Sub(Vec<Tree>),
Mul(Vec<Tree>),
Div(Vec<Tree>),
}
#[derive(Clone, Debug)]
pub enum Token<'s> {
Int(i64),
Float(f64),
Ident(&'s str),
Lparen,
Rparen,
use rustyline::validate::{
MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
};
use rustyline::{Editor, Result};
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
#[derive(Completer, Helper, Highlighter, Hinter)]
struct InputValidator {
brackets: MatchingBracketValidator,
}
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)),
};
Some(Ok((span.start, t, span.end)))
}
}
#[derive(Clone, Debug)]
pub enum Tree<'s> {
Leaf(Val<'s>),
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")
}
}
impl Validator for InputValidator {
fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
self.brackets.validate(ctx)
}
}
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)]
@ -132,15 +65,42 @@ mod tests {
use super::*;
#[test]
fn math_exprs() {
fn test(s: &str, v: f64) {
let tree = grammar::TreesParser::new().parse(Lexer::new(s)).unwrap();
assert_eq!(tree.len(), 1);
assert_eq!(eval(&tree[0]), v);
}
fn simple_math_space() {
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),
])
])
);
}
test("1", 1.0);
test("(+ 1 2)", 3.0);
test("(+ 1 2 (/ 2 3 4 5))", 3.033333333333333);
#[test]
fn simple_math_dence() {
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),
])
])
);
}
}

View File

@ -1 +1 @@
(+ 1 2 (/ 2 3 4 5))
( + 1 2 ( / 2 3 4 5) )