svg-filters & basic parser #15
5 changed files with 148 additions and 156 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -850,9 +850,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.8.0"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
|
@ -860,9 +860,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon-core"
|
name = "rayon-core"
|
||||||
version = "1.12.0"
|
version = "1.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
use rowan::ast::{AstNode, AstPtr};
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
error::{Error, WorldCreationError},
|
error::{Error, WorldCreationError},
|
||||||
mod_tree::{Module, ModuleTree},
|
mod_tree::ModuleTree,
|
||||||
source_file::SourceFile,
|
source_file::SourceFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ impl World {
|
||||||
Err(e) => return Err(WorldCreationError::FailedToOpenEntryPoint(entry_point, e)),
|
Err(e) => return Err(WorldCreationError::FailedToOpenEntryPoint(entry_point, e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (src, mut errors) = SourceFile::parse_from(entry_point.clone(), source);
|
let (src, mut errors) = SourceFile::parse_from(&entry_point, source);
|
||||||
|
|
||||||
let (module_tree, mut files, new_errors) = ModuleTree::parse_from_main(&entry_point, &src);
|
let (module_tree, mut files, new_errors) = ModuleTree::parse_from_main(&entry_point, &src);
|
||||||
errors.extend(new_errors);
|
errors.extend(new_errors);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
cell::RefCell,
|
||||||
path::PathBuf,
|
collections::HashMap,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
use rowan::ast::AstNode;
|
||||||
|
|
||||||
use crate::{lst_parser::syntax_kind::SyntaxKind, SyntaxNode};
|
use crate::{lst_parser::syntax_kind::SyntaxKind, SyntaxNode};
|
||||||
|
|
||||||
|
@ -16,7 +18,80 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ModuleTree {
|
pub struct ModuleTree {
|
||||||
modules: HashMap<String, Arc<Module>>,
|
modules: Rc<HashMap<String, Module>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ModuleParsingContext {
|
||||||
|
files: Rc<RefCell<HashMap<PathBuf, SourceFile>>>,
|
||||||
|
errors: Rc<RefCell<Vec<Error>>>,
|
||||||
|
proj_dir: Rc<PathBuf>,
|
||||||
|
cur_path: Vec<String>,
|
||||||
|
cur_file: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleParsingContext {
|
||||||
|
fn new(entry_path: &Path) -> Self {
|
||||||
|
let proj_dir = entry_path.parent().unwrap().to_owned();
|
||||||
|
Self {
|
||||||
|
files: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
errors: Rc::new(RefCell::new(Vec::new())),
|
||||||
|
proj_dir: Rc::new(entry_path.to_owned()),
|
||||||
|
cur_path: Vec::new(),
|
||||||
|
cur_file: entry_path.to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_path(&self) -> PathBuf {
|
||||||
|
self.proj_dir.to_path_buf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_mod_file_path(&self, mod_path: &[String], mod_name: &str) -> PathBuf {
|
||||||
|
let mut entry_path = self.entry_path();
|
||||||
|
for el in mod_path {
|
||||||
|
entry_path.push(format!("{el}/"));
|
||||||
|
}
|
||||||
|
entry_path.push(format!("{mod_name}.owo"));
|
||||||
|
entry_path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_cur_path(&mut self, name_to_add: String) {
|
||||||
|
self.cur_path.push(name_to_add);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cur_file(&mut self, new: PathBuf) {
|
||||||
|
self.cur_file = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_errs(&self, errs: Vec<Error>) {
|
||||||
|
self.errors.borrow_mut().extend(errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_child_modules(
|
||||||
|
&self,
|
||||||
|
node: &SyntaxNode,
|
||||||
|
name: Option<String>,
|
||||||
|
) -> HashMap<String, Module> {
|
||||||
|
let mut ctx = self.clone();
|
||||||
|
if let Some(name) = name {
|
||||||
|
ctx.push_cur_path(name)
|
||||||
|
}
|
||||||
|
node.children()
|
||||||
|
.filter_map(Mod::cast)
|
||||||
|
.filter_map(|m| match Module::parse_mod(m, self.clone()) {
|
||||||
|
Ok(module) => Some((module.name(), module)),
|
||||||
|
Err(error) => {
|
||||||
|
self.errors.borrow_mut().push(error);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<HashMap<String, Module>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dissolve(self) -> (HashMap<PathBuf, SourceFile>, Vec<Error>) {
|
||||||
|
let Self { files, errors, .. } = self;
|
||||||
|
(files.take(), errors.take())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleTree {
|
impl ModuleTree {
|
||||||
|
@ -24,37 +99,18 @@ impl ModuleTree {
|
||||||
path: &PathBuf,
|
path: &PathBuf,
|
||||||
main_file: &SourceFile,
|
main_file: &SourceFile,
|
||||||
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>) {
|
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>) {
|
||||||
let tree = main_file.tree();
|
|
||||||
let mut files = HashMap::new();
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
let entry_path = path.parent().unwrap().to_owned();
|
let entry_path = path.parent().unwrap().to_owned();
|
||||||
let modules = main_file
|
let ctx = ModuleParsingContext::new(&entry_path);
|
||||||
.top_level_modules()
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|m| {
|
|
||||||
let module =
|
|
||||||
Module::parse_mod(m.to_node(tree.syntax()), Vec::new(), &path, &entry_path);
|
|
||||||
match module {
|
|
||||||
Ok(module) => {
|
|
||||||
files.extend(module.1);
|
|
||||||
errors.extend(module.2);
|
|
||||||
Some((module.0.name(), Arc::new(module.0)))
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
errors.push(err);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<HashMap<String, Arc<Module>>>();
|
|
||||||
|
|
||||||
|
let modules = Rc::new(ctx.parse_child_modules(main_file.tree().syntax(), None));
|
||||||
|
|
||||||
|
let (files, errors) = ctx.dissolve();
|
||||||
(Self { modules }, files, errors)
|
(Self { modules }, files, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_tree(&self, lst: &Root) {
|
pub fn print_tree(&self, lst: &Root) {
|
||||||
let name = "main";
|
let name = "main";
|
||||||
print_tree(&name, &self.modules, 0)
|
print_tree(&name, self.modules.clone(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,19 +118,12 @@ pub struct Module {
|
||||||
path: Vec<String>,
|
path: Vec<String>,
|
||||||
name: String,
|
name: String,
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
children: HashMap<String, Arc<Module>>,
|
children: Rc<HashMap<String, Module>>,
|
||||||
parent: Option<Arc<Module>>,
|
parent: Option<Arc<Module>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
fn parse_mod(
|
fn parse_mod(module: Mod, ctx: ModuleParsingContext) -> Result<Self, Error> {
|
||||||
module: Mod,
|
|
||||||
cur_path: Vec<String>,
|
|
||||||
cur_file: &PathBuf,
|
|
||||||
entry_path: &PathBuf,
|
|
||||||
) -> Result<(Self, HashMap<PathBuf, SourceFile>, Vec<Error>), Error> {
|
|
||||||
dbg!(cur_file);
|
|
||||||
dbg!(entry_path);
|
|
||||||
let children = module
|
let children = module
|
||||||
.syntax()
|
.syntax()
|
||||||
.children()
|
.children()
|
||||||
|
@ -86,138 +135,77 @@ impl Module {
|
||||||
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
||||||
return Self::parse_file_mod(
|
return Self::parse_file_mod(
|
||||||
name.text().to_string(),
|
name.text().to_string(),
|
||||||
Loc::new(cur_file.clone(), &module),
|
ctx.clone(),
|
||||||
cur_path,
|
Loc::new(ctx.cur_file.clone(), &module),
|
||||||
entry_path,
|
|
||||||
);
|
);
|
||||||
} else if children.len() == 2 {
|
} else if children.len() == 2 {
|
||||||
let name = &children[0];
|
let name = &children[0];
|
||||||
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
||||||
let body = &children[1];
|
let body = &children[1];
|
||||||
assert_eq!(body.kind(), SyntaxKind::MODULE_BODY);
|
assert_eq!(body.kind(), SyntaxKind::MODULE_BODY);
|
||||||
return Ok(Self::parse_inline_mod(
|
return Ok(Self::parse_inline_mod(module, ctx.clone()));
|
||||||
module, cur_path, cur_file, entry_path,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_file_mod(
|
fn parse_file_mod(
|
||||||
name: String,
|
name: String,
|
||||||
|
mut ctx: ModuleParsingContext,
|
||||||
decl: Loc<Mod>,
|
decl: Loc<Mod>,
|
||||||
mut cur_path: Vec<String>,
|
) -> Result<Self, Error> {
|
||||||
entry_path: &PathBuf,
|
ctx.set_cur_file(ctx.make_mod_file_path(&ctx.cur_path, &name));
|
||||||
) -> Result<(Self, HashMap<PathBuf, SourceFile>, Vec<Error>), Error> {
|
|
||||||
let mut mod_file_path = entry_path.to_owned();
|
|
||||||
|
|
||||||
for el in &cur_path {
|
let source = match std::fs::read_to_string(&ctx.cur_file) {
|
||||||
mod_file_path.push(format!("{el}/"));
|
|
||||||
}
|
|
||||||
mod_file_path.push(format!("{name}.owo"));
|
|
||||||
|
|
||||||
let mut files = HashMap::new();
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
let source = match std::fs::read_to_string(dbg!(&mod_file_path)) {
|
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => return Err(Error::FailedToOpenFileMod(mod_file_path, e)),
|
Err(e) => return Err(Error::FailedToOpenFileMod(ctx.cur_file, e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (source_file, file_errors) = SourceFile::parse_from(mod_file_path.clone(), source);
|
let (source_file, file_errors) = SourceFile::parse_from(&ctx.cur_file, source);
|
||||||
errors.extend(file_errors);
|
|
||||||
|
|
||||||
let tree = source_file.tree();
|
let old_path = ctx.cur_path.clone();
|
||||||
let old_path = cur_path.clone();
|
ctx.push_cur_path(name.clone());
|
||||||
cur_path.push(name.clone());
|
ctx.push_errs(file_errors);
|
||||||
let children = source_file
|
|
||||||
.top_level_modules()
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|m| {
|
|
||||||
let module = Module::parse_mod(
|
|
||||||
m.to_node(tree.syntax()),
|
|
||||||
cur_path.clone(),
|
|
||||||
&mod_file_path,
|
|
||||||
&entry_path,
|
|
||||||
);
|
|
||||||
match module {
|
|
||||||
Ok(module) => {
|
|
||||||
files.extend(module.1);
|
|
||||||
errors.extend(module.2);
|
|
||||||
Some((module.0.name(), Arc::new(module.0)))
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
errors.push(err);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<HashMap<String, Arc<Module>>>();
|
|
||||||
|
|
||||||
files.insert(mod_file_path.clone(), source_file);
|
let children =
|
||||||
|
Rc::new(ctx.parse_child_modules(source_file.tree().syntax(), Some(name.clone())));
|
||||||
|
|
||||||
Ok((
|
ctx.files
|
||||||
Self {
|
.borrow_mut()
|
||||||
path: old_path,
|
.insert(ctx.cur_file.clone(), source_file);
|
||||||
name,
|
|
||||||
kind: ModuleKind::File {
|
Ok(Self {
|
||||||
declaration: decl,
|
path: old_path,
|
||||||
file_id: mod_file_path,
|
name,
|
||||||
},
|
kind: ModuleKind::File {
|
||||||
children,
|
declaration: decl,
|
||||||
parent: None,
|
file_id: ctx.cur_file.clone(),
|
||||||
},
|
},
|
||||||
files,
|
children,
|
||||||
errors,
|
parent: None,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_inline_mod(
|
fn parse_inline_mod(module: Mod, mut ctx: ModuleParsingContext) -> Self {
|
||||||
module: Mod,
|
|
||||||
mut cur_path: Vec<String>,
|
|
||||||
cur_file: &PathBuf,
|
|
||||||
entry_path: &PathBuf,
|
|
||||||
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>) {
|
|
||||||
let mut children = module.syntax().children().collect::<Vec<_>>();
|
let mut children = module.syntax().children().collect::<Vec<_>>();
|
||||||
|
|
||||||
let body = ModBody::cast(children.pop().unwrap()).unwrap();
|
let body = ModBody::cast(children.pop().unwrap()).unwrap();
|
||||||
let name = ModName::cast(children.pop().unwrap()).unwrap();
|
let name = ModName::cast(children.pop().unwrap())
|
||||||
|
.unwrap()
|
||||||
let mut files = HashMap::new();
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
let old_path = cur_path.clone();
|
|
||||||
cur_path.push(name.syntax().to_string());
|
|
||||||
let children = body
|
|
||||||
.syntax()
|
.syntax()
|
||||||
.children()
|
.text()
|
||||||
.filter_map(|node| Mod::cast(node))
|
.to_string();
|
||||||
.filter_map(|m| {
|
|
||||||
let m = Self::parse_mod(m, cur_path.clone(), cur_file, entry_path);
|
|
||||||
match m {
|
|
||||||
Ok(module) => {
|
|
||||||
files.extend(module.1);
|
|
||||||
errors.extend(module.2);
|
|
||||||
Some((module.0.name(), Arc::new(module.0)))
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
errors.push(err);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<HashMap<String, Arc<Module>>>();
|
|
||||||
|
|
||||||
(
|
let old_path = ctx.cur_path.clone();
|
||||||
Self {
|
ctx.push_cur_path(name.clone());
|
||||||
name: name.syntax().text().to_string(),
|
let children = Rc::new(ctx.parse_child_modules(body.syntax(), Some(name.clone())));
|
||||||
kind: ModuleKind::Inline(Loc::new(cur_file.to_owned(), &module)),
|
|
||||||
children,
|
Self {
|
||||||
parent: None,
|
name,
|
||||||
path: old_path,
|
kind: ModuleKind::Inline(Loc::new(ctx.cur_file.to_owned(), &module)),
|
||||||
},
|
children,
|
||||||
files,
|
parent: None,
|
||||||
errors,
|
path: old_path,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
|
@ -226,7 +214,7 @@ impl Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_tree(name: &str, children: &HashMap<String, Arc<Module>>, level: u32) {
|
fn print_tree(name: &str, children: Rc<HashMap<String, Module>>, level: u32) {
|
||||||
const INDENT_STR: &str = " ";
|
const INDENT_STR: &str = " ";
|
||||||
|
|
||||||
for _ in 0..level {
|
for _ in 0..level {
|
||||||
|
@ -234,9 +222,12 @@ fn print_tree(name: &str, children: &HashMap<String, Arc<Module>>, level: u32) {
|
||||||
}
|
}
|
||||||
print!("{name}\n");
|
print!("{name}\n");
|
||||||
|
|
||||||
for (name, module) in children {
|
// for (name, module) in children.iter() {
|
||||||
print_tree(name, &module.children, level + 1);
|
// ;
|
||||||
}
|
// }
|
||||||
|
children
|
||||||
|
.iter()
|
||||||
|
.for_each(|(name, m)| print_tree(name, m.children.clone(), level + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModuleKind {
|
enum ModuleKind {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rowan::Language;
|
||||||
macro_rules! ast_nodes {
|
macro_rules! ast_nodes {
|
||||||
($($ast:ident, $kind:ident);+) => {
|
($($ast:ident, $kind:ident);+) => {
|
||||||
$(
|
$(
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct $ast(SyntaxNode);
|
pub struct $ast(SyntaxNode);
|
||||||
impl rowan::ast::AstNode for $ast {
|
impl rowan::ast::AstNode for $ast {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
use rowan::ast::{AstNode, AstPtr};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use super::{
|
||||||
nodes::{Def, Mod, Root, Use},
|
nodes::{Def, Mod, Root, Use},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SourceFile {
|
pub struct SourceFile {
|
||||||
lst: Root,
|
lst: Root,
|
||||||
modules: Vec<AstPtr<Mod>>,
|
modules: Vec<AstPtr<Mod>>,
|
||||||
|
@ -23,7 +24,7 @@ pub struct SourceFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceFile {
|
impl SourceFile {
|
||||||
pub fn parse_from(path: PathBuf, source_text: String) -> (Self, Vec<Error>) {
|
pub fn parse_from(path: &Path, source_text: String) -> (Self, Vec<Error>) {
|
||||||
let toks = syntax_kind::lex(&source_text);
|
let toks = syntax_kind::lex(&source_text);
|
||||||
let input = Input::new(&toks);
|
let input = Input::new(&toks);
|
||||||
let mut parser = Parser::new(input);
|
let mut parser = Parser::new(input);
|
||||||
|
@ -57,7 +58,7 @@ impl SourceFile {
|
||||||
},
|
},
|
||||||
out.errors()
|
out.errors()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|err| Error::from_syntax(path.clone(), err))
|
.map(|err| Error::from_syntax(path.to_owned(), err))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue