Skip to main content

Crate tabnas_expr

Crate tabnas_expr 

Source
Expand description

Pratt expression-operator plugin for the tabnas parser engine, layered on the jsonic relaxed-JSON base grammar.

The algorithm is Pratt parsing, and draws heavily from the explanation written by Aleksey Kladov at https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html. See prattify for the core.

Expressions parse into LISP-style S-expressions: an array whose first element describes the operator and whose remaining elements are the operand terms, so 1+2*3 becomes ["+", 1, ["*", 2, 3]] once the operator descriptions are reduced to their source text. A caller supplied evaluator can reduce the tree to a value during the parse.

TypeScript is canonical: ts/src/expr.ts defines the behaviour, the option names, the defaults and the order of alternates. The shared fixtures in test/spec/*.tsv are the parity contract across TypeScript, Go and Rust.

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let value = tabnas_expr::parse("a:1+2*3")?;
    assert_eq!(tabnas_expr::simplify(&value).to_string(),
               r#"{"a":["+",1,["*",2,3]]}"#);
    Ok(())
}

§Untrusted input

A parsed expression is data, never instructions. This plugin reads expression text of unknown provenance and returns S-expressions for a caller supplied evaluator to reduce, and that hand-off is where hostile input could become execution. Treat every operand and operator as untrusted text, and never let a document select which evaluator or operator implementation runs.

Structs§

EvalSite
The site an evaluator is called from: the rule the reduction belongs to and the live parse context, and neither when evaluation is called on a finished tree.
ExprError
The error a failed parse produces, re-exported so callers need not depend on the engine crate directly.
ExprOptions
Options for the plugin.
Op
The full operator description carried by a parsed expression and handed to an evaluator.
OpDef
One entry of the op option map: the definition of an operator.
OpRef
One occurrence of an operator: the shared description and the token that introduced it. The canonical makeOp builds the same pair by copying the description and attaching the token.
PrevalDef
Paren preval configuration: whether a value may precede the opening paren (foo(1), a[1]), whether one is required, and which values are allowed to.
TranslationPart
One optional alchemy translation source and its explicit entry point.
TranslationParts
The package-local structural translation interface.

Constants§

MAX_SAFE_INTEGER
JavaScript’s Number.MAX_SAFE_INTEGER, the binding power an operator with no declared right takes: it binds tightest on the right.
MIN_SAFE_INTEGER
JavaScript’s Number.MIN_SAFE_INTEGER, the binding power an operator with no declared left takes: it binds loosest on the left.
NODE_LIMIT
The most nodes one expression may hold.
PLUGIN_NAME
The name this plugin registers under.
RULE_LIMIT
The deepest rule stack a parse may reach.
VERSION
VERSION is this crate’s version. It MUST equal ts/package.json “version” and the version field in rs/Cargo.toml: the release orchestrator rewrites all of them, and tests/version_test.rs fails the build if they drift. Mirrors VERSION in ts/src/expr.ts and const VERSION in go/expr.go.

Functions§

apply
Install the expression grammar on a parser through Tabnas::use_plugin, so that a derived instance rebuilds it.
defaults
The default operator table, as the plugin declares it to the engine.
evaluation
Reduce an expression tree with an evaluator, innermost first.
expr
Install the expression grammar on a parser that already carries the jsonic base rules (val, map, list, pair, elem).
is_op
Whether a value is an expression node, the port of the canonical isOp.
make
Build a parser with the jsonic base grammar and the default operator table.
make_with
Build a parser with the jsonic base grammar and the given options.
manifest_text
The plugin’s manifest, tabnas.plugin.json, as the repository carries it. Its translate object is what a host that translates reads: the shape an expression document is read as and written from (tree), the root the render takes, the schema of the tree its events carry (expr), the files that hold the embedding of a plain tree in that schema and the render, and the sentences that say what a written document does not keep. The crate embeds its own copy, translate/manifest.json, since a packaged crate holds nothing outside rs/; tests/translate_test.rs holds the copy to the file.
op_of
The operator heading an expression node.
opify
Normalize an operator built by hand, filling the derived term count when it is unset, as the parser’s own operator builder does. The Rust spelling of the canonical testing.opify.
parse
Parse one document with the default operator table.
parse_scope
Parse one document and hand the unrealized value to a closure, with the expression arena held open for as long as it runs.
parse_simplified
Parse one document and reduce it to the S-expression form the shared fixtures compare.
parse_with
Parse one document with a parser this crate configured, and realize the expression nodes in the result.
plugin
The plugin, for Tabnas::use_plugin, carrying the default operator table as its declared defaults.
plugin_with
The plugin with typed options, which is how an evaluator and any operator data that no Value can carry reach the grammar.
prattify
Embed a new operator into an expression tree, in place, according to operator precedence.
realize
Replace every expression handle in a parsed value with the plain array the canonical port returns: the operator description followed by the operand terms.
render_text
The expression format’s render, alchemy/render.alc, the file the manifest’s translate.render names: a library of alchemy definitions, with no export, whose entry point expr-render writes a tree’s events as one document. A host links it with its own program. The crate embeds its own copy, translate/render.alc, held to the file as the manifest’s is; the embedding, translate/embed.alc, is translate().embed.
simplify
Reduce a parsed value to the S-expression form the shared fixtures compare: every operator description becomes its source text, and a term that was never filled is dropped.
terms_of
The operand terms of an expression node.
translate
Return the expression format’s immutable translation parts.

Type Aliases§

Evaluate
Resolve the value of an operation. The Rust spelling of the canonical Evaluate callback: it takes the operator and its already reduced terms, and returns the value the expression stands for.