parser: pass through token ranges in errors & add simple diagnostics output that cites the source file

This commit is contained in:
Michael Sippel 2024-05-16 13:14:00 +02:00
parent f8a967abbf
commit f06bf14b52
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 153 additions and 74 deletions

View file

@ -21,7 +21,7 @@ pub enum ParseError {
pub fn parse_expect<It>(
tokens: &mut Peekable<It>,
expected_token: LTIRToken,
) -> Result<(), ParseError>
) -> Result<(), (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
match tokens.next() {
@ -29,24 +29,24 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
if t == expected_token {
Ok(())
} else {
Err(ParseError::UnexpectedToken)
Err((region, ParseError::UnexpectedToken))
}
}
Some((region, Err(err))) => Err(ParseError::LexError(err)),
None => Err(ParseError::UnexpectedEnd),
Some((region, Err(err))) => Err((region, ParseError::LexError(err))),
None => Err((InputRegionTag::default(), ParseError::UnexpectedEnd)),
}
}
/* parse symbol name
*/
pub fn parse_symbol<It>(tokens: &mut Peekable<It>) -> Result<String, ParseError>
pub fn parse_symbol<It>(tokens: &mut Peekable<It>) -> Result<String, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
match tokens.next() {
Some((region, Ok(LTIRToken::Symbol(name)))) => Ok(name),
Some((region, Ok(_))) => Err(ParseError::UnexpectedToken),
Some((region, Err(err))) => Err(ParseError::LexError(err)),
None => Err(ParseError::UnexpectedEnd),
Some((region, Ok(_))) => Err((region, ParseError::UnexpectedToken)),
Some((region, Err(err))) => Err((region, ParseError::LexError(err))),
None => Err((InputRegionTag::default(), ParseError::UnexpectedEnd)),
}
}
@ -56,16 +56,17 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
pub fn parse_type_tag<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result<Option<laddertypes::TypeTerm>, ParseError>
) -> Result<Option<laddertypes::TypeTerm>, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
if let Some((region, peektok)) = tokens.peek().clone() {
match peektok.clone() {
let peek = { tokens.peek().cloned() };
if let Some((region, peektok)) = peek {
match peektok {
Ok(LTIRToken::AssignType(typeterm_str)) => {
tokens.next();
match typectx.write().unwrap().parse(typeterm_str.as_str()) {
Ok(typeterm) => Ok(Some(typeterm)),
Err(parse_error) => Err(ParseError::TypeParseError(parse_error)),
Err(parse_error) => Err((region, ParseError::TypeParseError(parse_error))),
}
}
_ => Ok(None),
@ -109,7 +110,7 @@ impl VariableBinding {
pub fn parse_binding_expr<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result< VariableBinding, ParseError>
) -> Result< VariableBinding, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
if let Some((region, peektok)) = tokens.peek().clone() {
@ -126,11 +127,11 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
typtag: parse_type_tag(typectx, tokens)?
})
}
Err(err) => Err(ParseError::LexError(err.clone())),
_ => Err(ParseError::UnexpectedToken)
Err(err) => Err((*region, ParseError::LexError(err.clone()))),
_ => Err((*region, ParseError::UnexpectedToken))
}
} else {
Err(ParseError::UnexpectedEnd)
Err((InputRegionTag::default(), ParseError::UnexpectedEnd))
}
}
@ -140,13 +141,16 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
pub fn parse_binding_block<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result< Vec<VariableBinding>, ParseError>
) -> Result< Vec<VariableBinding>, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
let mut last_region = InputRegionTag::default();
let _ = parse_expect(tokens, LTIRToken::BlockOpen)?;
let mut bindings = Vec::new();
while let Some((region, peektok)) = tokens.peek() {
last_region = *region;
match peektok {
Ok(LTIRToken::BlockClose) => {
tokens.next();
@ -159,18 +163,18 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
bindings.push(parse_binding_expr(typectx, tokens)?);
}
Err(err) => {
return Err(ParseError::LexError(err.clone()));
return Err((last_region, ParseError::LexError(err.clone())));
}
}
}
Err(ParseError::UnexpectedEnd)
Err((last_region, ParseError::UnexpectedEnd))
}
pub fn parse_statement<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result<crate::expr::Statement, ParseError>
) -> Result<crate::expr::Statement, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
if let Some((region, peektok)) = tokens.peek() {
@ -237,17 +241,17 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::Expr(expr))
}
Err(err) => Err(ParseError::LexError(err.clone())),
Err(err) => Err((*region, ParseError::LexError(err.clone()))),
}
} else {
Err(ParseError::UnexpectedEnd)
Err((InputRegionTag::default(), ParseError::UnexpectedEnd))
}
}
pub fn parse_statement_block<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result<Vec<Statement>, ParseError>
) -> Result<Vec<Statement>, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
let _ = parse_expect(tokens, LTIRToken::BlockOpen)?;
@ -263,33 +267,33 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
statements.push(parse_statement(typectx, tokens)?);
}
Err(err) => {
return Err(ParseError::LexError(err.clone()));
return Err((*region, ParseError::LexError(err.clone())));
}
}
}
Err(ParseError::UnexpectedEnd)
Err((InputRegionTag::default(), ParseError::UnexpectedEnd))
}
pub fn parse_atom<It>(
tokens: &mut Peekable<It>,
) -> Result<crate::expr::LTExpr, ParseError>
) -> Result<crate::expr::LTExpr, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
match tokens.next() {
Some((region, Ok(LTIRToken::Symbol(sym)))) => Ok(LTExpr::symbol(sym.as_str())),
Some((region, Ok(LTIRToken::Char(c)))) => Ok(LTExpr::lit_uint(c as u64)),
Some((region, Ok(LTIRToken::Num(n)))) => Ok(LTExpr::lit_uint(n as u64)),
Some((region, Ok(_))) => Err(ParseError::UnexpectedToken),
Some((region, Err(err))) => Err(ParseError::LexError(err)),
None => Err(ParseError::UnexpectedEnd),
Some((region, Ok(_))) => Err((region, ParseError::UnexpectedToken)),
Some((region, Err(err))) => Err((region, ParseError::LexError(err))),
None => Err((InputRegionTag::default(), ParseError::UnexpectedEnd)),
}
}
pub fn parse_expr<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<It>,
) -> Result<crate::expr::LTExpr, ParseError>
) -> Result<crate::expr::LTExpr, (InputRegionTag, ParseError)>
where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{
let mut children = Vec::new();
@ -309,7 +313,7 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
body: Box::new(body),
});
} else {
return Err(ParseError::UnexpectedToken);
return Err((*region, ParseError::UnexpectedToken));
}
}
Ok(LTIRToken::ExprOpen) => {
@ -369,7 +373,7 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
children.push(parse_atom(tokens)?);
}
Err(err) => {
return Err(ParseError::LexError(err.clone()));
return Err((*region, ParseError::LexError(err.clone())));
}
}
}
@ -382,7 +386,7 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
body: children,
})
} else {
Err(ParseError::UnexpectedEnd)
Err((InputRegionTag::default(), ParseError::UnexpectedEnd))
}
}