8 releases

0.1.10 Dec 17, 2024
0.1.9 Dec 12, 2024
0.1.5 Nov 29, 2024

#1280 in Rust patterns

Download history 331/week @ 2024-11-24 39/week @ 2024-12-01 586/week @ 2024-12-08 182/week @ 2024-12-15 4/week @ 2024-12-22

775 downloads per month
Used in 2 crates

MIT license

135KB
3K SLoC

backyard-nodes

Nodes representing PHP code AST, with simple builder and walker.

features

  • Ast Nodes
  • "builder" simplify building AST nodes (behind the builder feature)
  • "walker" walker through AST nodes, support explorer to ancestors and siblings (behind the walker feature)
  • "printer" print AST nodes as treeline (behind the printer feature)

usage

builder

use backyard_nodes::{ builder::{ BlueprintBuildable, BoxBlueprint, Builder }, AssignmentType };

fn main() {
  let arena = bumpalo::Bump::new();
  let b = Builder::new();
  let node = b
    .Program(
      &[
        b
          .Assignment(b.Variable(b.Identifier("a")), AssignmentType::Default, b.Number("21"))
          .add_leading(b.CommentLine("Test leading")),
      ]
    )
    .build(&arena);

  println!("{:?}", node.print(true, false));
}

Resulting this:

ProgramNode
├-children[]
│ ╙-AssignmentNode
│   ├-left
│   │ └-VariableNode
│   │   ├-name
│   │   │ └-IdentifierNode
│   │   │   ├-name: "a"
│   │   │   ├-leadings: -
│   │   │   └-trailings: -
│   │   ├-leadings: -
│   │   └-trailings: -
│   ├-operator: AssignmentType::Default
│   ├-right
│   │ └-NumberNode
│   │   ├-value: "21"
│   │   ├-leadings: -
│   │   └-trailings: -
│   ├-leadings[]
│   │ ╙-CommentLineNode
│   │   ├-comment: "Test leading"
│   │   ├-leadings: -
│   │   └-trailings: -
│   └-trailings: --leadings: --trailings: -

walker

use backyard_nodes::{
  builder::{ BlueprintBuildable, BoxBlueprint, Builder },
  AssignmentType,
  NodeType,
};

fn main() {
  let arena = bumpalo::Bump::new();
  let b = Builder::new();
  let node = b
    .Program(
      &[
        b
          .Assignment(b.Variable(b.Identifier("a")), AssignmentType::Default, b.Number("21"))
          .add_leading(b.CommentLine("Test leading")),
      ]
    )
    .build(&arena);
  let mut walker = node.walk();

  assert_eq!(NodeType::Program, walker.next().unwrap().1.node_type);
  assert_eq!(NodeType::Assignment, walker.next().unwrap().1.node_type);
  assert_eq!(NodeType::Variable, walker.next().unwrap().1.node_type);
  assert_eq!(NodeType::Identifier, walker.next().unwrap().1.node_type);
  assert_eq!(NodeType::Number, walker.next().unwrap().1.node_type);
  assert!(walker.next().is_none());
}

printer

Printer has 2 parameters, first is to print leadings and trailings, second is to print location. We use parser for this example, more on backyard-parser.

fn main() {
  let arena = bumpalo::Bump::new();
  let code = r#"<?php
  // leading comment
  function hello_world($foo) {
    var_dump($foo);
  }"#;

  let parsed = backyard_parser::parse(&arena, code).unwrap();
  println!("{:?}", parsed.print(true, true));
}

Resulting this:

ProgramNode
├-children[]
│ ╙-FunctionNode
│   ├-is_ref: false
│   ├-name
│   │ └-IdentifierNode
│   │   ├-name: "hello_world"
│   │   ├-leadings: -
│   │   ├-trailings: -
│   │   └-location
│   │     └-start: line 3, column 11, offset 38
│   │       end: line 3, column 22, offset 49
│   ├-parameters[]
│   │ ╙-ParameterNode
│   │   ├-variable_type: -
│   │   ├-is_ref: false
│   │   ├-is_ellipsis: false
│   │   ├-name
│   │   │ └-IdentifierNode
│   │   │   ├-name: "foo"
│   │   │   ├-leadings: -
│   │   │   ├-trailings: -
│   │   │   └-location
│   │   │     └-start: line 3, column 23, offset 50
│   │   │       end: line 3, column 26, offset 53
│   │   ├-value: -
│   │   ├-leadings: -
│   │   ├-trailings: -
│   │   └-location
│   │     └-start: line 3, column 23, offset 50
│   │       end: line 3, column 23, offset 50
│   ├-return_type: -
│   ├-body
│   │ └-BlockNode
│   │   ├-statements[]
│   │   │ ╙-CallNode
│   │   │   ├-name
│   │   │   │ └-IdentifierNode
│   │   │   │   ├-name: "var_dump"
│   │   │   │   ├-leadings: -
│   │   │   │   ├-trailings: -
│   │   │   │   └-location
│   │   │   │     └-start: line 4, column 4, offset 62
│   │   │   │       end: line 4, column 12, offset 70
│   │   │   ├-arguments[]
│   │   │   │ ╙-CallArgumentNode
│   │   │   │   ├-name: -
│   │   │   │   ├-value
│   │   │   │   │ └-VariableNode
│   │   │   │   │   ├-name
│   │   │   │   │   │ └-IdentifierNode
│   │   │   │   │   │   ├-name: "foo"
│   │   │   │   │   │   ├-leadings: -
│   │   │   │   │   │   ├-trailings: -
│   │   │   │   │   │   └-location
│   │   │   │   │   │     └-start: line 4, column 13, offset 71
│   │   │   │   │   │       end: line 4, column 16, offset 74
│   │   │   │   │   ├-leadings: -
│   │   │   │   │   ├-trailings: -
│   │   │   │   │   └-location
│   │   │   │   │     └-start: line 4, column 13, offset 71
│   │   │   │   │       end: line 4, column 16, offset 74
│   │   │   │   ├-leadings: -
│   │   │   │   ├-trailings: -
│   │   │   │   └-location
│   │   │   │     └-start: line 4, column 13, offset 71
│   │   │   │       end: line 4, column 13, offset 71
│   │   │   ├-leadings: -
│   │   │   ├-trailings: -
│   │   │   └-location
│   │   │     └-start: line 4, column 12, offset 70
│   │   │       end: line 4, column 17, offset 75
│   │   ├-leadings: -
│   │   ├-trailings: -
│   │   └-location
│   │     └-start: line 3, column 29, offset 56
│   │       end: line 5, column 2, offset 80
│   ├-leadings[]
│   │ ╙-CommentLineNode
│   │   ├-comment: " leading comment"
│   │   ├-leadings: -
│   │   ├-trailings: -
│   │   └-location
│   │     └-start: line 2, column 2, offset 8
│   │       end: line 2, column 2, offset 8
│   ├-trailings: -
│   └-location
│     └-start: line 3, column 2, offset 29
│       end: line 5, column 2, offset 80-leadings: --trailings: --location
  └-start: line 1, column 0, offset 0
    end: line 5, column 2, offset 80

ecosystem

heavily inspired by

license

MIT

Dependencies

~1–1.8MB
~33K SLoC