doughlang: Preserve errors through entire pipeline

lexer:
- Un-stringify errors
- Reserve more words
- Doc the comments

parser:
- MASSIVE changes to peek, peek_if, next_if, consume_if=>expect.
- Keep track of when EOF is allowable
- TKind is stupidly cheap with >100 niches, so we can fit like 4 of them in a single ParseError lmao
- TODO: make sure EOF/UnexpectedEOF propagation is correct. It seems... Kinda Not correct.
- Add meta-expressions
This commit is contained in:
2025-10-17 06:25:11 -04:00
parent c8f1f082c4
commit 6368e68941
6 changed files with 543 additions and 351 deletions

View File

@@ -9,7 +9,7 @@ use doughlang::{
Expr,
macro_matcher::{Match, Subst},
},
lexer::{LexError, Lexer},
lexer::{EOF, LexError, Lexer},
parser::{ParseError, Parser},
span::Span,
token::{TKind, Token},
@@ -73,7 +73,7 @@ fn lex() -> Result<(), Box<dyn Error>> {
}
loop {
match lexer.scan() {
Err(LexError { res: "EOF", .. }) => {
Err(LexError { res: EOF, .. }) => {
break Ok(Response::Accept);
}
Err(e) => {
@@ -97,7 +97,7 @@ fn exprs() -> Result<(), Box<dyn Error>> {
}
for idx in 0.. {
match parser.parse::<Anno<Expr>>(0) {
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => {
Err(ParseError::FromLexer(LexError { res: EOF, .. })) => {
return Ok(Response::Accept);
}
Err(e) => {
@@ -120,7 +120,7 @@ fn pats() -> Result<(), Box<dyn Error>> {
}
loop {
match parser.parse::<Pat>(PPrec::Min) {
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => {
Err(ParseError::FromLexer(LexError { res: EOF, .. })) => {
break Ok(Response::Accept);
}
Err(e) => {
@@ -142,7 +142,7 @@ fn tys() -> Result<(), Box<dyn Error>> {
}
loop {
match parser.parse::<Ty>(()) {
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => {
Err(ParseError::FromLexer(LexError { res: EOF, .. })) => {
break Ok(Response::Accept);
}
Err(e) => {
@@ -205,16 +205,25 @@ fn subst() -> Result<(), Box<dyn Error>> {
fn parse(document: &str) {
let mut parser = Parser::new(Lexer::new(document));
let isatty = std::io::stdin().is_terminal();
for idx in 0.. {
match parser.parse::<Expr>(0) {
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => break,
Err(e) => {
println!("\x1b[31m{e}\x1b[0m");
Err(e @ ParseError::EOF(s)) if s.tail == document.len() as _ => {
println!("\x1b[92m{e} (total {} bytes)\x1b[0m", document.len());
break;
}
Ok(v) => {
Err(e @ ParseError::EOF(_)) => {
println!("\x1b[93m{e} (total {} bytes)\x1b[0m", document.len());
break;
}
Err(e) => {
println!("\x1b[91m{e}\x1b[0m");
break;
}
Ok(v) if isatty => {
println!("\x1b[{}m{v}", (idx + 5) % 6 + 31);
}
_ => {}
}
}
}