Browse Source

thread a FileRef through as well

Getty Ritter 2 years ago
parent
commit
e7b0380358
6 changed files with 37 additions and 14 deletions
  1. 2 1
      build.rs
  2. 9 1
      src/ast.rs
  3. 3 3
      src/grammar.lalrpop
  4. 10 4
      src/interp.rs
  5. 11 4
      src/lexer.rs
  6. 2 1
      tools/regenerate.rs

+ 2 - 1
build.rs

@@ -43,7 +43,8 @@ fn test_%PREFIX%() {
   let state = crate::interp::State::new();
   let source = include_str!(\"%ROOT%/tests/%PREFIX%.matzo\");
   let lexer = lexer::tokens(source);
-  let stmts = grammar::StmtsParser::new().parse(&mut state.get_ast().borrow_mut(), lexer);
+  let file = state.get_ast().borrow_mut().add_file(source.to_string());
+  let stmts = grammar::StmtsParser::new().parse(&mut state.get_ast().borrow_mut(), file, lexer);
   assert!(stmts.is_ok());
   let stmts = stmts.unwrap();
 

+ 9 - 1
src/ast.rs

@@ -1,10 +1,11 @@
 use std::fmt;
-pub use crate::lexer::Located;
+pub use crate::lexer::{FileRef, Located};
 
 pub type StrRef = string_interner::DefaultSymbol;
 pub type Name = Located<StrRef>;
 
 pub struct ASTArena {
+    files: Vec<String>,
     strings: string_interner::StringInterner,
     exprs: Vec<Expr>,
 }
@@ -18,6 +19,7 @@ impl Default for ASTArena {
 impl ASTArena {
     pub fn new() -> ASTArena {
         ASTArena {
+            files: Vec::new(),
             strings: string_interner::StringInterner::new(),
             exprs: vec![Expr::Nil],
         }
@@ -69,6 +71,12 @@ impl ASTArena {
         }
     }
 
+    pub fn add_file(&mut self, file: String) -> FileRef {
+        let idx = self.files.len();
+        self.files.push(file);
+        FileRef { idx }
+    }
+
     fn indent(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
         for _ in 0..depth {
             write!(f, " ")?;

+ 3 - 3
src/grammar.lalrpop

@@ -1,7 +1,7 @@
 use crate::ast::*;
 use crate::lexer::*;
 
-grammar<'input>(ast: &mut ASTArena);
+grammar<'input>(ast: &mut ASTArena, file: FileRef);
 
 extern {
     type Location = usize;
@@ -65,7 +65,7 @@ pub AtomLit: string_interner::DefaultSymbol = {
 
 pub Name: Name = {
     <start: @L> <str:"var"> <end: @R> =>
-        Located::new(ast.add_string(str), Span { start: start as u32, end: end as u32 }),
+        Located::new(ast.add_string(str), file, Span { start: start as u32, end: end as u32 }),
 };
 
 pub Expr: ExprId = {
@@ -161,5 +161,5 @@ pub Literal: Literal = {
 #[inline]
 Located<T>: Located<T> = {
     <start: @L> <data: T> <end: @R> =>
-        Located::new(data, Span { start: start as u32, end: end as u32 }),
+        Located::new(data, file, Span { start: start as u32, end: end as u32 }),
 };

+ 10 - 4
src/interp.rs

@@ -337,9 +337,10 @@ impl State {
     /// results to stdout.
     pub fn run(&self, src: &str) -> Result<(), Error> {
         let lexed = crate::lexer::tokens(src);
+        let file = self.ast.borrow_mut().add_file(src.to_string());
         let stmts = self
             .parser
-            .parse(&mut self.ast.borrow_mut(), lexed)
+            .parse(&mut self.ast.borrow_mut(), file, lexed)
             .map_err(|err| anyhow!("Got {:?}", err))?;
         let mut stdout = io::stdout();
         for stmt in stmts {
@@ -352,9 +353,10 @@ impl State {
     /// results to the provided writer.
     pub fn run_with_writer(&self, src: &str, w: &mut impl std::io::Write) -> Result<(), Error> {
         let lexed = crate::lexer::tokens(src);
+        let file = self.ast.borrow_mut().add_file(src.to_string());
         let stmts = self
             .parser
-            .parse(&mut self.ast.borrow_mut(), lexed)
+            .parse(&mut self.ast.borrow_mut(), file, lexed)
             .map_err(|err| anyhow!("Got {:?}", err))?;
         for stmt in stmts {
             self.execute(&stmt, &mut *w)?;
@@ -371,16 +373,18 @@ impl State {
     /// simply types an expression.
     pub fn run_repl(&self, src: &str) -> Result<(), Error> {
         let lexed = crate::lexer::tokens(src);
+        let file = self.ast.borrow_mut().add_file(src.to_string());
         let stmts = {
             let mut ast = self.ast.borrow_mut();
-            self.parser.parse(&mut ast, lexed)
+            self.parser.parse(&mut ast, file, lexed)
         };
         let stmts = match stmts {
             Ok(stmts) => stmts,
             Err(err) => {
                 let with_puts = format!("puts {}", src);
                 let lexed = crate::lexer::tokens(&with_puts);
-                if let Ok(stmts) = self.parser.parse(&mut self.ast.borrow_mut(), lexed) {
+                let file = self.ast.borrow_mut().add_file(src.to_string());
+                if let Ok(stmts) = self.parser.parse(&mut self.ast.borrow_mut(), file, lexed) {
                     stmts
                 } else {
                     bail!("{:?}", err);
@@ -477,6 +481,7 @@ impl State {
                         Choice {
                             weight: None,
                             value: Located {
+                                file: s.file,
                                 span: s.span,
                                 item: self.ast.borrow_mut().add_expr(Expr::Lit(Literal::Str(str))),
                             },
@@ -484,6 +489,7 @@ impl State {
                     })
                     .collect();
                 let choices = Located {
+                    file: choices.first().unwrap().value.file,
                     span: Span {
                         start: choices.first().unwrap().value.span.start,
                         end: choices.last().unwrap().value.span.end,

+ 11 - 4
src/lexer.rs

@@ -1,5 +1,10 @@
 use logos::{Lexer, Logos};
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct FileRef {
+    pub idx: usize,
+}
+
 /// A location in a source file
 #[derive(Debug, Clone, Copy)]
 pub struct Span {
@@ -22,21 +27,23 @@ impl Span {
 
 #[derive(Debug, Clone, Copy)]
 pub struct Located<T> {
-    pub span: Span,
     pub item: T,
+    pub span: Span,
+    pub file: FileRef,
 }
 
 impl<T> Located<T> {
-    pub fn new(item: T, span: Span) -> Located<T> {
-        Located { span, item }
+    pub fn new(item: T, file: FileRef, span: Span) -> Located<T> {
+        Located { span, file, item }
     }
 }
 
 impl <T: Clone> Located<T> {
     pub fn map<R>(&self, func: impl FnOnce(T) -> R) -> Located<R> {
         Located {
-            span: self.span,
             item: func(self.item.clone()),
+            span: self.span,
+            file: self.file,
         }
     }
 }

+ 2 - 1
tools/regenerate.rs

@@ -38,7 +38,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
             let mut ast = matzo::ast::ASTArena::new();
             let src = std::fs::read_to_string(&exp)?;
             let tokens = lexer::tokens(&src);
-            if let Ok(stmts) = grammar::StmtsParser::new().parse(&mut ast, tokens) {
+            let file = ast.add_file(src.to_string());
+            if let Ok(stmts) = grammar::StmtsParser::new().parse(&mut ast, file, tokens) {
                 let mut f = std::fs::File::create(exp_filename("parsed"))?;
                 for stmt in stmts {
                     writeln!(f, "{:#?}", stmt.show(&ast))?;