989 lines
31 KiB
Rust
989 lines
31 KiB
Rust
use super::lexer::Token;
|
|
use crate::model::{
|
|
AssignmentOperator, BinaryOperator, Block, Call, CompilerError, ConstExpr, Declaration,
|
|
Dependency, Expression, Number, Program, Statement, TypeId, UnaryOperator, Variable,
|
|
};
|
|
use crate::{expect_tt, expect_value};
|
|
use std::ops::{ControlFlow, FromResidual, Residual, Try};
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum ParseResult<T, E> {
|
|
Accept(T),
|
|
Deny,
|
|
Reject(E),
|
|
}
|
|
|
|
pub struct Parser {
|
|
tokens: Vec<Token>,
|
|
idx: usize,
|
|
}
|
|
|
|
impl Parser {
|
|
pub fn new(tokens: Vec<Token>) -> Self {
|
|
Self { tokens, idx: 0 }
|
|
}
|
|
|
|
pub fn parse(&mut self) -> ParseResult<Program, CompilerError> {
|
|
let mut declarations = Vec::new();
|
|
|
|
while let ParseResult::Accept(_) = self.peek_next() {
|
|
declarations.push(self.parse_declaration()?);
|
|
}
|
|
|
|
ParseResult::Accept(Program { declarations })
|
|
}
|
|
|
|
fn parse_declaration(&mut self) -> ParseResult<Declaration, CompilerError> {
|
|
if expect_tt!(self.peek_next()?, Fn).accepted() {
|
|
return self.parse_func();
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Struct).accepted() {
|
|
return self.parse_struct();
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Include).accepted() {
|
|
// expect include keyword
|
|
let _ = self.next();
|
|
|
|
// expect namespace identifier
|
|
let name = expect_value!(self.next()?, Identifier)?;
|
|
|
|
// expect colon
|
|
let _ = expect_tt!(self.next()?, Colon)?;
|
|
|
|
// expect string literal (module path)
|
|
let path = expect_value!(self.next()?, String)?;
|
|
|
|
// expect semicolon
|
|
let _ = expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
return ParseResult::Accept(Declaration::Dependency(Dependency {
|
|
name: name.name,
|
|
path,
|
|
}));
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Const, Static).accepted() {
|
|
let is_const = match self.next()? {
|
|
Token::Const => true,
|
|
Token::Static => false,
|
|
_ => {
|
|
return ParseResult::Reject(CompilerError::Generic(String::from(
|
|
"This can't happen!",
|
|
)));
|
|
}
|
|
};
|
|
|
|
let var = self.parse_var_decl()?;
|
|
|
|
let _ = expect_tt!(self.next()?, Assign)?;
|
|
|
|
let value = self.next()?;
|
|
let init = match value {
|
|
Token::String(x) => Some(ConstExpr::String(x)),
|
|
Token::SignedInt(x, _) => Some(ConstExpr::Number(x)),
|
|
Token::UnsignedInt(x, _) => Some(ConstExpr::Number(x as i32)),
|
|
_ => {
|
|
return ParseResult::Reject(CompilerError::UnexpectedToken(
|
|
value.tt().to_string(),
|
|
));
|
|
}
|
|
};
|
|
|
|
let _ = expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
return ParseResult::Accept(Declaration::Variable {
|
|
var,
|
|
init,
|
|
is_const,
|
|
});
|
|
}
|
|
|
|
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
|
}
|
|
|
|
fn parse_struct(&mut self) -> ParseResult<Declaration, CompilerError> {
|
|
let _ = expect_tt!(self.next()?, Struct)?;
|
|
let name = expect_value!(self.next()?, Identifier)?;
|
|
|
|
let _ = expect_tt!(self.next()?, LeftBrace)?;
|
|
|
|
let mut fields = Vec::new();
|
|
while expect_tt!(self.peek_next()?, Identifier).accepted() {
|
|
let arg = self.parse_var_decl()?;
|
|
fields.push(arg);
|
|
|
|
if expect_tt!(self.peek_next()?, Comma).accepted() {
|
|
self.next()?;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
let _ = expect_tt!(self.next()?, RightBrace)?;
|
|
ParseResult::Accept(Declaration::Struct { name, fields })
|
|
}
|
|
|
|
fn parse_func(&mut self) -> ParseResult<Declaration, CompilerError> {
|
|
// expect function keyword
|
|
let _ = expect_tt!(self.next()?, Fn);
|
|
// expect function name
|
|
let name = expect_value!(self.next()?, Identifier)?;
|
|
|
|
// expect left paren
|
|
let _ = expect_tt!(self.next()?, LeftParen)?;
|
|
|
|
let mut params = Vec::new();
|
|
while expect_tt!(self.peek_next()?, Identifier).accepted() {
|
|
let arg = self.parse_var_decl()?;
|
|
params.push(arg);
|
|
|
|
if expect_tt!(self.peek_next()?, Comma).accepted() {
|
|
self.next()?;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// expect right paren
|
|
let _ = expect_tt!(self.next()?, RightParen)?;
|
|
|
|
// see if we can parse the return type!
|
|
let mut return_type = TypeId::Void;
|
|
if expect_tt!(self.peek_next()?, RightArrow).accepted() {
|
|
let _ = self.next();
|
|
return_type = self.parse_type()?;
|
|
}
|
|
|
|
// expect vald block
|
|
if expect_tt!(self.peek_next()?, LeftBrace).accepted() {
|
|
ParseResult::Accept(Declaration::Function {
|
|
name: name.name,
|
|
params,
|
|
return_type,
|
|
body: self.parse_block()?,
|
|
})
|
|
} else {
|
|
ParseResult::Reject(CompilerError::UnexpectedToken(
|
|
self.peek_next()?.tt().to_string(),
|
|
))
|
|
}
|
|
}
|
|
|
|
fn parse_block(&mut self) -> ParseResult<Block, CompilerError> {
|
|
// expect left brace
|
|
let _ = expect_tt!(self.next()?, LeftBrace)?;
|
|
|
|
let mut block = Vec::new();
|
|
while !expect_tt!(self.peek_next()?, RightBrace).accepted() {
|
|
block.push(self.parse_statement()?);
|
|
}
|
|
|
|
// expect right brace
|
|
let _ = expect_tt!(self.next()?, RightBrace)?;
|
|
|
|
ParseResult::Accept(block)
|
|
}
|
|
|
|
fn parse_statement(&mut self) -> ParseResult<Statement, CompilerError> {
|
|
// handle if statements
|
|
if expect_tt!(self.peek_next()?, If).accepted() {
|
|
self.next()?;
|
|
|
|
let condition = self.parse_expression()?;
|
|
|
|
let then_stmt = self.parse_block()?;
|
|
|
|
if !expect_tt!(self.peek_next()?, Else).accepted() {
|
|
return ParseResult::Accept(Statement::If {
|
|
condition,
|
|
then_stmt,
|
|
else_stmt: vec![],
|
|
});
|
|
}
|
|
|
|
let _ = expect_tt!(self.next()?, Else)?;
|
|
|
|
let else_stmt = self.parse_block()?;
|
|
|
|
return ParseResult::Accept(Statement::If {
|
|
condition,
|
|
then_stmt,
|
|
else_stmt,
|
|
});
|
|
}
|
|
|
|
// handle while loops
|
|
if expect_tt!(self.peek_next()?, While).accepted() {
|
|
self.next()?;
|
|
|
|
// expect valid expression
|
|
let expr = self.parse_expression()?;
|
|
|
|
// expect valid block after
|
|
let block = self.parse_block()?;
|
|
|
|
// return result
|
|
return ParseResult::Accept(Statement::While {
|
|
condition: expr,
|
|
body: block,
|
|
});
|
|
}
|
|
|
|
// handle indefinite loops
|
|
if expect_tt!(self.peek_next()?, Loop).accepted() {
|
|
self.next()?;
|
|
|
|
// parse the inner block
|
|
return ParseResult::Accept(Statement::Loop(self.parse_block()?));
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Return).accepted() {
|
|
self.next()?;
|
|
|
|
// handle case where nothing is returned
|
|
if expect_tt!(self.peek_next()?, Semicolon).accepted() {
|
|
return ParseResult::Accept(Statement::Return(None));
|
|
}
|
|
|
|
let expr = self.parse_expression()?;
|
|
expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
return ParseResult::Accept(Statement::Return(Some(expr)));
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Break).accepted() {
|
|
self.next()?;
|
|
|
|
// expect semicolon
|
|
expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
// return result
|
|
return ParseResult::Accept(Statement::Break);
|
|
}
|
|
|
|
if expect_tt!(self.peek_next()?, Continue).accepted() {
|
|
self.next()?;
|
|
|
|
// expect semicolon
|
|
expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
// return result
|
|
return ParseResult::Accept(Statement::Continue);
|
|
}
|
|
|
|
// handle writes to pointers!
|
|
if expect_tt!(self.peek_next()?, Star).accepted() {
|
|
self.next()?;
|
|
|
|
let left = if expect_tt!(self.peek_next()?, Identifier).accepted() {
|
|
let identifier = expect_value!(self.next()?, Identifier)?;
|
|
|
|
Expression::Variable {
|
|
name: identifier,
|
|
expr_type: None,
|
|
}
|
|
} else if expect_tt!(self.peek_next()?, LeftParen).accepted() {
|
|
self.next()?;
|
|
|
|
let expr = self.parse_expression()?;
|
|
|
|
let _ = expect_tt!(self.next()?, RightParen).accepted();
|
|
|
|
expr
|
|
} else {
|
|
return ParseResult::Reject(CompilerError::UnexpectedToken(
|
|
self.peek_next()?.tt().to_string(),
|
|
));
|
|
};
|
|
|
|
let _ = expect_tt!(self.next()?, Assign)?;
|
|
|
|
let right = self.parse_expression()?;
|
|
|
|
// expect semicolon
|
|
expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
// return result
|
|
return ParseResult::Accept(Statement::PtrWrite {
|
|
ptr: left,
|
|
value: right,
|
|
});
|
|
}
|
|
|
|
// handle let statements (declarations)
|
|
if expect_tt!(self.peek_next()?, Let).accepted() {
|
|
self.next();
|
|
|
|
// expect variable name and type.
|
|
let name = self.parse_var_decl()?;
|
|
|
|
// handle uninitialised variable case
|
|
if expect_tt!(self.peek_next()?, Semicolon).accepted() {
|
|
self.next();
|
|
return ParseResult::Accept(Statement::Declaration {
|
|
var: name,
|
|
value: None,
|
|
});
|
|
}
|
|
|
|
// handle initialised case
|
|
// expect equals
|
|
let _ = expect_tt!(self.next()?, Assign)?;
|
|
|
|
// expect a valid expression
|
|
let expr = self.parse_expression()?;
|
|
|
|
let _ = expect_tt!(self.next()?, Semicolon);
|
|
|
|
// return statement
|
|
return ParseResult::Accept(Statement::Declaration {
|
|
var: name,
|
|
value: Some(expr),
|
|
});
|
|
}
|
|
|
|
// handle an in-place function call
|
|
if let ParseResult::Accept(name) = expect_value!(self.peek_next()?, Identifier)
|
|
&& let ParseResult::Accept(operator) = expect_tt!(
|
|
self.peek(1)?,
|
|
Assign,
|
|
PlusEqual,
|
|
MinusEqual,
|
|
StarEqual,
|
|
SlashEqual,
|
|
PercentEqual,
|
|
AndEqual,
|
|
OrEqual,
|
|
XorEqual,
|
|
ShlEqual,
|
|
ShrEqual
|
|
)
|
|
{
|
|
// consume name token
|
|
self.next()?;
|
|
|
|
// pattern match to find operator
|
|
let operator = match operator {
|
|
Token::Assign => AssignmentOperator::Assign,
|
|
Token::PlusEqual => AssignmentOperator::AddAssign,
|
|
Token::MinusEqual => AssignmentOperator::SubAssign,
|
|
Token::StarEqual => AssignmentOperator::MulAssign,
|
|
Token::SlashEqual => AssignmentOperator::DivAssign,
|
|
Token::PercentEqual => AssignmentOperator::ModAssign,
|
|
Token::AndEqual => AssignmentOperator::AndAssign,
|
|
Token::OrEqual => AssignmentOperator::OrAssign,
|
|
Token::XorEqual => AssignmentOperator::XorAssign,
|
|
Token::ShlEqual => AssignmentOperator::LeftShiftAssign,
|
|
Token::ShrEqual => AssignmentOperator::RightShiftAssign,
|
|
_ => {
|
|
return ParseResult::Reject(CompilerError::UnexpectedToken(
|
|
self.peek_next()?.tt().to_string(),
|
|
));
|
|
}
|
|
};
|
|
|
|
// consume operator token
|
|
self.next()?;
|
|
|
|
let value = self.parse_expression()?;
|
|
|
|
let _ = expect_tt!(self.next()?, Semicolon);
|
|
|
|
return ParseResult::Accept(Statement::Assign {
|
|
varname: name.name,
|
|
operator,
|
|
value,
|
|
});
|
|
}
|
|
|
|
// parse an expression and a semicolon
|
|
let expr = self.parse_expression()?;
|
|
let _ = expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
ParseResult::Accept(Statement::Expression { expr })
|
|
}
|
|
|
|
fn parse_expression(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
self.parse_logical_or()
|
|
}
|
|
|
|
fn parse_logical_or(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_logical_and()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::LogicalOr => BinaryOperator::LogicalOr,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_logical_or()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_logical_and(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_bitwise_or()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::LogicalAnd => BinaryOperator::LogicalAnd,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_logical_and()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_bitwise_or(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_bitwise_xor()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::Pipe => BinaryOperator::BitwiseOr,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_bitwise_or()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_bitwise_xor(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_bitwise_and()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::Caret => BinaryOperator::BitwiseXor,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_bitwise_xor()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_bitwise_and(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_comparison()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::Ampersand => BinaryOperator::BitwiseAnd,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_bitwise_and()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_comparison(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_shift()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::EqualEqual => BinaryOperator::Equal,
|
|
Token::BangEqual => BinaryOperator::NotEqual,
|
|
Token::Less => BinaryOperator::LessThan,
|
|
Token::Greater => BinaryOperator::GreaterThan,
|
|
Token::LessEqual => BinaryOperator::LessOrEqual,
|
|
Token::GreaterEqual => BinaryOperator::GreaterOrEqual,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_comparison()?),
|
|
type_id: Some(TypeId::Bool),
|
|
})
|
|
}
|
|
|
|
fn parse_shift(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_additive()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::LeftShift => BinaryOperator::LeftShift,
|
|
Token::RightShift => BinaryOperator::RightShift,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_shift()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_additive(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_multiplicative()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::Plus => BinaryOperator::Add,
|
|
Token::Minus => BinaryOperator::Sub,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_additive()?),
|
|
type_id: Some(TypeId::U32),
|
|
})
|
|
}
|
|
|
|
fn parse_multiplicative(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let left = self.parse_unary()?;
|
|
|
|
let op = match self.peek_next()? {
|
|
Token::Star => BinaryOperator::Mul,
|
|
Token::Slash => BinaryOperator::Div,
|
|
_ => return ParseResult::Accept(left),
|
|
};
|
|
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Binary {
|
|
op,
|
|
left: Box::new(left),
|
|
right: Box::new(self.parse_multiplicative()?),
|
|
type_id: None,
|
|
})
|
|
}
|
|
|
|
fn parse_unary(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
let op = match self.peek_next()? {
|
|
// prefix inc/dec
|
|
Token::PlusPlus => UnaryOperator::Increment,
|
|
Token::MinusMinus => UnaryOperator::Decrement,
|
|
|
|
// arithmetic
|
|
Token::Plus => UnaryOperator::Plus,
|
|
Token::Minus => UnaryOperator::Minus,
|
|
|
|
// pointer
|
|
Token::Star => UnaryOperator::Dereference,
|
|
Token::Ampersand => UnaryOperator::AddressOf,
|
|
|
|
// boolean
|
|
Token::Bang => UnaryOperator::LogicalNot,
|
|
Token::Tilde => UnaryOperator::BitwiseNot,
|
|
|
|
Token::SizeOf => UnaryOperator::SizeOf,
|
|
_ => {
|
|
let expr = self.parse_primary()?;
|
|
return self.parse_postfix(expr);
|
|
}
|
|
};
|
|
|
|
self.next()?;
|
|
let operand = Box::new(self.parse_unary()?);
|
|
ParseResult::Accept(Expression::Unary {
|
|
op,
|
|
operand,
|
|
type_id: None,
|
|
})
|
|
}
|
|
|
|
fn parse_postfix(&mut self, mut expr: Expression) -> ParseResult<Expression, CompilerError> {
|
|
loop {
|
|
match self.peek_next()? {
|
|
// Type cast: expr as Type
|
|
Token::As => {
|
|
self.next()?; // consume 'as'
|
|
let target_type = self.parse_type()?;
|
|
expr = Expression::TypeCast {
|
|
expr: Box::new(expr),
|
|
target_type,
|
|
type_id: None,
|
|
};
|
|
}
|
|
|
|
// Postfix increment/decrement
|
|
Token::PlusPlus => {
|
|
self.next()?;
|
|
expr = Expression::UnaryPostfix {
|
|
op: UnaryOperator::Increment,
|
|
operand: Box::new(expr),
|
|
type_id: None,
|
|
};
|
|
}
|
|
Token::MinusMinus => {
|
|
self.next()?;
|
|
expr = Expression::UnaryPostfix {
|
|
op: UnaryOperator::Decrement,
|
|
operand: Box::new(expr),
|
|
type_id: None,
|
|
};
|
|
}
|
|
|
|
// Array indexing: expr[index]
|
|
Token::LeftBracket => {
|
|
self.next()?; // consume '['
|
|
let index = Box::new(self.parse_expression()?);
|
|
|
|
let _ = expect_tt!(self.next()?, RightBracket)?;
|
|
|
|
expr = Expression::IndexAccess {
|
|
expr: Box::new(expr),
|
|
index,
|
|
type_id: None,
|
|
};
|
|
}
|
|
|
|
// Function call: expr(args...)
|
|
Token::LeftParen => {
|
|
self.next()?; // consume '('
|
|
let mut args = Vec::new();
|
|
|
|
if !matches!(self.peek_next()?, Token::RightParen) {
|
|
loop {
|
|
args.push(self.parse_expression()?);
|
|
if !matches!(self.peek_next()?, Token::Comma) {
|
|
break;
|
|
}
|
|
self.next()?; // consume comma
|
|
}
|
|
}
|
|
|
|
let _ = expect_tt!(self.next()?, RightParen)?;
|
|
|
|
if let Expression::Variable { name, .. } = expr {
|
|
expr = Expression::Call {
|
|
func: Call { name, args },
|
|
type_id: None,
|
|
};
|
|
}
|
|
}
|
|
|
|
// Member access: expr.member (if you support structs)
|
|
Token::Dot => {
|
|
self.next()?;
|
|
let field_name = expect_value!(self.next()?, Identifier)?;
|
|
expr = Expression::MemberAccess {
|
|
expr: Box::new(expr),
|
|
field_name,
|
|
type_id: None,
|
|
};
|
|
}
|
|
|
|
// No more postfix operations
|
|
_ => break,
|
|
}
|
|
}
|
|
|
|
ParseResult::Accept(expr)
|
|
}
|
|
|
|
fn parse_primary(&mut self) -> ParseResult<Expression, CompilerError> {
|
|
match self.peek_next()? {
|
|
Token::UnsignedInt(value, type_id) => {
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Number(Number::Unsigned(value, type_id)))
|
|
}
|
|
Token::SignedInt(value, type_id) => {
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::Number(Number::Signed(value, type_id)))
|
|
}
|
|
Token::String(value) => {
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::StringLiteral(value))
|
|
}
|
|
Token::Char(value) => {
|
|
self.next()?;
|
|
ParseResult::Accept(Expression::CharLiteral(value))
|
|
}
|
|
|
|
Token::Identifier(name) => {
|
|
self.next()?;
|
|
|
|
// if the next token isn't the beginning of a struct literal this is just
|
|
// an identifier.
|
|
// if !expect_tt!(self.peek_next()?, LeftBrace).accepted() {
|
|
// return ParseResult::Accept(Expression::Variable {
|
|
// name,
|
|
// expr_type: None,
|
|
// });
|
|
// }
|
|
//
|
|
ParseResult::Accept(Expression::Variable {
|
|
name,
|
|
expr_type: None,
|
|
})
|
|
|
|
// let _ = self.next()?;
|
|
|
|
// let mut fields = Vec::new();
|
|
// while !expect_tt!(self.peek_next()?, RightBrace).accepted() {
|
|
// let name = expect_value!(self.next()?, Identifier)?;
|
|
// let _ = expect_tt!(self.next()?, Colon)?;
|
|
// let expr = self.parse_expression()?;
|
|
|
|
// fields.push((name, expr));
|
|
|
|
// if expect_tt!(self.peek_next()?, Comma).accepted() {
|
|
// self.next()?;
|
|
// } else {
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// let _ = expect_tt!(self.next()?, RightBrace)?;
|
|
|
|
// ParseResult::Accept(Expression::StructLiteral {
|
|
// name,
|
|
// fields,
|
|
// type_id: None,
|
|
// })
|
|
}
|
|
Token::LeftBracket => {
|
|
self.next()?; // consume '['
|
|
let mut elements = Vec::new();
|
|
|
|
if !matches!(self.peek_next()?, Token::RightBracket) {
|
|
loop {
|
|
elements.push(self.parse_expression()?);
|
|
if !matches!(self.peek_next()?, Token::Comma) {
|
|
break;
|
|
}
|
|
self.next()?; // consume comma
|
|
}
|
|
}
|
|
|
|
expect_tt!(self.next()?, RightBracket)?;
|
|
ParseResult::Accept(Expression::ArrayLiteral {
|
|
elements,
|
|
type_id: None,
|
|
})
|
|
}
|
|
Token::LeftParen => {
|
|
self.next()?;
|
|
let expr = self.parse_expression()?;
|
|
let _ = expect_tt!(self.next()?, RightParen)?;
|
|
ParseResult::Accept(expr)
|
|
}
|
|
_ => ParseResult::Reject(CompilerError::UnexpectedToken(
|
|
self.peek_next()?.tt().to_string(),
|
|
)),
|
|
}
|
|
}
|
|
|
|
fn parse_var_decl(&mut self) -> ParseResult<Variable, CompilerError> {
|
|
let name = expect_value!(self.next()?, Identifier)?;
|
|
|
|
let _ = expect_tt!(self.next()?, Colon)?;
|
|
|
|
let type_id = self.parse_type()?;
|
|
|
|
ParseResult::Accept(Variable {
|
|
name: name.name,
|
|
type_id,
|
|
})
|
|
}
|
|
|
|
fn parse_type(&mut self) -> ParseResult<TypeId, CompilerError> {
|
|
// parse primitive or named type
|
|
if expect_tt!(self.peek_next()?, Identifier).accepted() {
|
|
return self.parse_type_identifier();
|
|
}
|
|
|
|
// parse array type
|
|
if expect_tt!(self.peek_next()?, LeftBracket).accepted() {
|
|
let _ = self.next()?;
|
|
|
|
let internal_type = self.parse_type()?;
|
|
let _ = expect_tt!(self.next()?, Semicolon)?;
|
|
|
|
let size = expect_value!(self.next()?, UnsignedInt)?;
|
|
|
|
let _ = expect_tt!(self.next()?, RightBracket)?;
|
|
|
|
return ParseResult::Accept(TypeId::Array {
|
|
r#type: Box::new(internal_type),
|
|
size: size as usize,
|
|
});
|
|
}
|
|
|
|
// parse tuple type
|
|
if expect_tt!(self.peek_next()?, LeftParen).accepted() {
|
|
let _ = self.next()?;
|
|
|
|
let mut types = Vec::new();
|
|
while !expect_tt!(self.peek_next()?, RightParen).accepted() {
|
|
types.push(self.parse_type()?);
|
|
if !expect_tt!(self.peek_next()?, Comma).accepted() {
|
|
break;
|
|
}
|
|
let _ = self.next()?;
|
|
}
|
|
let _ = expect_tt!(self.next()?, RightParen)?;
|
|
|
|
return ParseResult::Accept(TypeId::Tuple(types));
|
|
}
|
|
|
|
ParseResult::Reject(CompilerError::Generic(format!(
|
|
"Parsing type but no valid type was detected: {:?}",
|
|
self.peek_next()?
|
|
)))
|
|
}
|
|
|
|
fn parse_type_identifier(&mut self) -> ParseResult<TypeId, CompilerError> {
|
|
// get the type name incl namespace
|
|
let name = expect_value!(self.next()?, Identifier)?;
|
|
|
|
let type_id = match name.name.as_str() {
|
|
"u32" => TypeId::U32,
|
|
"u16" => TypeId::U16,
|
|
"u8" => TypeId::U8,
|
|
"i32" => TypeId::I32,
|
|
"i16" => TypeId::I16,
|
|
"i8" => TypeId::I8,
|
|
"void" => TypeId::Void,
|
|
"char" => TypeId::Char,
|
|
"str" => TypeId::Ptr(Box::new(TypeId::Char)),
|
|
_ => {
|
|
let mut generics = Vec::new();
|
|
if expect_tt!(self.peek_next()?, Less).accepted() {
|
|
let _ = self.next()?;
|
|
|
|
// loop until we find the closing '>'
|
|
while !expect_tt!(self.peek_next()?, Greater).accepted() {
|
|
generics.push(self.parse_type()?);
|
|
if !expect_tt!(self.peek_next()?, Comma).accepted() {
|
|
break;
|
|
}
|
|
let _ = self.next()?;
|
|
}
|
|
let _ = expect_tt!(self.next()?, Greater)?;
|
|
}
|
|
|
|
TypeId::UnknownCustom { name, generics }
|
|
}
|
|
};
|
|
|
|
ParseResult::Accept(type_id)
|
|
}
|
|
|
|
fn next(&mut self) -> ParseResult<Token, CompilerError> {
|
|
if self.idx >= self.tokens.len() {
|
|
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
|
} else {
|
|
let token = self.tokens[self.idx].clone();
|
|
self.idx += 1;
|
|
ParseResult::Accept(token)
|
|
}
|
|
}
|
|
|
|
fn peek_next(&self) -> ParseResult<Token, CompilerError> {
|
|
if self.idx >= self.tokens.len() {
|
|
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
|
} else {
|
|
ParseResult::Accept(self.tokens[self.idx].clone())
|
|
}
|
|
}
|
|
|
|
fn peek(&self, offset: usize) -> ParseResult<Token, CompilerError> {
|
|
if self.idx + offset >= self.tokens.len() {
|
|
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
|
} else {
|
|
ParseResult::Accept(self.tokens[self.idx + offset].clone())
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T, E> ParseResult<T, E> {
|
|
pub fn accepted(&self) -> bool {
|
|
matches!(self, ParseResult::Accept(_))
|
|
}
|
|
}
|
|
|
|
pub enum ParseResultResidual<T> {
|
|
Deny,
|
|
Reject(T),
|
|
}
|
|
|
|
impl<T, E> Residual<T> for ParseResultResidual<E> {
|
|
type TryType = ParseResult<T, E>;
|
|
}
|
|
|
|
impl<T, E> Try for ParseResult<T, E> {
|
|
type Output = T;
|
|
type Residual = ParseResultResidual<E>;
|
|
|
|
fn from_output(output: T) -> Self {
|
|
ParseResult::Accept(output)
|
|
}
|
|
|
|
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
|
match self {
|
|
ParseResult::Accept(v) => ControlFlow::Continue(v),
|
|
ParseResult::Deny => ControlFlow::Break(ParseResultResidual::Deny),
|
|
ParseResult::Reject(e) => ControlFlow::Break(ParseResultResidual::Reject(e)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T, E> FromResidual for ParseResult<T, E> {
|
|
fn from_residual(residual: ParseResultResidual<E>) -> Self {
|
|
match residual {
|
|
ParseResultResidual::Deny => ParseResult::Deny,
|
|
ParseResultResidual::Reject(e) => ParseResult::Reject(e),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! expect_tt {
|
|
($token:expr, $($variant:ident),+) => {{
|
|
let token = $token.clone();
|
|
let tt = token.tt().to_string();
|
|
|
|
let mut vs = String::new();
|
|
$(
|
|
let s = stringify!($variant);
|
|
vs.push_str(s);
|
|
vs.push_str("|");
|
|
)+
|
|
|
|
match tt.as_str() {
|
|
$(
|
|
stringify!($variant) => ParseResult::Accept(token),
|
|
)+
|
|
_ => {
|
|
// let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | "));
|
|
ParseResult::Reject(CompilerError::UnexpectedToken(tt))
|
|
}
|
|
}
|
|
}};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! expect_value {
|
|
($expr:expr, $variant:ident) => {{
|
|
let tok = $expr;
|
|
match tok.clone() {
|
|
Token::$variant(first, ..) => ParseResult::Accept(first),
|
|
_ => ParseResult::Reject(CompilerError::UnexpectedToken(tok.tt().to_string())),
|
|
}
|
|
}};
|
|
}
|