From 8171b30adbc4cddd2c51f043c3379d78428666b8 Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 25 Mar 2021 13:08:25 +0530 Subject: use new error kinds; track Environment nesting with stack --- src/lisp/lex.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 8 deletions(-) (limited to 'src/lisp/lex.rs') 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 @@ use std::{fmt, str::CharIndices}; -use super::error::LispError; +use crate::lisp::error::{LispError, ParseError, ParseErrorKind}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Token<'a> { @@ -19,6 +19,26 @@ pub enum Token<'a> { End, } +impl<'a> Token<'a> { + pub fn name(&self) -> &'static str { + match self { + Token::LeftParen => "(", + Token::RightParen => ")", + Token::Float(_) => "float", + Token::Integer(_) => "integer", + // Token::Char(_) => "char", + Token::String(_) => "string", + Token::Name(_) => "name", + // Token::Keyword(_) => "keyword", + Token::BackQuote => "`", + Token::Comma => ",", + Token::CommaAt => ",@", + Token::Quote => "'", + Token::End => "EOF", + } + } +} + impl<'a> fmt::Display for Token<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -54,6 +74,25 @@ impl Span { } } +#[derive(Debug, Clone)] +pub struct SpanDisplay<'src> { + pub source: &'src str, + pub line: usize, + pub col: usize, +} + +impl<'src> SpanDisplay<'src> { + pub fn highlight_span(span: Span, source: &'src str) -> Self { + let line_start = match source[..span.low as usize].rfind('\n') { + Some(pos) => pos + 1, + None => 0, + }; + let line = source[..line_start].chars().filter(|&c| c == '\n').count() + 1; + let col = source[line_start..span.low as usize].chars().count(); + Self { source, line, col } + } +} + pub struct Lexer<'input> { input: &'input str, cur_pos: u32, @@ -68,6 +107,7 @@ impl<'a> Lexer<'a> { offset, } } + pub fn next_token(&mut self) -> Result<(Span, Token<'a>), LispError> { let mut chars = self.input.char_indices(); @@ -94,11 +134,19 @@ impl<'a> Lexer<'a> { self.cur_pos += ch.len_utf8() as u32; continue; } - _ => Err(LispError::ParseError), + ch => Err(ParseErrorKind::InvalidChar(ch)), }; let (size, token) = match res { Ok(v) => v, - Err(_) => return Err(LispError::ParseError), + Err(kind) => { + return Err(LispError::Parse(ParseError { + span: Span { + low, + high: low + chr.len_utf8() as u32, + }, + kind, + })) + } }; self.cur_pos += size as u32; self.input = &self.input[ind + size..]; @@ -113,7 +161,7 @@ impl<'a> Lexer<'a> { } } -fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError> { +fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> { let mut dot = false; let mut minus = false; let mut size = 0; @@ -137,12 +185,12 @@ fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError> dot = true; size += 1; } else { - return Err(LispError::ParseError); + return Err(ParseErrorKind::InvalidChar(chr)); } } else if !is_ident(chr) { break; } else { - return Err(LispError::ParseError); + return Err(ParseErrorKind::InvalidChar(chr)); } } @@ -156,7 +204,7 @@ fn parse_number<'a>(mut input: &'a str) -> Result<(usize, Token<'a>), LispError> return Ok((size, tok)); } -fn parse_string<'a>(input: &'a str) -> Result<(usize, Token<'a>), LispError> { +fn parse_string<'a>(input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> { // count opening quote let mut size = 1; let mut chars = input.char_indices().skip(1); @@ -197,7 +245,7 @@ fn consume_comment(start: usize, chars: &mut CharIndices) -> usize { last - start + 1 } -fn parse_name<'a>(input: &'a str) -> Result<(usize, Token<'a>), LispError> { +fn parse_name<'a>(input: &'a str) -> Result<(usize, Token<'a>), ParseErrorKind> { for (ind, chr) in input.char_indices() { if !is_ident(chr) { return Ok((ind, Token::Name(&input[..ind]))); -- cgit v1.2.3