Attribute Macro pear_codegen::parser[][src]

#[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>] here I implements [Input]. This is the input parameter.
  • The return type must be Result<O, I> where I is the inner type of the input parameter and O 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 form foo(a, b, c, ...)? is converted to foo(input, a, b, c, ...)? where input is the input parameter.

  • The inputs to every macro whose name starts with parse_ are prefixed with [PARSER_NAME, INPUT, MARKER, OUTPUT] where PARSER_NAME is the raw string literal of the functon’s name, INPUT is the input parameter expression, MARKER is the marker expression, and OUTPUT 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 of Result<O, I> by wrapping it in Ok.
  • 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());