Initial Commit
This commit is contained in:
121
src/main.rs
Normal file
121
src/main.rs
Normal 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user