Syntax Tree
The syntax API shares many similarities with the lexis API architecture:
- The syntax grammar, implemented by the Node type, is distinct from the syntax tree manager responsible for actual parsing and storage of the syntax tree.
- The syntax tree manager implements the SyntaxTree trait, providing access to the parsed syntax tree through its functions.
- There are several syntax manager implementations with distinct sets of features and performance characteristics.
- Individual nodes within the syntax tree are addressed using the NodeRef referential object, which points to concrete node instances owned by the syntax tree manager.
The simplest implementation of the syntax tree manager is the ImmutableSyntaxTree, which performs one-time parsing without incremental reparsing capabilities but has the fastest computation performance.
This object accepts a token cursor providing access to the input stream. For example, you can obtain this cursor from the TokenBuffer.
use lady_deirdre::{
lexis::{SourceCode, TokenBuffer},
syntax::{ImmutableSyntaxTree, SyntaxTree},
};
let tokens = TokenBuffer::<JsonToken>::from(r#"{
"foo": true,
"bar": [123, null]
}"#);
// Parsing the entire set of tokens in the token buffer.
let tree = ImmutableSyntaxTree::<JsonNode>::parse(tokens.cursor(..));
// Ensuring that the ImmutableSyntaxTree successfully parsed
// the input stream without syntax errors.
assert!(tree.errors().next().is_none());
The above code is verbose because it requires manual setup of the TokenBuffer and its token cursor.
More commonly, we can utilize the immutable Document, which is backed by the TokenBuffer and ImmutableSyntaxTree under the hood. Through this object, we can directly scan and parse the source code text. This object implements both the SourceCode and SyntaxTree traits, allowing us to access the lexical structure of the compilation unit as well.
use lady_deirdre::{syntax::SyntaxTree, units::Document};
let doc = Document::<JsonNode>::new_immutable(r#"{
"foo": true,
"bar": [123, null]
}"#);
assert!(doc.errors().next().is_none());