Crate lavendeux_parser
source · [−]Expand description
lavendeux-parser is an exensible parsing engine for mathematical expressions. It supports variable and function assignments, a variety of datatypes, and can be extended easily at runtime through extensions written in javascript.
Extensions are run in a sandboxed environment with no host or network access. This project is the engine behind Lavendeux.
For help on the syntax of expressions, visit https://rscarson.github.io/lavendeux
Getting Started
To use it, create a ParserState
object, and use it to tokenize input with Token::new
:
use lavendeux_parser::{ParserState, ParserError, Token, Value};
fn main() -> Result<(), ParserError> {
// Create a new parser, and tokenize 2 lines
let mut state : ParserState = ParserState::new();
let lines = Token::new("x=9\nsqrt(x) @bin", &mut state)?;
// The resulting token contains the resulting values and text
assert_eq!(lines.text(), "9\n0b11");
assert_eq!(lines.child(1).unwrap().value(), Value::Integer(3));
Ok(())
}
The result will be a Token
object:
use lavendeux_parser::{ParserState, ParserError, Token, Value};
fn main() -> Result<(), ParserError> {
let mut state : ParserState = ParserState::new();
let lines = Token::new("x=9\nsqrt(x) @bin", &mut state)?;
// String representation of the full result
assert_eq!(lines.text(), "9\n0b11");
// String representation of the first line's result
assert_eq!(lines.child(0).unwrap().text(), "9");
// Actual value of the first line's result
// Values are integers, floats, booleans or strings
let value = lines.child(0).unwrap().value();
assert_eq!(value.as_int().unwrap(), 9);
assert_eq!(true, matches!(value, Value::Integer(_)));
Ok(())
}
A number of functions and @decorators are available for expressions to use - add more using the state:
use lavendeux_parser::{ParserState, ParserError, DecoratorDefinition, FunctionDefinition, FunctionArgument, Value};
use lavendeux_parser::errors::*;
let mut state : ParserState = ParserState::new();
state.decorators.register(DecoratorDefinition {
name: &["upper", "uppercase"],
description: "Outputs an uppercase version of the input",
argument: ExpectedTypes::Any,
handler: |_, input| Ok(input.as_string().to_uppercase())
});
// Functions take in an array of values, and return a single value
state.functions.register(FunctionDefinition {
name: "echo",
description: "Echo back the provided input",
arguments: || vec![
FunctionArgument::new_required("input", ExpectedTypes::String),
],
handler: |_, args: &[Value]| {
Ok(Value::String(args[0].as_string()))
}
});
// Expressions being parsed can now call new_function(), and use the @new_decorator
Using Extensions
Extensions give a more flexible way of adding functionality at runtime. Extensions are written in javascript.
Extensions are enabled by default, and can be excluded by disabling the crate’s “extensions” feature
Extensions can be loaded as follows:
use lavendeux_parser::{ParserState, ParserError, Value, Token};
fn main() -> Result<(), ParserError> {
let mut state : ParserState = ParserState::new();
// Load one extension
state.extensions.load("example_extensions/colour_utils.js")?;
// Load a whole directory
state.extensions.load_all("./example_extensions")?;
// Once loaded, functions and @decorators decribed in the extensions
// can be called in expressions being parsed
let token = Token::new("complement(0xFF0000) @colour", &mut state)?;
assert_eq!(token.text(), "#ffff00");
Ok(())
}
Extensions give a more flexible way of adding functionality at runtime. Extensions are written in javascript.
Re-exports
pub use errors::ParserError;
Modules
Module defining errors that can occur during parsing
Structs
Holds the definition of a builtin callable decorator
Holds a set of callable decorators
Represents a single loaded extension. It describes the functions and decorators it adds, as well as metadata about the extension and it’s author.
Describes an argument for a callable function
Holds the definition of a builtin callable function
Holds a set of callable functions
Represents the current state of the parser Holds the functions, decorators, variables and extensions available for expressions to use
Represents a token tree for a parsed expression The root contains the text result of parsing the expression, as well as one child per line being parsed
Enums
Represents a single value resulting from a calculation Can take the form of an integer, float, boolean or string
Type Definitions
The datatype for floating point values
The datatype for integer values