mod prefix_parselet;
mod infix_parselet;
mod number_parselet;
mod identifier_parselet;
mod assignment_parselet;
mod symbolic_parselet;
mod reassignment_parselet;
mod binary_operation_parselet;
use std::collections::HashMap;
pub use crate::{
BinaryOperation,
Error,
Expression,
PREFIXES,
Token,
TokenClass,
Tokenstream,
UNITS,
};
use prefix_parselet::PrefixParselet;
use infix_parselet::InfixParselet;
use number_parselet::NumberParselet;
use identifier_parselet::IdentifierParselet;
use assignment_parselet::AssignmentParselet;
use symbolic_parselet::SymbolicParselet;
use reassignment_parselet::ReassignmentParselet;
use binary_operation_parselet::BinaryOperationParselet;
pub struct Parser {
prefix_parselets: HashMap<TokenClass, Box<dyn PrefixParselet>>,
infix_parselets: HashMap<TokenClass, Box<dyn InfixParselet>>,
pub debug: bool,
}
impl Parser {
pub fn new(debug: bool) -> Self {
use TokenClass::*;
let mut prefix_parselets: HashMap<TokenClass, Box<dyn PrefixParselet>> = HashMap::new();
let mut infix_parselets: HashMap<TokenClass, Box<dyn InfixParselet>> = HashMap::new();
prefix_parselets.insert(Number, Box::new(NumberParselet {}));
prefix_parselets.insert(Minus, Box::new(NumberParselet {}));
prefix_parselets.insert(Identifier, Box::new(IdentifierParselet {}));
prefix_parselets.insert(Symbolic, Box::new(SymbolicParselet {}));
prefix_parselets.insert(Let, Box::new(AssignmentParselet {}));
infix_parselets.insert(Assignment, Box::new(ReassignmentParselet {}));
infix_parselets.insert(Plus, Box::new(BinaryOperationParselet {}));
infix_parselets.insert(Minus, Box::new(BinaryOperationParselet {}));
infix_parselets.insert(Times, Box::new(BinaryOperationParselet {}));
infix_parselets.insert(Divide, Box::new(BinaryOperationParselet {}));
Self {
prefix_parselets,
infix_parselets,
debug,
}
}
pub fn parse(&self, input: &str) -> Vec<Expression> {
let mut expressions = Vec::new();
let mut tokenstream = Tokenstream::from(input, self.debug);
while let Some(_) = tokenstream.peek() {
let expr = self.parse_expr(&mut tokenstream, 0, 0);
expressions.push(expr);
}
expressions
}
fn parse_expr(&self, tokenstream: &mut Tokenstream, precedence: u8, nesting: usize) -> Expression {
use TokenClass::*;
let token = tokenstream.next_unwrap();
if token.check(Newline) {
return Expression::Null;
}
let prefix_parselet = match self.prefix_parselets.get(&token.class) {
Some (p) => p,
None => {
Error::CouldNotParse (&token.value.replace("\n", "newline")).warn();
return Expression::Null;
},
};
let mut indent = String::new();
for _ in 0..nesting {
indent.push_str(" ");
}
if self.debug {
println!("{}Current token: {}", indent, &token);
println!();
println!("{}Parsing precedence: {}", indent, precedence);
println!("{}Tokenstream precedence: {}", indent, tokenstream.precedence());
println!();
}
let mut expression = prefix_parselet.parse(
tokenstream,
self,
token,
nesting,
);
while precedence < tokenstream.precedence() {
let token = match tokenstream.peek() {
Some (t) => t,
None => return expression,
};
if self.debug {
println!("{}Conducting infix parsing with token {}", indent, token);
println!();
}
let infix_parselet = match self.infix_parselets.get(&token.class) {
Some (p) => p,
None => return expression,
};
tokenstream.next();
expression = infix_parselet.parse(
tokenstream,
self,
expression,
token,
nesting,
);
}
if self.debug {
println!("{}Parsing complete", indent);
println!();
}
expression
}
}