parser done
This commit is contained in:
parent
8705272a77
commit
f6dd337ba1
61
src/ast.rs
61
src/ast.rs
@ -8,6 +8,7 @@ pub struct Node<T> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expr {
|
||||
Error(String),
|
||||
Unit,
|
||||
Id(String),
|
||||
Int(i64),
|
||||
@ -15,9 +16,15 @@ pub enum Expr {
|
||||
String(String),
|
||||
Bool(bool),
|
||||
Array(Vec<Node<Expr>>),
|
||||
Object(Vec<ObjectEntry>),
|
||||
Object(Vec<Node<ObjectEntry>>),
|
||||
Tuple(Vec<Node<Expr>>),
|
||||
|
||||
If {
|
||||
condition: Box<Node<Expr>>,
|
||||
truthy: Box<Node<Expr>>,
|
||||
falsy: Option<Box<Node<Expr>>>,
|
||||
},
|
||||
|
||||
Member {
|
||||
subject: Box<Node<Expr>>,
|
||||
value: String,
|
||||
@ -39,11 +46,44 @@ pub enum Expr {
|
||||
left: Box<Node<Expr>>,
|
||||
right: Box<Node<Expr>>,
|
||||
},
|
||||
|
||||
Assign {
|
||||
assign_type: AssignType,
|
||||
subject: Box<Node<Expr>>,
|
||||
value: Box<Node<Expr>>,
|
||||
},
|
||||
Let {
|
||||
subject: Node<Parameter>,
|
||||
value: Option<Box<Node<Expr>>>,
|
||||
},
|
||||
Continue,
|
||||
Break,
|
||||
While {
|
||||
condition: Box<Node<Expr>>,
|
||||
body: Box<Node<Expr>>,
|
||||
},
|
||||
Return(Option<Box<Node<Expr>>>),
|
||||
Function {
|
||||
name: String,
|
||||
parameters: Vec<Node<Parameter>>,
|
||||
body: Box<Node<Expr>>,
|
||||
},
|
||||
Block {
|
||||
statements: Vec<Node<Expr>>,
|
||||
value: Option<Box<Node<Expr>>>,
|
||||
},
|
||||
|
||||
Spread(Box<Node<Expr>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ObjectEntry {
|
||||
Pair(Box<Node<Expr>>, Box<Expr>),
|
||||
Error(String),
|
||||
Pair {
|
||||
key: Box<Node<Expr>>,
|
||||
value: Box<Node<Expr>>,
|
||||
},
|
||||
Spread(Box<Node<Expr>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -73,3 +113,20 @@ pub enum BinaryType {
|
||||
And,
|
||||
Or,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AssignType {
|
||||
Assign,
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Modulo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Parameter {
|
||||
Error(String),
|
||||
Id { name: String, mutable: bool },
|
||||
Spread(Box<Node<Parameter>>),
|
||||
}
|
||||
|
25
src/lexer.rs
25
src/lexer.rs
@ -46,9 +46,7 @@ impl<'a> Lexer<'a> {
|
||||
'=',
|
||||
TokenType::PercentEqual,
|
||||
)),
|
||||
'=' => {
|
||||
Some(self.single_or_double_char_token(TokenType::Equal, '=', TokenType::EqualEqual))
|
||||
}
|
||||
'=' => Some(self.equal_token()),
|
||||
'!' => Some(self.single_or_double_char_token(
|
||||
TokenType::Exclamation,
|
||||
'=',
|
||||
@ -104,7 +102,7 @@ impl<'a> Lexer<'a> {
|
||||
self.step();
|
||||
}
|
||||
if self.done() || self.current() != '"' {
|
||||
self.step_and_token(TokenType::MalformedString, start)
|
||||
self.token(TokenType::MalformedString, start)
|
||||
} else {
|
||||
self.step_and_token(TokenType::String, start)
|
||||
}
|
||||
@ -213,6 +211,18 @@ impl<'a> Lexer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn equal_token(&mut self) -> Token {
|
||||
let start = self.pos();
|
||||
self.step();
|
||||
if !self.done() && self.current() == '=' {
|
||||
self.step_and_token(TokenType::EqualEqual, start)
|
||||
} else if !self.done() && self.current() == '>' {
|
||||
self.step_and_token(TokenType::EqualLessThan, start)
|
||||
} else {
|
||||
self.step_and_token(TokenType::Equal, start)
|
||||
}
|
||||
}
|
||||
|
||||
fn dot_token(&mut self) -> Token {
|
||||
let start = self.pos();
|
||||
self.step();
|
||||
@ -222,6 +232,13 @@ impl<'a> Lexer<'a> {
|
||||
self.step();
|
||||
}
|
||||
self.token(TokenType::Decimal, start)
|
||||
} else if !self.done() && self.current() == '.' {
|
||||
self.step();
|
||||
if !self.done() && self.current() == '.' {
|
||||
self.step_and_token(TokenType::DotDotDot, start)
|
||||
} else {
|
||||
self.token(TokenType::DotDot, start)
|
||||
}
|
||||
} else {
|
||||
self.token(TokenType::Dot, start)
|
||||
}
|
||||
|
30
src/main.rs
30
src/main.rs
@ -9,15 +9,33 @@ use crate::lexer::Lexer;
|
||||
use crate::parser::Parser;
|
||||
|
||||
fn main() {
|
||||
// println!("tokens = [");
|
||||
// let text = "** 3.14 \"foo\" false true ( ) + += /* 1 /* 2 */ 3 */ // 4 \n 5";
|
||||
// let lexer = Lexer::new(text);
|
||||
// lexer.for_each(|token| {
|
||||
// println!(
|
||||
// " {:?} = `{}`,",
|
||||
// token.token_type,
|
||||
// &text[token.pos.index..token.pos.index + token.length]
|
||||
// );
|
||||
// });
|
||||
// println!("]");
|
||||
|
||||
let text2 = "[1, 2, ...a]";
|
||||
let lexer2 = Lexer::new(text2);
|
||||
println!("tokens = [");
|
||||
let text = "** 3.14 \"foo\" false true ( ) + += /* 1 /* 2 */ 3 */ // 4 \n 5";
|
||||
let lexer = Lexer::new(text);
|
||||
lexer.for_each(|token| {
|
||||
println!(" {:?},", token);
|
||||
lexer2.for_each(|token| {
|
||||
println!(
|
||||
" ({:?}, `{}`, [{}], {}, {}:{}),",
|
||||
token.token_type,
|
||||
&text2[token.pos.index..token.pos.index + token.length],
|
||||
token.pos.index,
|
||||
token.length,
|
||||
token.pos.line,
|
||||
token.pos.col,
|
||||
);
|
||||
});
|
||||
println!("]");
|
||||
|
||||
let text2 = "1 + 2 * 3";
|
||||
let mut parser = Parser::new(text2, Lexer::new(text2));
|
||||
let expr = parser.parse_expr();
|
||||
println!("ast = {:#?}", expr);
|
||||
|
558
src/parser.rs
558
src/parser.rs
@ -1,11 +1,8 @@
|
||||
use crate::ast::{BinaryType, Expr, Node, UnaryType};
|
||||
use crate::tokens::{Position, PositionKnowing, Token, TokenType};
|
||||
use std::iter::Peekable;
|
||||
use std::str::Chars;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserError {
|
||||
pos: Position,
|
||||
message: String,
|
||||
}
|
||||
use crate::ast::{AssignType, BinaryType, Expr, Node, ObjectEntry, Parameter, UnaryType};
|
||||
use crate::tokens::{PositionKnowing, Token, TokenType};
|
||||
|
||||
pub struct Parser<'a, Tokens>
|
||||
where
|
||||
@ -28,16 +25,239 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_expr(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
pub fn parse_top_level_statements(&mut self) -> Vec<Node<Expr>> {
|
||||
let mut statements = Vec::<Node<Expr>>::new();
|
||||
while !self.done() {
|
||||
statements.push(self.parse_statement());
|
||||
}
|
||||
statements
|
||||
}
|
||||
|
||||
fn parse_block(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let mut statements = Vec::<Node<Expr>>::new();
|
||||
let mut last = None;
|
||||
while !self.done() && !self.current_is(TokenType::RBrace) {
|
||||
if let Some(statement) = last {
|
||||
statements.push(statement);
|
||||
}
|
||||
last = Some(self.parse_statement());
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RBrace) {
|
||||
statements.push(self.error("expected '}'"));
|
||||
}
|
||||
self.node(Expr::Block {
|
||||
statements,
|
||||
value: last.map(|v| Box::new(v)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_statement(&mut self) -> Node<Expr> {
|
||||
if self.done() {
|
||||
return self.error("expected statement");
|
||||
}
|
||||
match self.current().token_type {
|
||||
TokenType::Fn => self.parse_function(),
|
||||
TokenType::Return => self.parse_function(),
|
||||
TokenType::While => self.parse_function(),
|
||||
TokenType::Break => self.parse_function(),
|
||||
TokenType::Continue => self.parse_function(),
|
||||
_ => self.parse_assign(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_function(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
if self.done() || !self.current_is(TokenType::Id) {
|
||||
return self.error("expected Id");
|
||||
}
|
||||
let name = self.token_string(self.current());
|
||||
self.step();
|
||||
if self.done() || !self.current_is(TokenType::LParen) {
|
||||
return self.error("expected '('");
|
||||
}
|
||||
self.step();
|
||||
let mut parameters = Vec::<Node<Parameter>>::new();
|
||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
self.step();
|
||||
let inner = self.parse_parameter();
|
||||
parameters.push(self.node(Parameter::Spread(Box::new(inner))));
|
||||
} else {
|
||||
parameters.push(self.parse_parameter());
|
||||
while !self.done() && self.current_is(TokenType::Comma) {
|
||||
self.step();
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
self.step();
|
||||
let inner = self.parse_parameter();
|
||||
parameters.push(self.node(Parameter::Spread(Box::new(inner))));
|
||||
break;
|
||||
}
|
||||
if self.done() || self.current_is(TokenType::RParen) {
|
||||
break;
|
||||
}
|
||||
parameters.push(self.parse_parameter());
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RParen) {
|
||||
return self.error("expected ')'");
|
||||
}
|
||||
self.step();
|
||||
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||
return self.error("expected '{'");
|
||||
}
|
||||
let body = self.parse_block();
|
||||
self.node(Expr::Function {
|
||||
name,
|
||||
parameters,
|
||||
body: Box::new(body),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_parameter(&mut self) -> Node<Parameter> {
|
||||
let mutable = if !self.done() && self.current_is(TokenType::Mut) {
|
||||
self.step();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if self.done() || !self.current_is(TokenType::Id) {
|
||||
return self.node(Parameter::Error("expected Id".to_string()));
|
||||
}
|
||||
let name = self.token_string(self.current());
|
||||
self.step_and_node(Parameter::Id { mutable, name })
|
||||
}
|
||||
|
||||
fn parse_return(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
if !self.done() && !self.current_is(TokenType::Semicolon) {
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Return(Some(Box::new(value))))
|
||||
} else {
|
||||
self.node(Expr::Return(None))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_while(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let condition = self.parse_expr();
|
||||
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||
return self.error("expected '{'");
|
||||
}
|
||||
let body = self.parse_block();
|
||||
self.node(Expr::While {
|
||||
condition: Box::new(condition),
|
||||
body: Box::new(body),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_break(&mut self) -> Node<Expr> {
|
||||
self.step_and_node(Expr::Continue)
|
||||
}
|
||||
|
||||
fn parse_continue(&mut self) -> Node<Expr> {
|
||||
self.step_and_node(Expr::Continue)
|
||||
}
|
||||
|
||||
fn parse_let(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let subject = self.parse_parameter();
|
||||
if !self.done() && self.current_is(TokenType::Equal) {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Let {
|
||||
subject,
|
||||
value: Some(Box::new(value)),
|
||||
})
|
||||
} else {
|
||||
self.node(Expr::Let {
|
||||
subject,
|
||||
value: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_assign(&mut self) -> Node<Expr> {
|
||||
let subject = self.parse_expr();
|
||||
if self.done() {
|
||||
return subject;
|
||||
}
|
||||
match self.current().token_type {
|
||||
TokenType::Equal => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Assign,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
TokenType::PlusEqual => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Add,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
TokenType::MinusEqual => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Subtract,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
TokenType::AsteriskEqual => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Multiply,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
TokenType::SlashEqual => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Divide,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
TokenType::PercentEqual => {
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(Expr::Assign {
|
||||
assign_type: AssignType::Modulo,
|
||||
subject: Box::new(subject),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
_ => subject,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_spread(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let inner = self.parse_expr();
|
||||
self.node(Expr::Spread(Box::new(inner)))
|
||||
}
|
||||
|
||||
pub fn parse_expr(&mut self) -> Node<Expr> {
|
||||
self.parse_prec_or()
|
||||
}
|
||||
|
||||
fn parse_prec_or(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_and()?;
|
||||
fn parse_prec_or(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_and();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::Or) {
|
||||
self.step();
|
||||
let right = self.parse_prec_and()?;
|
||||
let right = self.parse_prec_and();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Or,
|
||||
left: Box::new(left),
|
||||
@ -47,15 +267,15 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_and(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_equal_inequal()?;
|
||||
fn parse_prec_and(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_equal_inequal();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::And) {
|
||||
self.step();
|
||||
let right = self.parse_prec_equal_inequal()?;
|
||||
let right = self.parse_prec_equal_inequal();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::And,
|
||||
left: Box::new(left),
|
||||
@ -65,15 +285,15 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_equal_inequal(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_lt_lte_gt_gte_in()?;
|
||||
fn parse_prec_equal_inequal(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_lt_lte_gt_gte_in();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::EqualEqual) {
|
||||
self.step();
|
||||
let right = self.parse_prec_lt_lte_gt_gte_in()?;
|
||||
let right = self.parse_prec_lt_lte_gt_gte_in();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Equal,
|
||||
left: Box::new(left),
|
||||
@ -81,7 +301,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::ExclamationEqual) {
|
||||
self.step();
|
||||
let right = self.parse_prec_lt_lte_gt_gte_in()?;
|
||||
let right = self.parse_prec_lt_lte_gt_gte_in();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Inequal,
|
||||
left: Box::new(left),
|
||||
@ -91,15 +311,15 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_add_subtract()?;
|
||||
fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_add_subtract();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::LessThan) {
|
||||
self.step();
|
||||
let right = self.parse_prec_add_subtract()?;
|
||||
let right = self.parse_prec_add_subtract();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::LT,
|
||||
left: Box::new(left),
|
||||
@ -107,7 +327,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::GreaterThan) {
|
||||
self.step();
|
||||
let right = self.parse_prec_add_subtract()?;
|
||||
let right = self.parse_prec_add_subtract();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::GT,
|
||||
left: Box::new(left),
|
||||
@ -115,7 +335,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::LessThanEqual) {
|
||||
self.step();
|
||||
let right = self.parse_prec_add_subtract()?;
|
||||
let right = self.parse_prec_add_subtract();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::LTE,
|
||||
left: Box::new(left),
|
||||
@ -123,7 +343,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::GreaterThanEqual) {
|
||||
self.step();
|
||||
let right = self.parse_prec_add_subtract()?;
|
||||
let right = self.parse_prec_add_subtract();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::GTE,
|
||||
left: Box::new(left),
|
||||
@ -131,7 +351,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::In) {
|
||||
self.step();
|
||||
let right = self.parse_prec_add_subtract()?;
|
||||
let right = self.parse_prec_add_subtract();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::In,
|
||||
left: Box::new(left),
|
||||
@ -141,15 +361,15 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_add_subtract(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_multiply_divide_modulo()?;
|
||||
fn parse_prec_add_subtract(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_multiply_divide_modulo();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::Plus) {
|
||||
self.step();
|
||||
let right = self.parse_prec_multiply_divide_modulo()?;
|
||||
let right = self.parse_prec_multiply_divide_modulo();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Add,
|
||||
left: Box::new(left),
|
||||
@ -157,7 +377,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::Minus) {
|
||||
self.step();
|
||||
let right = self.parse_prec_multiply_divide_modulo()?;
|
||||
let right = self.parse_prec_multiply_divide_modulo();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Subtract,
|
||||
left: Box::new(left),
|
||||
@ -167,15 +387,15 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_multiply_divide_modulo(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut left = self.parse_prec_unary()?;
|
||||
fn parse_prec_multiply_divide_modulo(&mut self) -> Node<Expr> {
|
||||
let mut left = self.parse_prec_unary();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::Asterisk) {
|
||||
self.step();
|
||||
let right = self.parse_prec_unary()?;
|
||||
let right = self.parse_prec_unary();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Multiply,
|
||||
left: Box::new(left),
|
||||
@ -183,7 +403,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::Slash) {
|
||||
self.step();
|
||||
let right = self.parse_prec_unary()?;
|
||||
let right = self.parse_prec_unary();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Divide,
|
||||
left: Box::new(left),
|
||||
@ -191,7 +411,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::Percent) {
|
||||
self.step();
|
||||
let right = self.parse_prec_unary()?;
|
||||
let right = self.parse_prec_unary();
|
||||
left = self.node(Expr::Binary {
|
||||
binary_type: BinaryType::Modulo,
|
||||
left: Box::new(left),
|
||||
@ -201,21 +421,21 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
|
||||
fn parse_prec_unary(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
fn parse_prec_unary(&mut self) -> Node<Expr> {
|
||||
if !self.done() && self.current_is(TokenType::Not) {
|
||||
self.step();
|
||||
let subject = Box::new(self.parse_prec_unary()?);
|
||||
self.ok_node(Expr::Unary {
|
||||
let subject = Box::new(self.parse_prec_unary());
|
||||
self.node(Expr::Unary {
|
||||
unary_type: UnaryType::Not,
|
||||
subject,
|
||||
})
|
||||
} else if !self.done() && self.current_is(TokenType::Minus) {
|
||||
self.step();
|
||||
let subject = Box::new(self.parse_prec_unary()?);
|
||||
self.ok_node(Expr::Unary {
|
||||
let subject = Box::new(self.parse_prec_unary());
|
||||
self.node(Expr::Unary {
|
||||
unary_type: UnaryType::Negate,
|
||||
subject,
|
||||
})
|
||||
@ -223,22 +443,22 @@ where
|
||||
self.step();
|
||||
if !self.done() && self.current_is(TokenType::Mut) {
|
||||
self.step();
|
||||
let subject = Box::new(self.parse_prec_unary()?);
|
||||
self.ok_node(Expr::Unary {
|
||||
let subject = Box::new(self.parse_prec_unary());
|
||||
self.node(Expr::Unary {
|
||||
unary_type: UnaryType::ReferenceMut,
|
||||
subject,
|
||||
})
|
||||
} else {
|
||||
let subject = Box::new(self.parse_prec_unary()?);
|
||||
self.ok_node(Expr::Unary {
|
||||
let subject = Box::new(self.parse_prec_unary());
|
||||
self.node(Expr::Unary {
|
||||
unary_type: UnaryType::Reference,
|
||||
subject,
|
||||
})
|
||||
}
|
||||
} else if !self.done() && self.current_is(TokenType::Asterisk) {
|
||||
self.step();
|
||||
let subject = Box::new(self.parse_prec_unary()?);
|
||||
self.ok_node(Expr::Unary {
|
||||
let subject = Box::new(self.parse_prec_unary());
|
||||
self.node(Expr::Unary {
|
||||
unary_type: UnaryType::Dereference,
|
||||
subject,
|
||||
})
|
||||
@ -247,22 +467,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_prec_exponentiate(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let left = self.parse_prec_member_index_call()?;
|
||||
fn parse_prec_exponentiate(&mut self) -> Node<Expr> {
|
||||
let left = self.parse_prec_member_index_call();
|
||||
if !self.done() && self.current_is(TokenType::AsteriskEqual) {
|
||||
let right = self.parse_prec_exponentiate()?;
|
||||
self.step_and_ok_node(Expr::Binary {
|
||||
let right = self.parse_prec_exponentiate();
|
||||
self.step_and_node(Expr::Binary {
|
||||
binary_type: BinaryType::Exponentiate,
|
||||
left: Box::new(left),
|
||||
right: Box::new(right),
|
||||
})
|
||||
} else {
|
||||
Ok(left)
|
||||
left
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_prec_member_index_call(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
let mut subject = self.parse_operand()?;
|
||||
fn parse_prec_member_index_call(&mut self) -> Node<Expr> {
|
||||
let mut subject = self.parse_operand();
|
||||
while !self.done() {
|
||||
if self.current_is(TokenType::Dot) {
|
||||
self.step();
|
||||
@ -277,7 +497,7 @@ where
|
||||
});
|
||||
} else if self.current_is(TokenType::LBracket) {
|
||||
self.step();
|
||||
let value = self.parse_expr()?;
|
||||
let value = self.parse_expr();
|
||||
if self.done() || !self.current_is(TokenType::RBracket) {
|
||||
return self.error("expected ']'");
|
||||
}
|
||||
@ -289,13 +509,13 @@ where
|
||||
self.step();
|
||||
let mut arguments = Vec::<Node<Expr>>::new();
|
||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
||||
arguments.push(self.parse_expr()?);
|
||||
arguments.push(self.parse_expr());
|
||||
while !self.done() && self.current_is(TokenType::Comma) {
|
||||
self.step();
|
||||
if self.done() || self.current_is(TokenType::RParen) {
|
||||
self.step();
|
||||
}
|
||||
arguments.push(self.parse_expr()?);
|
||||
arguments.push(self.parse_expr());
|
||||
}
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RParen) {
|
||||
@ -310,82 +530,172 @@ where
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(subject)
|
||||
subject
|
||||
}
|
||||
|
||||
fn parse_operand(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
fn parse_operand(&mut self) -> Node<Expr> {
|
||||
if self.done() {
|
||||
return self.error("expected value, got eof");
|
||||
}
|
||||
match self.current().token_type {
|
||||
TokenType::Id => self.step_and_ok_node(Expr::Id(self.token_string(self.current()))),
|
||||
match &self.current().token_type {
|
||||
TokenType::Id => self.step_and_node(Expr::Id(self.token_string(self.current()))),
|
||||
TokenType::Int => {
|
||||
let mut value_string = self.token_string(self.current());
|
||||
self.step();
|
||||
if !self.done() && self.current_is(TokenType::Decimal) {
|
||||
value_string.push_str(&self.token_string(self.current()));
|
||||
self.step_and_ok_node(Expr::Float(
|
||||
value_string.parse::<f64>().expect("valid f64"),
|
||||
))
|
||||
self.step_and_node(Expr::Float(value_string.parse::<f64>().expect("valid f64")))
|
||||
} else {
|
||||
self.ok_node(Expr::Int((value_string).parse::<i64>().expect("valid i64")))
|
||||
self.node(Expr::Int((value_string).parse::<i64>().expect("valid i64")))
|
||||
}
|
||||
}
|
||||
TokenType::Decimal => self.step_and_ok_node(Expr::Float(
|
||||
TokenType::Decimal => self.step_and_node(Expr::Float(
|
||||
self.token_string(self.current())
|
||||
.parse::<f64>()
|
||||
.expect("valid f64"),
|
||||
)),
|
||||
TokenType::False => self.step_and_ok_node(Expr::Bool(false)),
|
||||
TokenType::True => self.step_and_ok_node(Expr::Bool(true)),
|
||||
TokenType::String => self.parse_string(),
|
||||
TokenType::False => self.step_and_node(Expr::Bool(false)),
|
||||
TokenType::True => self.step_and_node(Expr::Bool(true)),
|
||||
TokenType::LParen => self.parse_unit_group_or_tuple(),
|
||||
TokenType::LBrace => self.parse_object(),
|
||||
TokenType::LBrace => self.parse_block(),
|
||||
TokenType::Underscore => todo!(),
|
||||
TokenType::LBracket => self.parse_array(),
|
||||
TokenType::Fn => self.parse_function(),
|
||||
_ => self.error("expected value"),
|
||||
TokenType::If => self.parse_if(),
|
||||
TokenType::MalformedString => self.error("malformed string"),
|
||||
other => self.node(Expr::Error(format!("expected value, got {:?}", other))),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_unit_group_or_tuple(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
fn parse_string(&mut self) -> Node<Expr> {
|
||||
let value_result = parse_string_value(&self.token_string(self.current()));
|
||||
self.step_and_node(match value_result {
|
||||
Ok(value) => Expr::String(value),
|
||||
Err(error) => Expr::Error(error),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_unit_group_or_tuple(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
||||
todo!()
|
||||
let first_value = self.parse_expr();
|
||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
||||
todo!()
|
||||
} else {
|
||||
self.step_and(first_value)
|
||||
}
|
||||
} else {
|
||||
self.step_and_ok_node(Expr::Unit)
|
||||
self.step_and_node(Expr::Unit)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_object(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
todo!()
|
||||
fn parse_object(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let mut values = Vec::<Node<ObjectEntry>>::new();
|
||||
if !self.done() && !self.current_is(TokenType::RBracket) {
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
values.push(self.parse_object_entry());
|
||||
} else {
|
||||
values.push(self.parse_object_entry());
|
||||
while !self.done() && self.current_is(TokenType::Comma) {
|
||||
self.step();
|
||||
if self.done() || self.current_is(TokenType::RBracket) {
|
||||
break;
|
||||
}
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
values.push(self.parse_object_entry());
|
||||
break;
|
||||
}
|
||||
values.push(self.parse_object_entry());
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RBracket) {
|
||||
return self.error("expected ']'");
|
||||
}
|
||||
self.step_and_node(Expr::Object(values))
|
||||
}
|
||||
|
||||
fn parse_array(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
todo!()
|
||||
fn parse_object_entry(&mut self) -> Node<ObjectEntry> {
|
||||
if self.done() {
|
||||
return self.node(ObjectEntry::Error("expected object entry".to_string()));
|
||||
}
|
||||
match self.current().token_type {
|
||||
TokenType::DotDotDot => {
|
||||
let expr = self.parse_spread();
|
||||
self.node(ObjectEntry::Spread(Box::new(expr)))
|
||||
}
|
||||
TokenType::String => {
|
||||
let key = self.parse_string();
|
||||
if self.done() || !self.current_is(TokenType::Colon) {
|
||||
return self.node(ObjectEntry::Error("expected ':'".to_string()));
|
||||
}
|
||||
self.step();
|
||||
let value = self.parse_expr();
|
||||
self.node(ObjectEntry::Pair {
|
||||
key: Box::new(key),
|
||||
value: Box::new(value),
|
||||
})
|
||||
}
|
||||
_ => self.node(ObjectEntry::Error("expected object entry".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_function(&mut self) -> Result<Node<Expr>, ParserError> {
|
||||
todo!()
|
||||
fn parse_array(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let mut values = Vec::<Node<Expr>>::new();
|
||||
if !self.done() && !self.current_is(TokenType::RBracket) {
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
values.push(self.parse_spread());
|
||||
} else {
|
||||
values.push(self.parse_expr());
|
||||
while !self.done() && self.current_is(TokenType::Comma) {
|
||||
self.step();
|
||||
if self.done() || self.current_is(TokenType::RBracket) {
|
||||
break;
|
||||
}
|
||||
if self.current_is(TokenType::DotDotDot) {
|
||||
values.push(self.parse_spread());
|
||||
break;
|
||||
}
|
||||
values.push(self.parse_expr());
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.done() || !self.current_is(TokenType::RBracket) {
|
||||
return self.error("expected ']'");
|
||||
}
|
||||
self.step_and_node(Expr::Array(values))
|
||||
}
|
||||
|
||||
fn parse_if(&mut self) -> Node<Expr> {
|
||||
self.step();
|
||||
let condition = self.parse_expr();
|
||||
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||
return self.error("expected '{'");
|
||||
}
|
||||
let truthy = self.parse_block();
|
||||
let mut falsy = None;
|
||||
if !self.done() && self.current_is(TokenType::Else) {
|
||||
self.step();
|
||||
if self.done() || !self.current_is(TokenType::LBrace) {
|
||||
return self.error("expected '{'");
|
||||
}
|
||||
falsy = Some(self.parse_block());
|
||||
}
|
||||
return self.node(Expr::If {
|
||||
condition: Box::new(condition),
|
||||
truthy: Box::new(truthy),
|
||||
falsy: falsy.map(Box::new),
|
||||
});
|
||||
}
|
||||
|
||||
fn token_string(&self, token: &Token) -> String {
|
||||
self.text[token.pos.index..token.pos.index + token.length].to_string()
|
||||
}
|
||||
|
||||
fn step_and_ok_node<T>(&mut self, value: T) -> Result<Node<T>, ParserError> {
|
||||
self.step();
|
||||
self.ok_node(value)
|
||||
}
|
||||
|
||||
fn ok_node<T>(&self, value: T) -> Result<Node<T>, ParserError> {
|
||||
Ok(Node {
|
||||
value,
|
||||
pos: self.tokens.pos(),
|
||||
})
|
||||
}
|
||||
|
||||
fn step_and_node<T>(&mut self, value: T) -> Node<T> {
|
||||
self.step();
|
||||
self.node(value)
|
||||
self.step_and(self.node(value))
|
||||
}
|
||||
|
||||
fn node<T>(&self, value: T) -> Node<T> {
|
||||
@ -400,11 +710,8 @@ where
|
||||
value
|
||||
}
|
||||
|
||||
fn error(&self, message: &str) -> Result<Node<Expr>, ParserError> {
|
||||
Err(ParserError {
|
||||
pos: self.tokens.pos(),
|
||||
message: message.to_string(),
|
||||
})
|
||||
fn error(&self, message: &str) -> Node<Expr> {
|
||||
self.node(Expr::Error(message.to_string()))
|
||||
}
|
||||
|
||||
fn done(&self) -> bool {
|
||||
@ -423,3 +730,48 @@ where
|
||||
self.current_token = self.tokens.next();
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string_value(text: &str) -> Result<String, String> {
|
||||
let mut input = text.chars().peekable();
|
||||
let mut value = String::new();
|
||||
input.next().ok_or_else(|| "invalid string".to_string())?;
|
||||
while !matches!(input.peek(), Some('"')) {
|
||||
value.push(unescape_char_value(&mut input)?)
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn unescape_char_value(input: &mut Peekable<Chars>) -> Result<char, String> {
|
||||
let step_and = |input2: &mut Peekable<Chars>, value: char| {
|
||||
input2.next().ok_or("invalid string".to_string())?;
|
||||
Ok(value)
|
||||
};
|
||||
if matches!(input.peek(), Some('\\')) {
|
||||
input.next().ok_or("invalid string".to_string())?;
|
||||
match input.peek() {
|
||||
Some('t') => step_and(input, '\t'),
|
||||
Some('r') => step_and(input, '\r'),
|
||||
Some('n') => step_and(input, '\n'),
|
||||
Some('0') => step_and(input, '\0'),
|
||||
Some('x') => {
|
||||
input.next().ok_or("invalid string".to_string())?;
|
||||
let mut value = String::new();
|
||||
for _ in 0..2 {
|
||||
value.push(
|
||||
input
|
||||
.next()
|
||||
.ok_or_else(|| "invalid escape sequence".to_string())?,
|
||||
);
|
||||
}
|
||||
let int_value = value
|
||||
.parse::<u8>()
|
||||
.map_err(|error| format!("invalid char code: {}", error.to_string()))?;
|
||||
char::from_u32(int_value.into()).ok_or_else(|| "invalid char code".to_string())
|
||||
}
|
||||
Some(_) => input.next().ok_or_else(|| "invalid string".to_string()),
|
||||
None => Err("invalid escape sequence".to_string()),
|
||||
}
|
||||
} else {
|
||||
input.next().ok_or("invalid string".to_string())
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ pub enum TokenType {
|
||||
Colon,
|
||||
Semicolon,
|
||||
Ampersand,
|
||||
DotDot,
|
||||
DotDotDot,
|
||||
EqualLessThan,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user