diff options
Diffstat (limited to 'src/lisp/parse.rs')
-rw-r--r-- | src/lisp/parse.rs | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/src/lisp/parse.rs b/src/lisp/parse.rs index 89a272a..4e0f427 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, | 2 | error::{LispError, ParseError, ParseErrorKind}, |
3 | lex::{Lexer, Span, Token}, | 3 | lex::{Lexer, Span, Token}, |
4 | number::LispNumber, | 4 | number::LispNumber, |
5 | LispExpr, | 5 | LispExpr, |
@@ -10,26 +10,6 @@ pub struct Parser<'lex> { | |||
10 | cur_token: Option<(Span, Token<'lex>)>, | 10 | cur_token: Option<(Span, Token<'lex>)>, |
11 | } | 11 | } |
12 | 12 | ||
13 | // pub struct ParseError { | ||
14 | // pub span: Span, | ||
15 | // pub kind: ParseErrorKind, | ||
16 | // } | ||
17 | // | ||
18 | // pub enum ParseErrorKind { | ||
19 | // InvalidLiteral, | ||
20 | // InvalidToken, | ||
21 | // LiteralParseError, | ||
22 | // MissingCloseParen, | ||
23 | // UnbalancedComma, | ||
24 | // UnexpectedEof, | ||
25 | // UnexpectedToken { | ||
26 | // expected: &'static str, | ||
27 | // found: &'static str, | ||
28 | // }, | ||
29 | // UnmatchedParen, | ||
30 | // UnterminatedString, | ||
31 | // } | ||
32 | |||
33 | enum Group { | 13 | enum Group { |
34 | Backticks(i32), | 14 | Backticks(i32), |
35 | CommaAt, | 15 | CommaAt, |
@@ -49,7 +29,7 @@ impl<'lex> Parser<'lex> { | |||
49 | let mut stack = Vec::new(); | 29 | let mut stack = Vec::new(); |
50 | let mut total_backticks = 0; | 30 | let mut total_backticks = 0; |
51 | loop { | 31 | loop { |
52 | let (_, token) = self.next()?; | 32 | let (span, token) = self.next()?; |
53 | let r: Result<LispExpr, LispError> = match token { | 33 | let r: Result<LispExpr, LispError> = match token { |
54 | Token::LeftParen => { | 34 | Token::LeftParen => { |
55 | stack.push(Group::Parens(Vec::new())); | 35 | stack.push(Group::Parens(Vec::new())); |
@@ -57,21 +37,27 @@ impl<'lex> Parser<'lex> { | |||
57 | } | 37 | } |
58 | Token::RightParen => { | 38 | Token::RightParen => { |
59 | let group = stack.pop().ok_or_else( | 39 | let group = stack.pop().ok_or_else( |
60 | || LispError::ParseError, // unmatched paren here | 40 | || (ParseError::new(span, ParseErrorKind::UnmatchedParen)), // unmatched paren here |
61 | )?; | 41 | )?; |
62 | match group { | 42 | match group { |
63 | Group::Parens(v) => Ok(LispExpr::List(v)), | 43 | Group::Parens(v) => Ok(LispExpr::List(v)), |
64 | _ => Err(LispError::ParseError), | 44 | _ => Err(From::from(ParseError::new( |
45 | span, | ||
46 | ParseErrorKind::UnexpectedToken { | ||
47 | expected: "expression", | ||
48 | found: "(", | ||
49 | }, | ||
50 | ))), | ||
65 | } | 51 | } |
66 | } | 52 | } |
67 | Token::Float(f) => f | 53 | Token::Float(f) => f |
68 | .parse::<f64>() | 54 | .parse::<f64>() |
69 | .map(|n| LispExpr::Number(LispNumber::Float(n))) | 55 | .map(|n| LispExpr::Number(LispNumber::Float(n))) |
70 | .map_err(|_| LispError::ParseError), | 56 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), |
71 | Token::Integer(i) => i | 57 | Token::Integer(i) => i |
72 | .parse::<i64>() | 58 | .parse::<i64>() |
73 | .map(|n| LispExpr::Number(LispNumber::Integer(n))) | 59 | .map(|n| LispExpr::Number(LispNumber::Integer(n))) |
74 | .map_err(|_| LispError::ParseError), | 60 | .map_err(|_| ParseError::new(span, ParseErrorKind::LiteralParseError).into()), |
75 | Token::String(s) => Ok(LispExpr::StringLit(s.into())), | 61 | Token::String(s) => Ok(LispExpr::StringLit(s.into())), |
76 | Token::Name(n) => Ok(name_expr(n)), | 62 | Token::Name(n) => Ok(name_expr(n)), |
77 | Token::BackQuote => { | 63 | Token::BackQuote => { |
@@ -85,7 +71,7 @@ impl<'lex> Parser<'lex> { | |||
85 | } | 71 | } |
86 | Token::Comma => { | 72 | Token::Comma => { |
87 | if total_backticks <= 0 { | 73 | if total_backticks <= 0 { |
88 | return Err(LispError::ParseError); // unbalanced comma | 74 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); |
89 | } | 75 | } |
90 | total_backticks -= 1; | 76 | total_backticks -= 1; |
91 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { | 77 | if let Some(&mut Group::Backticks(ref mut n)) = stack.last_mut() { |
@@ -97,7 +83,7 @@ impl<'lex> Parser<'lex> { | |||
97 | } | 83 | } |
98 | Token::CommaAt => { | 84 | Token::CommaAt => { |
99 | if total_backticks <= 0 { | 85 | if total_backticks <= 0 { |
100 | return Err(LispError::ParseError); // unbalanced comma | 86 | return Err(ParseError::new(span, ParseErrorKind::UnbalancedComma).into()); |
101 | } | 87 | } |
102 | total_backticks -= 1; | 88 | total_backticks -= 1; |
103 | stack.push(Group::CommaAt); | 89 | stack.push(Group::CommaAt); |
@@ -118,9 +104,9 @@ impl<'lex> Parser<'lex> { | |||
118 | }); | 104 | }); |
119 | 105 | ||
120 | if any_paren { | 106 | if any_paren { |
121 | Err(LispError::ParseError) // unbalanced paren | 107 | Err(ParseError::new(span, ParseErrorKind::MissingCloseParen).into()) |
122 | } else { | 108 | } else { |
123 | Err(LispError::ParseError) // unexpected eof | 109 | Err(ParseError::new(span, ParseErrorKind::UnexpectedEof).into()) |
124 | } | 110 | } |
125 | } | 111 | } |
126 | }; | 112 | }; |
@@ -178,7 +164,14 @@ impl<'lex> Parser<'lex> { | |||
178 | 164 | ||
179 | match self.next()? { | 165 | match self.next()? { |
180 | (_, Token::End) => Ok(expr), | 166 | (_, Token::End) => Ok(expr), |
181 | _ => Err(LispError::ParseError), // too many tokens | 167 | (span, token) => Err(ParseError::new( |
168 | span, | ||
169 | ParseErrorKind::UnexpectedToken { | ||
170 | expected: "EOF", | ||
171 | found: token.name(), | ||
172 | }, | ||
173 | ) | ||
174 | .into()), | ||
182 | } | 175 | } |
183 | } | 176 | } |
184 | 177 | ||