parser: pass through token ranges in errors & add simple diagnostics output that cites the source file
This commit is contained in:
parent
f8a967abbf
commit
f06bf14b52
4 changed files with 153 additions and 74 deletions
src
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue