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:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,15 @@ type Result<T = (), E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
||||
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, "<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();
|
||||
while !parser.is_eof() {
|
||||
stmts.extend(parser.next_stmt_list()?);
|
||||
|
||||
@@ -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<String>,
|
||||
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);
|
||||
|
||||
@@ -10,14 +10,9 @@ pub struct Parser<'t> {
|
||||
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> {
|
||||
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
|
||||
|
||||
@@ -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<String>,
|
||||
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<T> Spanned<T> {
|
||||
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<T> Spanned<T> {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user