blanket_script/parser/
mod.rs1use expression::parse_expression;
2use nom::{
3 character::complete::{multispace0, multispace1},
4 error::ParseError,
5 sequence::delimited,
6 IResult, Parser,
7};
8use thiserror::Error;
9
10pub(super) mod expression;
11
12pub use expression::{Associativity, BinaryOperator, Expression, StringLiteral, UnaryOperator};
13
14#[derive(Error, Debug, PartialEq)]
15pub enum SyntaxErrorKind {
16 #[error("Empty input")]
17 EmptyInput,
18 #[error("Trailing characters")]
19 TrailingCharacters,
20 #[error("Numeric literals cannot have consecutive underscores")]
21 ConsecutiveUnderscoreInNumericLiteral,
22 #[error("Numeric literals cannot start with an underscore")]
23 NumericLiteralStartsWithUnderscore,
24 #[error("Numeric literals cannot end with an underscore")]
25 NumericLiteralEndsWithUnderscore,
26 #[error("Empty bigint literal")]
27 EmptyBigIntLiteral,
28 #[error("Invalid hexadecimal digit")]
29 InvalidHexDigit,
30 #[error("Missing opening brace in unicode code point escape sequence")]
31 MissingUnicodeCodePointOpeningBrace,
32 #[error("Missing closing brace in unicode code point escape sequence")]
33 MissingUnicodeCodePointClosingBrace,
34 #[error("Invalid unicode code point: {0}")]
35 InvalidUnicodeCodePoint(u32),
36 #[error("Nom error: {0:?}")]
37 NomError(nom::error::ErrorKind),
38}
39
40#[derive(Debug, PartialEq)]
41pub struct SyntaxError<'a> {
42 pub input: &'a str,
43 pub error: SyntaxErrorKind,
44}
45
46impl<'a> nom::error::ParseError<&'a str> for SyntaxError<'a> {
47 fn from_error_kind(input: &'a str, kind: nom::error::ErrorKind) -> Self {
48 SyntaxError {
49 input,
50 error: match kind {
51 nom::error::ErrorKind::Eof => SyntaxErrorKind::EmptyInput,
52 _ => SyntaxErrorKind::NomError(kind),
53 },
54 }
55 }
56
57 fn append(_: &'a str, _: nom::error::ErrorKind, other: Self) -> Self {
58 other
59 }
60}
61
62pub type ParseResult<'a, T> = IResult<&'a str, T, SyntaxError<'a>>;
63
64pub fn parse(input: &str) -> ParseResult<Expression> {
65 if input.is_empty() {
66 return Err(nom::Err::Failure(SyntaxError {
67 input,
68 error: SyntaxErrorKind::EmptyInput,
69 }));
70 }
71 let (remaining, parsed) = parse_expression(input)?;
72 if remaining.is_empty() {
73 return Ok((remaining, parsed));
74 }
75 Err(nom::Err::Failure(SyntaxError {
76 input,
77 error: SyntaxErrorKind::TrailingCharacters,
78 }))
79}
80
81fn ws0<'a, O, E: ParseError<&'a str>, F>(inner: F) -> impl Parser<&'a str, Output = O, Error = E>
83where
84 F: Parser<&'a str, Output = O, Error = E>,
85{
86 delimited(multispace0, inner, multispace0)
87}
88
89fn ws1<'a, O, E: ParseError<&'a str>, F>(inner: F) -> impl Parser<&'a str, Output = O, Error = E>
91where
92 F: Parser<&'a str, Output = O, Error = E>,
93{
94 delimited(multispace1, inner, multispace1)
95}