Giter Club home page Giter Club logo

nixel's Introduction

πŸ‰ NixEL

Parser for the Nix Expressions Language.

CI/CD Documentation Coverage Version License

Features

  • βœ”οΈ Fast

    It parses all the files in Nixpkgs in under 25 seconds, single-threaded. 1

    It's written in Rust and a little bit of C++, Flex and GNU Bison.

  • βœ”οΈ Correct

    This library is a copy-paste of the original lexer and parser of Nix, with some types adapted for better ergonomy.

    No parser can get closer to the original implementation than this.

  • βœ”οΈ Reliable

    High coverage, battle-tested, and memory-safe2.

  • βœ”οΈ Useful

    It gives you comments, whitespace, starting and end positions, automatic string un-escaping, multiline string indentation handling, a typed API, and everything you need to parse the Nix language!

Usage

You can check out the documentation at docs.rs/nixel.

This is a full usage example:

let input: String = String::from(
    r#"
        # Greet the user
        "Hello, World!"
        # Bye!
    "#,
);

let parsed: nixel::Parsed = nixel::parse(input);

match &*parsed.expression {
    nixel::Expression::String(string) => {
        assert_eq!(
            &string.span,
            &nixel::Span {
                start: nixel::Position { line: 3, column: 9 }.into(),
                end: nixel::Position { line: 3, column: 24 }.into(),
            }
            .into()
        );
        assert_eq!(
            &parsed.trivia_before(&string.span.start)[1],
            &nixel::Trivia::Comment(nixel::TriviaComment {
                content: "# Greet the user".into(),
                span: nixel::Span {
                    start: nixel::Position { line: 2, column: 9 }.into(),
                    end: nixel::Position { line: 2, column: 25 }.into(),
                }
                .into()
            })
        );
        assert_eq!(
            &string.parts[0],
            &nixel::Part::Raw(nixel::PartRaw {
                content: "Hello, World!".into(),
                span: nixel::Span {
                    start: nixel::Position { line: 3, column: 10 }.into(),
                    end: nixel::Position { line: 3, column: 23 }.into(),
                }
                .into()
            })
        );
        assert_eq!(
            &parsed.trivia_after(&string.span.end)[1],
            &nixel::Trivia::Comment(nixel::TriviaComment {
                content: "# Bye!".into(),
                span: nixel::Span {
                    start: nixel::Position { line: 4, column: 9 }.into(),
                    end: nixel::Position { line: 4, column: 15 }.into(),
                }
                .into()
            })
        );
    },
    expression => unreachable!("Expected a String, got: {expression:#?}"),
}

Or from the CLI using Rust's Debug trait:

$ echo '1 + 2' | nix run github:kamadorueda/nixel -- --format=debug

BinaryOperation(
    BinaryOperation {
        left: Integer(
            Integer {
                value: "1",
                span: Span {
                    start: Position {
                        line: 1,
                        column: 1,
                    },
                    end: Position {
                        line: 1,
                        column: 2,
                    },
                },
            },
        ),
        operator: Addition,
        right: Integer(
            Integer {
                value: "2",
                span: Span {
                    start: Position {
                        line: 1,
                        column: 5,
                    },
                    end: Position {
                        line: 1,
                        column: 6,
                    },
                },
            },
        ),
    },
)

Or from the CLI using JSON format:

$ echo '1 + 2' | nix run github:kamadorueda/nixel -- --format=json

{
  "BinaryOperation": {
    "left": {
      "Integer": {
        "value": "1",
        "span": {
          "start": {
            "line": 1,
            "column": 1
          },
          "end": {
            "line": 1,
            "column": 2
          }
        }
      }
    },
    "operator": "Addition",
    "right": {
      "Integer": {
        "value": "2",
        "span": {
          "start": {
            "line": 1,
            "column": 5
          },
          "end": {
            "line": 1,
            "column": 6
          }
        }
      }
    }
  }
}

You can check out more examples in the tests folder.

Alternatives

License

Please read LICENSE.md.

Footnotes

Footnotes

  1. Running on a machine with:

    • CPU: 4 physical, 4 logical, 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
    • MHz: from 400 to 4700 MHz
    • BogoMips: 5606.40
    • Cache L3: 12 MiB

    The following command takes around 1 minute:

    $ nix build --system x86_64-linux
    $ time find /data/nixpkgs -type f -name '*.nix' \
      -exec ./result/bin/nixel --format=none {} \;
    
    real  0m24.293s
    user  0m15.066s
    sys   0m8.955s
    
    ↩
  2. Tested under real-life workloads using Valgrind, and by running an infinite loop of parsing cycles over Nixpkgs :).

    $ nix build --system x86_64-linux
    $ valgrind ./result/bin/nixel $file
    
      LEAK SUMMARY:
        definitely lost: 0 bytes in 0 blocks
        indirectly lost: 0 bytes in 0 blocks
          possibly lost: 0 bytes in 0 blocks
             suppressed: 0 bytes in 0 blocks
    
    ↩

nixel's People

Contributors

kamadorueda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

cisen fvkd

nixel's Issues

Parsing invalid input

One attractive feature of rnix-parser is, through its use of rowan, it is able to recover from errors and provide partial parses for input. This is especially useful in the context of editor tooling where the code is frequently invalid while it is being edited. How does nixel/santiago stack up in this respect?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.