mirror of
https://github.com/oxalica/nil.git
synced 2025-12-23 09:19:49 +00:00
Switch to use our custom parser
This commit is contained in:
parent
d3b30a688a
commit
d0132c886c
6 changed files with 72 additions and 151 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
|
@ -14,15 +14,6 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cbitset"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
|
@ -146,19 +137,10 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"expect-test",
|
||||
"la-arena",
|
||||
"rnix",
|
||||
"rowan",
|
||||
"salsa",
|
||||
"smol_str",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -241,15 +223,6 @@ version = "0.6.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "rnix"
|
||||
version = "0.11.0-dev"
|
||||
source = "git+https://github.com/oxalica/rnix-parser.git#80fabb304defc3b488f21d225128bde0758d1eb3"
|
||||
dependencies = [
|
||||
"cbitset",
|
||||
"rowan",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.15.6"
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
la-arena = "0.2.1"
|
||||
rnix = { git = "https://github.com/oxalica/rnix-parser.git" }
|
||||
rowan = "0.15.6"
|
||||
salsa = "0.17.0-pre.2"
|
||||
smol_str = "0.1.23"
|
||||
|
||||
syntax = { path = "./syntax" }
|
||||
|
||||
[dev-dependencies]
|
||||
expect-test = "1.3.0"
|
||||
|
||||
|
|
|
|||
131
src/def/lower.rs
131
src/def/lower.rs
|
|
@ -1,17 +1,15 @@
|
|||
use super::{AstPtr, Expr, ExprId, Literal, Module, ModuleSourceMap, Path, PathAnchor};
|
||||
use super::{AstPtr, Expr, ExprId, Literal, Module, ModuleSourceMap};
|
||||
use crate::source::{FileId, InFile};
|
||||
use rnix::types::{ParsedType, Root, TokenWrapper, TypedNode, Wrapper};
|
||||
use rnix::value::Anchor;
|
||||
use rnix::{NixValue, SyntaxNode, AST};
|
||||
use rowan::ast::AstNode;
|
||||
use syntax::ast::{self, LiteralKind};
|
||||
|
||||
pub(super) fn lower(ast: InFile<AST>) -> (Module, ModuleSourceMap) {
|
||||
pub(super) fn lower(root: InFile<ast::SourceFile>) -> (Module, ModuleSourceMap) {
|
||||
let mut ctx = LowerCtx {
|
||||
file_id: ast.file_id,
|
||||
file_id: root.file_id,
|
||||
module: Module::default(),
|
||||
source_map: ModuleSourceMap::default(),
|
||||
};
|
||||
let node = Root::cast(ast.value.node()).map(|root| root.node().clone());
|
||||
ctx.lower_node_opt(node);
|
||||
ctx.lower_expr_opt(root.value.expr());
|
||||
(ctx.module, ctx.source_map)
|
||||
}
|
||||
|
||||
|
|
@ -29,83 +27,60 @@ impl LowerCtx {
|
|||
id
|
||||
}
|
||||
|
||||
fn lower_node_opt(&mut self, node: Option<SyntaxNode>) -> ExprId {
|
||||
if let Some(node) = node {
|
||||
if let Ok(expr) = ParsedType::try_from(node) {
|
||||
return self.lower_expr(expr);
|
||||
}
|
||||
fn lower_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
|
||||
if let Some(expr) = expr {
|
||||
return self.lower_expr(expr);
|
||||
}
|
||||
// Synthetic syntax has no coresponding text.
|
||||
self.module.exprs.alloc(Expr::Missing)
|
||||
}
|
||||
|
||||
fn lower_path(&mut self, anchor: Anchor, segments: &str, ptr: AstPtr) -> ExprId {
|
||||
let anchor = match anchor {
|
||||
Anchor::Relative => PathAnchor::Relative(self.file_id),
|
||||
Anchor::Absolute => todo!(),
|
||||
Anchor::Home => todo!(),
|
||||
Anchor::Store => todo!(),
|
||||
};
|
||||
let path = Path {
|
||||
anchor,
|
||||
raw_segments: segments.into(),
|
||||
};
|
||||
self.alloc_expr(Expr::Literal(Literal::Path(path)), ptr)
|
||||
fn lower_expr(&mut self, expr: ast::Expr) -> ExprId {
|
||||
let ptr = AstPtr::new(expr.syntax());
|
||||
match expr {
|
||||
ast::Expr::Literal(e) => {
|
||||
let lit = self.lower_literal(e);
|
||||
self.alloc_expr(lit.map_or(Expr::Missing, Expr::Literal), ptr)
|
||||
}
|
||||
ast::Expr::Name(e) => {
|
||||
let name = e.token().map_or_else(|| "".into(), |tok| tok.text().into());
|
||||
self.alloc_expr(Expr::Ident(name), ptr)
|
||||
}
|
||||
ast::Expr::Apply(e) => {
|
||||
let func = self.lower_expr_opt(e.function());
|
||||
let arg = self.lower_expr_opt(e.argument());
|
||||
self.alloc_expr(Expr::Apply(func, arg), ptr)
|
||||
}
|
||||
ast::Expr::Paren(e) => self.lower_expr_opt(e.expr()),
|
||||
ast::Expr::Assert(_) => todo!(),
|
||||
ast::Expr::AttrSet(_) => todo!(),
|
||||
ast::Expr::BinaryOp(_) => todo!(),
|
||||
ast::Expr::HasAttr(_) => todo!(),
|
||||
ast::Expr::IfThenElse(_) => todo!(),
|
||||
ast::Expr::IndentString(_) => todo!(),
|
||||
ast::Expr::Lambda(_) => todo!(),
|
||||
ast::Expr::LetIn(_) => todo!(),
|
||||
ast::Expr::List(_) => todo!(),
|
||||
ast::Expr::Select(_) => todo!(),
|
||||
ast::Expr::String(_) => todo!(),
|
||||
ast::Expr::UnaryOp(_) => todo!(),
|
||||
ast::Expr::With(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_expr(&mut self, expr: ParsedType) -> ExprId {
|
||||
let ptr = AstPtr::new(expr.node());
|
||||
let expr = match expr {
|
||||
ParsedType::Root(e) => return self.lower_node_opt(e.inner()),
|
||||
ParsedType::Paren(e) => return self.lower_node_opt(e.inner()),
|
||||
ParsedType::Ident(e) => {
|
||||
let ident = e.to_inner_string();
|
||||
Expr::Ident(ident.into())
|
||||
}
|
||||
ParsedType::Value(e) => match e.to_value() {
|
||||
Ok(v) => {
|
||||
let lit = match v {
|
||||
NixValue::Integer(x) => Literal::Int(x),
|
||||
NixValue::Float(_) => todo!(),
|
||||
NixValue::String(s) => Literal::String(s.into()),
|
||||
NixValue::Path(anchor, path) => return self.lower_path(anchor, &path, ptr),
|
||||
};
|
||||
Expr::Literal(lit)
|
||||
}
|
||||
Err(_) => Expr::Missing,
|
||||
},
|
||||
ParsedType::Apply(e) => {
|
||||
let lam = self.lower_node_opt(e.lambda());
|
||||
let arg = self.lower_node_opt(e.value());
|
||||
Expr::Apply(lam, arg)
|
||||
}
|
||||
ParsedType::Assert(_) => todo!(),
|
||||
ParsedType::IfElse(_) => todo!(),
|
||||
ParsedType::Select(_) => todo!(),
|
||||
ParsedType::Inherit(_) => todo!(),
|
||||
ParsedType::InheritFrom(_) => todo!(),
|
||||
ParsedType::Lambda(_) => todo!(),
|
||||
ParsedType::LegacyLet(_) => todo!(),
|
||||
ParsedType::LetIn(_) => todo!(),
|
||||
ParsedType::List(_) => todo!(),
|
||||
ParsedType::BinOp(_) => todo!(),
|
||||
ParsedType::OrDefault(_) => todo!(),
|
||||
ParsedType::AttrSet(_) => todo!(),
|
||||
ParsedType::KeyValue(_) => todo!(),
|
||||
ParsedType::Str(_) => todo!(),
|
||||
ParsedType::StrInterpol(_) => todo!(),
|
||||
ParsedType::UnaryOp(_) => todo!(),
|
||||
ParsedType::With(_) => todo!(),
|
||||
ParsedType::PathWithInterpol(_) => todo!(),
|
||||
fn lower_literal(&mut self, lit: ast::Literal) -> Option<Literal> {
|
||||
let kind = lit.kind()?;
|
||||
let tok = lit.token().unwrap();
|
||||
let text = tok.text();
|
||||
|
||||
// Invalid nodes in expression location.
|
||||
ParsedType::Pattern(_)
|
||||
| ParsedType::PatBind(_)
|
||||
| ParsedType::PatEntry(_)
|
||||
| ParsedType::Key(_)
|
||||
| ParsedType::Dynamic(_)
|
||||
| ParsedType::Error(_) => Expr::Missing,
|
||||
};
|
||||
self.alloc_expr(expr, ptr)
|
||||
Some(match kind {
|
||||
LiteralKind::Int => Literal::Int(text.parse::<i64>().ok()?),
|
||||
LiteralKind::Float => todo!(),
|
||||
LiteralKind::Uri => Literal::String(text.into()),
|
||||
LiteralKind::RelativePath => todo!(),
|
||||
LiteralKind::AbsolutePath => todo!(),
|
||||
LiteralKind::HomePath => todo!(),
|
||||
LiteralKind::SearchPath => todo!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ fn module_with_source_map(
|
|||
db: &dyn DefDatabase,
|
||||
file_id: FileId,
|
||||
) -> (Arc<Module>, Arc<ModuleSourceMap>) {
|
||||
let root = db.parse(file_id);
|
||||
let (module, source_map) = lower::lower(root);
|
||||
let parse = db.parse(file_id);
|
||||
let (module, source_map) = lower::lower(parse.map(|p| p.root()));
|
||||
(Arc::new(module), Arc::new(source_map))
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ impl ops::Index<ExprId> for Module {
|
|||
}
|
||||
}
|
||||
|
||||
pub type AstPtr = rowan::ast::SyntaxNodePtr<rnix::NixLanguage>;
|
||||
pub type AstPtr = rowan::ast::SyntaxNodePtr<syntax::NixLanguage>;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ModuleSourceMap {
|
||||
|
|
|
|||
|
|
@ -4,15 +4,11 @@ use expect_test::expect;
|
|||
|
||||
#[test]
|
||||
fn module_basic() {
|
||||
let (db, root_id) = TestDB::from_file(
|
||||
r#"
|
||||
foo 123 ./bar.nix
|
||||
"#,
|
||||
);
|
||||
let (db, root_id) = TestDB::from_file("foo 123");
|
||||
expect![[r#"
|
||||
Module {
|
||||
exprs: Arena {
|
||||
len: 5,
|
||||
len: 3,
|
||||
data: [
|
||||
Ident(
|
||||
Name(
|
||||
|
|
@ -28,22 +24,6 @@ fn module_basic() {
|
|||
Idx::<Expr>(0),
|
||||
Idx::<Expr>(1),
|
||||
),
|
||||
Literal(
|
||||
Path(
|
||||
Path {
|
||||
anchor: Relative(
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
),
|
||||
raw_segments: "./bar.nix",
|
||||
},
|
||||
),
|
||||
),
|
||||
Apply(
|
||||
Idx::<Expr>(2),
|
||||
Idx::<Expr>(3),
|
||||
),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
@ -57,24 +37,16 @@ fn module_basic() {
|
|||
expect![[r#"
|
||||
[
|
||||
SyntaxNodePtr {
|
||||
kind: NODE_IDENT,
|
||||
range: 9..12,
|
||||
kind: NAME,
|
||||
range: 0..3,
|
||||
},
|
||||
SyntaxNodePtr {
|
||||
kind: NODE_LITERAL,
|
||||
range: 13..16,
|
||||
kind: LITERAL,
|
||||
range: 4..7,
|
||||
},
|
||||
SyntaxNodePtr {
|
||||
kind: NODE_APPLY,
|
||||
range: 9..16,
|
||||
},
|
||||
SyntaxNodePtr {
|
||||
kind: NODE_LITERAL,
|
||||
range: 17..26,
|
||||
},
|
||||
SyntaxNodePtr {
|
||||
kind: NODE_APPLY,
|
||||
range: 9..26,
|
||||
kind: APPLY,
|
||||
range: 0..7,
|
||||
},
|
||||
]
|
||||
"#]]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rnix::AST;
|
||||
use std::sync::Arc;
|
||||
use syntax::Parse;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FileId(pub u32);
|
||||
|
|
@ -31,12 +31,12 @@ pub trait SourceDatabase {
|
|||
#[salsa::input]
|
||||
fn file_content(&self, file_id: FileId) -> Arc<[u8]>;
|
||||
|
||||
fn parse(&self, file_id: FileId) -> InFile<AST>;
|
||||
fn parse(&self, file_id: FileId) -> InFile<Parse>;
|
||||
}
|
||||
|
||||
fn parse(db: &dyn SourceDatabase, file_id: FileId) -> InFile<AST> {
|
||||
fn parse(db: &dyn SourceDatabase, file_id: FileId) -> InFile<Parse> {
|
||||
let content = db.file_content(file_id);
|
||||
let content = std::str::from_utf8(&content).unwrap_or_default();
|
||||
let ast = rnix::parse(content);
|
||||
InFile::new(file_id, ast)
|
||||
let parse = syntax::parse_file(content);
|
||||
InFile::new(file_id, parse)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue