diff options
Diffstat (limited to 'src/lisp/parse.rs')
-rw-r--r-- | src/lisp/parse.rs | 159 |
1 files changed, 76 insertions, 83 deletions
diff --git a/src/lisp/parse.rs b/src/lisp/parse.rs index 737e7ad..8aeb672 100644 --- a/src/lisp/parse.rs +++ b/src/lisp/parse.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use crate::lisp::{ | 1 | use crate::lisp::{ |
2 | error::{LispError, ParseError, ParseErrorKind}, | 2 | error::{ParseError, ParseErrorKind}, |
3 | lex::{Lexer, Span, Token}, | 3 | lex::{Lexer, Span, Token}, |
4 | number::LispNumber, | 4 | number::LispNumber, |
5 | LispExpr, | 5 | LispExpr, |
@@ -30,97 +30,91 @@ impl<'lex> Parser<'lex> { | |||
30 | let mut total_backticks = 0; | 30 | let mut total_backticks = 0; |
31 | loop { | 31 | loop { |
32 | let (span, token) = self.next()?; | 32 | let (span, token) = self.next()?; |
33 | let r: Result<LispExpr, ParseError> = match token { | 33 | let r: Result<LispExpr, ParseError> = |
34 | Token::LeftParen => { | 34 | match token { |
35 | stack.push(Group::Parens(Vec::new())); | 35 | Token::LeftParen => { |
36 | continue; | 36 | stack.push(Group::Parens(Vec::new())); |
37 | } | 37 | continue; |
38 | Token::RightParen => { | 38 | } |
39 | let group = stack | 39 | Token::RightParen => { |
40 | .pop() | 40 | let group = stack |
41 | .ok_or_else(|| (ParseError::new(span, ParseErrorKind::UnmatchedParen)))?; | 41 | .pop() |
42 | match group { | 42 | .ok_or_else(|| ParseError::new(span, ParseErrorKind::UnmatchedParen))?; |
43 | Group::Parens(v) => { | 43 | match group { |
44 | if v.len() == 0 { | 44 | Group::Parens(v) => { |
45 | Ok(LispExpr::Unit) | 45 | if v.is_empty() { |
46 | } else { | 46 | Ok(LispExpr::Unit) |
47 | Ok(LispExpr::List(v)) | 47 | } else { |
48 | Ok(LispExpr::List(v)) | ||
49 | } | ||
48 | } | 50 | } |
51 | _ => Err(ParseError::new( | ||
52 | span, | ||
53 | ParseErrorKind::UnexpectedToken { | ||
54 | expected: "expression", | ||
55 | found: "(", | ||
56 | }, | ||
57 | )), | ||
49 | } | 58 | } |
50 | _ => Err(From::from(ParseError::new( | ||
51 | span, | ||
52 | ParseErrorKind::UnexpectedToken { | ||
53 | expected: "expression", | ||
54 | found: "(", | ||
55 | }, | ||
56 | ))), | ||
57 | } | 59 | } |
58 | } | 60 | Token::Float(f) => f |
59 | Token::Float(f) => f | 61 | .parse::<f64>() |
60 | .parse::<f64>() | 62 | .map(|n| LispExpr::Number(LispNumber::Float(n))) |
61 | .map(|n| LispExpr::Number(LispNumber::Float(n))) | 63 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError)), |
62 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), | 64 | Token::Integer(i) => i |
63 | Token::Integer(i) => i | 65 | .parse::<i64>() |
64 | .parse::<i64>() | 66 | .map(|n| LispExpr::Number(LispNumber::Integer(n))) |
65 | .map(|n| LispExpr::Number(LispNumber::Integer(n))) | 67 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError)), |
66 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), | 68 | Token::String(s) => Ok(LispExpr::StringLit(s[1..s.len() - 1].into())), |
67 | Token::String(s) => Ok(LispExpr::StringLit(s[1..s.len() - 1].into())), | 69 | Token::Char(s) => Ok(LispExpr::Char(s.chars().nth(2).ok_or_else(|| { |
68 | Token::Char(s) => { | ||
69 | Ok(LispExpr::Char(s.chars().nth(2).ok_or_else(|| { | ||
70 | ParseError::new(span, ParseErrorKind::LiteralParseError) | 70 | ParseError::new(span, ParseErrorKind::LiteralParseError) |
71 | })?)) | 71 | })?)), |
72 | } | 72 | Token::Name(n) => Ok(name_expr(n)), |
73 | Token::Name(n) => Ok(name_expr(n)), | 73 | Token::BackQuote => { |
74 | Token::BackQuote => { | 74 | total_backticks += 1; |
75 | total_backticks += 1; | 75 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { |
76 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { | 76 | *n += 1; |
77 | *n += 1; | 77 | continue; |
78 | } | ||
79 | stack.push(Group::Backticks(1)); | ||
78 | continue; | 80 | continue; |
79 | } | 81 | } |
80 | stack.push(Group::Backticks(1)); | 82 | Token::Comma => { |
81 | continue; | 83 | if total_backticks <= 0 { |
82 | } | 84 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); |
83 | Token::Comma => { | 85 | } |
84 | if total_backticks <= 0 { | 86 | total_backticks -= 1; |
85 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); | 87 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { |
86 | } | 88 | *n -= 1; |
87 | total_backticks -= 1; | 89 | continue; |
88 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { | 90 | } |
89 | *n -= 1; | 91 | stack.push(Group::Backticks(-1)); |
90 | continue; | 92 | continue; |
91 | } | 93 | } |
92 | stack.push(Group::Backticks(-1)); | 94 | Token::CommaAt => { |
93 | continue; | 95 | if total_backticks <= 0 { |
94 | } | 96 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); |
95 | Token::CommaAt => { | 97 | } |
96 | if total_backticks <= 0 { | 98 | total_backticks -= 1; |
97 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma)); | 99 | stack.push(Group::CommaAt); |
100 | continue; | ||
98 | } | 101 | } |
99 | total_backticks -= 1; | 102 | Token::Quote => { |
100 | stack.push(Group::CommaAt); | 103 | if let Some(&mut Group::Quotes(ref mut n)) = stack.last_mut() { |
101 | continue; | 104 | *n += 1; |
102 | } | 105 | continue; |
103 | Token::Quote => { | 106 | } |
104 | if let Some(&mut Group::Quotes(ref mut n)) = stack.last_mut() { | 107 | stack.push(Group::Quotes(1)); |
105 | *n += 1; | ||
106 | continue; | 108 | continue; |
107 | } | 109 | } |
108 | stack.push(Group::Quotes(1)); | 110 | Token::End => { |
109 | continue; | 111 | if stack.iter().any(|group| matches!(*group, Group::Parens(_))) { |
110 | } | 112 | Err(ParseError::new(span, ParseErrorKind::MissingCloseParen)) |
111 | Token::End => { | 113 | } else { |
112 | let any_paren = stack.iter().any(|group| match *group { | 114 | Err(ParseError::new(span, ParseErrorKind::UnexpectedEof)) |
113 | Group::Parens(_) => true, | 115 | } |
114 | _ => false, | ||
115 | }); | ||
116 | |||
117 | if any_paren { | ||
118 | Err(ParseError::new(span, ParseErrorKind::MissingCloseParen)) | ||
119 | } else { | ||
120 | Err(ParseError::new(span, ParseErrorKind::UnexpectedEof)) | ||
121 | } | 116 | } |
122 | } | 117 | }; |
123 | }; | ||
124 | let mut v = r?; | 118 | let mut v = r?; |
125 | loop { | 119 | loop { |
126 | match stack.last_mut() { | 120 | match stack.last_mut() { |
@@ -181,8 +175,7 @@ impl<'lex> Parser<'lex> { | |||
181 | expected: "EOF", | 175 | expected: "EOF", |
182 | found: token.name(), | 176 | found: token.name(), |
183 | }, | 177 | }, |
184 | ) | 178 | )), |
185 | .into()), | ||
186 | } | 179 | } |
187 | } | 180 | } |
188 | 181 | ||
@@ -210,7 +203,7 @@ fn name_expr(input: &str) -> LispExpr { | |||
210 | mod tests { | 203 | mod tests { |
211 | use super::*; | 204 | use super::*; |
212 | fn parse(input: &str) -> Result<LispExpr, ParseError> { | 205 | fn parse(input: &str) -> Result<LispExpr, ParseError> { |
213 | let mut parser = Parser::new(Lexer::new(input, 0)); | 206 | let mut parser = Parser::new(Lexer::new(input)); |
214 | 207 | ||
215 | parser.parse_single_expr() | 208 | parser.parse_single_expr() |
216 | } | 209 | } |