wasm_wave/
parser.rs

1//! Parsing types
2
3use core::{error::Error, fmt::Display};
4
5use alloc::{
6    boxed::Box,
7    collections::{BTreeMap, btree_set::BTreeSet},
8    format,
9    string::{String, ToString},
10    vec::Vec,
11};
12
13use crate::{
14    WasmValue,
15    ast::{Node, NodeType},
16    lex::{Keyword, Lexer, Span, Token},
17    untyped::{UntypedFuncCall, UntypedValue},
18};
19
20/// A Web Assembly Value Encoding parser.
21pub struct Parser<'source> {
22    lex: Lexer<'source>,
23    curr: Option<Token>,
24}
25
26impl<'source> Parser<'source> {
27    /// Returns a new Parser of the given source.
28    pub fn new(source: &'source str) -> Self {
29        Self::with_lexer(Lexer::new(source))
30    }
31
32    /// Returns a new Parser with the given [`Lexer`].
33    pub fn with_lexer(lexer: Lexer<'source>) -> Self {
34        Self {
35            lex: lexer,
36            curr: None,
37        }
38    }
39
40    /// Parses a WAVE-encoded value of the given [`crate::wasm::WasmType`] into a
41    /// corresponding [`WasmValue`].
42    pub fn parse_value<V: WasmValue>(&mut self, ty: &V::Type) -> Result<V, ParserError> {
43        let node = self.parse_node()?;
44        node.to_wasm_value(ty, self.lex.source())
45    }
46
47    /// Parses a WAVE-encoded value into an [`UntypedValue`].
48    pub fn parse_raw_value(&mut self) -> Result<UntypedValue<'source>, ParserError> {
49        let node = self.parse_node()?;
50        Ok(UntypedValue::new(self.lex.source(), node))
51    }
52
53    /// Parses a function name followed by a WAVE-encoded, parenthesized,
54    /// comma-separated sequence of values into an [`UntypedFuncCall`].
55    pub fn parse_raw_func_call(&mut self) -> Result<UntypedFuncCall<'source>, ParserError> {
56        self.advance()?;
57        let name = self.parse_label()?;
58        self.advance()?;
59        self.expect_token(Token::ParenOpen)?;
60
61        let params = if self.next_is(Token::ParenClose) {
62            self.advance()?;
63            None
64        } else {
65            Some(self.parse_tuple()?)
66        };
67        Ok(UntypedFuncCall::new(self.lex.source(), name, params))
68    }
69
70    /// Returns an error if any significant input remains unparsed.
71    pub fn finish(&mut self) -> Result<(), ParserError> {
72        match self.lex.clone().spanned().next() {
73            None => Ok(()),
74            Some((_, span)) => Err(ParserError::new(
75                ParserErrorKind::TrailingCharacters,
76                span.clone(),
77            )),
78        }
79    }
80
81    fn parse_node(&mut self) -> Result<Node, ParserError> {
82        Ok(match self.advance()? {
83            Token::Number => self.leaf_node(NodeType::Number),
84            Token::Char => self.leaf_node(NodeType::Char),
85            Token::String => self.leaf_node(NodeType::String),
86            Token::MultilineString => self.leaf_node(NodeType::MultilineString),
87            Token::ParenOpen => self.parse_tuple()?,
88            Token::BracketOpen => self.parse_list()?,
89            Token::BraceOpen => self.parse_record_or_flags()?,
90            Token::LabelOrKeyword => match Keyword::decode(self.slice()) {
91                Some(Keyword::True) => self.leaf_node(NodeType::BoolTrue),
92                Some(Keyword::False) => self.leaf_node(NodeType::BoolFalse),
93                Some(Keyword::Some) => self.parse_option(NodeType::OptionSome)?,
94                Some(Keyword::None) => self.parse_option(NodeType::OptionNone)?,
95                Some(Keyword::Ok) => self.parse_result(NodeType::ResultOk)?,
96                Some(Keyword::Err) => self.parse_result(NodeType::ResultErr)?,
97                Some(Keyword::Inf | Keyword::Nan) => self.leaf_node(NodeType::Number),
98                None => self.parse_label_maybe_payload()?,
99            },
100            Token::BraceClose
101            | Token::ParenClose
102            | Token::BracketClose
103            | Token::Colon
104            | Token::Comma => return Err(self.unexpected_token()),
105        })
106    }
107
108    fn parse_tuple(&mut self) -> Result<Node, ParserError> {
109        let start = self.span().start;
110        let children = self.parse_comma_separated_nodes(Token::ParenClose)?;
111        let span = start..self.span().end;
112        if children.is_empty() {
113            return Err(ParserError::new(ParserErrorKind::EmptyTuple, span));
114        }
115        Ok(Node::new(NodeType::Tuple, span, children))
116    }
117
118    fn parse_list(&mut self) -> Result<Node, ParserError> {
119        let start = self.span().start;
120        let children = self.parse_comma_separated_nodes(Token::BracketClose)?;
121        Ok(Node::new(NodeType::List, start..self.span().end, children))
122    }
123
124    fn parse_record_or_flags(&mut self) -> Result<Node, ParserError> {
125        let start = self.span().start;
126        self.advance()?;
127
128        match self.token() {
129            // Handle empty record (`{:}`)
130            Token::Colon => {
131                self.advance()?; // Advance to `}`
132                self.expect_token(Token::BraceClose)?;
133                return Ok(Node::new(NodeType::Record, start..self.span().end, []));
134            }
135            // Handle empty flags (`{}`)
136            Token::BraceClose => return Ok(Node::new(NodeType::Flags, start..self.span().end, [])),
137            _ => (),
138        }
139
140        // Check for a following `:` to distinguish records from flags
141        if self.next_is(Token::Colon) {
142            self.finish_record(start)
143        } else {
144            self.finish_flags(start)
145        }
146    }
147
148    fn finish_record(&mut self, start: usize) -> Result<Node, ParserError> {
149        let mut seen = BTreeSet::new();
150        let mut children = Vec::with_capacity(2);
151        loop {
152            // Parse field label
153            let label = self.parse_label()?;
154            // Check for duplicate fields
155            let field = self.slice().trim_start_matches('%');
156            if !seen.insert(field) {
157                return Err(ParserError::with_detail(
158                    ParserErrorKind::DuplicateField,
159                    label.span(),
160                    format!("{field:?}"),
161                ));
162            }
163            // Parse colon
164            self.advance()?;
165            self.expect_token(Token::Colon)?;
166            // Parse value
167            let value = self.parse_node()?;
168            children.extend([label, value]);
169            // Parse comma and/or end of record
170            if self.advance()? == Token::Comma {
171                self.advance()?;
172            }
173            if self.token() == Token::BraceClose {
174                break;
175            }
176        }
177        Ok(Node::new(
178            NodeType::Record,
179            start..self.span().end,
180            children,
181        ))
182    }
183
184    fn finish_flags(&mut self, start: usize) -> Result<Node, ParserError> {
185        let mut flags = BTreeMap::new();
186        loop {
187            // Parse flag label
188            let label = self.parse_label()?;
189            // Insert and check for duplicate flags
190            let span = label.span();
191            let flag = self.slice().trim_start_matches('%');
192            if flags.insert(flag, label).is_some() {
193                return Err(ParserError::with_detail(
194                    ParserErrorKind::DuplicateFlag,
195                    span,
196                    format!("{flag:?}"),
197                ));
198            }
199            // Parse comma and/or end of flags
200            if self.advance()? == Token::Comma {
201                self.advance()?;
202            }
203            if self.token() == Token::BraceClose {
204                break;
205            }
206        }
207        Ok(Node::new(
208            NodeType::Flags,
209            start..self.span().end,
210            flags.into_values(),
211        ))
212    }
213
214    fn parse_label_maybe_payload(&mut self) -> Result<Node, ParserError> {
215        let start = self.span().start;
216        let label = self.parse_label()?;
217        if self.next_is(Token::ParenOpen) {
218            self.advance()?;
219            let payload = self.parse_node()?;
220            self.advance()?;
221            self.expect_token(Token::ParenClose)?;
222            Ok(Node::new(
223                NodeType::VariantWithPayload,
224                start..self.span().end,
225                [label, payload],
226            ))
227        } else {
228            Ok(label)
229        }
230    }
231
232    fn parse_option(&mut self, ty: NodeType) -> Result<Node, ParserError> {
233        let start = self.span().start;
234        let payload = match ty {
235            NodeType::OptionSome => {
236                self.advance()?;
237                self.expect_token(Token::ParenOpen)?;
238                let payload = self.parse_node()?;
239                self.advance()?;
240                self.expect_token(Token::ParenClose)?;
241                Some(payload)
242            }
243            NodeType::OptionNone => None,
244            _ => unreachable!(),
245        };
246        Ok(Node::new(ty, start..self.span().end, payload))
247    }
248
249    fn parse_result(&mut self, ty: NodeType) -> Result<Node, ParserError> {
250        let start = self.span().start;
251        let mut payload = None;
252        if self.next_is(Token::ParenOpen) {
253            self.advance()?;
254            self.expect_token(Token::ParenOpen)?;
255            payload = Some(self.parse_node()?);
256            self.advance()?;
257            self.expect_token(Token::ParenClose)?;
258        }
259        Ok(Node::new(ty, start..self.span().end, payload))
260    }
261
262    fn parse_label(&mut self) -> Result<Node, ParserError> {
263        self.expect_token(Token::LabelOrKeyword)?;
264        Ok(self.leaf_node(NodeType::Label))
265    }
266
267    fn advance(&mut self) -> Result<Token, ParserError> {
268        let token = match self.lex.next() {
269            Some(Ok(token)) => token,
270            Some(Err(span)) => {
271                let span = span.unwrap_or_else(|| self.lex.span());
272                return Err(ParserError::new(ParserErrorKind::InvalidToken, span));
273            }
274            None => {
275                return Err(ParserError::new(
276                    ParserErrorKind::UnexpectedEnd,
277                    self.lex.span(),
278                ));
279            }
280        };
281        self.curr = Some(token);
282        Ok(token)
283    }
284
285    fn token(&self) -> Token {
286        self.curr.unwrap()
287    }
288
289    fn span(&self) -> Span {
290        self.lex.span()
291    }
292
293    fn slice(&self) -> &'source str {
294        &self.lex.source()[self.span()]
295    }
296
297    fn next_is(&mut self, token: Token) -> bool {
298        self.lex.clone().next().and_then(|res| res.ok()) == Some(token)
299    }
300
301    fn expect_token(&self, token: Token) -> Result<(), ParserError> {
302        if self.token() == token {
303            Ok(())
304        } else {
305            Err(self.unexpected_token())
306        }
307    }
308
309    fn unexpected_token(&self) -> ParserError {
310        ParserError::with_detail(ParserErrorKind::UnexpectedToken, self.span(), self.token())
311    }
312
313    fn parse_comma_separated_nodes(&mut self, end_token: Token) -> Result<Vec<Node>, ParserError> {
314        let mut nodes = Vec::new();
315        if self.next_is(end_token) {
316            self.advance()?;
317            return Ok(nodes);
318        }
319        loop {
320            nodes.push(self.parse_node()?);
321
322            match self.advance()? {
323                Token::Comma => {
324                    if self.next_is(end_token) {
325                        self.advance()?;
326                        break;
327                    }
328                }
329                _ => {
330                    self.expect_token(end_token)?;
331                    break;
332                }
333            }
334        }
335        Ok(nodes)
336    }
337
338    fn leaf_node(&self, ty: NodeType) -> Node {
339        Node::new(ty, self.span(), [])
340    }
341}
342
343/// A WAVE parsing error.
344#[derive(Debug)]
345pub struct ParserError {
346    kind: ParserErrorKind,
347    span: Span,
348    detail: Option<String>,
349    source: Option<Box<dyn Error + Send + Sync + 'static>>,
350}
351
352impl ParserError {
353    pub(crate) fn new(kind: ParserErrorKind, span: Span) -> Self {
354        Self {
355            kind,
356            span,
357            detail: None,
358            source: None,
359        }
360    }
361
362    pub(crate) fn with_detail(kind: ParserErrorKind, span: Span, detail: impl Display) -> Self {
363        Self {
364            kind,
365            span,
366            detail: Some(detail.to_string()),
367            source: None,
368        }
369    }
370
371    pub(crate) fn with_source(
372        kind: ParserErrorKind,
373        span: Span,
374        source: impl Into<Box<dyn Error + Send + Sync>>,
375    ) -> Self {
376        Self {
377            kind,
378            span,
379            detail: None,
380            source: Some(source.into()),
381        }
382    }
383
384    /// Returns the [`ParserErrorKind`] of this error.
385    pub fn kind(&self) -> ParserErrorKind {
386        self.kind
387    }
388
389    /// Returns the [`Span`] of this error.
390    pub fn span(&self) -> Span {
391        self.span.clone()
392    }
393
394    /// Returns any detail string for this error.
395    pub fn detail(&self) -> Option<&str> {
396        self.detail.as_deref()
397    }
398}
399
400impl Display for ParserError {
401    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
402        if let Some(source) = &self.source {
403            write!(f, "{}: {} at {:?}", self.kind, source, self.span)
404        } else if let Some(detail) = &self.detail {
405            write!(f, "{}: {} at {:?}", self.kind, detail, self.span)
406        } else {
407            write!(f, "{} at {:?}", self.kind, self.span)
408        }
409    }
410}
411
412impl Error for ParserError {
413    fn source(&self) -> Option<&(dyn Error + 'static)> {
414        Some(self.source.as_deref()? as _)
415    }
416}
417
418/// The kind of a WAVE parsing error.
419#[derive(Clone, Copy, Debug, PartialEq)]
420#[non_exhaustive]
421#[allow(missing_docs)]
422pub enum ParserErrorKind {
423    EmptyTuple,
424    MultipleChars,
425    InvalidEscape,
426    InvalidMultilineString,
427    InvalidParams,
428    InvalidToken,
429    InvalidType,
430    InvalidValue,
431    TrailingCharacters,
432    UnexpectedEnd,
433    UnexpectedToken,
434    DuplicateField,
435    DuplicateFlag,
436    WasmValueError,
437}
438
439impl Display for ParserErrorKind {
440    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
441        let msg = match self {
442            ParserErrorKind::EmptyTuple => "empty tuple",
443            ParserErrorKind::MultipleChars => "multiple characters in char value",
444            ParserErrorKind::InvalidEscape => "invalid character escape",
445            ParserErrorKind::InvalidMultilineString => "invalid multiline string",
446            ParserErrorKind::InvalidParams => "invalid params",
447            ParserErrorKind::InvalidToken => "invalid token",
448            ParserErrorKind::InvalidType => "invalid value type",
449            ParserErrorKind::InvalidValue => "invalid value",
450            ParserErrorKind::TrailingCharacters => "trailing characters after value",
451            ParserErrorKind::UnexpectedEnd => "unexpected end of input",
452            ParserErrorKind::UnexpectedToken => "unexpected token",
453            ParserErrorKind::DuplicateField => "duplicate field",
454            ParserErrorKind::DuplicateFlag => "duplicate flag",
455            ParserErrorKind::WasmValueError => "error converting Wasm value",
456        };
457        write!(f, "{msg}")
458    }
459}
460
461#[cfg(test)]
462mod tests {
463    use super::*;
464    use crate::value::{Type, Value};
465
466    #[test]
467    fn parse_option_or_result() {
468        let ty = Type::option(Type::BOOL);
469        assert_eq!(
470            parse_value("some(true)", &ty),
471            Value::make_option(&ty, Some(Value::make_bool(true))).unwrap()
472        );
473        let ty = Type::result(Some(Type::BOOL), None);
474        assert_eq!(
475            parse_value("ok(false)", &ty),
476            Value::make_result(&ty, Ok(Some(Value::make_bool(false)))).unwrap()
477        );
478    }
479
480    #[test]
481    fn parse_flat_option_or_result() {
482        let ty = Type::option(Type::BOOL);
483        assert_eq!(
484            parse_value("true", &ty),
485            Value::make_option(&ty, Some(Value::make_bool(true))).unwrap()
486        );
487        let ty = Type::result(Some(Type::BOOL), None);
488        assert_eq!(
489            parse_value("false", &ty),
490            Value::make_result(&ty, Ok(Some(Value::make_bool(false)))).unwrap()
491        );
492    }
493
494    #[test]
495    fn parse_record_reordering() {
496        let ty = Type::record([("red", Type::S32), ("green", Type::CHAR)]).unwrap();
497        // Parse the fields in the order they appear in the type.
498        assert_eq!(
499            parse_value("{red: 0, green: 'a'}", &ty),
500            Value::make_record(
501                &ty,
502                [
503                    ("red", Value::make_s32(0)),
504                    ("green", Value::make_char('a'))
505                ]
506            )
507            .unwrap()
508        );
509        // Parse the fields in reverse order.
510        assert_eq!(
511            parse_value("{green: 'a', red: 0}", &ty),
512            Value::make_record(
513                &ty,
514                [
515                    ("red", Value::make_s32(0)),
516                    ("green", Value::make_char('a'))
517                ]
518            )
519            .unwrap()
520        );
521    }
522
523    #[test]
524    fn parse_record_with_optional_fields() {
525        let field_ty = Type::option(Type::CHAR);
526        let ty = Type::record([("red", Type::S32), ("green", field_ty.clone())]).unwrap();
527        // Explicit `some`.
528        assert_eq!(
529            parse_value("{red: 0, green: some('a')}", &ty),
530            Value::make_record(
531                &ty,
532                [
533                    ("red", Value::make_s32(0)),
534                    (
535                        "green",
536                        Value::make_option(&field_ty, Some(Value::make_char('a'))).unwrap()
537                    )
538                ]
539            )
540            .unwrap()
541        );
542        // Flattened `some`.
543        assert_eq!(
544            parse_value("{red: 0, green: 'a'}", &ty),
545            Value::make_record(
546                &ty,
547                [
548                    ("red", Value::make_s32(0)),
549                    (
550                        "green",
551                        Value::make_option(&field_ty, Some(Value::make_char('a'))).unwrap()
552                    )
553                ]
554            )
555            .unwrap()
556        );
557        // Explicit `none`.
558        assert_eq!(
559            parse_value("{red: 0, green: none}", &ty),
560            Value::make_record(
561                &ty,
562                [
563                    ("red", Value::make_s32(0)),
564                    ("green", Value::make_option(&field_ty, None).unwrap())
565                ]
566            )
567            .unwrap()
568        );
569        // Implied `none`.
570        assert_eq!(
571            parse_value("{red: 0}", &ty),
572            Value::make_record(
573                &ty,
574                [
575                    ("red", Value::make_s32(0)),
576                    ("green", Value::make_option(&field_ty, None).unwrap())
577                ]
578            )
579            .unwrap()
580        );
581    }
582
583    #[test]
584    fn parse_flag_reordering() {
585        let ty = Type::flags(["hot", "cold"]).unwrap();
586        // Parse the flags in the order they appear in the type.
587        assert_eq!(
588            parse_value("{hot, cold}", &ty),
589            Value::make_flags(&ty, ["hot", "cold"]).unwrap()
590        );
591        // Parse the flags in reverse order.
592        assert_eq!(
593            parse_value("{cold, hot}", &ty),
594            Value::make_flags(&ty, ["hot", "cold"]).unwrap()
595        );
596    }
597
598    #[test]
599    fn parse_percent_identifiers() {
600        let ty = Type::record([
601            ("red", Type::S32),
602            ("green", Type::CHAR),
603            ("color-42-2A-5d", Type::BOOL),
604        ])
605        .unwrap();
606        // Test identifiers with '%' prefixes.
607        assert_eq!(
608            parse_value("{ %red: 0, %green: 'a', %color-42-2A-5d: true }", &ty),
609            Value::make_record(
610                &ty,
611                [
612                    ("red", Value::make_s32(0)),
613                    ("green", Value::make_char('a')),
614                    ("color-42-2A-5d", Value::make_bool(true))
615                ]
616            )
617            .unwrap()
618        );
619    }
620
621    #[test]
622    fn parse_prefixed_keyword_variant_cases() {
623        let ty = Type::list(
624            Type::variant([
625                ("true", Some(Type::U8)),
626                ("false", None),
627                ("inf", Some(Type::U8)),
628                ("nan", None),
629                ("some", Some(Type::U8)),
630                ("none", None),
631                ("ok", Some(Type::U8)),
632                ("err", None),
633            ])
634            .unwrap(),
635        );
636        parse_value(
637            "[%true(1), %false, %inf(1), %nan, %some(1), %none, %ok(1), %err]",
638            &ty,
639        );
640    }
641
642    #[test]
643    fn reject_unprefixed_keyword_enum_cases() {
644        let cases = ["true", "false", "inf", "nan", "none", "ok", "err"];
645        let ty = Type::enum_ty(cases).unwrap();
646        for case in cases {
647            let err = Parser::new(case).parse_value::<Value>(&ty).unwrap_err();
648            assert_eq!(err.kind(), ParserErrorKind::InvalidType);
649        }
650    }
651
652    #[test]
653    fn parse_unprefixed_keyword_fields() {
654        let ty = Type::record([
655            ("true", Type::U8),
656            ("false", Type::U8),
657            ("inf", Type::U8),
658            ("nan", Type::U8),
659            ("some", Type::U8),
660            ("none", Type::U8),
661            ("ok", Type::U8),
662            ("err", Type::U8),
663        ])
664        .unwrap();
665        parse_value(
666            "{true: 1, false: 1, inf: 1, nan: 1, some: 1, none: 1, ok: 1, err: 1}",
667            &ty,
668        );
669    }
670
671    #[test]
672    fn parse_unprefixed_keyword_flags() {
673        let ty = Type::flags(["true", "false", "inf", "nan", "some", "none", "ok", "err"]).unwrap();
674        parse_value("{true, false, inf, nan, some, none, ok, err}", &ty);
675    }
676
677    #[test]
678    fn reject_unprefixed_some_variant_case() {
679        let ty = Type::variant([("some", Some(Type::U8))]).unwrap();
680        let err = Parser::new("some(1)")
681            .parse_value::<Value>(&ty)
682            .unwrap_err();
683        assert_eq!(err.kind(), ParserErrorKind::InvalidType);
684    }
685
686    fn parse_value(input: &str, ty: &Type) -> Value {
687        Parser::new(input)
688            .parse_value(ty)
689            .unwrap_or_else(|err| panic!("error decoding {input:?}: {err}"))
690    }
691}