aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/ast/error.rs34
-rw-r--r--compiler/src/ast/parser.rs86
2 files changed, 67 insertions, 53 deletions
diff --git a/compiler/src/ast/error.rs b/compiler/src/ast/error.rs
index 11f552d..ced2231 100644
--- a/compiler/src/ast/error.rs
+++ b/compiler/src/ast/error.rs
@@ -1,7 +1,37 @@
1use std::{error, fmt}; 1use std::{
2 error, fmt,
3 num::{ParseFloatError, ParseIntError},
4 rc::Rc,
5};
2 6
3#[derive(Debug)] 7#[derive(Debug)]
4pub enum Error {} 8pub enum Error {
9 // Number
10 InvalidFloatLiteral(ParseFloatError),
11 InvalidIntegerLiteral(ParseIntError),
12
13 // String
14 UnclosedString(Rc<str>),
15 UnexpectedEscapeChar(char),
16
17 // Par
18 UnexpectedRightPar,
19 UnclosedLeftPar,
20
21 UnexpectedEof,
22}
23
24impl From<ParseFloatError> for Error {
25 fn from(value: ParseFloatError) -> Self {
26 Self::InvalidFloatLiteral(value)
27 }
28}
29
30impl From<ParseIntError> for Error {
31 fn from(value: ParseIntError) -> Self {
32 Self::InvalidIntegerLiteral(value)
33 }
34}
5 35
6impl fmt::Display for Error { 36impl fmt::Display for Error {
7 fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { 37 fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs
index 2e6d2dd..89a1280 100644
--- a/compiler/src/ast/parser.rs
+++ b/compiler/src/ast/parser.rs
@@ -1,4 +1,4 @@
1use std::{iter::Peekable, result}; 1use std::iter::Peekable;
2 2
3use crate::{ 3use crate::{
4 ast::{Atom, Error, Expr, Program}, 4 ast::{Atom, Error, Expr, Program},
@@ -6,25 +6,19 @@ use crate::{
6 span::{Pos, Span, Spanned}, 6 span::{Pos, Span, Spanned},
7}; 7};
8 8
9type Result<T> = result::Result<T, Spanned<Error>>; 9fn parse_number(number: &str) -> Result<Atom, Error> {
10
11fn parse_number(number: &str) -> Atom {
12 let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E')); 10 let is_float = number.bytes().any(|b| matches!(b, b'.' | b'e' | b'E'));
13 11
14 if is_float { 12 let atom = if is_float {
15 match number.parse() { 13 Atom::Float(number.parse()?)
16 Ok(ok) => Atom::Float(ok),
17 Err(err) => todo!("invalid float literal {number}: {err}"),
18 }
19 } else { 14 } else {
20 match number.parse() { 15 Atom::Integer(number.parse()?)
21 Ok(ok) => Atom::Integer(ok), 16 };
22 Err(err) => todo!("invalid integer literal {number}: {err}"), 17
23 } 18 Ok(atom)
24 }
25} 19}
26 20
27fn parse_string(string: &str) -> Atom { 21fn parse_string(string: &str) -> Result<Atom, Error> {
28 let mut result = String::new(); 22 let mut result = String::new();
29 let mut is_escape = false; 23 let mut is_escape = false;
30 24
@@ -40,17 +34,17 @@ fn parse_string(string: &str) -> Atom {
40 'n' => result.push('\n'), 34 'n' => result.push('\n'),
41 '\\' => result.push('\\'), 35 '\\' => result.push('\\'),
42 '\n' => {} 36 '\n' => {}
43 _ => todo!("unexpected escape char {ch:?}"), 37 _ => return Err(Error::UnexpectedEscapeChar(ch)),
44 } 38 }
45 is_escape = false; 39 is_escape = false;
46 } 40 }
47 } 41 }
48 42
49 if is_escape { 43 if is_escape {
50 todo!("unclosed string"); 44 return Err(Error::UnclosedString(string.into()));
51 } 45 }
52 46
53 Atom::String(result.into()) 47 Ok(Atom::String(result.into()))
54} 48}
55 49
56fn parse_symbol(symbol: &str) -> Atom { 50fn parse_symbol(symbol: &str) -> Atom {
@@ -67,7 +61,7 @@ where
67 I: Iterator<Item = Spanned<Token<'a>>>, 61 I: Iterator<Item = Spanned<Token<'a>>>,
68{ 62{
69 tokens: Peekable<I>, 63 tokens: Peekable<I>,
70 last_token_end: Pos, 64 last_token_span: Span,
71} 65}
72 66
73impl<'a, I> Parser<'a, I> 67impl<'a, I> Parser<'a, I>
@@ -77,7 +71,7 @@ where
77 pub fn new(tokens: I) -> Self { 71 pub fn new(tokens: I) -> Self {
78 Self { 72 Self {
79 tokens: tokens.peekable(), 73 tokens: tokens.peekable(),
80 last_token_end: Pos::new(1, 0, 0), 74 last_token_span: Span::new(Pos::new(1, 0, 0), Pos::new(1, 0, 0)),
81 } 75 }
82 } 76 }
83 77
@@ -88,75 +82,65 @@ where
88 fn consume(&mut self) -> Option<Spanned<Token<'a>>> { 82 fn consume(&mut self) -> Option<Spanned<Token<'a>>> {
89 self.tokens 83 self.tokens
90 .next() 84 .next()
91 .inspect(|s| self.last_token_end = s.span.end) 85 .inspect(|s| self.last_token_span = s.span)
92 } 86 }
93 87
94 fn parse_expr(&mut self) -> Result<Spanned<Expr>> { 88 fn parse_expr(&mut self) -> Result<Spanned<Expr>, Spanned<Error>> {
95 let Spanned { inner: token, span } = match self.peek() { 89 let Spanned { inner: token, span } = match self.peek() {
96 Some(spanned) => spanned, 90 Some(spanned) => spanned,
97 None => todo!("unexpected eof"), 91 None => return Err(Spanned::new(Error::UnexpectedEof, self.last_token_span)),
98 }; 92 };
99 93
100 let expr = match token { 94 let expr = match token {
101 Token::LeftPar => { 95 Token::LeftPar => {
102 self.consume(); 96 self.consume();
103 let list = self.parse_list()?; 97 let list = self.parse_list(span)?;
104 let expr = if !list.is_empty() { 98 let expr = if !list.is_empty() {
105 Expr::List(list) 99 Expr::List(list)
106 } else { 100 } else {
107 Expr::Atom(Atom::Nil) 101 Expr::Atom(Atom::Nil)
108 }; 102 };
109 103
110 Spanned::new(expr, Span::new(span.start, self.last_token_end)) 104 Spanned::new(expr, Span::new(span.start, self.last_token_span.end))
105 }
106 Token::RightPar => {
107 self.consume();
108 return Err(Spanned::new(Error::UnexpectedRightPar, span));
111 } 109 }
112 Token::RightPar => todo!("unexpected par"),
113 Token::Quote => { 110 Token::Quote => {
114 self.consume(); 111 self.consume();
115 let quote = Spanned::new( 112 let quote = Spanned::new(Expr::Atom(Atom::Symbol("quote".into())), span);
116 Expr::Atom(Atom::Symbol("quote".into())),
117 Span::new(span.start, self.last_token_end),
118 );
119 let expr = self.parse_expr()?; 113 let expr = self.parse_expr()?;
120
121 Spanned::new( 114 Spanned::new(
122 Expr::List(vec![quote, expr]), 115 Expr::List(vec![quote, expr]),
123 Span::new(span.start, self.last_token_end), 116 Span::new(span.start, self.last_token_span.end),
124 ) 117 )
125 } 118 }
126 Token::Number(number) => { 119 Token::Number(number) => {
127 self.consume(); 120 self.consume();
128 121 let atom = parse_number(number).map_err(|e| Spanned::new(e, span))?;
129 Spanned::new( 122 Spanned::new(Expr::Atom(atom), span)
130 Expr::Atom(parse_number(number)),
131 Span::new(span.start, self.last_token_end),
132 )
133 } 123 }
134 Token::String(string) => { 124 Token::String(string) => {
135 self.consume(); 125 self.consume();
136 126 let atom = parse_string(string).map_err(|e| Spanned::new(e, span))?;
137 Spanned::new( 127 Spanned::new(Expr::Atom(atom), span)
138 Expr::Atom(parse_string(string)),
139 Span::new(span.start, self.last_token_end),
140 )
141 } 128 }
142 Token::UnclosedString(string) => { 129 Token::UnclosedString(string) => {
143 self.consume(); 130 self.consume();
144 todo!("unclosed string {string:?}") 131 return Err(Spanned::new(Error::UnclosedString(string.into()), span));
145 } 132 }
146 Token::Symbol(symbol) => { 133 Token::Symbol(symbol) => {
147 self.consume(); 134 self.consume();
148 135 let atom = parse_symbol(symbol);
149 Spanned::new( 136 Spanned::new(Expr::Atom(atom), span)
150 Expr::Atom(parse_symbol(symbol)),
151 Span::new(span.start, self.last_token_end),
152 )
153 } 137 }
154 }; 138 };
155 139
156 Ok(expr) 140 Ok(expr)
157 } 141 }
158 142
159 fn parse_list(&mut self) -> Result<Vec<Spanned<Expr>>> { 143 fn parse_list(&mut self, left_par_span: Span) -> Result<Vec<Spanned<Expr>>, Spanned<Error>> {
160 let mut list = Vec::new(); 144 let mut list = Vec::new();
161 145
162 while let Some(Spanned { inner: token, .. }) = self.peek() { 146 while let Some(Spanned { inner: token, .. }) = self.peek() {
@@ -169,10 +153,10 @@ where
169 } 153 }
170 } 154 }
171 155
172 todo!("unclosed par") 156 Err(Spanned::new(Error::UnclosedLeftPar, left_par_span))
173 } 157 }
174 158
175 pub fn parse(mut self) -> Result<Program> { 159 pub fn parse(mut self) -> Result<Program, Spanned<Error>> {
176 let mut program = Vec::new(); 160 let mut program = Vec::new();
177 161
178 while self.peek().is_some() { 162 while self.peek().is_some() {