refactor(ast): Improve error type, remove unnecessary eof judge

This commit is contained in:
2026-06-12 11:11:31 +08:00
parent 4dabf32c2a
commit ef3dcb41aa
8 changed files with 62 additions and 231 deletions
+12 -41
View File
@@ -1,12 +1,10 @@
use crate::{
ast::err::ParseError,
ast::types::{
ArrayDimension, CompileUnit, FuncDeclStmt, GlobalDeclStmt, Param, VarDeclStmt, VarDeclStmtValue,
},
diagnostic::span::Span,
lexer::{
err::ParseError,
types::{TokenValue, TypeIdent},
},
lexer::types::{TokenValue, TypeIdent},
};
use super::{ParseProcessError, ParseType, Parser};
@@ -25,7 +23,6 @@ impl Parser {
}
fn parse_global_decl_stmt(&mut self) -> Option<GlobalDeclStmt> {
assert!(!self.is_eof());
match self.parse_func_decl_stmt() {
Ok(func_decl) => return Some(GlobalDeclStmt::FuncDecl(func_decl)),
Err(ParseProcessError::ErrorInMatch) => {
@@ -42,7 +39,7 @@ impl Parser {
}
let token = self.next().clone();
self.diagnostics.add_from_frontend_error(
ParseError::UnexpectedToken(token.value, "ident"),
ParseError::ExpectedBefore(token.value, "ident"),
token.span,
);
None
@@ -58,7 +55,6 @@ impl Parser {
// }
// }
fn parse_type_and_name(&mut self, parse_type: ParseType) -> Result<(TypeIdent, String, Span, Span), ParseProcessError> {
assert!(!self.is_eof());
let type_token = self.peek().clone();
let type_ident = match self.peek().value.as_type_ident() {
Some(ti) => ti,
@@ -66,7 +62,7 @@ impl Parser {
if matches!(parse_type, ParseType::MustParse) {
let token = self.next().clone();
self.diagnostics.add_from_frontend_error(
ParseError::UnexpectedToken(token.value, "type ident"),
ParseError::ExpectedBefore(token.value, "type ident"),
token.span,
);
return Err(ParseProcessError::ErrorInMatch);
@@ -77,17 +73,10 @@ impl Parser {
let type_span = type_token.span;
self.advance(1);
let name = match self.peek().value.as_ident() {
None if self.is_eof() => {
self.diagnostics.add_from_frontend_error(
ParseError::ExpectButEof("ident"),
type_span,
);
return Err(ParseProcessError::ErrorInMatch);
},
None => {
let next_span = self.peek().span;
self.diagnostics.add_from_frontend_error(
ParseError::CantCombineWith(type_token.value),
ParseError::ExpectedIdentAfter(type_token.value),
next_span
);
return Err(ParseProcessError::ErrorInMatch);
@@ -99,7 +88,6 @@ impl Parser {
Ok((type_ident, name, type_span, name_span))
}
fn parse_func_decl_stmt(&mut self) -> Result<FuncDeclStmt, ParseProcessError> {
assert!(!self.is_eof());
let (return_type, name, ret_type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
if matches!(self.peek().value, TokenValue::LParen) {
} else {
@@ -108,14 +96,7 @@ impl Parser {
}
// from here we can be sure it's a function declaration, so we can report error if the syntax is wrong
let params = self.parse_param_list()?;
let body = if self.is_eof() {
let span = self.next().span;
self.diagnostics
.add_from_frontend_error(ParseError::ExpectButEof("function body"), span);
return Err(ParseProcessError::ErrorInMatch);
} else {
self.parse_block_stmt(ParseType::MustParse)?
};
let body = self.parse_block_stmt(ParseType::MustParse)?;
Ok(FuncDeclStmt {
return_type: return_type.into(),
name,
@@ -126,11 +107,10 @@ impl Parser {
})
}
fn parse_param_list(&mut self) -> Result<Vec<Param>, ParseProcessError> {
assert!(!self.is_eof());
if self.peek().value != TokenValue::LParen {
let token = self.next().clone();
self.diagnostics.add_from_frontend_error(
ParseError::UnexpectedToken(token.value, "`(`"),
ParseError::ExpectedBefore(token.value, "`(`"),
token.span,
);
return Err(ParseProcessError::ErrorInMatch);
@@ -163,7 +143,6 @@ impl Parser {
Ok(params)
}
fn parse_param(&mut self) -> Result<Param, ParseProcessError> {
assert!(!self.is_eof());
let (param_type, name, type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
Ok(Param {
param_type: param_type.into(),
@@ -183,7 +162,7 @@ impl Parser {
// } else {
// let token = self.next().clone();
// self.diagnostics
// .add_from_frontend_error(ParseError::UnexpectedToken(token.value, "`;`"), token.span);
// .add_from_frontend_error(ParseError::ExpectedBefore(token.value, "`;`"), token.span);
// while let Some(t) = self.peek() {
// if matches!(t.value, TokenValue::Semicolon) {
// self.advance(1);
@@ -202,7 +181,6 @@ impl Parser {
}
pub(super) fn parse_var_decl_stmt_inner(&mut self, parse_type: ParseType, consume_semicolon: bool) -> Result<VarDeclStmt, ParseProcessError> {
assert!(!self.is_eof());
let mut values = vec![];
let (var_type, name, type_span, name_span) = match self.parse_type_and_name(parse_type) {
Ok(res) => res,
@@ -231,13 +209,6 @@ impl Parser {
self.must_match_token(&TokenValue::Comma, "`,` or `;`")?;
last_name = false;
}
// check eof again
if self.is_eof() {
let span = self.last().span;
self.diagnostics
.add_from_frontend_error(ParseError::ExpectButEof("`,` or `;`"), span);
break;
}
if let Some(ident) = self.peek().value.as_ident() {
let span = self.next().span;
let dimensions = self.parse_array_dimensions(false)?;
@@ -252,7 +223,7 @@ impl Parser {
} else {
let token = self.next().clone();
self.diagnostics.add_from_frontend_error(
ParseError::CantCombineWith(TokenValue::TypeIdent(var_type)),
ParseError::ExpectedIdentAfter(TokenValue::TypeIdent(var_type)),
token.span,
);
return Err(ParseProcessError::ErrorInMatch);
@@ -272,7 +243,7 @@ impl Parser {
if !allow_empty_first || !dimensions.is_empty() {
let span = self.peek().span;
self.diagnostics.add_from_frontend_error(
ParseError::UnexpectedToken(TokenValue::RBracket, "array dimension expression"),
ParseError::ExpectedBefore(TokenValue::RBracket, "array dimension expression"),
span,
);
return Err(ParseProcessError::ErrorInMatch);
@@ -288,13 +259,13 @@ impl Parser {
span
}
TokenValue::Eof => {
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("`]`"), start_span);
self.diagnostics.add_from_frontend_error(ParseError::ExpectedBefore(TokenValue::Eof, "`]`"), start_span);
return Err(ParseProcessError::ErrorInMatch);
}
_ => {
let token = self.next();
self.diagnostics.add_from_frontend_error(
ParseError::UnexpectedToken(token.value, "`]`"),
ParseError::ExpectedBefore(token.value, "`]`"),
token.span,
);
return Err(ParseProcessError::ErrorInMatch);