pub trait ParseLiteral: 'static {
type Lit: Clone + Debug;
// Required method
fn parse_literal(input: InputSpan<'_>) -> NomResult<'_, Self::Lit>;
}Expand description
Encapsulates parsing literals in a grammar.
§Examples
If your grammar does not need to support type annotations, you can define a ParseLiteral impl
and wrap it into Untyped to get a Grammar / Parse:
use arithmetic_parser::{
grammars::{Features, ParseLiteral, Parse, Untyped},
ErrorKind, InputSpan, NomResult,
};
/// Grammar that parses `u64` numbers.
#[derive(Debug)]
struct IntegerGrammar;
impl ParseLiteral for IntegerGrammar {
type Lit = u64;
// We use the `nom` crate to construct necessary parsers.
fn parse_literal(input: InputSpan<'_>) -> NomResult<'_, Self::Lit> {
use nom::{character::complete::digit1, combinator::map_res, Parser};
let parser = |s: InputSpan<'_>| {
s.fragment().parse().map_err(ErrorKind::literal)
};
map_res(digit1, parser).parse(input)
}
}
// Here's how a grammar can be used.
let program = "
x = 1 + 2 * 3 + sin(a^3 / b^2);
some_function = |a, b| (a + b, a - b);
other_function = |x| {
r = min(rand(), 0);
r * x
};
(y, z) = some_function({ x = x - 1; x }, x);
other_function(y - z)
";
let parsed = Untyped::<IntegerGrammar>::parse_statements(program)?;
println!("{:#?}", parsed);Required Associated Types§
Required Methods§
Sourcefn parse_literal(input: InputSpan<'_>) -> NomResult<'_, Self::Lit>
fn parse_literal(input: InputSpan<'_>) -> NomResult<'_, Self::Lit>
Attempts to parse a literal.
Literals should follow these rules:
- A literal must be distinguished from other constructs, in particular, variable identifiers.
- If a literal may end with
.and methods are enabled inParse::FEATURES, care should be taken for cases when.is a part of a call, rather than a part of a literal. For example, a parser for real-valued literals should interpret1.abs()as a call of theabsmethod on receiver1, rather than1.followed by ineligibleabs().
If a literal may start with - or ! (in general, unary ops), these ops will be
consumed as a part of the literal, rather than Expr::Unary, unless the literal
is followed by an eligible higher-priority operation (i.e., a method call) and
the literal without a preceding unary op is still eligible. That is, if -1 and 1
are both valid literals, then -1.abs() will be parsed as negation applied to 1.abs().
On the other hand, if !foo! is a valid literal, but foo! isn’t, !foo!.bar() will
be parsed as method bar() called on !foo!.
§Return value
The output should follow nom conventions on errors / failures.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.