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)]
|
#[derive(Debug)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
|
Error(String),
|
||||||
Unit,
|
Unit,
|
||||||
Id(String),
|
Id(String),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
@ -15,9 +16,15 @@ pub enum Expr {
|
|||||||
String(String),
|
String(String),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Array(Vec<Node<Expr>>),
|
Array(Vec<Node<Expr>>),
|
||||||
Object(Vec<ObjectEntry>),
|
Object(Vec<Node<ObjectEntry>>),
|
||||||
Tuple(Vec<Node<Expr>>),
|
Tuple(Vec<Node<Expr>>),
|
||||||
|
|
||||||
|
If {
|
||||||
|
condition: Box<Node<Expr>>,
|
||||||
|
truthy: Box<Node<Expr>>,
|
||||||
|
falsy: Option<Box<Node<Expr>>>,
|
||||||
|
},
|
||||||
|
|
||||||
Member {
|
Member {
|
||||||
subject: Box<Node<Expr>>,
|
subject: Box<Node<Expr>>,
|
||||||
value: String,
|
value: String,
|
||||||
@ -39,11 +46,44 @@ pub enum Expr {
|
|||||||
left: Box<Node<Expr>>,
|
left: Box<Node<Expr>>,
|
||||||
right: 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)]
|
#[derive(Debug)]
|
||||||
pub enum ObjectEntry {
|
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)]
|
#[derive(Debug)]
|
||||||
@ -73,3 +113,20 @@ pub enum BinaryType {
|
|||||||
And,
|
And,
|
||||||
Or,
|
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,
|
TokenType::PercentEqual,
|
||||||
)),
|
)),
|
||||||
'=' => {
|
'=' => Some(self.equal_token()),
|
||||||
Some(self.single_or_double_char_token(TokenType::Equal, '=', TokenType::EqualEqual))
|
|
||||||
}
|
|
||||||
'!' => Some(self.single_or_double_char_token(
|
'!' => Some(self.single_or_double_char_token(
|
||||||
TokenType::Exclamation,
|
TokenType::Exclamation,
|
||||||
'=',
|
'=',
|
||||||
@ -104,7 +102,7 @@ impl<'a> Lexer<'a> {
|
|||||||
self.step();
|
self.step();
|
||||||
}
|
}
|
||||||
if self.done() || self.current() != '"' {
|
if self.done() || self.current() != '"' {
|
||||||
self.step_and_token(TokenType::MalformedString, start)
|
self.token(TokenType::MalformedString, start)
|
||||||
} else {
|
} else {
|
||||||
self.step_and_token(TokenType::String, start)
|
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 {
|
fn dot_token(&mut self) -> Token {
|
||||||
let start = self.pos();
|
let start = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
@ -222,6 +232,13 @@ impl<'a> Lexer<'a> {
|
|||||||
self.step();
|
self.step();
|
||||||
}
|
}
|
||||||
self.token(TokenType::Decimal, start)
|
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 {
|
} else {
|
||||||
self.token(TokenType::Dot, start)
|
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;
|
use crate::parser::Parser;
|
||||||
|
|
||||||
fn main() {
|
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 = [");
|
println!("tokens = [");
|
||||||
let text = "** 3.14 \"foo\" false true ( ) + += /* 1 /* 2 */ 3 */ // 4 \n 5";
|
lexer2.for_each(|token| {
|
||||||
let lexer = Lexer::new(text);
|
println!(
|
||||||
lexer.for_each(|token| {
|
" ({:?}, `{}`, [{}], {}, {}:{}),",
|
||||||
println!(" {:?},", token);
|
token.token_type,
|
||||||
|
&text2[token.pos.index..token.pos.index + token.length],
|
||||||
|
token.pos.index,
|
||||||
|
token.length,
|
||||||
|
token.pos.line,
|
||||||
|
token.pos.col,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
println!("]");
|
println!("]");
|
||||||
|
|
||||||
let text2 = "1 + 2 * 3";
|
|
||||||
let mut parser = Parser::new(text2, Lexer::new(text2));
|
let mut parser = Parser::new(text2, Lexer::new(text2));
|
||||||
let expr = parser.parse_expr();
|
let expr = parser.parse_expr();
|
||||||
println!("ast = {:#?}", expr);
|
println!("ast = {:#?}", expr);
|
||||||
|
558
src/parser.rs
558
src/parser.rs
@ -1,11 +1,8 @@
|
|||||||
use crate::ast::{BinaryType, Expr, Node, UnaryType};
|
use std::iter::Peekable;
|
||||||
use crate::tokens::{Position, PositionKnowing, Token, TokenType};
|
use std::str::Chars;
|
||||||
|
|
||||||
#[derive(Debug)]
|
use crate::ast::{AssignType, BinaryType, Expr, Node, ObjectEntry, Parameter, UnaryType};
|
||||||
pub struct ParserError {
|
use crate::tokens::{PositionKnowing, Token, TokenType};
|
||||||
pos: Position,
|
|
||||||
message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Parser<'a, Tokens>
|
pub struct Parser<'a, Tokens>
|
||||||
where
|
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()
|
self.parse_prec_or()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_or(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_or(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_and()?;
|
let mut left = self.parse_prec_and();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::Or) {
|
if self.current_is(TokenType::Or) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_and()?;
|
let right = self.parse_prec_and();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Or,
|
binary_type: BinaryType::Or,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -47,15 +267,15 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_and(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_and(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_equal_inequal()?;
|
let mut left = self.parse_prec_equal_inequal();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::And) {
|
if self.current_is(TokenType::And) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_equal_inequal()?;
|
let right = self.parse_prec_equal_inequal();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::And,
|
binary_type: BinaryType::And,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -65,15 +285,15 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_equal_inequal(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_equal_inequal(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_lt_lte_gt_gte_in()?;
|
let mut left = self.parse_prec_lt_lte_gt_gte_in();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::EqualEqual) {
|
if self.current_is(TokenType::EqualEqual) {
|
||||||
self.step();
|
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 {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Equal,
|
binary_type: BinaryType::Equal,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -81,7 +301,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::ExclamationEqual) {
|
} else if self.current_is(TokenType::ExclamationEqual) {
|
||||||
self.step();
|
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 {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Inequal,
|
binary_type: BinaryType::Inequal,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -91,15 +311,15 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_lt_lte_gt_gte_in(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_add_subtract()?;
|
let mut left = self.parse_prec_add_subtract();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::LessThan) {
|
if self.current_is(TokenType::LessThan) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_add_subtract()?;
|
let right = self.parse_prec_add_subtract();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::LT,
|
binary_type: BinaryType::LT,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -107,7 +327,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::GreaterThan) {
|
} else if self.current_is(TokenType::GreaterThan) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_add_subtract()?;
|
let right = self.parse_prec_add_subtract();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::GT,
|
binary_type: BinaryType::GT,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -115,7 +335,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::LessThanEqual) {
|
} else if self.current_is(TokenType::LessThanEqual) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_add_subtract()?;
|
let right = self.parse_prec_add_subtract();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::LTE,
|
binary_type: BinaryType::LTE,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -123,7 +343,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::GreaterThanEqual) {
|
} else if self.current_is(TokenType::GreaterThanEqual) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_add_subtract()?;
|
let right = self.parse_prec_add_subtract();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::GTE,
|
binary_type: BinaryType::GTE,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -131,7 +351,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::In) {
|
} else if self.current_is(TokenType::In) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_add_subtract()?;
|
let right = self.parse_prec_add_subtract();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::In,
|
binary_type: BinaryType::In,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -141,15 +361,15 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_add_subtract(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_add_subtract(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_multiply_divide_modulo()?;
|
let mut left = self.parse_prec_multiply_divide_modulo();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::Plus) {
|
if self.current_is(TokenType::Plus) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_multiply_divide_modulo()?;
|
let right = self.parse_prec_multiply_divide_modulo();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Add,
|
binary_type: BinaryType::Add,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -157,7 +377,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::Minus) {
|
} else if self.current_is(TokenType::Minus) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_multiply_divide_modulo()?;
|
let right = self.parse_prec_multiply_divide_modulo();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Subtract,
|
binary_type: BinaryType::Subtract,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -167,15 +387,15 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_multiply_divide_modulo(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_multiply_divide_modulo(&mut self) -> Node<Expr> {
|
||||||
let mut left = self.parse_prec_unary()?;
|
let mut left = self.parse_prec_unary();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::Asterisk) {
|
if self.current_is(TokenType::Asterisk) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_unary()?;
|
let right = self.parse_prec_unary();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Multiply,
|
binary_type: BinaryType::Multiply,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -183,7 +403,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::Slash) {
|
} else if self.current_is(TokenType::Slash) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_unary()?;
|
let right = self.parse_prec_unary();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Divide,
|
binary_type: BinaryType::Divide,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -191,7 +411,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::Percent) {
|
} else if self.current_is(TokenType::Percent) {
|
||||||
self.step();
|
self.step();
|
||||||
let right = self.parse_prec_unary()?;
|
let right = self.parse_prec_unary();
|
||||||
left = self.node(Expr::Binary {
|
left = self.node(Expr::Binary {
|
||||||
binary_type: BinaryType::Modulo,
|
binary_type: BinaryType::Modulo,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
@ -201,21 +421,21 @@ where
|
|||||||
break;
|
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) {
|
if !self.done() && self.current_is(TokenType::Not) {
|
||||||
self.step();
|
self.step();
|
||||||
let subject = Box::new(self.parse_prec_unary()?);
|
let subject = Box::new(self.parse_prec_unary());
|
||||||
self.ok_node(Expr::Unary {
|
self.node(Expr::Unary {
|
||||||
unary_type: UnaryType::Not,
|
unary_type: UnaryType::Not,
|
||||||
subject,
|
subject,
|
||||||
})
|
})
|
||||||
} else if !self.done() && self.current_is(TokenType::Minus) {
|
} else if !self.done() && self.current_is(TokenType::Minus) {
|
||||||
self.step();
|
self.step();
|
||||||
let subject = Box::new(self.parse_prec_unary()?);
|
let subject = Box::new(self.parse_prec_unary());
|
||||||
self.ok_node(Expr::Unary {
|
self.node(Expr::Unary {
|
||||||
unary_type: UnaryType::Negate,
|
unary_type: UnaryType::Negate,
|
||||||
subject,
|
subject,
|
||||||
})
|
})
|
||||||
@ -223,22 +443,22 @@ where
|
|||||||
self.step();
|
self.step();
|
||||||
if !self.done() && self.current_is(TokenType::Mut) {
|
if !self.done() && self.current_is(TokenType::Mut) {
|
||||||
self.step();
|
self.step();
|
||||||
let subject = Box::new(self.parse_prec_unary()?);
|
let subject = Box::new(self.parse_prec_unary());
|
||||||
self.ok_node(Expr::Unary {
|
self.node(Expr::Unary {
|
||||||
unary_type: UnaryType::ReferenceMut,
|
unary_type: UnaryType::ReferenceMut,
|
||||||
subject,
|
subject,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let subject = Box::new(self.parse_prec_unary()?);
|
let subject = Box::new(self.parse_prec_unary());
|
||||||
self.ok_node(Expr::Unary {
|
self.node(Expr::Unary {
|
||||||
unary_type: UnaryType::Reference,
|
unary_type: UnaryType::Reference,
|
||||||
subject,
|
subject,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if !self.done() && self.current_is(TokenType::Asterisk) {
|
} else if !self.done() && self.current_is(TokenType::Asterisk) {
|
||||||
self.step();
|
self.step();
|
||||||
let subject = Box::new(self.parse_prec_unary()?);
|
let subject = Box::new(self.parse_prec_unary());
|
||||||
self.ok_node(Expr::Unary {
|
self.node(Expr::Unary {
|
||||||
unary_type: UnaryType::Dereference,
|
unary_type: UnaryType::Dereference,
|
||||||
subject,
|
subject,
|
||||||
})
|
})
|
||||||
@ -247,22 +467,22 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_exponentiate(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_exponentiate(&mut self) -> Node<Expr> {
|
||||||
let left = self.parse_prec_member_index_call()?;
|
let left = self.parse_prec_member_index_call();
|
||||||
if !self.done() && self.current_is(TokenType::AsteriskEqual) {
|
if !self.done() && self.current_is(TokenType::AsteriskEqual) {
|
||||||
let right = self.parse_prec_exponentiate()?;
|
let right = self.parse_prec_exponentiate();
|
||||||
self.step_and_ok_node(Expr::Binary {
|
self.step_and_node(Expr::Binary {
|
||||||
binary_type: BinaryType::Exponentiate,
|
binary_type: BinaryType::Exponentiate,
|
||||||
left: Box::new(left),
|
left: Box::new(left),
|
||||||
right: Box::new(right),
|
right: Box::new(right),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(left)
|
left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_prec_member_index_call(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_prec_member_index_call(&mut self) -> Node<Expr> {
|
||||||
let mut subject = self.parse_operand()?;
|
let mut subject = self.parse_operand();
|
||||||
while !self.done() {
|
while !self.done() {
|
||||||
if self.current_is(TokenType::Dot) {
|
if self.current_is(TokenType::Dot) {
|
||||||
self.step();
|
self.step();
|
||||||
@ -277,7 +497,7 @@ where
|
|||||||
});
|
});
|
||||||
} else if self.current_is(TokenType::LBracket) {
|
} else if self.current_is(TokenType::LBracket) {
|
||||||
self.step();
|
self.step();
|
||||||
let value = self.parse_expr()?;
|
let value = self.parse_expr();
|
||||||
if self.done() || !self.current_is(TokenType::RBracket) {
|
if self.done() || !self.current_is(TokenType::RBracket) {
|
||||||
return self.error("expected ']'");
|
return self.error("expected ']'");
|
||||||
}
|
}
|
||||||
@ -289,13 +509,13 @@ where
|
|||||||
self.step();
|
self.step();
|
||||||
let mut arguments = Vec::<Node<Expr>>::new();
|
let mut arguments = Vec::<Node<Expr>>::new();
|
||||||
if !self.done() && !self.current_is(TokenType::RParen) {
|
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) {
|
while !self.done() && self.current_is(TokenType::Comma) {
|
||||||
self.step();
|
self.step();
|
||||||
if self.done() || self.current_is(TokenType::RParen) {
|
if self.done() || self.current_is(TokenType::RParen) {
|
||||||
self.step();
|
self.step();
|
||||||
}
|
}
|
||||||
arguments.push(self.parse_expr()?);
|
arguments.push(self.parse_expr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.done() || !self.current_is(TokenType::RParen) {
|
if self.done() || !self.current_is(TokenType::RParen) {
|
||||||
@ -310,82 +530,172 @@ where
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(subject)
|
subject
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_operand(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_operand(&mut self) -> Node<Expr> {
|
||||||
if self.done() {
|
if self.done() {
|
||||||
return self.error("expected value, got eof");
|
return self.error("expected value, got eof");
|
||||||
}
|
}
|
||||||
match self.current().token_type {
|
match &self.current().token_type {
|
||||||
TokenType::Id => self.step_and_ok_node(Expr::Id(self.token_string(self.current()))),
|
TokenType::Id => self.step_and_node(Expr::Id(self.token_string(self.current()))),
|
||||||
TokenType::Int => {
|
TokenType::Int => {
|
||||||
let mut value_string = self.token_string(self.current());
|
let mut value_string = self.token_string(self.current());
|
||||||
self.step();
|
self.step();
|
||||||
if !self.done() && self.current_is(TokenType::Decimal) {
|
if !self.done() && self.current_is(TokenType::Decimal) {
|
||||||
value_string.push_str(&self.token_string(self.current()));
|
value_string.push_str(&self.token_string(self.current()));
|
||||||
self.step_and_ok_node(Expr::Float(
|
self.step_and_node(Expr::Float(value_string.parse::<f64>().expect("valid f64")))
|
||||||
value_string.parse::<f64>().expect("valid f64"),
|
|
||||||
))
|
|
||||||
} else {
|
} 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())
|
self.token_string(self.current())
|
||||||
.parse::<f64>()
|
.parse::<f64>()
|
||||||
.expect("valid f64"),
|
.expect("valid f64"),
|
||||||
)),
|
)),
|
||||||
TokenType::False => self.step_and_ok_node(Expr::Bool(false)),
|
TokenType::String => self.parse_string(),
|
||||||
TokenType::True => self.step_and_ok_node(Expr::Bool(true)),
|
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::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::LBracket => self.parse_array(),
|
||||||
TokenType::Fn => self.parse_function(),
|
TokenType::If => self.parse_if(),
|
||||||
_ => self.error("expected value"),
|
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();
|
self.step();
|
||||||
if !self.done() && !self.current_is(TokenType::LParen) {
|
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 {
|
} else {
|
||||||
self.step_and_ok_node(Expr::Unit)
|
self.step_and_node(Expr::Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_object(&mut self) -> Result<Node<Expr>, ParserError> {
|
fn parse_object(&mut self) -> Node<Expr> {
|
||||||
todo!()
|
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> {
|
fn parse_object_entry(&mut self) -> Node<ObjectEntry> {
|
||||||
todo!()
|
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> {
|
fn parse_array(&mut self) -> Node<Expr> {
|
||||||
todo!()
|
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 {
|
fn token_string(&self, token: &Token) -> String {
|
||||||
self.text[token.pos.index..token.pos.index + token.length].to_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> {
|
fn step_and_node<T>(&mut self, value: T) -> Node<T> {
|
||||||
self.step();
|
self.step_and(self.node(value))
|
||||||
self.node(value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node<T>(&self, value: T) -> Node<T> {
|
fn node<T>(&self, value: T) -> Node<T> {
|
||||||
@ -400,11 +710,8 @@ where
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&self, message: &str) -> Result<Node<Expr>, ParserError> {
|
fn error(&self, message: &str) -> Node<Expr> {
|
||||||
Err(ParserError {
|
self.node(Expr::Error(message.to_string()))
|
||||||
pos: self.tokens.pos(),
|
|
||||||
message: message.to_string(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn done(&self) -> bool {
|
fn done(&self) -> bool {
|
||||||
@ -423,3 +730,48 @@ where
|
|||||||
self.current_token = self.tokens.next();
|
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,
|
Colon,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
Ampersand,
|
Ampersand,
|
||||||
|
DotDot,
|
||||||
|
DotDotDot,
|
||||||
|
EqualLessThan,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
Loading…
Reference in New Issue
Block a user