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?
|
// 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()?);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user