Crate ludtwig_parser

Source
Expand description

§Parser

This is a handwritten top-down parser for the twig templating language combined with HTML. It’s mostly developed together with the linter / formatter ludtwig.

Parsing both Twig and HTML together into a single hierarchical syntax tree gives some benefits, valid syntax trees follow some desirable properties:

  • non-self-closing HTML tags always need a corresponding closing tag
  • opening and closing HTML tag must exist inside the same Twig block
  • Twig syntax is only allowed in specific places instead of everywhere

which in turn make these templates and the HTML generated in the end less error-prone.

§Syntax trees

The parser constructs a syntax tree based on the library rowan. A conceptual overview can be found here Syntax in rust-analyzer. Basically the syntax tree consists of three layers:

  • GreenNodes
  • SyntaxNodes (aka RedNodes)
  • AstNodes (defined in this crate)

§Examples

§Parsing into a syntax tree

use ludtwig_parser::syntax::untyped::{debug_tree, SyntaxNode};

let parse = ludtwig_parser::parse("{{ 42 }}");

// parsing might result in errors
assert!(parse.errors.is_empty());

// in any case it will always produce a usable syntax tree
// and provide a green node of the root.

// for getting a SyntaxNode of the root you can use this shortcut
// or construct the root by hand from the GreenNode (see SyntaxNode::new_root)
let (tree_root, errors) = parse.split();

// you can now iterate or search through the syntax tree
// or debug print it with
println!("{}", debug_tree(&tree_root));

§Iterate in Preorder


use ludtwig_parser::syntax::untyped::WalkEvent;
use ludtwig_parser::syntax::typed::AstNode;
use ludtwig_parser::syntax::typed::TwigVar;

let mut preorder = tree_root.preorder();
while let Some(walk_event) = preorder.next() {
    match walk_event {
       WalkEvent::Enter(syntax_node) => {
           if let Some(twig_var) = TwigVar::cast(syntax_node) {
               // do something with ast node here
           }
       }
       WalkEvent::Leave(syntax_node) => {}
    }
}

§Utilities for retrieving a specific AstNode or Token

As of now there might be missing utility method implementations on AstNode’s. You can use these instead to retrieve any AstNode / Token you want (under a given AstNode).


use ludtwig_parser::syntax::typed::{AstNode, support, TwigVar};
use ludtwig_parser::syntax::untyped::SyntaxToken;
use ludtwig_parser::T;

// finding a specific AstNode in a (sub) tree (first occurrence)
// Note: only looks through the direct children of the given SyntaxNode
let twig_var: TwigVar = support::child(&tree_root).unwrap();

// you can freely get the underlaying SyntaxNode of an AstNode with
let twig_var_syntax_node = twig_var.syntax();

// finding a specific Token in a (sub) tree (first occurrence)
// Note: only looks through the direct children of the given SyntaxNode
let twig_var_opening_braces: SyntaxToken = support::token(twig_var_syntax_node, T!["{{"]).unwrap();

// finding specific AstNode's in a (sub) tree (all occurrence)
// returns an iterator
// Note: only looks through the direct children of the given SyntaxNode
let twig_vars = support::children::<TwigVar>(&tree_root);

Modules§

syntax
An overview of the syntax structure can be found at the crate level documentation.

Macros§

T

Structs§

Parse
Result of the parser
ParseError

Statics§

TWIG_NAME_REGEX

Functions§

parse
Parses a given string slice (of Twig+HTML code) into a syntax tree.