Initial Commit

This commit is contained in:
2025-08-28 02:26:06 -04:00
committed by Val
commit c83218d750
17 changed files with 2276 additions and 0 deletions

121
src/main.rs Normal file
View File

@@ -0,0 +1,121 @@
//! Tests the lexer
#[allow(unused_imports)]
use doughlang::{
ast::{
Expr,
matcher::{Match, Subst},
},
lexer::{LexError, Lexer},
parser::{ParseError, Parser},
span::Span,
token::{TKind, Token},
};
use repline::prebaked::*;
use std::{
error::Error,
io::{IsTerminal, stdin},
};
fn main() -> Result<(), Box<dyn Error>> {
if stdin().is_terminal() {
read_and("\x1b[32m", " >", "?>", |line| match line.trim_end() {
"" => Ok(Response::Continue),
"exit" => Ok(Response::Break),
"clear" => {
print!("\x1b[H\x1b[2J");
Ok(Response::Deny)
}
"pat" => {
if let Err(e) = subst() {
println!("\x1b[31m{e}\x1b[0m");
}
Ok(Response::Deny)
}
_ => {
parse(line);
Ok(Response::Accept)
}
})?;
} else {
let doc = std::io::read_to_string(stdin())?;
lex(&doc);
parse(&doc);
}
Ok(())
}
fn lex(document: &str) {
let mut lexer = Lexer::new(document);
loop {
match lexer.scan() {
Ok(Token { lexeme, kind, span: Span { head, tail } }) => {
println!(
"{kind:?}\x1b[11G {head:<4} {tail:<4} {}",
lexeme.escape_debug()
)
}
Err(e) => {
eprintln!("{e}");
break;
}
}
}
}
fn subst() -> Result<(), Box<dyn Error>> {
let mut rl = repline::Repline::new("\x1b[35mexp", " >", "?>");
let exp = rl.read()?;
let mut exp: Expr = Parser::new(Lexer::new(&exp)).parse(0)?;
println!("\x1b[G\x1b[J{exp}");
rl.accept();
loop {
rl.set_color("\x1b[36mpat");
let pat = rl.read()?;
rl.accept();
print!("\x1b[G\x1b[J");
let mut p = Parser::new(Lexer::new(&pat));
let Ok(pat) = p.parse::<Expr>(0) else {
println!("{exp}");
continue;
};
if p.next_if(TKind::Colon).is_err() {
let Some(Subst { exp, pat }) = exp.construct(&pat) else {
continue;
};
for (name, pat) in pat.iter() {
println!("{name}: {pat}")
}
for (name, expr) in exp.iter() {
println!("{name}: {expr}")
}
continue;
}
let sub: Expr = p.parse(0)?;
if exp.apply_rule(&pat, &sub) {
println!("{exp}");
} else {
println!("No match: {pat} in {exp}\n")
}
}
}
fn parse(document: &str) {
let mut parser = Parser::new(Lexer::new(document));
loop {
match parser.parse::<Expr>(0) {
// Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => break,
Err(e) => {
println!("\x1b[31m{e}\x1b[0m");
break;
}
Ok(v) => {
println!("{v}");
}
}
}
}