wasm_wave/
parser.rs

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