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 <alekratz@gmail.com>
This commit is contained in:
2022-01-16 14:40:09 -08:00
parent effa99e65d
commit 2752bdf6d3
5 changed files with 49 additions and 32 deletions

View File

@@ -64,9 +64,9 @@ impl<'s> Compile<'s> {
// TODO - is self.compile the right thing to do here? // TODO - is self.compile the right thing to do here?
let compiled = Rc::new(self.compile(stmts.clone())); let compiled = Rc::new(self.compile(stmts.clone()));
let locals = self.scope_stack.pop_scope().unwrap(); let locals = self.scope_stack.pop_scope().unwrap();
let quote = self let quote =
.quote_table self.quote_table
.insert(expr.span(), locals, stmts.clone(), compiled); .insert(expr.span().clone(), locals, stmts.clone(), compiled);
Inst::PushValue(Value::Quote(quote)).into() Inst::PushValue(Value::Quote(quote)).into()
} }
} }

View File

@@ -27,15 +27,15 @@ type Result<T = (), E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
fn main() -> Result { fn main() -> Result {
let opt = Opt::from_args(); let opt = Opt::from_args();
let text = if let Some(path) = opt.path.as_ref() { let (text, path) = if let Some(path) = opt.path.as_ref() {
std::fs::read_to_string(path)? (std::fs::read_to_string(path)?, path.display().to_string())
} else { } else {
let mut input = String::new(); let mut input = String::new();
std::io::stdin().read_to_string(&mut input)?; std::io::stdin().read_to_string(&mut input)?;
input (input, "<stdin>".to_string())
}; };
let mut parser = Parser::from(text.as_str()); let mut parser = Parser::new(path, text.as_str());
let mut stmts = Vec::new(); let mut stmts = Vec::new();
while !parser.is_eof() { while !parser.is_eof() {
stmts.extend(parser.next_stmt_list()?); stmts.extend(parser.next_stmt_list()?);

View File

@@ -1,6 +1,7 @@
use crate::syn::{error::*, span::*, token::*}; use crate::syn::{error::*, span::*, token::*};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::{Regex, RegexBuilder}; use regex::{Regex, RegexBuilder};
use std::rc::Rc;
lazy_static! { lazy_static! {
static ref LEX_PAT: Regex = RegexBuilder::new( static ref LEX_PAT: Regex = RegexBuilder::new(
@@ -24,15 +25,17 @@ lazy_static! {
/// Lexes things. /// Lexes things.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Lexer<'t> { pub struct Lexer<'t> {
source: Rc<String>,
text: &'t str, text: &'t str,
start: Pos, start: Pos,
end: Pos, end: Pos,
} }
impl<'t> Lexer<'t> { 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'); let c = text.chars().next().unwrap_or('\0');
Self { Self {
source: Rc::new(source.to_string()),
text, text,
start: Pos::new(c), start: Pos::new(c),
end: Pos::new(c), end: Pos::new(c),
@@ -58,6 +61,7 @@ impl<'t> Lexer<'t> {
fn catchup(&mut self) -> Span { fn catchup(&mut self) -> Span {
let start = std::mem::replace(&mut self.start, self.end); let start = std::mem::replace(&mut self.start, self.end);
Span { Span {
source: Rc::clone(&self.source),
start, start,
end: self.end, end: self.end,
} }
@@ -165,7 +169,7 @@ mod test {
#[test] #[test]
fn test_word() { 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, "a");
assert_token!(lexer, Token::Word, "b"); assert_token!(lexer, Token::Word, "b");
assert_token!(lexer, Token::Word, "c"); assert_token!(lexer, Token::Word, "c");
@@ -187,7 +191,7 @@ mod test {
#[test] #[test]
fn test_assign() { 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, ":a");
assert_token!(lexer, Token::Assign, ":="); assert_token!(lexer, Token::Assign, ":=");
assert_token!(lexer, Token::Assign, ":foo"); assert_token!(lexer, Token::Assign, ":foo");
@@ -198,7 +202,10 @@ mod test {
#[test] #[test]
fn test_meta() { 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, "%meta");
assert_token!(lexer, Token::Meta, "%meta1"); assert_token!(lexer, Token::Meta, "%meta1");
assert_token!(lexer, Token::Meta, "%include"); assert_token!(lexer, Token::Meta, "%include");
@@ -211,7 +218,10 @@ mod test {
#[test] #[test]
fn test_numbers() { 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, "1");
assert_token!(lexer, Token::Int, "-12"); assert_token!(lexer, Token::Int, "-12");
assert_token!(lexer, Token::Int, "123"); assert_token!(lexer, Token::Int, "123");
@@ -228,7 +238,7 @@ mod test {
#[test] #[test]
fn test_quotes() { fn test_quotes() {
let mut lexer = Lexer::new("[ ] ] ] ] [ [ [ ["); let mut lexer = Lexer::new("test", "[ ] ] ] ] [ [ [ [");
assert_token!(lexer, Token::LQuote); assert_token!(lexer, Token::LQuote);
assert_token!(lexer, Token::RQuote); assert_token!(lexer, Token::RQuote);
assert_token!(lexer, Token::RQuote); assert_token!(lexer, Token::RQuote);

View File

@@ -10,14 +10,9 @@ pub struct Parser<'t> {
token: Result<Option<SpToken>>, token: Result<Option<SpToken>>,
} }
impl<'t> From<&'t str> for Parser<'t> {
fn from(text: &'t str) -> Self {
Parser::new(Lexer::new(text))
}
}
impl<'t> Parser<'t> { 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(); let token = lexer.next();
Self { lexer, token } Self { lexer, token }
} }
@@ -101,7 +96,7 @@ impl<'t> Parser<'t> {
_ => { _ => {
let expr = self.next_expr()?; let expr = self.next_expr()?;
let span = expr.span(); 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 // get the include location string
let (path_span, _token) = self.expect_any_token(&[Token::Str])?.into_split(); let (path_span, _token) = self.expect_any_token(&[Token::Str])?.into_split();
let path = unescape_string(path_span.text_at(self.lexer.text())); 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!( todo!(
@@ -132,7 +130,7 @@ impl<'t> Parser<'t> {
_ => { _ => {
let atom = self.next_atom()?; let atom = self.next_atom()?;
let span = atom.span(); 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] #[test]
fn test_parser_atoms() { fn test_parser_atoms() {
let mut parser = Parser::from( let mut parser = Parser::new(
"test",
r#" r#"
a ab bcd dcefg foo bar baz a ab bcd dcefg foo bar baz
1 2 3 4 5 1 2 3 4 5
@@ -303,7 +302,8 @@ fn test_parser_atoms() {
#[test] #[test]
fn test_parser_quotes() { fn test_parser_quotes() {
let mut parser = Parser::from( let mut parser = Parser::new(
"test",
r#" r#"
[ [
a ab bcd dcefg foo bar baz a ab bcd dcefg foo bar baz

View File

@@ -5,6 +5,7 @@
use std::cmp::{Ord, Ordering, PartialOrd}; use std::cmp::{Ord, Ordering, PartialOrd};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::rc::Rc;
#[cfg_attr(not(test), derive(PartialEq))] #[cfg_attr(not(test), derive(PartialEq))]
#[derive(Debug, Default, Clone, Copy, Eq)] #[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 struct Span {
pub source: Rc<String>,
pub start: Pos, pub start: Pos,
pub end: Pos, pub end: Pos,
} }
@@ -82,10 +84,15 @@ impl Span {
&text[self.start.byte..self.end.byte] &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 start = self.start.min(other.start);
let end = self.end.max(other.end); 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<T> Spanned<T> {
Self { span, inner } Self { span, inner }
} }
pub fn span(&self) -> Span { pub fn span(&self) -> &Span {
self.span &self.span
} }
pub fn inner(&self) -> &T { pub fn inner(&self) -> &T {
@@ -117,11 +124,11 @@ impl<T> Spanned<T> {
} }
pub fn split(&self) -> (Span, &T) { pub fn split(&self) -> (Span, &T) {
(self.span(), self.inner()) (self.span().clone(), self.inner())
} }
pub fn into_split(self) -> (Span, T) { 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 { pub fn text_at<'t>(&self, text: &'t str) -> &'t str {