aboutsummaryrefslogtreecommitdiff
path: root/src/lisp/lex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lisp/lex.rs')
-rw-r--r--src/lisp/lex.rs64
1 files changed, 56 insertions, 8 deletions
diff --git a/src/lisp/lex.rs b/src/lisp/lex.rs
index a7b9586..b307e80 100644
--- a/src/lisp/lex.rs
+++ b/src/lisp/lex.rs
@@ -1,6 +1,6 @@
1use std::{fmt, str::CharIndices}; 1use std::{fmt, str::CharIndices};
2 2
3use super::error::LispError; 3use crate::lisp::error::{LispError, ParseError, ParseErrorKind};
4 4
5#[derive(Copy, Clone, Debug, Eq, PartialEq)] 5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6pub enum Token<'a> { 6pub enum Token<'a> {
@@ -19,6 +19,26 @@ pub enum Token<'a> {
19 End, 19 End,
20} 20}
21 21
22impl<'a> Token<'a> {
23 pub fn name(&self) -> &'static str {
24 match self {
25 Token::LeftParen => "(",
26 Token::RightParen => ")",
27 Token::Float(_) => "float",
28 Token::Integer(_) => "integer",
29 // Token::Char(_) => "char",
30 Token::String(_) => "string",
31 Token::Name(_) => "name",
32 // Token::Keyword(_) => "keyword",
33 Token::BackQuote => "`",
34 Token::Comma => ",",
35 Token::CommaAt => ",@",
36 Token::Quote => "'",
37 Token::End => "EOF",
38 }
39 }
40}
41
22impl<'a> fmt::Display for Token<'a> { 42impl<'a> fmt::Display for Token<'a> {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self { 44 match self {
@@ -54,6 +74,25 @@ impl Span {
54 } 74 }
55} 75}
56 76
77#[derive(Debug, Clone)]
78pub struct SpanDisplay<'src> {
79 pub source: &'src str,
80 pub line: usize,
81 pub col: usize,
82}
83
84impl<'src> SpanDisplay<'src> {
85 pub fn highlight_span(span: Span, source: &'src str) -> Self {
86 let line_start = match source[..span.low as usize].rfind('\n') {
87 Some(pos) => pos + 1,
88 None => 0,
89 };
90 let line = source[..line_start].chars().filter(|&c| c == '\n').count() + 1;
91 let col = source[line_start..span.low as usize].chars().count();
92 Self { source, line, col }
93 }
94}
95
57pub struct Lexer<'input> { 96pub struct Lexer<'input> {
58 input: &'input str, 97 input: &'input str,
59 cur_pos: u32, 98 cur_pos: u32,
@@ -68,6 +107,7 @@ impl<'a> Lexer<'a> {
68 offset, 107 offset,
69 } 108 }
70 } 109 }
110
71 pub fn next_token(&mut self) -> Result<(Span, Token<'a>), LispError> { 111 pub fn next_token(&mut self) -> Result<(Span, Token<'a>), LispError> {
72 let mut chars = self.input.char_indices(); 112 let mut chars = self.input.char_indices();
73 113
@@ -94,11 +134,19 @@ impl<'a> Lexer<'a> {
94 self.cur_pos += ch.len_utf8() as u32; 134 self.cur_pos += ch.len_utf8() as u32;
95 continue; 135 continue;
96 } 136 }
97 _ => Err(LispError::ParseError), 137 ch => Err(ParseErrorKind::InvalidChar(ch)),
98 }; 138 };
99 let (size, token) = match res { 139 let (size, token) = match res {
100 Ok(v) => v, 140 Ok(v) => v,
101 Err(_) => return Err(LispError::ParseError), 141 Err(kind) => {
142 return Err(LispError::Parse(ParseError {
143 span: Span {
144 low,
145 high: low + chr.len_utf8() as u32,
146 },
147 kind,
148 }))
149 }
102 }; 150 };
103 self.cur_pos += size as u32; 151 self.cur_pos += size as u32;
104 self.input = &self.input[ind + size..]; 152 self.input = &self.input[ind + size..];
@@ -113,7 +161,7 @@ impl<'a> Lexer<'a> {
113 } 161 }
114} 162}
115 163
116fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError> { 164fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> {
117 let mut dot = false; 165 let mut dot = false;
118 let mut minus = false; 166 let mut minus = false;
119 let mut size = 0; 167 let mut size = 0;
@@ -137,12 +185,12 @@ fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError>
137 dot = true; 185 dot = true;
138 size += 1; 186 size += 1;
139 } else { 187 } else {
140 return Err(LispError::ParseError); 188 return Err(ParseErrorKind::InvalidChar(chr));
141 } 189 }
142 } else if !is_ident(chr) { 190 } else if !is_ident(chr) {
143 break; 191 break;
144 } else { 192 } else {
145 return Err(LispError::ParseError); 193 return Err(ParseErrorKind::InvalidChar(chr));
146 } 194 }
147 } 195 }
148 196
@@ -156,7 +204,7 @@ fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError>
156 return Ok((size, tok)); 204 return Ok((size, tok));
157} 205}
158 206
159fn parse_string<'a>(input: &'a str) -> Result<(usize, Token<'a>), LispError> { 207fn parse_string<'a>(input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> {
160 // count opening quote 208 // count opening quote
161 let mut size = 1; 209 let mut size = 1;
162 let mut chars = input.char_indices().skip(1); 210 let mut chars = input.char_indices().skip(1);
@@ -197,7 +245,7 @@ fn consume_comment(start: usize, chars: &mut CharIndices) -> usize {
197 last - start + 1 245 last - start + 1
198} 246}
199 247
200fn parse_name<'a>(input: &'a str) -> Result<(usize, Token<'a>), LispError> { 248fn parse_name<'a>(input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> {
201 for (ind, chr) in input.char_indices() { 249 for (ind, chr) in input.char_indices() {
202 if !is_ident(chr) { 250 if !is_ident(chr) {
203 return Ok((ind, Token::Name(&input[..ind]))); 251 return Ok((ind, Token::Name(&input[..ind])));