prattle/
parser.rs

1// parser.rs - MIT License
2//  MIT License
3//  Copyright (c) 2018 Tyler Laing (ZerothLaw)
4// 
5//  Permission is hereby granted, free of charge, to any person obtaining a copy
6//  of this software and associated documentation files (the "Software"), to deal
7//  in the Software without restriction, including without limitation the rights
8//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9//  copies of the Software, and to permit persons to whom the Software is
10//  furnished to do so, subject to the following conditions:
11// 
12//  The above copyright notice and this permission notice shall be included in all
13//  copies or substantial portions of the Software.
14// 
15//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21//  SOFTWARE.
22
23//! # Parser
24//! 
25//! This is the core trait/implementation for a pratt parser. 
26//! The basic algorithm is as follows:
27//! > parse_expr(rbp: 0)
28//! > left = null denotation of current token //ie, what is the context of this token on its own?
29//! > while next token.rbp > rbp {
30//! >   left = left denotation of next token //ie, what is the context of this token 
31//! >                                        //combined with the context of the last node? 
32//! > }
33//! > return left;
34//! 
35//! The GeneralParser implementation here requires a provided ParserSpec and Lexer 
36//! containing the tokens to be parsed. 
37
38use std::collections::HashMap;
39use std::marker::{Send, Sync};
40use std::mem::{Discriminant, discriminant};
41
42use prelude::*;
43use types::*;
44
45/// Parser trait. Theoretically, one could use different parser impls during parse of a 
46/// language and so the syntax rules need to not be tied to any specific Parser impl. 
47/// Hence why the ParserSpec uses closures with the signature ```&mut dyn Parser<T>```
48pub trait Parser<T: Token + Send + Sync + 'static> {
49    fn parse(&mut self) -> Result<Node<T>, ParseError<T>>;
50    fn parse_expr(&mut self, rbp: PrecedenceLevel) -> Result<Node<T>, ParseError<T>>;
51    fn next_binds_tighter_than(&mut self, rbp: PrecedenceLevel) -> bool;
52    fn consume(&mut self, end_token: T) -> Result<(), ParseError<T>>;
53}
54
55/// General implementation of Parser trait. This implementation should work for any 
56/// valid set of Syntax rules. 
57/// A second generic, `L`, is added in order to allow us to decouple this impl from any specific 
58/// Lexer impl. 
59/// Here we just copy and consume the fields of the ParserSpec in order to set this up.
60/// If we instead held a ParserSpec internally, we get borrow checker error messages. 
61/// Consider: 
62/// ```Rust
63/// let null_info = self.spec.get_null(&tk);
64/// ```
65/// This inherently borrows self.spec, which then borrows self as an outcome. 
66/// If instead you own the HashMaps, only those specific members are considered 
67/// borrowed by borrowck. 
68pub struct GeneralParser<T, L>
69    where T: Token + Send + Sync + 'static, 
70          L: Lexer<T>
71{
72    null_map: HashMap<Discriminant<T>, NullInfo<T>>, 
73    left_map: HashMap<Discriminant<T>, LeftInfo<T>>,
74    lexer: L, 
75}
76
77/// GeneralParser impl
78/// Wraps trait methods to allow users to only need to import this, without 
79/// the trait. Also offers a compile time check that GeneralParser still
80/// impls Parser correctly. 
81#[allow(dead_code)]
82impl<T: Token + Send + Sync + 'static, L: Lexer<T>> GeneralParser<T, L> {
83    pub fn new(spec: ParserSpec<T>, lexer: L) -> GeneralParser<T, L> {
84        let (null_map, left_map) = spec.maps();
85        GeneralParser {
86            null_map: null_map,
87            left_map: left_map,
88            lexer: lexer
89        }
90    }
91
92    fn parse(&mut self) -> Result<Node<T>, ParseError<T>> {
93        self.parse_expr(PrecedenceLevel::Root)
94    }
95
96    fn parse_expr(&mut self, rbp: PrecedenceLevel) -> Result<Node<T>, ParseError<T>> {
97        <Self as Parser<T>>::parse_expr(self, rbp)
98    }
99
100    fn next_binds_tighter_than(&mut self, rbp: PrecedenceLevel) -> bool {
101        <Self as Parser<T>>::next_binds_tighter_than(self, rbp)
102    }
103
104    fn consume(&mut self, end_token: T) -> Result<(), ParseError<T>> {
105        <Self as Parser<T>>::consume(self, end_token)
106    }
107}
108
109impl<T: Token + Send + Sync + 'static, L: Lexer<T>> Parser<T> for GeneralParser<T, L> {
110    fn parse(&mut self) -> Result<Node<T>, ParseError<T>> {
111        self.parse_expr(PrecedenceLevel::Root)
112    }
113
114    fn parse_expr(&mut self, rbp: PrecedenceLevel) -> Result<Node<T>, ParseError<T>> {
115        if let Some(tk) = self.lexer.peek() {
116            self.lexer.next_token();
117            let (lbp, func) = {
118                let val = self.null_map.get(&discriminant(&tk));
119                match val {
120                    Some(val) => val.clone(), 
121                    None => return Err(ParseError::MissingRule {token: tk.clone(), ty: "Null".into()})
122                }
123            };
124            let mut left = func(self, tk, lbp)?;
125            while self.next_binds_tighter_than(rbp) {
126                let tk = self.lexer.next_token(); //implied that token exists
127                let val = {
128                    let v = self.left_map.get(&discriminant(&tk));
129                    match v {
130                        Some(val) => val.clone(), 
131                        None => return Err(ParseError::MissingRule {token: tk.clone(), ty: "Left".into()})
132                    }
133                };
134                let (lbp, _, func) = val;
135                left = func(self, tk, lbp, left)?;
136            }
137            Ok(left)
138        } else {
139            Err(ParseError::Incomplete)
140        }
141    }
142
143    fn next_binds_tighter_than(&mut self, rbp: PrecedenceLevel) -> bool {
144        if let Some(tk) = self.lexer.peek() {
145            if let Some((_, next_rbp, _)) = self.left_map.get(&discriminant(&tk)) {
146                *next_rbp > rbp
147            } else {
148                false
149            }
150        } else {
151            false
152        }
153    }
154
155    fn consume(&mut self, end_token: T) -> Result<(), ParseError<T>> {
156        if let Some(tk) = self.lexer.peek() {
157            if tk == end_token {
158                self.lexer.next_token();
159                Ok(())
160            } else {
161                Err(ParseError::ConsumeFailed{expected: end_token, found: tk.clone()})
162            }
163        } else {
164            Err(ParseError::Incomplete)
165        }
166    }
167}
168
169#[cfg(test)]
170mod test {
171    use super::*;
172    use lexer::LexerVec;
173    //Catch Send/Sync changes
174    #[test]
175    fn test_parser_send() {
176        fn assert_send<T: Send>() {}
177        assert_send::<GeneralParser<String, LexerVec<String>>>();
178    }
179
180    #[test]
181    fn test_parser_sync() {
182        fn assert_sync<T: Sync>() {}
183        assert_sync::<GeneralParser<String, LexerVec<String>>>();
184    }
185}