Expand description
Build rowan green ASTs using nom parsers
Example
use enum_ordinalize::Ordinalize;
use logos::Logos;
use rowan::SyntaxKind;
use rowan_nom::{alt, eof, join, many0, node, root_node, t, DummyError, IResult, Input};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Logos, Ordinalize)]
#[repr(u16)]
enum Token {
#[token("+")]
Add,
#[token("-")]
Sub,
#[token("*")]
Mul,
#[regex(r#"\d+"#)]
Literal,
#[regex(r#"\s+"#)]
Space,
#[error]
Error,
// Rowan nodes
Additive,
Multiplicative,
Root,
}
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct Language;
impl rowan::Language for Language {
type Kind = Token;
fn kind_from_raw(raw: SyntaxKind) -> Self::Kind {
Token::from_ordinal(raw.0).unwrap()
}
fn kind_to_raw(kind: Self::Kind) -> SyntaxKind {
SyntaxKind(kind as u16)
}
}
impl rowan_nom::RowanNomLanguage for Language {
fn is_trivia(kind: Self::Kind) -> bool {
matches!(kind, Token::Space)
}
fn get_error_kind() -> Self::Kind {
Token::Error
}
}
#[rustfmt::skip]
fn parse_multiplicative<'slice, 'src>(
input: Input<'slice, 'src, Language>,
) -> IResult<'slice, 'src, Language, DummyError> {
node(
Token::Multiplicative,
join((
t(Token::Literal),
many0(join((
t(Token::Mul),
t(Token::Literal),
))),
)),
)(input)
}
#[rustfmt::skip]
fn parse_additive<'slice, 'src>(
input: Input<'slice, 'src, Language>,
) -> IResult<'slice, 'src, Language, DummyError> {
node(
Token::Additive,
join((
parse_multiplicative,
many0(join((
alt((t(Token::Add), t(Token::Sub))),
parse_multiplicative,
))),
)),
)(input)
}
fn main() {
let source = "10 - 2 * 3";
let tokens = Token::lexer(source)
.spanned()
.map(|(token, span)| (token, &source[span]))
.collect::<Vec<_>>();
let input = Input::<Language>::from(tokens.as_slice());
let (_, (ast, errors)) = root_node(Token::Root, join((parse_additive, eof)))(input).unwrap();
dbg!(ast, errors);
}
Structs
- A partial green AST builder, used as an output for all parsers
- A ZST that implements
RowanNomError
when details or context don’t matter - Input type for nom parsers
Traits
Functions
- Tests a list of parsers one by one until one succeeds
- Succeeds if the input contains no tokens other than trivia, and returns a Children object with said trivia, effectively emptying last insignificant bits of input
- Tries to apply the given parser to the input without failing on error
- Similar to
nom::multi::fold_many1
, but more specialized - Similar to
fold_many1
, but folds right instead of left - Similar to
fold_many1
, but folds right instead of left — expression version - Joins the output trees of multiple parsers without creating a new node (yet)
- Repeats the given parser 0 or more times until it fails, and join all the results in a
Children
object - Maps a function on the result of a parser.
- Wraps the contained parser’s direct and indirect output into a node
- Optional parser, will return None on
nom::Err::Error
. - Makes a parser peek without consuming
- Negated peek, succeeds only if the given parser fails
- Wraps the contained parser’s output into a root node inside a SyntaxNode
- Succeeds without consuming the input
- Parses only the given token, fails if the wrong token is read or if the input is empty
- Parses any token
- Parses only the given token, fails if the wrong token is read or if the input is empty, but does not skip trivia tokens