good shit
This commit is contained in:
parent
a5cc6813d1
commit
a450eb05d8
|
@ -124,12 +124,12 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_raw(&mut self) {
|
pub fn disable_raw(&mut self) -> io::Result<()> {
|
||||||
self.stdout.suspend_raw_mode();
|
self.stdout.suspend_raw_mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_raw(&mut self) {
|
pub fn enable_raw(&mut self) -> io::Result<()> {
|
||||||
self.stdout.activate_raw_mode();
|
self.stdout.activate_raw_mode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,14 +165,11 @@ fn main() -> Result<(), io::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
input.disable_raw();
|
input.disable_raw()?;
|
||||||
|
|
||||||
let tokens = tokens_result.unwrap();
|
let tokens = tokens_result.unwrap();
|
||||||
let mut parser = Parser::new(tokens, &mut env);
|
let mut parser = Parser::new(tokens, &mut env);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
input.enable_raw();
|
|
||||||
|
|
||||||
let nodes = match parser.parse() {
|
let nodes = match parser.parse() {
|
||||||
Ok(nodes) => nodes,
|
Ok(nodes) => nodes,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -196,6 +193,9 @@ fn main() -> Result<(), io::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
input.enable_raw()?;
|
||||||
|
|
||||||
print!("{}", color::Fg(color::Reset));
|
print!("{}", color::Fg(color::Reset));
|
||||||
|
|
||||||
// println!("\t{}{source}{}", termion::color::Fg(termion::color::Blue), termion::color::Fg(termion::color::Reset));
|
// println!("\t{}{source}{}", termion::color::Fg(termion::color::Blue), termion::color::Fg(termion::color::Reset));
|
||||||
|
|
|
@ -7,29 +7,85 @@ pub type EnvironmentInternalSymbolKey = u16;
|
||||||
|
|
||||||
pub struct Environment {
|
pub struct Environment {
|
||||||
map: HashMap<EnvironmentInternalSymbolKey, Rc<NodeEnum>>,
|
map: HashMap<EnvironmentInternalSymbolKey, Rc<NodeEnum>>,
|
||||||
|
stack_depth: usize,
|
||||||
|
max_stack_depth: usize,
|
||||||
|
stack: Vec<Vec<EnvironmentInternalSymbolKey>>,
|
||||||
|
|
||||||
symbol_to_id: HashMap<String, EnvironmentInternalSymbolKey>,
|
symbol_to_id: HashMap<String, EnvironmentInternalSymbolKey>,
|
||||||
id_to_symbol: HashMap<EnvironmentInternalSymbolKey, String>,
|
id_to_symbol: HashMap<EnvironmentInternalSymbolKey, String>,
|
||||||
unique_keys: EnvironmentInternalSymbolKey
|
unique_keys: EnvironmentInternalSymbolKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
|
stack_depth: 0,
|
||||||
|
max_stack_depth: 5000,
|
||||||
|
stack: vec![vec![]],
|
||||||
|
|
||||||
symbol_to_id: HashMap::new(),
|
symbol_to_id: HashMap::new(),
|
||||||
id_to_symbol: HashMap::new(),
|
id_to_symbol: HashMap::new(),
|
||||||
unique_keys: 0
|
unique_keys: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_stack(&mut self) -> Result<(), String> {
|
||||||
|
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||||
|
|
||||||
|
if self.stack_depth == self.max_stack_depth {
|
||||||
|
self.unwind_stack();
|
||||||
|
return Err("Max Stack depth exceeded".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stack_depth += 1;
|
||||||
|
self.stack.push(vec![]);
|
||||||
|
|
||||||
|
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_stack(&mut self) -> Result<(), String> {
|
||||||
|
debug_assert!(
|
||||||
|
self.stack_depth == self.stack.len() - 1,
|
||||||
|
"Expected stack len: {}, stack_depth: {}",
|
||||||
|
self.stack.len(),
|
||||||
|
self.stack_depth
|
||||||
|
);
|
||||||
|
|
||||||
|
if self.stack_depth == 0 {
|
||||||
|
return Err("Trying to pop empty stack".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stack_depth -= 1;
|
||||||
|
|
||||||
|
for item in self.stack.pop().unwrap() {
|
||||||
|
self.map.remove(&item);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwind_stack(&mut self) {
|
||||||
|
for stack in &self.stack {
|
||||||
|
for item in stack {
|
||||||
|
self.map.remove(&item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stack = vec![vec![]];
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(&self, key: &EnvironmentInternalSymbolKey) -> Option<&Rc<NodeEnum>> {
|
pub fn get(&self, key: &EnvironmentInternalSymbolKey) -> Option<&Rc<NodeEnum>> {
|
||||||
self.map.get(key)
|
self.map.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, key: EnvironmentInternalSymbolKey, value: Rc<NodeEnum>) {
|
pub fn insert(&mut self, key: EnvironmentInternalSymbolKey, value: Rc<NodeEnum>) {
|
||||||
self.map.insert(key, value);
|
self.map.insert(key, value);
|
||||||
|
unsafe { self.stack.get_unchecked_mut(self.stack_depth).push(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_to_id(&self, value: &String) -> Option<&EnvironmentInternalSymbolKey> {
|
pub fn str_to_id(&self, value: &String) -> Option<&EnvironmentInternalSymbolKey> {
|
||||||
|
|
|
@ -50,15 +50,15 @@ impl Node for Call {
|
||||||
// Pass arguments to native function
|
// Pass arguments to native function
|
||||||
FunctionType::Native(_name, native_function) => native_function(&arguments),
|
FunctionType::Native(_name, native_function) => native_function(&arguments),
|
||||||
FunctionType::UserFunction(node_enum) => {
|
FunctionType::UserFunction(node_enum) => {
|
||||||
// TODO: Push scope
|
env.push_stack()?;
|
||||||
// Define variables
|
// Define variables
|
||||||
fargs.iter().zip(arguments).for_each(|(symbol, value)| {
|
fargs.iter().zip(arguments).for_each(|(symbol, value)| {
|
||||||
env.insert(symbol.get_value(), value.clone());
|
env.insert(symbol.get_value(), value.clone());
|
||||||
});
|
});
|
||||||
let ev = node_enum.evaluate(env);
|
let ev = node_enum.evaluate(env)?;
|
||||||
// TODO: Pop scope
|
env.pop_stack()?;
|
||||||
// Return evaluated return value for function
|
// Return evaluated return value for function
|
||||||
ev
|
Ok(ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl Node for Empty {
|
||||||
fn as_string(&self, _: Option<&Environment>) -> String {
|
fn as_string(&self, _: Option<&Environment>) -> String {
|
||||||
match &self.message {
|
match &self.message {
|
||||||
Some(m) => m.clone(),
|
Some(m) => m.clone(),
|
||||||
None => String::from("{{#VOID}}"),
|
None => String::from("{{#EMPTY}}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::node::empty::Empty;
|
||||||
|
|
||||||
use super::{Environment, Node, NodeEnum, Precedence};
|
use super::{Environment, Node, NodeEnum, Precedence};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
|
@ -28,8 +30,9 @@ impl Node for Bool {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
pub enum ElseBranchEnum {
|
pub enum ElseBranchEnum {
|
||||||
ElseIf(Rc<IfElse>),
|
ElseIf(Rc<NodeEnum>),
|
||||||
Block(Vec<Rc<NodeEnum>>),
|
Block(Vec<Rc<NodeEnum>>),
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
|
@ -56,16 +59,17 @@ impl Node for IfElse {
|
||||||
block: &Vec<Rc<NodeEnum>>,
|
block: &Vec<Rc<NodeEnum>>,
|
||||||
env: &mut Environment,
|
env: &mut Environment,
|
||||||
) -> Result<Rc<NodeEnum>, String> {
|
) -> Result<Rc<NodeEnum>, String> {
|
||||||
// TODO: Push new scope
|
env.push_stack()?;
|
||||||
if let Some((last, to_evaluate)) = block.split_last() {
|
let ret = if let Some((last, to_evaluate)) = block.split_last() {
|
||||||
for expr in to_evaluate {
|
for expr in to_evaluate {
|
||||||
expr.evaluate(env)?;
|
expr.evaluate(env)?;
|
||||||
}
|
}
|
||||||
last.evaluate(env)
|
last.evaluate(env)
|
||||||
} else {
|
} else {
|
||||||
Err("Empty if statemenent true branch")?
|
Ok(Empty::EMPTY.clone())
|
||||||
}
|
};
|
||||||
// TODO: Pop scope
|
env.pop_stack()?;
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
match condition {
|
match condition {
|
||||||
|
@ -73,28 +77,32 @@ impl Node for IfElse {
|
||||||
Bool::False => match &self.else_branch {
|
Bool::False => match &self.else_branch {
|
||||||
ElseBranchEnum::ElseIf(if_else) => if_else.evaluate(env),
|
ElseBranchEnum::ElseIf(if_else) => if_else.evaluate(env),
|
||||||
ElseBranchEnum::Block(node_enums) => evaluate_block(node_enums, env),
|
ElseBranchEnum::Block(node_enums) => evaluate_block(node_enums, env),
|
||||||
|
ElseBranchEnum::None => Ok(Empty::EMPTY.clone()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_string(&self, env: Option<&Environment>) -> String {
|
fn as_string(&self, env: Option<&Environment>) -> String {
|
||||||
format!(
|
format!(
|
||||||
"if {} then\n{}\nelse\n{}",
|
"if {} then {} {}",
|
||||||
self.condition.as_string(env),
|
self.condition.as_string(env),
|
||||||
self.true_branch
|
self.true_branch
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.as_string(env))
|
.map(|x| x.as_string(env))
|
||||||
.reduce(|a, b| a + "\n" + &b)
|
.reduce(|a, b| a + " " + &b)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_str(),
|
.as_str(),
|
||||||
match &self.else_branch {
|
match &self.else_branch {
|
||||||
ElseBranchEnum::ElseIf(if_else) => if_else.as_string(env),
|
ElseBranchEnum::ElseIf(if_else) => if_else.as_string(env),
|
||||||
ElseBranchEnum::Block(vec) =>
|
ElseBranchEnum::Block(vec) =>
|
||||||
vec.iter()
|
"else ".to_owned()
|
||||||
.map(|x| x.as_string(env))
|
+ &vec
|
||||||
.reduce(|a, b| a + "\n" + &b)
|
.iter()
|
||||||
.unwrap()
|
.map(|x| x.as_string(env))
|
||||||
+ "\nend",
|
.reduce(|a, b| a + "\n" + &b)
|
||||||
|
.unwrap()
|
||||||
|
+ "end",
|
||||||
|
ElseBranchEnum::None => "end".to_owned(),
|
||||||
}
|
}
|
||||||
.as_str()
|
.as_str()
|
||||||
)
|
)
|
||||||
|
@ -104,3 +112,20 @@ impl Node for IfElse {
|
||||||
Precedence::Primary
|
Precedence::Primary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IfElse {
|
||||||
|
pub fn new(
|
||||||
|
condition: Rc<NodeEnum>,
|
||||||
|
true_branch: Vec<Rc<NodeEnum>>,
|
||||||
|
else_branch: ElseBranchEnum,
|
||||||
|
) -> Rc<NodeEnum> {
|
||||||
|
Rc::new(
|
||||||
|
Self {
|
||||||
|
condition,
|
||||||
|
true_branch,
|
||||||
|
else_branch,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ impl Node for Symbol {
|
||||||
|
|
||||||
fn as_string(&self, env: Option<&Environment>) -> String {
|
fn as_string(&self, env: Option<&Environment>) -> String {
|
||||||
if let Some(env) = env {
|
if let Some(env) = env {
|
||||||
if let Some(value) = env.get(&self.value) {
|
if let Some(str) = env.id_to_str(&self.value) {
|
||||||
value.as_string(Some(env))
|
str.clone()
|
||||||
} else {
|
} else {
|
||||||
env.id_to_str(&self.value)
|
env.id_to_str(&self.value)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
|
|
@ -3,18 +3,7 @@ use std::{collections::HashMap, iter::Peekable, rc::Rc, slice::Iter, str::Chars,
|
||||||
use crate::{
|
use crate::{
|
||||||
environment::Environment,
|
environment::Environment,
|
||||||
node::{
|
node::{
|
||||||
NodeEnum,
|
add::Add, assign::Assign, call::Call, constant::{Constant, ConstantValue}, divide::Divide, equals::Equals, function::{Function, FunctionType}, if_else::{Bool, ElseBranchEnum, IfElse}, multiply::Multiply, set::Set, subtract::Subtract, symbol::Symbol, NodeEnum
|
||||||
add::Add,
|
|
||||||
assign::Assign,
|
|
||||||
call::Call,
|
|
||||||
constant::{Constant, ConstantValue},
|
|
||||||
divide::Divide,
|
|
||||||
equals::Equals,
|
|
||||||
function::{Function, FunctionType},
|
|
||||||
multiply::Multiply,
|
|
||||||
set::Set,
|
|
||||||
subtract::Subtract,
|
|
||||||
symbol::Symbol,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,6 +34,9 @@ pub enum TokenType {
|
||||||
Then,
|
Then,
|
||||||
Else,
|
Else,
|
||||||
End,
|
End,
|
||||||
|
|
||||||
|
True,
|
||||||
|
False
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenType {
|
impl TokenType {
|
||||||
|
@ -70,6 +62,9 @@ impl TokenType {
|
||||||
TokenType::Then => 4,
|
TokenType::Then => 4,
|
||||||
TokenType::Else => 4,
|
TokenType::Else => 4,
|
||||||
TokenType::End => 3,
|
TokenType::End => 3,
|
||||||
|
|
||||||
|
TokenType::True => 4,
|
||||||
|
TokenType::False => 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,6 +200,10 @@ impl<'a> Lexer<'a> {
|
||||||
"then" => TokenType::Then,
|
"then" => TokenType::Then,
|
||||||
"else" => TokenType::Else,
|
"else" => TokenType::Else,
|
||||||
"end" => TokenType::End,
|
"end" => TokenType::End,
|
||||||
|
|
||||||
|
"true" => TokenType::True,
|
||||||
|
"false" => TokenType::False,
|
||||||
|
|
||||||
_ => TokenType::Identifier(identifier),
|
_ => TokenType::Identifier(identifier),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -222,7 +221,7 @@ pub enum ParserError {
|
||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
tokens: Peekable<IntoIter<Token>>,
|
tokens: Peekable<IntoIter<Token>>,
|
||||||
environment: &'a mut Environment,
|
environment: &'a mut Environment,
|
||||||
previous: Option<&'a Token>,
|
previous: Option<Token>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tokens<'a> = Peekable<Iter<'a, Token>>;
|
type Tokens<'a> = Peekable<Iter<'a, Token>>;
|
||||||
|
@ -249,15 +248,31 @@ impl<'a> Parser<'a> {
|
||||||
Ok(expressions)
|
Ok(expressions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn consume<'b>(&'b mut self) -> &'b Option<Token> {
|
||||||
|
self.previous = self.tokens.next();
|
||||||
|
&self.previous
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_at_end(&mut self) -> bool {
|
||||||
|
if self.tokens.peek().is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the next token is `t`, if it is then consume it and return true. Otherwise does
|
||||||
|
/// nothing and returns false.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn matchType<'b>(&'b mut self, t: TokenType) -> bool {
|
fn matchType<'b>(&'b mut self, t: TokenType) -> bool {
|
||||||
if let Some(Token(_, token_type)) = self.tokens.peek() {
|
if let Some(Token(_, token_type)) = self.tokens.peek() {
|
||||||
if *token_type == t {
|
if *token_type == t {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +305,7 @@ impl<'a> Parser<'a> {
|
||||||
let expr = self.equality();
|
let expr = self.equality();
|
||||||
|
|
||||||
if let Some(Token(_, TokenType::ColonEquals)) = self.tokens.peek() {
|
if let Some(Token(_, TokenType::ColonEquals)) = self.tokens.peek() {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
return Ok(Rc::new(Assign::new(expr?, self.equality()?).into()));
|
return Ok(Rc::new(Assign::new(expr?, self.equality()?).into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +331,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.matchType(TokenType::Plus) {
|
if self.matchType(TokenType::Plus) {
|
||||||
Ok(Rc::new(Add::new(expr, self.comparison()?).into()))
|
Ok(Rc::new(Add::new(expr, self.comparison()?).into()))
|
||||||
} else if let Some(Token(_, TokenType::Minus)) = self.tokens.peek() {
|
} else if let Some(Token(_, TokenType::Minus)) = self.tokens.peek() {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
Ok(Rc::new(Subtract::new(expr, self.comparison()?).into()))
|
Ok(Rc::new(Subtract::new(expr, self.comparison()?).into()))
|
||||||
} else {
|
} else {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
|
@ -326,10 +341,10 @@ impl<'a> Parser<'a> {
|
||||||
fn factor(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
fn factor(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||||
let expr = self.unary()?;
|
let expr = self.unary()?;
|
||||||
if let Some(Token(_, TokenType::Star)) = self.tokens.peek() {
|
if let Some(Token(_, TokenType::Star)) = self.tokens.peek() {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
Ok(Rc::new(Multiply::new(expr, self.comparison()?).into()))
|
Ok(Rc::new(Multiply::new(expr, self.comparison()?).into()))
|
||||||
} else if let Some(Token(_, TokenType::Slash)) = self.tokens.peek() {
|
} else if let Some(Token(_, TokenType::Slash)) = self.tokens.peek() {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
Ok(Rc::new(Divide::new(expr, self.comparison()?).into()))
|
Ok(Rc::new(Divide::new(expr, self.comparison()?).into()))
|
||||||
} else {
|
} else {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
|
@ -366,7 +381,7 @@ impl<'a> Parser<'a> {
|
||||||
Set::new(vec![potential_parameters])
|
Set::new(vec![potential_parameters])
|
||||||
};
|
};
|
||||||
|
|
||||||
expr = Ok(Call::new(expr?, parameters));
|
expr = Ok(Call::new(expr?, parameters));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +397,7 @@ impl<'a> Parser<'a> {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
let expr = self.primary()?;
|
let expr = self.if_else()?;
|
||||||
|
|
||||||
if self.matchType(TokenType::LeftArrow) {
|
if self.matchType(TokenType::LeftArrow) {
|
||||||
let right = self.equality()?;
|
let right = self.equality()?;
|
||||||
|
@ -397,6 +412,8 @@ impl<'a> Parser<'a> {
|
||||||
let mut symbols = vec![];
|
let mut symbols = vec![];
|
||||||
for (i, value) in set.get_values().into_iter().enumerate() {
|
for (i, value) in set.get_values().into_iter().enumerate() {
|
||||||
match value.as_ref() {
|
match value.as_ref() {
|
||||||
|
NodeEnum::Symbol(symbol) => symbols.push(symbol.clone()),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ParserError::UnexpectedNode(
|
return Err(ParserError::UnexpectedNode(
|
||||||
error_loc,
|
error_loc,
|
||||||
|
@ -405,8 +422,6 @@ impl<'a> Parser<'a> {
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeEnum::Symbol(symbol) => symbols.push(symbol.clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,6 +439,54 @@ impl<'a> Parser<'a> {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn if_else(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||||
|
if self.matchType(TokenType::If) {
|
||||||
|
let condition = self.equality()?;
|
||||||
|
|
||||||
|
let _ = self.matchOrErr(TokenType::Then)?;
|
||||||
|
|
||||||
|
let mut expressions = vec![];
|
||||||
|
|
||||||
|
while !(self.matchType(TokenType::End) || self.matchType(TokenType::Else)) {
|
||||||
|
if self.is_at_end() {
|
||||||
|
return Err(ParserError::UnexpectedEndOfTokens(
|
||||||
|
"Expected an else or end here".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
expressions.push(self.expression()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe to unwrap since the while loop would terminate if previous was none (it didnt
|
||||||
|
// find an End or Else before running out of tokens)
|
||||||
|
let else_branch = match self.previous.as_ref().unwrap() {
|
||||||
|
Token(_, TokenType::End) => ElseBranchEnum::None,
|
||||||
|
Token(_, TokenType::Else) => {
|
||||||
|
if let Some(Token(_, TokenType::If)) = self.tokens.peek() {
|
||||||
|
ElseBranchEnum::ElseIf(self.if_else()?)
|
||||||
|
} else {
|
||||||
|
let mut expressions = vec![];
|
||||||
|
while !self.matchType(TokenType::End) {
|
||||||
|
if self.is_at_end() {
|
||||||
|
return Err(ParserError::UnexpectedEndOfTokens(
|
||||||
|
"Expected an end here".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
expressions.push(self.expression()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElseBranchEnum::Block(expressions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => panic!("Not possible"),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(IfElse::new(condition, expressions, else_branch));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.primary()
|
||||||
|
}
|
||||||
|
|
||||||
fn primary(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
fn primary(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||||
let (i, token) = if let Some(Token(i, token)) = self.tokens.next() {
|
let (i, token) = if let Some(Token(i, token)) = self.tokens.next() {
|
||||||
(i, token)
|
(i, token)
|
||||||
|
@ -438,6 +501,9 @@ impl<'a> Parser<'a> {
|
||||||
TokenType::Identifier(string) => Ok(Rc::new(
|
TokenType::Identifier(string) => Ok(Rc::new(
|
||||||
Symbol::new_from_str(string, self.environment).into(),
|
Symbol::new_from_str(string, self.environment).into(),
|
||||||
)),
|
)),
|
||||||
|
TokenType::True => Ok(Rc::new(Bool::True.into())),
|
||||||
|
TokenType::False => Ok(Rc::new(Bool::False.into())),
|
||||||
|
|
||||||
TokenType::LParen => {
|
TokenType::LParen => {
|
||||||
let expr = self.expression()?;
|
let expr = self.expression()?;
|
||||||
let (i, t) = if let Some(Token(i, x)) = self.tokens.peek() {
|
let (i, t) = if let Some(Token(i, x)) = self.tokens.peek() {
|
||||||
|
@ -450,14 +516,14 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
match t {
|
match t {
|
||||||
TokenType::RParen => {
|
TokenType::RParen => {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
TokenType::Comma => {
|
TokenType::Comma => {
|
||||||
let mut values = vec![expr];
|
let mut values = vec![expr];
|
||||||
while {
|
while {
|
||||||
if let Some(Token(_, TokenType::RParen)) = self.tokens.peek() {
|
if let Some(Token(_, TokenType::RParen)) = self.tokens.peek() {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -472,7 +538,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if *token == TokenType::Comma {
|
if *token == TokenType::Comma {
|
||||||
self.tokens.next();
|
self.consume();
|
||||||
} else {
|
} else {
|
||||||
return Err(ParserError::UnexpectedToken(
|
return Err(ParserError::UnexpectedToken(
|
||||||
*i,
|
*i,
|
||||||
|
|
Loading…
Reference in a new issue