refactor(frontend): Move parser to ast folder, use TokenValue::Eof to replace None
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
pub mod parser;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::{
|
|||||||
ArrayDimension, BinaryOp, BlockStmt, BreakStmt, CompileUnit, ContinueStmt, Expr, ExprValue, FuncDeclStmt, GlobalDeclStmt, IfElseBranch, IfStmt, Param, ReturnStmt, Statement, UnaryOp, VarDeclStmt, VarDeclStmtValue, WhileStmt
|
ArrayDimension, BinaryOp, BlockStmt, BreakStmt, CompileUnit, ContinueStmt, Expr, ExprValue, FuncDeclStmt, GlobalDeclStmt, IfElseBranch, IfStmt, Param, ReturnStmt, Statement, UnaryOp, VarDeclStmt, VarDeclStmtValue, WhileStmt
|
||||||
},
|
},
|
||||||
diagnostic::{Diagnositics, span::Span},
|
diagnostic::{Diagnositics, span::Span},
|
||||||
frontend::{
|
lexer::{
|
||||||
err::ParseError,
|
err::ParseError,
|
||||||
types::{Token, TokenValue, TypeIdent},
|
types::{Token, TokenValue, TypeIdent},
|
||||||
},
|
},
|
||||||
@@ -11,6 +11,7 @@ use crate::{
|
|||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
|
eof_token: Token,
|
||||||
pub diagnostics: Diagnositics,
|
pub diagnostics: Diagnositics,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
}
|
}
|
||||||
@@ -25,8 +26,16 @@ enum ParseProcessError {
|
|||||||
}
|
}
|
||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn new(tokens: Vec<Token>, diagnostics: Diagnositics) -> Self {
|
pub fn new(tokens: Vec<Token>, diagnostics: Diagnositics) -> Self {
|
||||||
|
let eof_pos = tokens.last().map_or(0, |token| token.span.end);
|
||||||
Self {
|
Self {
|
||||||
tokens,
|
tokens,
|
||||||
|
eof_token: Token {
|
||||||
|
value: TokenValue::Eof,
|
||||||
|
span: Span {
|
||||||
|
start: eof_pos,
|
||||||
|
end: eof_pos,
|
||||||
|
},
|
||||||
|
},
|
||||||
diagnostics,
|
diagnostics,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
}
|
}
|
||||||
@@ -34,12 +43,12 @@ impl Parser {
|
|||||||
pub fn parse(&mut self) -> CompileUnit {
|
pub fn parse(&mut self) -> CompileUnit {
|
||||||
self.parse_compile_unit()
|
self.parse_compile_unit()
|
||||||
}
|
}
|
||||||
fn peek(&self) -> Option<&Token> {
|
fn peek(&self) -> &Token {
|
||||||
self.tokens.get(self.pos)
|
self.tokens.get(self.pos).unwrap_or(&self.eof_token)
|
||||||
}
|
}
|
||||||
fn next(&mut self) -> Option<&Token> {
|
fn next(&mut self) -> Token {
|
||||||
let token = self.tokens.get(self.pos);
|
let token = self.peek().clone();
|
||||||
if token.is_some() {
|
if !matches!(token.value, TokenValue::Eof) {
|
||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
}
|
}
|
||||||
token
|
token
|
||||||
@@ -52,37 +61,37 @@ impl Parser {
|
|||||||
assert!(self.pos >= n);
|
assert!(self.pos >= n);
|
||||||
self.pos -= n;
|
self.pos -= n;
|
||||||
}
|
}
|
||||||
fn last(&self) -> Option<&Token> {
|
fn last(&self) -> &Token {
|
||||||
if self.pos == 0 {
|
if self.pos == 0 {
|
||||||
None
|
&self.eof_token
|
||||||
} else {
|
} else {
|
||||||
self.tokens.get(self.pos - 1)
|
self.tokens.get(self.pos - 1).unwrap_or(&self.eof_token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn is_eof(&self) -> bool {
|
||||||
|
matches!(self.peek().value, TokenValue::Eof)
|
||||||
|
}
|
||||||
fn must_match_token(&mut self, expected: &TokenValue, diagnostic_text: &'static str) -> Result<(), ParseProcessError> {
|
fn must_match_token(&mut self, expected: &TokenValue, diagnostic_text: &'static str) -> Result<(), ParseProcessError> {
|
||||||
if let Some(t) = self.peek() {
|
if &self.peek().value == expected {
|
||||||
if &t.value == expected {
|
self.advance(1);
|
||||||
self.advance(1);
|
Ok(())
|
||||||
Ok(())
|
} else if self.is_eof() {
|
||||||
} else {
|
let span = self.peek().span;
|
||||||
let token = self.next().unwrap().clone();
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
|
||||||
ParseError::UnexpectedToken(token.value, diagnostic_text),
|
|
||||||
token.span,
|
|
||||||
);
|
|
||||||
Err(ParseProcessError::ErrorInMatch)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
let span = self.next().unwrap().span;
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof(diagnostic_text), span);
|
.add_from_frontend_error(ParseError::ExpectButEof(diagnostic_text), span);
|
||||||
Err(ParseProcessError::ErrorInMatch)
|
Err(ParseProcessError::ErrorInMatch)
|
||||||
|
} else {
|
||||||
|
let token = self.next();
|
||||||
|
self.diagnostics.add_from_frontend_error(
|
||||||
|
ParseError::UnexpectedToken(token.value, diagnostic_text),
|
||||||
|
token.span,
|
||||||
|
);
|
||||||
|
Err(ParseProcessError::ErrorInMatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn must_have_some(&mut self, diagnostic_text: &'static str) -> Result<(), ParseProcessError> {
|
fn must_have_some(&mut self, diagnostic_text: &'static str) -> Result<(), ParseProcessError> {
|
||||||
if self.peek().is_none() {
|
if self.is_eof() {
|
||||||
let span = self.last().unwrap().span;
|
let span = self.last().span;
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof(diagnostic_text), span);
|
.add_from_frontend_error(ParseError::ExpectButEof(diagnostic_text), span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
@@ -91,8 +100,8 @@ impl Parser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
fn until_next_token(&mut self, expected: &[TokenValue]) {
|
fn until_next_token(&mut self, expected: &[TokenValue]) {
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
if expected.contains(&t.value) {
|
if expected.contains(&self.peek().value) {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -101,7 +110,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
fn parse_compile_unit(&mut self) -> CompileUnit {
|
fn parse_compile_unit(&mut self) -> CompileUnit {
|
||||||
let mut global_decls = vec![];
|
let mut global_decls = vec![];
|
||||||
while self.peek().is_some() {
|
while !self.is_eof() {
|
||||||
if let Some(decl) = self.parse_global_decl_stmt() {
|
if let Some(decl) = self.parse_global_decl_stmt() {
|
||||||
global_decls.push(decl);
|
global_decls.push(decl);
|
||||||
} else {
|
} else {
|
||||||
@@ -112,7 +121,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_global_decl_stmt(&mut self) -> Option<GlobalDeclStmt> {
|
fn parse_global_decl_stmt(&mut self) -> Option<GlobalDeclStmt> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
match self.parse_func_decl_stmt() {
|
match self.parse_func_decl_stmt() {
|
||||||
Ok(func_decl) => return Some(GlobalDeclStmt::FuncDecl(func_decl)),
|
Ok(func_decl) => return Some(GlobalDeclStmt::FuncDecl(func_decl)),
|
||||||
Err(ParseProcessError::ErrorInMatch) => {
|
Err(ParseProcessError::ErrorInMatch) => {
|
||||||
@@ -127,7 +136,7 @@ impl Parser {
|
|||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "ident"),
|
ParseError::UnexpectedToken(token.value, "ident"),
|
||||||
token.span,
|
token.span,
|
||||||
@@ -145,13 +154,13 @@ impl Parser {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
fn parse_type_and_name(&mut self, parse_type: ParseType) -> Result<(TypeIdent, String, Span, Span), ParseProcessError> {
|
fn parse_type_and_name(&mut self, parse_type: ParseType) -> Result<(TypeIdent, String, Span, Span), ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let type_token = self.peek().unwrap().clone();
|
let type_token = self.peek().clone();
|
||||||
let type_ident = match self.peek().unwrap().value.as_type_ident() {
|
let type_ident = match self.peek().value.as_type_ident() {
|
||||||
Some(ti) => ti,
|
Some(ti) => ti,
|
||||||
None => {
|
None => {
|
||||||
if matches!(parse_type, ParseType::MustParse) {
|
if matches!(parse_type, ParseType::MustParse) {
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "type ident"),
|
ParseError::UnexpectedToken(token.value, "type ident"),
|
||||||
token.span,
|
token.span,
|
||||||
@@ -163,49 +172,45 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
let type_span = type_token.span;
|
let type_span = type_token.span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let name = match self.peek().map(|t| t.value.as_ident()) {
|
let name = match self.peek().value.as_ident() {
|
||||||
None => {
|
None if self.is_eof() => {
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("ident"),
|
ParseError::ExpectButEof("ident"),
|
||||||
type_span,
|
type_span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
},
|
},
|
||||||
Some(None) => {
|
None => {
|
||||||
let next_span = self.peek().unwrap().span;
|
let next_span = self.peek().span;
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::CantCombineWith(type_token.value),
|
ParseError::CantCombineWith(type_token.value),
|
||||||
next_span
|
next_span
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
Some(Some(ident)) => ident,
|
Some(ident) => ident,
|
||||||
};
|
};
|
||||||
let name_span = self.peek().unwrap().span;
|
let name_span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
Ok((type_ident, name, type_span, name_span))
|
Ok((type_ident, name, type_span, name_span))
|
||||||
}
|
}
|
||||||
fn parse_func_decl_stmt(&mut self) -> Result<FuncDeclStmt, ParseProcessError> {
|
fn parse_func_decl_stmt(&mut self) -> Result<FuncDeclStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let (return_type, name, ret_type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
|
let (return_type, name, ret_type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
|
||||||
if self
|
if matches!(self.peek().value, TokenValue::LParen) {
|
||||||
.peek()
|
|
||||||
.is_some_and(|t| matches!(t.value, TokenValue::LParen))
|
|
||||||
{
|
|
||||||
} else {
|
} else {
|
||||||
self.back(2);
|
self.back(2);
|
||||||
return Err(ParseProcessError::TryNext);
|
return Err(ParseProcessError::TryNext);
|
||||||
}
|
}
|
||||||
// from here we can be sure it's a function declaration, so we can report error if the syntax is wrong
|
// 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 params = self.parse_param_list()?;
|
||||||
let body = match self.peek().map(|t| &t.value) {
|
let body = if self.is_eof() {
|
||||||
Some(_) => self.parse_block_stmt(ParseType::MustParse)?,
|
let span = self.next().span;
|
||||||
None => {
|
|
||||||
let span = self.next().unwrap().span;
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("function body"), span);
|
.add_from_frontend_error(ParseError::ExpectButEof("function body"), span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_block_stmt(ParseType::MustParse)?
|
||||||
};
|
};
|
||||||
Ok(FuncDeclStmt {
|
Ok(FuncDeclStmt {
|
||||||
return_type: return_type.into(),
|
return_type: return_type.into(),
|
||||||
@@ -217,9 +222,9 @@ impl Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn parse_param_list(&mut self) -> Result<Vec<Param>, ParseProcessError> {
|
fn parse_param_list(&mut self) -> Result<Vec<Param>, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
if self.peek().unwrap().value != TokenValue::LParen {
|
if self.peek().value != TokenValue::LParen {
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`(`"),
|
ParseError::UnexpectedToken(token.value, "`(`"),
|
||||||
token.span,
|
token.span,
|
||||||
@@ -229,8 +234,8 @@ impl Parser {
|
|||||||
self.advance(1);
|
self.advance(1);
|
||||||
let mut params = vec![];
|
let mut params = vec![];
|
||||||
let mut last_is_var = false;
|
let mut last_is_var = false;
|
||||||
while self.peek().is_some() {
|
while !self.is_eof() {
|
||||||
if self.peek().map(|t| &t.value) == Some(&TokenValue::RParen) {
|
if self.peek().value == TokenValue::RParen {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -245,7 +250,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
self.until_next_token(&[TokenValue::RParen]);
|
self.until_next_token(&[TokenValue::RParen]);
|
||||||
if self.last().map(|t| &t.value) == Some(&TokenValue::RParen) {
|
if self.last().value == TokenValue::RParen {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,7 +259,7 @@ impl Parser {
|
|||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
fn parse_param(&mut self) -> Result<Param, ParseProcessError> {
|
fn parse_param(&mut self) -> Result<Param, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let (param_type, name, type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
|
let (param_type, name, type_span, name_span) = self.parse_type_and_name(ParseType::MustParse)?;
|
||||||
Ok(Param {
|
Ok(Param {
|
||||||
param_type: param_type.into(),
|
param_type: param_type.into(),
|
||||||
@@ -272,7 +277,7 @@ impl Parser {
|
|||||||
// self.advance(1);
|
// self.advance(1);
|
||||||
// Some(())
|
// Some(())
|
||||||
// } else {
|
// } else {
|
||||||
// let token = self.next().unwrap().clone();
|
// let token = self.next().clone();
|
||||||
// self.diagnostics
|
// self.diagnostics
|
||||||
// .add_from_frontend_error(ParseError::UnexpectedToken(token.value, "`;`"), token.span);
|
// .add_from_frontend_error(ParseError::UnexpectedToken(token.value, "`;`"), token.span);
|
||||||
// while let Some(t) = self.peek() {
|
// while let Some(t) = self.peek() {
|
||||||
@@ -289,7 +294,7 @@ impl Parser {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
fn parse_var_decl_stmt(&mut self, parse_type: ParseType) -> Result<VarDeclStmt, ParseProcessError> {
|
fn parse_var_decl_stmt(&mut self, parse_type: ParseType) -> Result<VarDeclStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
let (var_type, name, type_span, name_span) = match self.parse_type_and_name(parse_type) {
|
let (var_type, name, type_span, name_span) = match self.parse_type_and_name(parse_type) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
@@ -304,8 +309,8 @@ impl Parser {
|
|||||||
let dimensions = self.parse_array_dimensions(false)?;
|
let dimensions = self.parse_array_dimensions(false)?;
|
||||||
values.push(VarDeclStmtValue { name, name_span, dimensions });
|
values.push(VarDeclStmtValue { name, name_span, dimensions });
|
||||||
let mut last_name = true; // indicate whether the last parsed token is a variable name
|
let mut last_name = true; // indicate whether the last parsed token is a variable name
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
if matches!(t.value, TokenValue::Semicolon) { // statement end
|
if matches!(self.peek().value, TokenValue::Semicolon) { // statement end
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if last_name { // expect a comma after a variable name
|
if last_name { // expect a comma after a variable name
|
||||||
@@ -313,19 +318,19 @@ impl Parser {
|
|||||||
last_name = false;
|
last_name = false;
|
||||||
}
|
}
|
||||||
// check eof again
|
// check eof again
|
||||||
if self.peek().is_none() {
|
if self.is_eof() {
|
||||||
let span = self.last().unwrap().span;
|
let span = self.last().span;
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("`,` or `;`"), span);
|
.add_from_frontend_error(ParseError::ExpectButEof("`,` or `;`"), span);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some(ident) = self.peek().unwrap().value.as_ident() {
|
if let Some(ident) = self.peek().value.as_ident() {
|
||||||
let span = self.next().unwrap().span;
|
let span = self.next().span;
|
||||||
let dimensions = self.parse_array_dimensions(false)?;
|
let dimensions = self.parse_array_dimensions(false)?;
|
||||||
values.push(VarDeclStmtValue { name: ident, name_span: span, dimensions });
|
values.push(VarDeclStmtValue { name: ident, name_span: span, dimensions });
|
||||||
last_name = true;
|
last_name = true;
|
||||||
} else {
|
} else {
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::CantCombineWith(TokenValue::TypeIdent(var_type)),
|
ParseError::CantCombineWith(TokenValue::TypeIdent(var_type)),
|
||||||
token.span,
|
token.span,
|
||||||
@@ -339,11 +344,11 @@ impl Parser {
|
|||||||
|
|
||||||
fn parse_array_dimensions(&mut self, allow_empty_first: bool) -> Result<Vec<ArrayDimension>, ParseProcessError> {
|
fn parse_array_dimensions(&mut self, allow_empty_first: bool) -> Result<Vec<ArrayDimension>, ParseProcessError> {
|
||||||
let mut dimensions = vec![];
|
let mut dimensions = vec![];
|
||||||
while self.peek().is_some_and(|t| t.value == TokenValue::LBracket) {
|
while self.peek().value == TokenValue::LBracket {
|
||||||
let start_span = self.next().unwrap().span;
|
let start_span = self.next().span;
|
||||||
let value = if self.peek().is_some_and(|t| t.value == TokenValue::RBracket) {
|
let value = if self.peek().value == TokenValue::RBracket {
|
||||||
if !allow_empty_first || !dimensions.is_empty() {
|
if !allow_empty_first || !dimensions.is_empty() {
|
||||||
let span = self.peek().unwrap().span;
|
let span = self.peek().span;
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(TokenValue::RBracket, "array dimension expression"),
|
ParseError::UnexpectedToken(TokenValue::RBracket, "array dimension expression"),
|
||||||
span,
|
span,
|
||||||
@@ -354,24 +359,24 @@ impl Parser {
|
|||||||
} else {
|
} else {
|
||||||
Some(self.parse_expr()?)
|
Some(self.parse_expr()?)
|
||||||
};
|
};
|
||||||
let end_span = match self.peek() {
|
let end_span = match &self.peek().value {
|
||||||
Some(t) if t.value == TokenValue::RBracket => {
|
TokenValue::RBracket => {
|
||||||
let span = t.span;
|
let span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
span
|
span
|
||||||
}
|
}
|
||||||
Some(_) => {
|
TokenValue::Eof => {
|
||||||
let token = self.next().unwrap().clone();
|
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("`]`"), start_span);
|
||||||
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let token = self.next();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`]`"),
|
ParseError::UnexpectedToken(token.value, "`]`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("`]`"), start_span);
|
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
dimensions.push(ArrayDimension {
|
dimensions.push(ArrayDimension {
|
||||||
value,
|
value,
|
||||||
@@ -382,13 +387,10 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block_stmt(&mut self, parse_type: ParseType) -> Result<BlockStmt, ParseProcessError> {
|
fn parse_block_stmt(&mut self, parse_type: ParseType) -> Result<BlockStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
if self
|
if self.peek().value != TokenValue::LBrace {
|
||||||
.peek()
|
|
||||||
.unwrap().value != TokenValue::LBrace
|
|
||||||
{
|
|
||||||
if parse_type == ParseType::MustParse {
|
if parse_type == ParseType::MustParse {
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`{`"),
|
ParseError::UnexpectedToken(token.value, "`{`"),
|
||||||
token.span,
|
token.span,
|
||||||
@@ -401,26 +403,18 @@ impl Parser {
|
|||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
// println!("parse block stmt");
|
// println!("parse block stmt");
|
||||||
loop {
|
loop {
|
||||||
if self.peek().is_none() {
|
if self.is_eof() {
|
||||||
let span = self.last().unwrap().span;
|
let span = self.last().span;
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("`}`"), span);
|
.add_from_frontend_error(ParseError::ExpectButEof("`}`"), span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
if self
|
if matches!(self.peek().value, TokenValue::Semicolon) {
|
||||||
.peek()
|
|
||||||
.map(|t| matches!(t.value, TokenValue::Semicolon))
|
|
||||||
.unwrap()
|
|
||||||
{
|
|
||||||
// like a();;
|
// like a();;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if self
|
if matches!(self.peek().value, TokenValue::RBrace) {
|
||||||
.peek()
|
|
||||||
.map(|t| matches!(t.value, TokenValue::RBrace))
|
|
||||||
.unwrap()
|
|
||||||
{
|
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -429,7 +423,7 @@ impl Parser {
|
|||||||
Ok(stmt) => statements.push(stmt),
|
Ok(stmt) => statements.push(stmt),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.until_next_token(&[TokenValue::Semicolon, TokenValue::RBrace]);
|
self.until_next_token(&[TokenValue::Semicolon, TokenValue::RBrace]);
|
||||||
if self.last().unwrap().value == TokenValue::RBrace {
|
if self.last().value == TokenValue::RBrace {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,7 +436,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stmt(&mut self) -> Result<Statement, ParseProcessError> {
|
fn parse_stmt(&mut self) -> Result<Statement, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
match self.parse_var_decl_stmt(ParseType::TryParse) {
|
match self.parse_var_decl_stmt(ParseType::TryParse) {
|
||||||
Ok(var_decl) => return Ok(Statement::VarDecl(var_decl)),
|
Ok(var_decl) => return Ok(Statement::VarDecl(var_decl)),
|
||||||
Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch),
|
Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch),
|
||||||
@@ -491,16 +485,12 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_return_stmt(&mut self) -> Result<ReturnStmt, ParseProcessError> {
|
fn parse_return_stmt(&mut self) -> Result<ReturnStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
if self.peek().unwrap().value != TokenValue::Return {
|
if self.peek().value != TokenValue::Return {
|
||||||
return Err(ParseProcessError::TryNext);
|
return Err(ParseProcessError::TryNext);
|
||||||
}
|
}
|
||||||
let span = self.next().unwrap().span;
|
let span = self.next().span;
|
||||||
let value = if self
|
let value = if matches!(self.peek().value, TokenValue::Semicolon) {
|
||||||
.peek()
|
|
||||||
.map(|t| matches!(t.value, TokenValue::Semicolon))
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(self.parse_expr()?)
|
Some(self.parse_expr()?)
|
||||||
@@ -512,8 +502,8 @@ impl Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn parse_if_stmt(&mut self) -> Result<IfStmt, ParseProcessError> {
|
fn parse_if_stmt(&mut self) -> Result<IfStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
if self.peek().unwrap().value != TokenValue::If {
|
if self.peek().value != TokenValue::If {
|
||||||
return Err(ParseProcessError::TryNext);
|
return Err(ParseProcessError::TryNext);
|
||||||
}
|
}
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
@@ -525,20 +515,20 @@ impl Parser {
|
|||||||
let mut ifelse_branch = vec![];
|
let mut ifelse_branch = vec![];
|
||||||
let mut else_branch = None;
|
let mut else_branch = None;
|
||||||
self.must_have_some("if statement body")?;
|
self.must_have_some("if statement body")?;
|
||||||
if self.peek().unwrap().value != TokenValue::LBrace {
|
if self.peek().value != TokenValue::LBrace {
|
||||||
let stmt = self.parse_stmt()?;
|
let stmt = self.parse_stmt()?;
|
||||||
then_branch = BlockStmt { statements: vec![stmt] };
|
then_branch = BlockStmt { statements: vec![stmt] };
|
||||||
} else {
|
} else {
|
||||||
then_branch = self.parse_block_stmt(ParseType::MustParse)?;
|
then_branch = self.parse_block_stmt(ParseType::MustParse)?;
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
if self.peek().is_none() {
|
if self.is_eof() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if self.peek().unwrap().value == TokenValue::Else {
|
if self.peek().value == TokenValue::Else {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
self.must_have_some("else body")?;
|
self.must_have_some("else body")?;
|
||||||
if self.peek().unwrap().value != TokenValue::If {
|
if self.peek().value != TokenValue::If {
|
||||||
self.back(1);
|
self.back(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -549,7 +539,7 @@ impl Parser {
|
|||||||
let condition = self.parse_expr()?;
|
let condition = self.parse_expr()?;
|
||||||
self.must_match_token(&TokenValue::RParen, "`)`")?;
|
self.must_match_token(&TokenValue::RParen, "`)`")?;
|
||||||
let then_branch;
|
let then_branch;
|
||||||
if self.peek().unwrap().value != TokenValue::LBrace {
|
if self.peek().value != TokenValue::LBrace {
|
||||||
let stmt = self.parse_stmt()?;
|
let stmt = self.parse_stmt()?;
|
||||||
then_branch = BlockStmt { statements: vec![stmt] };
|
then_branch = BlockStmt { statements: vec![stmt] };
|
||||||
} else {
|
} else {
|
||||||
@@ -561,11 +551,11 @@ impl Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.peek().is_some_and(|t| t.value == TokenValue::Else) {
|
if self.peek().value == TokenValue::Else {
|
||||||
// Parse else branch
|
// Parse else branch
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
self.must_have_some("else body")?;
|
self.must_have_some("else body")?;
|
||||||
if self.peek().unwrap().value != TokenValue::LBrace {
|
if self.peek().value != TokenValue::LBrace {
|
||||||
let stmt = self.parse_stmt()?;
|
let stmt = self.parse_stmt()?;
|
||||||
else_branch = Some(BlockStmt { statements: vec![stmt] });
|
else_branch = Some(BlockStmt { statements: vec![stmt] });
|
||||||
} else {
|
} else {
|
||||||
@@ -581,8 +571,8 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_while_stmt(&mut self) -> Result<WhileStmt, ParseProcessError> {
|
fn parse_while_stmt(&mut self) -> Result<WhileStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
if self.peek().unwrap().value != TokenValue::While {
|
if self.peek().value != TokenValue::While {
|
||||||
return Err(ParseProcessError::TryNext);
|
return Err(ParseProcessError::TryNext);
|
||||||
}
|
}
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
@@ -591,7 +581,7 @@ impl Parser {
|
|||||||
let condition = self.parse_expr()?;
|
let condition = self.parse_expr()?;
|
||||||
self.must_match_token(&TokenValue::RParen, "`)`")?;
|
self.must_match_token(&TokenValue::RParen, "`)`")?;
|
||||||
let body;
|
let body;
|
||||||
if self.peek().unwrap().value != TokenValue::LBrace {
|
if self.peek().value != TokenValue::LBrace {
|
||||||
let stmt = self.parse_stmt()?;
|
let stmt = self.parse_stmt()?;
|
||||||
body = BlockStmt { statements: vec![stmt] };
|
body = BlockStmt { statements: vec![stmt] };
|
||||||
} else {
|
} else {
|
||||||
@@ -604,9 +594,9 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_break_stmt(&mut self) -> Result<BreakStmt, ParseProcessError> {
|
fn parse_break_stmt(&mut self) -> Result<BreakStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let start_span = self.peek().unwrap().span;
|
let start_span = self.peek().span;
|
||||||
if self.peek().unwrap().value == TokenValue::Break {
|
if self.peek().value == TokenValue::Break {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
self.must_match_token(&TokenValue::Semicolon, "`;`")?;
|
self.must_match_token(&TokenValue::Semicolon, "`;`")?;
|
||||||
Ok(BreakStmt {
|
Ok(BreakStmt {
|
||||||
@@ -618,9 +608,9 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_continue_stmt(&mut self) -> Result<ContinueStmt, ParseProcessError> {
|
fn parse_continue_stmt(&mut self) -> Result<ContinueStmt, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let start_span = self.peek().unwrap().span;
|
let start_span = self.peek().span;
|
||||||
if self.peek().unwrap().value == TokenValue::Continue {
|
if self.peek().value == TokenValue::Continue {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
self.must_match_token(&TokenValue::Semicolon, "`;`")?;
|
self.must_match_token(&TokenValue::Semicolon, "`;`")?;
|
||||||
Ok(ContinueStmt {
|
Ok(ContinueStmt {
|
||||||
@@ -646,59 +636,56 @@ impl Parser {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
fn parse_primary_atom(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_primary_atom(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let token = self.next().unwrap().clone();
|
let token = self.next().clone();
|
||||||
match token.value {
|
match token.value {
|
||||||
TokenValue::Ident(name) => {
|
TokenValue::Ident(name) => {
|
||||||
if self
|
if matches!(self.peek().value, TokenValue::LParen) {
|
||||||
.peek()
|
|
||||||
.is_some_and(|t| matches!(t.value, TokenValue::LParen))
|
|
||||||
{
|
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
match &self.peek().value {
|
||||||
Some(t) if matches!(t.value, TokenValue::RParen) => {
|
TokenValue::RParen => {
|
||||||
let end_span = t.span;
|
let end_span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
return Ok(Expr {
|
return Ok(Expr {
|
||||||
value: ExprValue::FuncCall(name, args),
|
value: ExprValue::FuncCall(name, args),
|
||||||
span: Span::from_two(token.span, end_span),
|
span: Span::from_two(token.span, end_span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(_) => {}
|
TokenValue::Eof => {
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("`)`"),
|
ParseError::ExpectButEof("`)`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
args.push(self.parse_expr()?);
|
args.push(self.parse_expr()?);
|
||||||
match self.peek() {
|
match &self.peek().value {
|
||||||
Some(t) if matches!(t.value, TokenValue::Comma) => {
|
TokenValue::Comma => {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
}
|
}
|
||||||
Some(t) if matches!(t.value, TokenValue::RParen) => {
|
TokenValue::RParen => {
|
||||||
let end_span = t.span;
|
let end_span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
return Ok(Expr {
|
return Ok(Expr {
|
||||||
value: ExprValue::FuncCall(name, args),
|
value: ExprValue::FuncCall(name, args),
|
||||||
span: Span::from_two(token.span, end_span),
|
span: Span::from_two(token.span, end_span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(_) => {
|
TokenValue::Eof => {
|
||||||
let token = self.next().unwrap().clone();
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`,` or `)`"),
|
ParseError::ExpectButEof("`)`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
None => {
|
_ => {
|
||||||
|
let token = self.next();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("`)`"),
|
ParseError::UnexpectedToken(token.value, "`,` or `)`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
@@ -716,38 +703,37 @@ impl Parser {
|
|||||||
span: token.span,
|
span: token.span,
|
||||||
}),
|
}),
|
||||||
TokenValue::LParen => {
|
TokenValue::LParen => {
|
||||||
let expr = match self.peek() {
|
let expr = if self.is_eof() {
|
||||||
Some(_) => self.parse_expr()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("expression"),
|
ParseError::ExpectButEof("expression"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_expr()?
|
||||||
};
|
};
|
||||||
match self.peek() {
|
match &self.peek().value {
|
||||||
Some(t) if matches!(t.value, TokenValue::RParen) => {
|
TokenValue::RParen => {
|
||||||
let end_span = t.span;
|
let end_span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
Ok(Expr {
|
Ok(Expr {
|
||||||
span: Span::from_two(token.span, end_span),
|
span: Span::from_two(token.span, end_span),
|
||||||
..expr
|
..expr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(_) => {
|
TokenValue::Eof => {
|
||||||
let token = self.next().unwrap().clone();
|
self.diagnostics
|
||||||
|
.add_from_frontend_error(ParseError::ExpectButEof("`)`"), expr.span);
|
||||||
|
Err(ParseProcessError::ErrorInMatch)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let token = self.next();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`)`"),
|
ParseError::UnexpectedToken(token.value, "`)`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
Err(ParseProcessError::ErrorInMatch)
|
Err(ParseProcessError::ErrorInMatch)
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
self.diagnostics
|
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("`)`"), expr.span);
|
|
||||||
Err(ParseProcessError::ErrorInMatch)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -761,34 +747,33 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
fn parse_primary(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_primary(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
let mut expr = self.parse_primary_atom()?;
|
let mut expr = self.parse_primary_atom()?;
|
||||||
while self.peek().is_some_and(|t| t.value == TokenValue::LBracket) {
|
while self.peek().value == TokenValue::LBracket {
|
||||||
let start_span = expr.span;
|
let start_span = expr.span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let index = match self.peek() {
|
let index = if self.is_eof() {
|
||||||
Some(_) => self.parse_expr()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("array index expression"), start_span);
|
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("array index expression"), start_span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_expr()?
|
||||||
};
|
};
|
||||||
let end_span = match self.peek() {
|
let end_span = match &self.peek().value {
|
||||||
Some(t) if t.value == TokenValue::RBracket => {
|
TokenValue::RBracket => {
|
||||||
let span = t.span;
|
let span = self.peek().span;
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
span
|
span
|
||||||
}
|
}
|
||||||
Some(_) => {
|
TokenValue::Eof => {
|
||||||
let token = self.next().unwrap().clone();
|
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("`]`"), index.span);
|
||||||
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let token = self.next();
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::UnexpectedToken(token.value, "`]`"),
|
ParseError::UnexpectedToken(token.value, "`]`"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(ParseError::ExpectButEof("`]`"), index.span);
|
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
expr = Expr {
|
expr = Expr {
|
||||||
value: ExprValue::ArrayAccess {
|
value: ExprValue::ArrayAccess {
|
||||||
@@ -801,20 +786,19 @@ impl Parser {
|
|||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
fn parse_unary(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_unary(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let token = self.peek().unwrap().clone();
|
let token = self.peek().clone();
|
||||||
match token.value {
|
match token.value {
|
||||||
TokenValue::Plus => {
|
TokenValue::Plus => {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let expr = match self.peek() {
|
let expr = if self.is_eof() {
|
||||||
Some(_) => self.parse_unary()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("expression"),
|
ParseError::ExpectButEof("expression"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_unary()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(token.span, expr.span);
|
let span = Span::from_two(token.span, expr.span);
|
||||||
Ok(Expr {
|
Ok(Expr {
|
||||||
@@ -827,15 +811,14 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
TokenValue::Minus => {
|
TokenValue::Minus => {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let rhs = match self.peek() {
|
let rhs = if self.is_eof() {
|
||||||
Some(_) => self.parse_unary()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("expression"),
|
ParseError::ExpectButEof("expression"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_unary()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(token.span, rhs.span);
|
let span = Span::from_two(token.span, rhs.span);
|
||||||
Ok(Expr {
|
Ok(Expr {
|
||||||
@@ -848,15 +831,14 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
TokenValue::Not => {
|
TokenValue::Not => {
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let rhs = match self.peek() {
|
let rhs = if self.is_eof() {
|
||||||
Some(_) => self.parse_unary()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("expression"),
|
ParseError::ExpectButEof("expression"),
|
||||||
token.span,
|
token.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_unary()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(token.span, rhs.span);
|
let span = Span::from_two(token.span, rhs.span);
|
||||||
Ok(Expr {
|
Ok(Expr {
|
||||||
@@ -871,23 +853,22 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn parse_multiplicative(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_multiplicative(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut left = self.parse_unary()?;
|
let mut left = self.parse_unary()?;
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
let op = match t.value {
|
let op = match self.peek().value {
|
||||||
TokenValue::Star => BinaryOp::Mul,
|
TokenValue::Star => BinaryOp::Mul,
|
||||||
TokenValue::Slash => BinaryOp::Div,
|
TokenValue::Slash => BinaryOp::Div,
|
||||||
TokenValue::Percent => BinaryOp::Mod,
|
TokenValue::Percent => BinaryOp::Mod,
|
||||||
_ => break,
|
_ => break,
|
||||||
};
|
};
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let right = match self.peek() {
|
let right = if self.is_eof() {
|
||||||
Some(_) => self.parse_unary()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_unary()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(left.span, right.span);
|
let span = Span::from_two(left.span, right.span);
|
||||||
left = Expr {
|
left = Expr {
|
||||||
@@ -902,22 +883,21 @@ impl Parser {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
fn parse_additive(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_additive(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut left = self.parse_multiplicative()?;
|
let mut left = self.parse_multiplicative()?;
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
let op = match t.value {
|
let op = match self.peek().value {
|
||||||
TokenValue::Plus => BinaryOp::Add,
|
TokenValue::Plus => BinaryOp::Add,
|
||||||
TokenValue::Minus => BinaryOp::Sub,
|
TokenValue::Minus => BinaryOp::Sub,
|
||||||
_ => break,
|
_ => break,
|
||||||
};
|
};
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let right = match self.peek() {
|
let right = if self.is_eof() {
|
||||||
Some(_) => self.parse_multiplicative()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_multiplicative()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(left.span, right.span);
|
let span = Span::from_two(left.span, right.span);
|
||||||
left = Expr {
|
left = Expr {
|
||||||
@@ -932,10 +912,10 @@ impl Parser {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
fn parse_relational(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_relational(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut left = self.parse_additive()?;
|
let mut left = self.parse_additive()?;
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
let op = match t.value {
|
let op = match self.peek().value {
|
||||||
TokenValue::Less => BinaryOp::Less,
|
TokenValue::Less => BinaryOp::Less,
|
||||||
TokenValue::Greater => BinaryOp::Greater,
|
TokenValue::Greater => BinaryOp::Greater,
|
||||||
TokenValue::LessEqual => BinaryOp::LessEqual,
|
TokenValue::LessEqual => BinaryOp::LessEqual,
|
||||||
@@ -945,13 +925,12 @@ impl Parser {
|
|||||||
_ => break,
|
_ => break,
|
||||||
};
|
};
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let right = match self.peek() {
|
let right = if self.is_eof() {
|
||||||
Some(_) => self.parse_additive()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_additive()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(left.span, right.span);
|
let span = Span::from_two(left.span, right.span);
|
||||||
left = Expr {
|
left = Expr {
|
||||||
@@ -966,21 +945,20 @@ impl Parser {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
fn parse_logical_and(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_logical_and(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut left = self.parse_relational()?;
|
let mut left = self.parse_relational()?;
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
let op = match t.value {
|
let op = match self.peek().value {
|
||||||
TokenValue::And => BinaryOp::And,
|
TokenValue::And => BinaryOp::And,
|
||||||
_ => break,
|
_ => break,
|
||||||
};
|
};
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let right = match self.peek() {
|
let right = if self.is_eof() {
|
||||||
Some(_) => self.parse_relational()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_relational()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(left.span, right.span);
|
let span = Span::from_two(left.span, right.span);
|
||||||
left = Expr {
|
left = Expr {
|
||||||
@@ -995,21 +973,20 @@ impl Parser {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
fn parse_logical_or(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_logical_or(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let mut left = self.parse_logical_and()?;
|
let mut left = self.parse_logical_and()?;
|
||||||
while let Some(t) = self.peek() {
|
while !self.is_eof() {
|
||||||
let op = match t.value {
|
let op = match self.peek().value {
|
||||||
TokenValue::Or => BinaryOp::Or,
|
TokenValue::Or => BinaryOp::Or,
|
||||||
_ => break,
|
_ => break,
|
||||||
};
|
};
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let right = match self.peek() {
|
let right = if self.is_eof() {
|
||||||
Some(_) => self.parse_logical_and()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics
|
self.diagnostics
|
||||||
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
.add_from_frontend_error(ParseError::ExpectButEof("expression"), left.span);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_logical_and()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(left.span, right.span);
|
let span = Span::from_two(left.span, right.span);
|
||||||
left = Expr {
|
left = Expr {
|
||||||
@@ -1024,21 +1001,20 @@ impl Parser {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
fn parse_assign(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_assign(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
let lvalue = self.parse_logical_or()?;
|
let lvalue = self.parse_logical_or()?;
|
||||||
if !self.peek().is_some_and(|t| t.value == TokenValue::Equal) {
|
if self.peek().value != TokenValue::Equal {
|
||||||
return Ok(lvalue);
|
return Ok(lvalue);
|
||||||
}
|
}
|
||||||
self.advance(1);
|
self.advance(1);
|
||||||
let rvalue = match self.peek() {
|
let rvalue = if self.is_eof() {
|
||||||
Some(_) => self.parse_assign()?,
|
|
||||||
None => {
|
|
||||||
self.diagnostics.add_from_frontend_error(
|
self.diagnostics.add_from_frontend_error(
|
||||||
ParseError::ExpectButEof("expression"),
|
ParseError::ExpectButEof("expression"),
|
||||||
lvalue.span,
|
lvalue.span,
|
||||||
);
|
);
|
||||||
return Err(ParseProcessError::ErrorInMatch);
|
return Err(ParseProcessError::ErrorInMatch);
|
||||||
}
|
} else {
|
||||||
|
self.parse_assign()?
|
||||||
};
|
};
|
||||||
let span = Span::from_two(lvalue.span, rvalue.span);
|
let span = Span::from_two(lvalue.span, rvalue.span);
|
||||||
Ok(Expr {
|
Ok(Expr {
|
||||||
@@ -1090,7 +1066,7 @@ impl Parser {
|
|||||||
| "(" expr ")"
|
| "(" expr ")"
|
||||||
*/
|
*/
|
||||||
fn parse_expr(&mut self) -> Result<Expr, ParseProcessError> {
|
fn parse_expr(&mut self) -> Result<Expr, ParseProcessError> {
|
||||||
assert!(self.peek().is_some());
|
assert!(!self.is_eof());
|
||||||
self.parse_assign()
|
self.parse_assign()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1101,7 +1077,7 @@ mod tests {
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use crate::ast::graph::AstGraphExt;
|
use crate::ast::graph::AstGraphExt;
|
||||||
use crate::frontend::lexer::Lexer;
|
use crate::lexer::lexer::Lexer;
|
||||||
use crate::utils::case_list::CaseList;
|
use crate::utils::case_list::CaseList;
|
||||||
use crate::utils::num_sequence::NumberSequence;
|
use crate::utils::num_sequence::NumberSequence;
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
use crate::{diagnostic::span::Span, frontend::types::{Token, TokenValue, TypeIdent}};
|
use crate::{diagnostic::span::Span, lexer::types::{TokenValue, TypeIdent}};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub struct CompileUnit {
|
pub struct CompileUnit {
|
||||||
|
|||||||
+2
-2
@@ -10,8 +10,8 @@ mod tests {
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use crate::frontend::lexer::Lexer;
|
use crate::ast::parser::Parser;
|
||||||
use crate::frontend::parser::Parser;
|
use crate::lexer::lexer::Lexer;
|
||||||
use crate::utils::case_list::CaseList;
|
use crate::utils::case_list::CaseList;
|
||||||
use crate::utils::num_sequence::NumberSequence;
|
use crate::utils::num_sequence::NumberSequence;
|
||||||
use crate::ir::generator::Generator as IRGenerator;
|
use crate::ir::generator::Generator as IRGenerator;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{diagnostic::span::Span, err::CompileError, frontend::err::FrontendError, ir::err::IRError};
|
use crate::{diagnostic::span::Span, err::CompileError, ir::err::IRError, lexer::err::FrontendError};
|
||||||
|
|
||||||
pub mod span;
|
pub mod span;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{frontend::err::FrontendError, sema::err::SemaError};
|
use crate::{lexer::err::FrontendError, sema::err::SemaError};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Error)]
|
#[derive(Debug, Clone, PartialEq, Eq, Error)]
|
||||||
pub enum CompileError {
|
pub enum CompileError {
|
||||||
|
|||||||
+2
-2
@@ -663,8 +663,8 @@ mod tests {
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use crate::ast::graph::AstGraphExt;
|
use crate::ast::graph::AstGraphExt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use crate::frontend::lexer::Lexer;
|
use crate::ast::parser::Parser;
|
||||||
use crate::frontend::parser::Parser;
|
use crate::lexer::lexer::Lexer;
|
||||||
use crate::sema::analyzer::Analyzer;
|
use crate::sema::analyzer::Analyzer;
|
||||||
use crate::utils::case_list::CaseList;
|
use crate::utils::case_list::CaseList;
|
||||||
use crate::utils::num_sequence::NumberSequence;
|
use crate::utils::num_sequence::NumberSequence;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::frontend::types::{Token, TokenValue};
|
use crate::lexer::types::TokenValue;
|
||||||
|
|
||||||
// #[derive(Debug, Clone, PartialEq, Eq, Error)]
|
// #[derive(Debug, Clone, PartialEq, Eq, Error)]
|
||||||
// pub enum ParseError {
|
// pub enum ParseError {
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
use std::{io::BufRead, str::FromStr};
|
use std::str::FromStr;
|
||||||
|
|
||||||
use codespan_reporting::diagnostic;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{diagnostic::{Diagnositics, span::{self, Span}}, frontend::{err::LexingError, types::{TokenValue, TypeIdent}}};
|
use crate::{diagnostic::{Diagnositics, span::Span}, lexer::{err::LexingError, types::{TokenValue, TypeIdent}}};
|
||||||
|
|
||||||
use super::types::Token;
|
use super::types::Token;
|
||||||
|
|
||||||
@@ -359,6 +358,7 @@ fn parse_ident(
|
|||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::io::BufRead;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use crate::utils::case_list::CaseList;
|
use crate::utils::case_list::CaseList;
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
pub mod types;
|
|
||||||
pub mod lexer;
|
|
||||||
pub mod parser;
|
|
||||||
pub mod err;
|
pub mod err;
|
||||||
|
pub mod lexer;
|
||||||
|
pub mod types;
|
||||||
@@ -26,7 +26,7 @@ pub enum TokenValue {
|
|||||||
|
|
||||||
If, Else, While, Return, Break, Continue,
|
If, Else, While, Return, Break, Continue,
|
||||||
|
|
||||||
// Eof,
|
Eof,
|
||||||
Unrecognized,
|
Unrecognized,
|
||||||
}
|
}
|
||||||
impl TokenValue {
|
impl TokenValue {
|
||||||
@@ -80,7 +80,7 @@ impl std::fmt::Display for TokenValue {
|
|||||||
TokenValue::Return => write!(f, "return"),
|
TokenValue::Return => write!(f, "return"),
|
||||||
TokenValue::Break => write!(f, "break"),
|
TokenValue::Break => write!(f, "break"),
|
||||||
TokenValue::Continue => write!(f, "continue"),
|
TokenValue::Continue => write!(f, "continue"),
|
||||||
// TokenValue::Eof => write!(f, "<EOF>"),
|
TokenValue::Eof => write!(f, "<EOF>"),
|
||||||
TokenValue::Unrecognized => write!(f, "unrecognized"),
|
TokenValue::Unrecognized => write!(f, "unrecognized"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ pub enum TokenKind {
|
|||||||
|
|
||||||
If, Else, While, Return, Break, Continue,
|
If, Else, While, Return, Break, Continue,
|
||||||
|
|
||||||
// Eof,
|
Eof,
|
||||||
Unrecognized,
|
Unrecognized,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString, AsRefStr)]
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
mod frontend;
|
mod lexer;
|
||||||
mod ast;
|
mod ast;
|
||||||
mod ir;
|
mod ir;
|
||||||
mod backend;
|
mod backend;
|
||||||
@@ -11,7 +11,7 @@ use std::{fs::File, io::BufRead};
|
|||||||
|
|
||||||
use clap::Parser as ArgParser;
|
use clap::Parser as ArgParser;
|
||||||
|
|
||||||
use crate::{frontend::{lexer::Lexer, parser::Parser}, ir::generator::Generator, sema::analyzer::Analyzer};
|
use crate::{ast::parser::Parser, ir::generator::Generator, lexer::lexer::Lexer, sema::analyzer::Analyzer};
|
||||||
use crate::backend::generator::Generator as ASMGerenerator;
|
use crate::backend::generator::Generator as ASMGerenerator;
|
||||||
/// Simple minic compiler built by Rust
|
/// Simple minic compiler built by Rust
|
||||||
#[derive(ArgParser, Debug)]
|
#[derive(ArgParser, Debug)]
|
||||||
|
|||||||
Reference in New Issue
Block a user