From 2752bdf6d3a64dc40fe0e9070e511eb27b1b99a0 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Sun, 16 Jan 2022 14:40:09 -0800 Subject: [PATCH] Add `source` string to Span This is the path to the location that this span is pointing to. This is usually going to be a file path, but it can really be anything you want. Signed-off-by: Alek Ratzloff --- src/compile.rs | 6 +++--- src/main.rs | 8 ++++---- src/syn/lexer.rs | 22 ++++++++++++++++------ src/syn/parser.rs | 24 ++++++++++++------------ src/syn/span.rs | 21 ++++++++++++++------- 5 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/compile.rs b/src/compile.rs index 7974cc6..edfbef2 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -64,9 +64,9 @@ impl<'s> Compile<'s> { // TODO - is self.compile the right thing to do here? let compiled = Rc::new(self.compile(stmts.clone())); let locals = self.scope_stack.pop_scope().unwrap(); - let quote = self - .quote_table - .insert(expr.span(), locals, stmts.clone(), compiled); + let quote = + self.quote_table + .insert(expr.span().clone(), locals, stmts.clone(), compiled); Inst::PushValue(Value::Quote(quote)).into() } } diff --git a/src/main.rs b/src/main.rs index 6627bfb..842fbec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,15 +27,15 @@ type Result> = std::result::Result; fn main() -> Result { let opt = Opt::from_args(); - let text = if let Some(path) = opt.path.as_ref() { - std::fs::read_to_string(path)? + let (text, path) = if let Some(path) = opt.path.as_ref() { + (std::fs::read_to_string(path)?, path.display().to_string()) } else { let mut input = String::new(); std::io::stdin().read_to_string(&mut input)?; - input + (input, "".to_string()) }; - let mut parser = Parser::from(text.as_str()); + let mut parser = Parser::new(path, text.as_str()); let mut stmts = Vec::new(); while !parser.is_eof() { stmts.extend(parser.next_stmt_list()?); diff --git a/src/syn/lexer.rs b/src/syn/lexer.rs index 6112128..667d486 100644 --- a/src/syn/lexer.rs +++ b/src/syn/lexer.rs @@ -1,6 +1,7 @@ use crate::syn::{error::*, span::*, token::*}; use lazy_static::lazy_static; use regex::{Regex, RegexBuilder}; +use std::rc::Rc; lazy_static! { static ref LEX_PAT: Regex = RegexBuilder::new( @@ -24,15 +25,17 @@ lazy_static! { /// Lexes things. #[derive(Debug, Clone)] pub struct Lexer<'t> { + source: Rc, text: &'t str, start: Pos, end: Pos, } impl<'t> Lexer<'t> { - pub fn new(text: &'t str) -> Self { + pub fn new(source: impl ToString, text: &'t str) -> Self { let c = text.chars().next().unwrap_or('\0'); Self { + source: Rc::new(source.to_string()), text, start: Pos::new(c), end: Pos::new(c), @@ -58,6 +61,7 @@ impl<'t> Lexer<'t> { fn catchup(&mut self) -> Span { let start = std::mem::replace(&mut self.start, self.end); Span { + source: Rc::clone(&self.source), start, end: self.end, } @@ -165,7 +169,7 @@ mod test { #[test] fn test_word() { - let mut lexer = Lexer::new(r"a b c d foo bar baz = == === =a ==a ===a"); + let mut lexer = Lexer::new("test", r"a b c d foo bar baz = == === =a ==a ===a"); assert_token!(lexer, Token::Word, "a"); assert_token!(lexer, Token::Word, "b"); assert_token!(lexer, Token::Word, "c"); @@ -187,7 +191,7 @@ mod test { #[test] fn test_assign() { - let mut lexer = Lexer::new(r":a := :foo :foo-bar :foo-bar-baz"); + let mut lexer = Lexer::new("test", r":a := :foo :foo-bar :foo-bar-baz"); assert_token!(lexer, Token::Assign, ":a"); assert_token!(lexer, Token::Assign, ":="); assert_token!(lexer, Token::Assign, ":foo"); @@ -198,7 +202,10 @@ mod test { #[test] fn test_meta() { - let mut lexer = Lexer::new(r"%meta %meta1 %include %include1029 %10239meta % %%"); + let mut lexer = Lexer::new( + "test", + r"%meta %meta1 %include %include1029 %10239meta % %%", + ); assert_token!(lexer, Token::Meta, "%meta"); assert_token!(lexer, Token::Meta, "%meta1"); assert_token!(lexer, Token::Meta, "%include"); @@ -211,7 +218,10 @@ mod test { #[test] fn test_numbers() { - let mut lexer = Lexer::new(r"1 -12 123 -9 98 987 -987654321 1248 9764321 -1.2 2.3"); + let mut lexer = Lexer::new( + "test", + r"1 -12 123 -9 98 987 -987654321 1248 9764321 -1.2 2.3", + ); assert_token!(lexer, Token::Int, "1"); assert_token!(lexer, Token::Int, "-12"); assert_token!(lexer, Token::Int, "123"); @@ -228,7 +238,7 @@ mod test { #[test] fn test_quotes() { - let mut lexer = Lexer::new("[ ] ] ] ] [ [ [ ["); + let mut lexer = Lexer::new("test", "[ ] ] ] ] [ [ [ ["); assert_token!(lexer, Token::LQuote); assert_token!(lexer, Token::RQuote); assert_token!(lexer, Token::RQuote); diff --git a/src/syn/parser.rs b/src/syn/parser.rs index f3ed707..86da028 100644 --- a/src/syn/parser.rs +++ b/src/syn/parser.rs @@ -10,14 +10,9 @@ pub struct Parser<'t> { token: Result>, } -impl<'t> From<&'t str> for Parser<'t> { - fn from(text: &'t str) -> Self { - Parser::new(Lexer::new(text)) - } -} - impl<'t> Parser<'t> { - pub fn new(mut lexer: Lexer<'t>) -> Self { + pub fn new(source: impl ToString, text: &'t str) -> Self { + let mut lexer = Lexer::new(source, text); let token = lexer.next(); Self { lexer, token } } @@ -101,7 +96,7 @@ impl<'t> Parser<'t> { _ => { let expr = self.next_expr()?; let span = expr.span(); - Ok(SpStmt::new(span, Stmt::Expr(expr))) + Ok(SpStmt::new(span.clone(), Stmt::Expr(expr))) } } } @@ -114,7 +109,10 @@ impl<'t> Parser<'t> { // get the include location string let (path_span, _token) = self.expect_any_token(&[Token::Str])?.into_split(); let path = unescape_string(path_span.text_at(self.lexer.text())); - Ok(SpStmt::new(meta_span.union(path_span), Stmt::Include(path))) + Ok(SpStmt::new( + meta_span.union(&path_span), + Stmt::Include(path), + )) } _ => { todo!( @@ -132,7 +130,7 @@ impl<'t> Parser<'t> { _ => { let atom = self.next_atom()?; let span = atom.span(); - Ok(SpExpr::new(span, Expr::Atom(atom))) + Ok(SpExpr::new(span.clone(), Expr::Atom(atom))) } } } @@ -262,7 +260,8 @@ macro_rules! make_atom { #[test] fn test_parser_atoms() { - let mut parser = Parser::from( + let mut parser = Parser::new( + "test", r#" a ab bcd dcefg foo bar baz 1 2 3 4 5 @@ -303,7 +302,8 @@ fn test_parser_atoms() { #[test] fn test_parser_quotes() { - let mut parser = Parser::from( + let mut parser = Parser::new( + "test", r#" [ a ab bcd dcefg foo bar baz diff --git a/src/syn/span.rs b/src/syn/span.rs index 88f93e7..71e0585 100644 --- a/src/syn/span.rs +++ b/src/syn/span.rs @@ -5,6 +5,7 @@ use std::cmp::{Ord, Ordering, PartialOrd}; use std::fmt::{self, Debug}; +use std::rc::Rc; #[cfg_attr(not(test), derive(PartialEq))] #[derive(Debug, Default, Clone, Copy, Eq)] @@ -71,8 +72,9 @@ impl Ord for Pos { } } -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Span { + pub source: Rc, pub start: Pos, pub end: Pos, } @@ -82,10 +84,15 @@ impl Span { &text[self.start.byte..self.end.byte] } - pub fn union(&self, other: Span) -> Self { + pub fn union(&self, other: &Span) -> Self { let start = self.start.min(other.start); let end = self.end.max(other.end); - Span { start, end } + // TODO - what to do if start.source != end.source + Span { + source: Rc::clone(&self.source), + start, + end, + } } } @@ -100,8 +107,8 @@ impl Spanned { Self { span, inner } } - pub fn span(&self) -> Span { - self.span + pub fn span(&self) -> &Span { + &self.span } pub fn inner(&self) -> &T { @@ -117,11 +124,11 @@ impl Spanned { } pub fn split(&self) -> (Span, &T) { - (self.span(), self.inner()) + (self.span().clone(), self.inner()) } pub fn into_split(self) -> (Span, T) { - (self.span(), self.into_inner()) + (self.span().clone(), self.into_inner()) } pub fn text_at<'t>(&self, text: &'t str) -> &'t str {