Attribute Macro pear_codegen::parser
source · #[parser]
Expand description
The core attribute macro. Can only be applied to free functions with at least one parameter and a return value. To typecheck, the free function must meet the following typing requirements:
- The first parameter’s type must be a mutable reference to a [
Pear<I>
] hereI
implements [Input
]. This is the input parameter. - The return type must be
Result<O, I>
whereI
is the inner type of the input parameter andO
can be any type.
The following transformations are applied to the contents of the attributed function:
-
The functions first parameter (of type
&mut Pear<I>
) is passed as the first parameter to every function call in the function with a posfix?
. That is, every function call of the formfoo(a, b, c, ...)?
is converted tofoo(input, a, b, c, ...)?
whereinput
is the input parameter. -
The inputs to every macro whose name starts with
parse_
are prefixed with[PARSER_NAME, INPUT, MARKER, OUTPUT]
wherePARSER_NAME
is the raw string literal of the functon’s name,INPUT
is the input parameter expression,MARKER
is the marker expression, andOUTPUT
is the output type. Aditionally, if the input to the macro is a valid Rust expression, it is applied the same transformations as a function atributed with#[parser]
.Declare a
parse_
macro as:ⓘmacro_rules! parse_my_macro { ([$n:expr; $i:expr; $m:expr; $T:ty] ..) => { /* .. */ } }
The following transformations are applied around the attributed function:
- The [
Input::mark()
] method is called before the function executes. The returned mark, if any, is stored on the stack. - A return value of
O
is automatically converted (or “lifted”) into a type ofResult<O, I>
by wrapping it inOk
. - If the function returns an
Err
, [Input::context()
] is called with the current mark, and the returned context, if any, is pushed into the error via [ParseError::push_context()
]. - The [
Input::unmark()
] method is called after the function executes, passing in the current mark.
Example
use pear::input::{Pear, Text, Result};
use pear::macros::{parser, parse};
use pear::parsers::*;
#[parser]
fn ab_in_dots<'a, I: Input<'a>>(input: &mut Pear<I>) -> Result<&'a str, I> {
eat('.')?;
let inside = take_while(|&c| c == 'a' || c == 'b')?;
eat('.')?;
inside
}
let x = parse!(ab_in_dots: Text::from(".abba."));
assert_eq!(x.unwrap(), "abba");
let x = parse!(ab_in_dots: Text::from(".ba."));
assert_eq!(x.unwrap(), "ba");
let x = parse!(ab_in_dots: Text::from("..."));
assert!(x.is_err());