elemental/parser/
mod.rs

1//! Main library for the Elemental parser.
2
3mod identifier_parselet;
4mod literal_parselet;
5mod assignment_parselet;
6mod binop_parselet;
7mod paren_parselet;
8mod matrix_parselet;
9mod func_parselet;
10mod prime_parselet;
11
12use std::collections::HashMap;
13
14use crate::{
15    Expression,
16    Token,
17    TokenClass,
18    Tokenizer,
19};
20
21use identifier_parselet::IdentifierParselet;
22use literal_parselet::LiteralParselet;
23use assignment_parselet::AssignmentParselet;
24use binop_parselet::BinOpParselet;
25use paren_parselet::ParenParselet;
26use matrix_parselet::MatrixParselet;
27use func_parselet::FuncParselet;
28use prime_parselet::PrimeParselet;
29
30
31/// Converts a token class into a precedence value.
32impl From<TokenClass> for u8 {
33    fn from(t: TokenClass) -> u8 {
34        match t {
35            TokenClass::Assignment => 1,
36            TokenClass::Plus => 3,
37            TokenClass::Minus => 3,
38            TokenClass::Multiply => 4,
39            TokenClass::Divide => 4,
40            TokenClass::OpenParen => 6,
41            TokenClass::OpenBracket => 7,
42            TokenClass::Prime => 8,
43            _ => 0,
44        }
45    }
46}
47
48
49/// Abstracts over "prefix parselets".
50pub trait PrefixParselet {
51    fn parse(&self, parser: &Parser, tokenizer: &mut Tokenizer, token: Token) -> Expression;
52}
53
54/// Abstracts over "infix parselets".
55pub trait InfixParselet {
56    fn parse(&self, parser: &Parser, tokenizer: &mut Tokenizer, token: Token, left: Expression) -> Expression;
57}
58
59
60/// Abstracts over parser behavior.
61pub struct Parser {
62    prefix_parselets: HashMap<TokenClass, Box<dyn PrefixParselet>>,
63    infix_parselets: HashMap<TokenClass, Box<dyn InfixParselet>>,
64}
65
66impl Parser {
67    /// Constructs a new parser.
68    pub fn new() -> Self {
69        let mut prefix_parselets: HashMap<TokenClass, Box<dyn PrefixParselet>> = HashMap::new();
70        let mut infix_parselets: HashMap<TokenClass, Box<dyn InfixParselet>> = HashMap::new();
71
72        // Declarative grammar begins here.
73        prefix_parselets.insert(TokenClass::Identifier, Box::new(IdentifierParselet {}));
74        prefix_parselets.insert(TokenClass::Int, Box::new(LiteralParselet {}));
75        prefix_parselets.insert(TokenClass::Float, Box::new(LiteralParselet {}));
76        prefix_parselets.insert(TokenClass::OpenParen, Box::new(ParenParselet {}));
77        prefix_parselets.insert(TokenClass::OpenBracket, Box::new(MatrixParselet {}));
78        infix_parselets.insert(TokenClass::Assignment, Box::new(AssignmentParselet {}));
79        infix_parselets.insert(TokenClass::Plus, Box::new(BinOpParselet {}));
80        infix_parselets.insert(TokenClass::Minus, Box::new(BinOpParselet {}));
81        infix_parselets.insert(TokenClass::Multiply, Box::new(BinOpParselet {}));
82        infix_parselets.insert(TokenClass::Divide, Box::new(BinOpParselet {}));
83        infix_parselets.insert(TokenClass::OpenParen, Box::new(FuncParselet {}));
84        infix_parselets.insert(TokenClass::Prime, Box::new(PrimeParselet {}));
85
86        Self {
87            prefix_parselets,
88            infix_parselets,
89        }
90    }
91
92    /// Parse code into an expression.
93    pub fn parse(&self, tokenizer: &mut Tokenizer, precedence: u8) -> Expression {
94        let token = match tokenizer.next() {
95            Some(t) => t,
96            None => return Expression::Nil,
97        };
98
99        let parselet: &Box<dyn PrefixParselet> = match self.prefix_parselets.get(&token.get_class()) {
100            Some(p) => p,
101            None => return Expression::Nil,
102        };
103        let mut left = parselet.parse(self, tokenizer, token);
104
105        while precedence < tokenizer.get_next_precedence() {
106            let next = match tokenizer.peek() {
107                Some(t) => t,
108                None => break,
109            };
110            
111            let parselet: &Box<dyn InfixParselet> = match self.infix_parselets.get(&next.get_class()) {
112                Some(p) => p,
113                None => break,
114            };
115            tokenizer.next();
116
117            left = parselet.parse(self, tokenizer, next, left);
118        }
119
120        left
121    }
122}