1use 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
14pub struct Parser<'source> {
16 lex: Lexer<'source>,
17 curr: Option<Token>,
18}
19
20impl<'source> Parser<'source> {
21 pub fn new(source: &'source str) -> Self {
23 Self::with_lexer(Lexer::new(source))
24 }
25
26 pub fn with_lexer(lexer: Lexer<'source>) -> Self {
28 Self {
29 lex: lexer,
30 curr: None,
31 }
32 }
33
34 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 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 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 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 Token::Colon => {
125 self.advance()?; self.expect_token(Token::BraceClose)?;
127 return Ok(Node::new(NodeType::Record, start..self.span().end, []));
128 }
129 Token::BraceClose => return Ok(Node::new(NodeType::Flags, start..self.span().end, [])),
131 _ => (),
132 }
133
134 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 let label = self.parse_label()?;
148 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 self.advance()?;
159 self.expect_token(Token::Colon)?;
160 let value = self.parse_node()?;
162 children.extend([label, value]);
163 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 let label = self.parse_label()?;
183 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 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#[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 pub fn kind(&self) -> ParserErrorKind {
380 self.kind
381 }
382
383 pub fn span(&self) -> Span {
385 self.span.clone()
386 }
387
388 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#[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 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 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 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 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 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 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 assert_eq!(
582 parse_value("{hot, cold}", &ty),
583 Value::make_flags(&ty, ["hot", "cold"]).unwrap()
584 );
585 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 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}