Crate arithmetic_parser[−][src]
Expand description
Parser for arithmetic expressions with flexible definition of literals and support of type annotations.
Overall, parsed grammars are similar to Rust syntax, with a few notable differences.
Supported syntax features
- Variables. A variable name is defined similar to Rust and other programming languages, as a sequence of alphanumeric chars and underscores that does not start with a digit.
- Literals. The parser for literals is user-provided, thus allowing to apply the library to different domains (e.g., finite group arithmetic).
//
and/* .. */
comments.- Basic arithmetic operations:
+
,-
(binary and unary),*
,/
,^
(power). The parser outputs AST with nodes organized according to the operation priority. - Function calls:
foo(1.0, x)
. - Parentheses which predictably influence operation priority.
The parser supports both complete and streaming (incomplete) modes; the latter is useful for REPLs and similar applications.
Optional syntax features
These features can be switched on or off when defining a Parse
impl
by declaring the corresponding Features
.
- Tuples. A tuple is two or more elements separated by commas, such as
(x, y)
or(1, 2 * x)
. Tuples are parsed both as lvalues and rvalues. - Tuple destructuring. Using a tuple as an lvalue, for example,
(x, y, z) = foo
. The “rest” syntax is also supported, either named or unnamed:(head, ...tail) = foo
,(a, ..., b, c) = foo
. - Function definitions. A definition looks like a closure definition in Rust, e.g.,
|x| x - 10
or|x, y| { z = max(x, y); (z - x, z - y) }
. A definition may be assigned to a variable (which is the way to define named functions). - Destructuring for function args. Similar to tuple destructuring, it is possible to
destructure and group args in function definitions, for example,
|(x, y), ...zs| { }
. - Blocks. A block is several
;
-delimited statements enclosed in{}
braces, e.g,{ z = max(x, y); (z - x, z - y) }
. The blocks can be used in all contexts instead of a simple expression; for example,min({ z = 5; z - 1 }, 3)
. - Objects. Object is a mapping of string fields to values. Objects are defined via
object expressions, which look similar to struct initialization in Rust or object
initialization in JavaScript; for example,
#{ x: 1, y }
. (Note the#
char at the start of the block; it is used to distinguish object expressions from blocks.) - Methods. Method call is a function call separated from the receiver with a
.
char; for example,foo.bar(2, x)
. - Type annotations. A type annotation in the form
var: Type
can be present in the lvalues or in the function argument definitions. The parser for type annotations is user-defined. - Boolean operations:
==
,!=
,&&
,||
,!
. - Order comparisons, that is,
>
,<
,>=
, and<=
boolean ops.
Differences with Rust
(within shared syntax constructs; of course, Rust is much more expressive)
- No keyword for assigning a variable (i.e., no
let
/let mut
). There are no keywords in general. - Functions are only defined via the closure syntax.
- There is “rest” destructuting for tuples and function arguments.
- Type annotations are placed within tuple elements, for example,
(x: Num, _) = y
. - Object expressions are enclosed in
#{ ... }
, similarly to Rhai.
Crate features
std
. Enables support of types fromstd
, such as theError
trait, and propagates to dependencies.num-complex
. ImplementsNumLiteral
for floating-point complex numbers (Complex32
andComplex64
).num-bigint
. ImplementsNumLiteral
forBigInt
andBigUint
from thenum-bigint
crate.
Examples
Using a grammar for arithmetic on real values.
use arithmetic_parser::{ grammars::{F32Grammar, Parse, Untyped}, NomResult, Statement, Expr, FnDefinition, LvalueLen, }; const PROGRAM: &str = r#" // This is a comment. x = 1 + 2.5 * 3 + sin(a^3 / b^2 /* another comment */); // Function declarations have syntax similar to Rust closures. some_function = |a, b| (a + b, a - b); other_function = |x| { r = min(rand(), 0.5); r * x }; // Tuples and blocks are supported and have a similar syntax to Rust. (y, z) = some_function({ x = x - 0.5; x }, x); other_function(y - z) "#; let block = Untyped::<F32Grammar>::parse_statements(PROGRAM)?; // First statement is an assignment. assert_matches!( block.statements[0].extra, Statement::Assignment { ref lhs, .. } if *lhs.fragment() == "x" ); // The RHS of the second statement is a function. let some_function = match &block.statements[1].extra { Statement::Assignment { rhs, .. } => &rhs.extra, _ => panic!("Unexpected parsing result"), }; // This function has a single argument and a single statement in the body. assert_matches!( some_function, Expr::FnDefinition(FnDefinition { ref args, ref body, .. }) if args.extra.len() == LvalueLen::Exact(2) && body.statements.is_empty() && body.return_value.is_some() );
Modules
grammars | Grammar functionality and a collection of standard grammars. |
Structs
Block | Block of statements. |
Destructure | Tuple destructuring, such as |
FnDefinition | Function definition, e.g., |
LocatedSpan | Code span together with information related to where it is located in the code. |
ObjectDestructure | Object destructuring, such as |
ObjectDestructureField | Single field in |
ObjectExpr | Object expression, such as |
SpannedError | Parsing error with a generic code span. |
Enums
BinaryOp | Binary arithmetic operation. |
CodeFragment | Container for a code fragment that can be in one of the two states: either the code string is retained, or it is stripped away. |
Context | Parsing context. |
DestructureRest | Rest syntax, such as |
ErrorKind | Parsing error kind. |
Expr | Arithmetic expression with an abstract types for type annotations and literals. |
ExprType | Type of an |
Lvalue | Assignable value. |
LvalueLen | Length of an assigned lvalue. |
LvalueType | Type of an |
Op | Generic operation, either unary or binary. |
OpPriority | Priority of an operation. |
Statement | Statement: an expression or a variable assignment. |
StatementType | Type of a |
UnaryOp | Unary operation. |
UnsupportedType | Description of a construct not supported by a certain module (e.g., interpreter or type inference). |
Traits
StripCode | Encapsulates stripping references to code fragments. The result can outlive the code. |
StripResultExt | Helper trait for |
Functions
is_valid_variable_name | Checks if the provided string is a valid variable name. |
with_span | Wrapper around parsers allowing to capture both their output and the relevant span. |
Type Definitions
Error | Error with code span available as a string reference. |
InputSpan | Code span. |
MaybeSpanned | Value with an optional associated code span. |
NomResult | Parsing outcome generalized by the type returned on success. |
Spanned | Value with an associated code span. |
SpannedExpr |
|
SpannedLvalue |
|
SpannedStatement | Statement with the associated code span. |