Skip to content

Commit

Permalink
Rework and fix Attrpath and Dynamic parsing (nix-community#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
oxalica authored and oberblastmeister committed Jul 23, 2022
1 parent affdc51 commit b01384d
Show file tree
Hide file tree
Showing 44 changed files with 348 additions and 288 deletions.
10 changes: 5 additions & 5 deletions examples/list-fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ fn main() -> Result<(), Box<dyn Error>> {
_ => return Err("root isn't a set".into()),
};
for entry in set.entries() {
if let ast::Entry::KeyValue(key_value) = entry {
if let Some(ast::Expr::Lambda(lambda)) = key_value.value() {
let key = key_value.key().unwrap();
let ident = key.attrs().last().and_then(|attr| match attr {
if let ast::Entry::AttrpathValue(attrpath_value) = entry {
if let Some(ast::Expr::Lambda(lambda)) = attrpath_value.value() {
let attrpath = attrpath_value.attrpath().unwrap();
let ident = attrpath.attrs().last().and_then(|attr| match attr {
ast::Attr::Ident(ident) => Some(ident),
_ => None,
});
Expand All @@ -44,7 +44,7 @@ fn main() -> Result<(), Box<dyn Error>> {
);
println!("Function name: {}", s);
{
let comments = comments_before(key_value.syntax());
let comments = comments_before(attrpath_value.syntax());
if !comments.is_empty() {
println!("--> Doc: {comments}");
}
Expand Down
36 changes: 19 additions & 17 deletions src/ast/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub trait HasEntry: AstNode {
children(self)
}

fn key_values(&self) -> AstChildren<KeyValue>
fn attrpath_values(&self) -> AstChildren<AttrpathValue>
where
Self: Sized,
{
Expand Down Expand Up @@ -169,7 +169,6 @@ node! {
#[case(
NODE_APPLY => Apply,
NODE_ASSERT => Assert,
NODE_DYNAMIC => Dynamic,
NODE_ERROR => Error,
NODE_IF_ELSE => IfElse,
NODE_SELECT => Select,
Expand All @@ -181,14 +180,14 @@ node! {
NODE_LET_IN => LetIn,
NODE_LIST => List,
NODE_BIN_OP => BinOp,
NODE_OR_DEFAULT => OrDefault,
NODE_PAREN => Paren,
NODE_ROOT => Root,
NODE_ATTR_SET => AttrSet,
NODE_UNARY_OP => UnaryOp,
NODE_IDENT => Ident,
NODE_WITH => With,
NODE_STRING => Str,
NODE_HAS_ATTR => HasAttr,
)]
/// An expression. The fundamental nix ast type.
enum Expr;
Expand Down Expand Up @@ -224,9 +223,9 @@ impl Assert {
ng! { body, Expr, 1 }
}

node! { #[from(NODE_KEY)] struct Key; }
node! { #[from(NODE_ATTRPATH)] struct Attrpath; }

impl Key {
impl Attrpath {
ng! { attrs, [Attr] }
}

Expand All @@ -250,7 +249,9 @@ node! { #[from(NODE_SELECT)] struct Select; }
impl Select {
ng! { expr, Expr, 0 }
tg! { dot_token, . }
ng! { attr, Expr, 1 }
ng! { attrpath, Attrpath, 0 }
tg! { or_token, or }
ng! { default_expr, Expr, 1 }
}

node! { #[from(NODE_INHERIT)] struct Inherit; }
Expand Down Expand Up @@ -325,13 +326,6 @@ impl BinOp {
ng! { rhs, Expr, 1 }
}

node! { #[from(NODE_OR_DEFAULT)] struct OrDefault; }

impl OrDefault {
ng! { index, Select, 0 }
ng! { default, Expr, 1 }
}

node! { #[from(NODE_PAREN)] struct Paren; }

impl Paren {
Expand Down Expand Up @@ -390,15 +384,15 @@ impl AttrSet {
node! {
#[case(
NODE_INHERIT => Inherit,
NODE_KEY_VALUE => KeyValue,
NODE_ATTRPATH_VALUE => AttrpathValue,
)]
enum Entry;
}

node! { #[from(NODE_KEY_VALUE)] struct KeyValue; }
node! { #[from(NODE_ATTRPATH_VALUE)] struct AttrpathValue; }

impl KeyValue {
ng! { key, Key, 0 }
impl AttrpathValue {
ng! { attrpath, Attrpath, 0 }
tg! { assign_token, = }
ng! { value, Expr, 0 }
}
Expand All @@ -420,3 +414,11 @@ impl With {
tg! { semicolon_token, ; }
ng! { body, Expr, 1 }
}

node! { #[from(NODE_HAS_ATTR)] struct HasAttr; }

impl HasAttr {
ng! { expr, Expr, 0 }
tg! { question_token, ? }
ng! { attrpath, Attrpath, 0 }
}
2 changes: 0 additions & 2 deletions src/ast/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::SyntaxKind::{self, *};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BinOpKind {
Concat,
IsSet,
Update,

Add,
Expand All @@ -27,7 +26,6 @@ impl BinOpKind {
pub fn from_kind(token: SyntaxKind) -> Option<Self> {
match token {
TOKEN_CONCAT => Some(BinOpKind::Concat),
TOKEN_QUESTION => Some(BinOpKind::IsSet),
TOKEN_UPDATE => Some(BinOpKind::Update),

TOKEN_ADD => Some(BinOpKind::Add),
Expand Down
7 changes: 4 additions & 3 deletions src/kinds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub enum SyntaxKind {

NODE_APPLY,
NODE_ASSERT,
NODE_KEY,
NODE_ATTRPATH,
NODE_DYNAMIC,
NODE_ERROR,
NODE_IDENT,
Expand All @@ -86,18 +86,19 @@ pub enum SyntaxKind {
NODE_LET_IN,
NODE_LIST,
NODE_BIN_OP,
NODE_OR_DEFAULT,
NODE_PAREN,
NODE_PATTERN,
NODE_PAT_BIND,
NODE_PAT_ENTRY,
NODE_ROOT,
NODE_ATTR_SET,
NODE_KEY_VALUE,
NODE_ATTRPATH_VALUE,
NODE_UNARY_OP,
NODE_LITERAL,
NODE_WITH,
NODE_PATH_WITH_INTERPOL,
// Attrpath existence check: foo ? bar.${baz}."bux"
NODE_HAS_ATTR,

#[doc(hidden)]
__LAST,
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mod macros;
pub mod ast;
mod kinds;
pub mod parser;
pub mod tokenizer;
mod token_set;
pub mod tokenizer;

use std::marker::PhantomData;

Expand Down Expand Up @@ -124,8 +124,8 @@ mod tests {
let let_in = ast::LetIn::try_from(root.expr().unwrap()).unwrap();
let set = ast::AttrSet::try_from(let_in.body().unwrap()).unwrap();
let entry = set.entries().nth(1).unwrap();
let key_value = ast::KeyValue::try_from(entry).unwrap();
let value = ast::Str::try_from(key_value.value().unwrap()).unwrap();
let attrpath_value = ast::AttrpathValue::try_from(entry).unwrap();
let value = ast::Str::try_from(attrpath_value.value().unwrap()).unwrap();

match &*value.parts() {
&[
Expand Down
1 change: 1 addition & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ macro_rules! T {
(in) => ($crate::SyntaxKind::TOKEN_IN);
(inherit) => ($crate::SyntaxKind::TOKEN_INHERIT);
(let) => ($crate::SyntaxKind::TOKEN_LET);
(or) => ($crate::SyntaxKind::TOKEN_OR);
(rec) => ($crate::SyntaxKind::TOKEN_REC);
(then) => ($crate::SyntaxKind::TOKEN_THEN);
(with) => ($crate::SyntaxKind::TOKEN_WITH);
Expand Down
38 changes: 21 additions & 17 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ where
_ => self.expect_ident(),
}
}
fn parse_key(&mut self) {
self.start_node(NODE_KEY);
fn parse_attrpath(&mut self) {
self.start_node(NODE_ATTRPATH);
loop {
self.parse_attr();

Expand Down Expand Up @@ -397,8 +397,8 @@ where
self.finish_node();
}
Some(_) => {
self.start_node(NODE_KEY_VALUE);
self.parse_key();
self.start_node(NODE_ATTRPATH_VALUE);
self.parse_attrpath();
self.expect(TOKEN_ASSIGN);
self.parse_expr();
self.expect(TOKEN_SEMICOLON);
Expand Down Expand Up @@ -492,7 +492,6 @@ where
self.bump();
self.finish_node();
}
TOKEN_DYNAMIC_START => self.parse_dynamic(),
TOKEN_STRING_START => self.parse_string(),
TOKEN_PATH => {
let next = self.try_next();
Expand Down Expand Up @@ -569,7 +568,6 @@ where
TOKEN_REC,
TOKEN_CURLY_B_OPEN,
TOKEN_SQUARE_B_OPEN,
TOKEN_DYNAMIC_START,
TOKEN_STRING_START,
TOKEN_IDENT,
]
Expand All @@ -579,18 +577,17 @@ where
}
};

while self.peek() == Some(TOKEN_DOT) {
if self.peek() == Some(TOKEN_DOT) {
self.start_node_at(checkpoint, NODE_SELECT);
self.bump();
self.parse_attr();
self.finish_node();
}
if self.peek_data().map(|&(t, s)| t == TOKEN_IDENT && s == OR).unwrap_or(false) {
self.start_node_at(checkpoint, NODE_OR_DEFAULT);
self.bump();
self.parse_val();
self.parse_attrpath();
if self.peek_data().map(|&(t, s)| t == TOKEN_IDENT && s == OR).unwrap_or(false) {
self.bump();
self.parse_val();
}
self.finish_node();
}

checkpoint
}
fn parse_fn(&mut self) -> Checkpoint {
Expand Down Expand Up @@ -647,11 +644,18 @@ where
}
checkpoint
}
fn parse_isset(&mut self) -> Checkpoint {
self.handle_operation_left(false, Self::parse_negate, &[TOKEN_QUESTION])
fn parse_hasattr(&mut self) -> Checkpoint {
let checkpoint = self.parse_negate();
while self.peek().map(|t| t == TOKEN_QUESTION).unwrap_or(false) {
self.start_node_at(checkpoint, NODE_HAS_ATTR);
self.bump();
self.parse_attrpath();
self.finish_node();
}
checkpoint
}
fn parse_concat(&mut self) -> Checkpoint {
self.handle_operation_right(Self::parse_isset, &[TOKEN_CONCAT])
self.handle_operation_right(Self::parse_hasattr, &[TOKEN_CONCAT])
}
fn parse_mul(&mut self) -> Checkpoint {
self.handle_operation_left(false, Self::parse_concat, &[TOKEN_MUL, TOKEN_DIV])
Expand Down
14 changes: 8 additions & 6 deletions test_data/general/docs.expect
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ NODE_ROOT 0..306 {
TOKEN_WHITESPACE("\n ") 60..63
TOKEN_COMMENT("# Adds the integers x and y together and returns the result") 63..122
TOKEN_WHITESPACE("\n ") 122..125
NODE_KEY_VALUE 125..196 {
NODE_KEY 125..128 {
NODE_ATTRPATH_VALUE 125..196 {
NODE_ATTRPATH 125..128 {
NODE_IDENT 125..128 {
TOKEN_IDENT("add") 125..128
}
Expand Down Expand Up @@ -55,8 +55,8 @@ NODE_ROOT 0..306 {
TOKEN_WHITESPACE("\n ") 216..219
TOKEN_COMMENT("# Returns the sum of the integer array nums") 219..262
TOKEN_WHITESPACE("\n ") 262..265
NODE_KEY_VALUE 265..304 {
NODE_KEY 265..268 {
NODE_ATTRPATH_VALUE 265..304 {
NODE_ATTRPATH 265..268 {
NODE_IDENT 265..268 {
TOKEN_IDENT("sum") 265..268
}
Expand All @@ -78,8 +78,10 @@ NODE_ROOT 0..306 {
TOKEN_IDENT("builtins") 277..285
}
TOKEN_DOT(".") 285..286
NODE_IDENT 286..292 {
TOKEN_IDENT("foldl\'") 286..292
NODE_ATTRPATH 286..292 {
NODE_IDENT 286..292 {
TOKEN_IDENT("foldl\'") 286..292
}
}
}
TOKEN_WHITESPACE(" ") 292..293
Expand Down
Loading

0 comments on commit b01384d

Please sign in to comment.