wasmer_wit_parser/
ast.rs

1use anyhow::Result;
2use lex::{Span, Token, Tokenizer};
3use std::borrow::Cow;
4use std::collections::HashMap;
5use std::convert::TryFrom;
6use std::fmt;
7
8mod lex;
9mod resolve;
10
11pub use lex::validate_id;
12
13pub struct Ast<'a> {
14    pub items: Vec<Item<'a>>,
15}
16
17pub enum Item<'a> {
18    Use(Use<'a>),
19    Resource(Resource<'a>),
20    TypeDef(TypeDef<'a>),
21    Value(Value<'a>),
22    Interface(Interface<'a>),
23}
24
25pub struct Id<'a> {
26    pub name: Cow<'a, str>,
27    pub span: Span,
28}
29
30impl<'a> From<&'a str> for Id<'a> {
31    fn from(s: &'a str) -> Id<'a> {
32        Id {
33            name: s.into(),
34            span: Span { start: 0, end: 0 },
35        }
36    }
37}
38
39impl<'a> From<String> for Id<'a> {
40    fn from(s: String) -> Id<'a> {
41        Id {
42            name: s.into(),
43            span: Span { start: 0, end: 0 },
44        }
45    }
46}
47
48pub struct Use<'a> {
49    pub from: Vec<Id<'a>>,
50    names: Option<Vec<UseName<'a>>>,
51}
52
53struct UseName<'a> {
54    name: Id<'a>,
55    as_: Option<Id<'a>>,
56}
57
58pub struct Resource<'a> {
59    docs: Docs<'a>,
60    name: Id<'a>,
61    supertype: Option<Id<'a>>,
62    values: Vec<(bool, Value<'a>)>,
63}
64
65#[derive(Default)]
66struct Docs<'a> {
67    docs: Vec<Cow<'a, str>>,
68}
69
70pub struct TypeDef<'a> {
71    docs: Docs<'a>,
72    name: Id<'a>,
73    ty: Type<'a>,
74}
75
76enum Type<'a> {
77    Unit,
78    Bool,
79    U8,
80    U16,
81    U32,
82    U64,
83    S8,
84    S16,
85    S32,
86    S64,
87    Float32,
88    Float64,
89    Char,
90    String,
91    Handle(Id<'a>),
92    Name(Id<'a>),
93    List(Box<Type<'a>>),
94    Record(Record<'a>),
95    Flags(Flags<'a>),
96    Variant(Variant<'a>),
97    Tuple(Vec<Type<'a>>),
98    Enum(Enum<'a>),
99    Option(Box<Type<'a>>),
100    Expected(Expected<'a>),
101    Future(Box<Type<'a>>),
102    Stream(Stream<'a>),
103    Union(Union<'a>),
104}
105
106struct Record<'a> {
107    fields: Vec<Field<'a>>,
108}
109
110struct Field<'a> {
111    docs: Docs<'a>,
112    name: Id<'a>,
113    ty: Type<'a>,
114}
115
116struct Flags<'a> {
117    flags: Vec<Flag<'a>>,
118}
119
120struct Flag<'a> {
121    docs: Docs<'a>,
122    name: Id<'a>,
123}
124
125struct Variant<'a> {
126    span: Span,
127    cases: Vec<Case<'a>>,
128}
129
130struct Case<'a> {
131    docs: Docs<'a>,
132    name: Id<'a>,
133    ty: Option<Type<'a>>,
134}
135
136struct Enum<'a> {
137    span: Span,
138    cases: Vec<EnumCase<'a>>,
139}
140
141struct EnumCase<'a> {
142    docs: Docs<'a>,
143    name: Id<'a>,
144}
145
146struct Expected<'a> {
147    ok: Box<Type<'a>>,
148    err: Box<Type<'a>>,
149}
150
151struct Stream<'a> {
152    element: Box<Type<'a>>,
153    end: Box<Type<'a>>,
154}
155
156pub struct Value<'a> {
157    docs: Docs<'a>,
158    name: Id<'a>,
159    kind: ValueKind<'a>,
160}
161
162struct Union<'a> {
163    span: Span,
164    cases: Vec<UnionCase<'a>>,
165}
166
167struct UnionCase<'a> {
168    docs: Docs<'a>,
169    ty: Type<'a>,
170}
171
172enum ValueKind<'a> {
173    Function {
174        is_async: bool,
175        params: Vec<(Id<'a>, Type<'a>)>,
176        result: Type<'a>,
177    },
178    Global(Type<'a>),
179}
180
181#[allow(dead_code)] // TODO
182pub struct Interface<'a> {
183    docs: Docs<'a>,
184    name: Id<'a>,
185    items: Vec<Item<'a>>,
186}
187
188impl<'a> Ast<'a> {
189    pub fn parse(input: &'a str) -> Result<Ast<'a>> {
190        let mut lexer = Tokenizer::new(input)?;
191        let mut items = Vec::new();
192        while lexer.clone().next()?.is_some() {
193            let docs = parse_docs(&mut lexer)?;
194            items.push(Item::parse(&mut lexer, docs)?);
195        }
196        Ok(Ast { items })
197    }
198
199    pub fn resolve(
200        &self,
201        name: &str,
202        map: &HashMap<String, crate::Interface>,
203    ) -> Result<crate::Interface> {
204        let mut resolver = resolve::Resolver::default();
205        let instance = resolver.resolve(name, &self.items, map)?;
206        Ok(instance)
207    }
208}
209
210impl<'a> Item<'a> {
211    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Item<'a>> {
212        match tokens.clone().next()? {
213            Some((_span, Token::Use)) => Use::parse(tokens, docs).map(Item::Use),
214            Some((_span, Token::Type)) => TypeDef::parse(tokens, docs).map(Item::TypeDef),
215            Some((_span, Token::Flags)) => TypeDef::parse_flags(tokens, docs).map(Item::TypeDef),
216            Some((_span, Token::Enum)) => TypeDef::parse_enum(tokens, docs).map(Item::TypeDef),
217            Some((_span, Token::Variant)) => {
218                TypeDef::parse_variant(tokens, docs).map(Item::TypeDef)
219            }
220            Some((_span, Token::Record)) => TypeDef::parse_record(tokens, docs).map(Item::TypeDef),
221            Some((_span, Token::Union)) => TypeDef::parse_union(tokens, docs).map(Item::TypeDef),
222            Some((_span, Token::Resource)) => Resource::parse(tokens, docs).map(Item::Resource),
223            Some((_span, Token::Interface)) => Interface::parse(tokens, docs).map(Item::Interface),
224            Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
225                Value::parse(tokens, docs).map(Item::Value)
226            }
227            other => Err(err_expected(tokens, "`type`, `resource`, or `func`", other).into()),
228        }
229    }
230}
231
232impl<'a> Use<'a> {
233    fn parse(tokens: &mut Tokenizer<'a>, _docs: Docs<'a>) -> Result<Self> {
234        tokens.expect(Token::Use)?;
235        let mut names = None;
236        loop {
237            if names.is_none() {
238                if tokens.eat(Token::Star)? {
239                    break;
240                }
241                tokens.expect(Token::LeftBrace)?;
242                names = Some(Vec::new());
243            }
244            let names = names.as_mut().unwrap();
245            let mut name = UseName {
246                name: parse_id(tokens)?,
247                as_: None,
248            };
249            if tokens.eat(Token::As)? {
250                name.as_ = Some(parse_id(tokens)?);
251            }
252            names.push(name);
253            if !tokens.eat(Token::Comma)? {
254                break;
255            }
256        }
257        if names.is_some() {
258            tokens.expect(Token::RightBrace)?;
259        }
260        tokens.expect(Token::From_)?;
261        let mut from = vec![parse_id(tokens)?];
262        while tokens.eat(Token::Colon)? {
263            tokens.expect_raw(Token::Colon)?;
264            from.push(parse_id(tokens)?);
265        }
266        Ok(Use { from, names })
267    }
268}
269
270impl<'a> TypeDef<'a> {
271    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
272        tokens.expect(Token::Type)?;
273        let name = parse_id(tokens)?;
274        tokens.expect(Token::Equals)?;
275        let ty = Type::parse(tokens)?;
276        Ok(TypeDef { docs, name, ty })
277    }
278
279    fn parse_flags(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
280        tokens.expect(Token::Flags)?;
281        let name = parse_id(tokens)?;
282        let ty = Type::Flags(Flags {
283            flags: parse_list(
284                tokens,
285                Token::LeftBrace,
286                Token::RightBrace,
287                |docs, tokens| {
288                    let name = parse_id(tokens)?;
289                    Ok(Flag { docs, name })
290                },
291            )?,
292        });
293        Ok(TypeDef { docs, name, ty })
294    }
295
296    fn parse_record(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
297        tokens.expect(Token::Record)?;
298        let name = parse_id(tokens)?;
299        let ty = Type::Record(Record {
300            fields: parse_list(
301                tokens,
302                Token::LeftBrace,
303                Token::RightBrace,
304                |docs, tokens| {
305                    let name = parse_id(tokens)?;
306                    tokens.expect(Token::Colon)?;
307                    let ty = Type::parse(tokens)?;
308                    Ok(Field { docs, name, ty })
309                },
310            )?,
311        });
312        Ok(TypeDef { docs, name, ty })
313    }
314
315    fn parse_variant(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
316        tokens.expect(Token::Variant)?;
317        let name = parse_id(tokens)?;
318        let ty = Type::Variant(Variant {
319            span: name.span,
320            cases: parse_list(
321                tokens,
322                Token::LeftBrace,
323                Token::RightBrace,
324                |docs, tokens| {
325                    let name = parse_id(tokens)?;
326                    let ty = if tokens.eat(Token::LeftParen)? {
327                        let ty = Type::parse(tokens)?;
328                        tokens.expect(Token::RightParen)?;
329                        Some(ty)
330                    } else {
331                        None
332                    };
333                    Ok(Case { docs, name, ty })
334                },
335            )?,
336        });
337        Ok(TypeDef { docs, name, ty })
338    }
339
340    fn parse_union(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
341        tokens.expect(Token::Union)?;
342        let name = parse_id(tokens)?;
343        let ty = Type::Union(Union {
344            span: name.span,
345            cases: parse_list(
346                tokens,
347                Token::LeftBrace,
348                Token::RightBrace,
349                |docs, tokens| {
350                    let ty = Type::parse(tokens)?;
351                    Ok(UnionCase { docs, ty })
352                },
353            )?,
354        });
355        Ok(TypeDef { docs, name, ty })
356    }
357
358    fn parse_enum(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
359        tokens.expect(Token::Enum)?;
360        let name = parse_id(tokens)?;
361        let ty = Type::Enum(Enum {
362            span: name.span,
363            cases: parse_list(
364                tokens,
365                Token::LeftBrace,
366                Token::RightBrace,
367                |docs, tokens| {
368                    let name = parse_id(tokens)?;
369                    Ok(EnumCase { docs, name })
370                },
371            )?,
372        });
373        Ok(TypeDef { docs, name, ty })
374    }
375}
376
377impl<'a> Resource<'a> {
378    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
379        tokens.expect(Token::Resource)?;
380        let name = parse_id(tokens)?;
381        let supertype = if tokens.eat(Token::Implements)? {
382            Some(parse_id(tokens)?)
383        } else {
384            None
385        };
386        let mut values = Vec::new();
387        if tokens.eat(Token::LeftBrace)? {
388            loop {
389                let docs = parse_docs(tokens)?;
390                if tokens.eat(Token::RightBrace)? {
391                    break;
392                }
393                let statik = tokens.eat(Token::Static)?;
394                values.push((statik, Value::parse(tokens, docs)?));
395            }
396        }
397        Ok(Resource {
398            docs,
399            name,
400            supertype,
401            values,
402        })
403    }
404}
405
406impl<'a> Value<'a> {
407    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
408        let name = parse_id(tokens)?;
409        tokens.expect(Token::Colon)?;
410
411        let kind = if tokens.eat(Token::Func)? {
412            parse_func(tokens, false)?
413        } else if tokens.eat(Token::Async)? {
414            tokens.expect(Token::Func)?;
415            parse_func(tokens, true)?
416        } else {
417            ValueKind::Global(Type::parse(tokens)?)
418        };
419        return Ok(Value { docs, name, kind });
420
421        fn parse_func<'a>(tokens: &mut Tokenizer<'a>, is_async: bool) -> Result<ValueKind<'a>> {
422            let params = parse_list(
423                tokens,
424                Token::LeftParen,
425                Token::RightParen,
426                |_docs, tokens| {
427                    let name = parse_id(tokens)?;
428                    tokens.expect(Token::Colon)?;
429                    let ty = Type::parse(tokens)?;
430                    Ok((name, ty))
431                },
432            )?;
433            let result = if tokens.eat(Token::RArrow)? {
434                Type::parse(tokens)?
435            } else {
436                Type::Unit
437            };
438            Ok(ValueKind::Function {
439                is_async,
440                params,
441                result,
442            })
443        }
444    }
445}
446
447fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> Result<Id<'a>> {
448    match tokens.next()? {
449        Some((span, Token::Id)) => Ok(Id {
450            name: tokens.parse_id(span)?.into(),
451            span,
452        }),
453        Some((span, Token::ExplicitId)) => Ok(Id {
454            name: tokens.parse_explicit_id(span)?.into(),
455            span,
456        }),
457        other => Err(err_expected(tokens, "an identifier or string", other).into()),
458    }
459}
460
461fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>> {
462    let mut docs = Docs::default();
463    let mut clone = tokens.clone();
464    while let Some((span, token)) = clone.next_raw()? {
465        match token {
466            Token::Whitespace => {}
467            Token::Comment => docs.docs.push(tokens.get_span(span).into()),
468            _ => break,
469        };
470        *tokens = clone.clone();
471    }
472    Ok(docs)
473}
474
475impl<'a> Type<'a> {
476    fn parse(tokens: &mut Tokenizer<'a>) -> Result<Self> {
477        match tokens.next()? {
478            Some((_span, Token::U8)) => Ok(Type::U8),
479            Some((_span, Token::U16)) => Ok(Type::U16),
480            Some((_span, Token::U32)) => Ok(Type::U32),
481            Some((_span, Token::U64)) => Ok(Type::U64),
482            Some((_span, Token::S8)) => Ok(Type::S8),
483            Some((_span, Token::S16)) => Ok(Type::S16),
484            Some((_span, Token::S32)) => Ok(Type::S32),
485            Some((_span, Token::S64)) => Ok(Type::S64),
486            Some((_span, Token::Float32)) => Ok(Type::Float32),
487            Some((_span, Token::Float64)) => Ok(Type::Float64),
488            Some((_span, Token::Char)) => Ok(Type::Char),
489            Some((_span, Token::Handle)) => {
490                let name = parse_id(tokens)?;
491                Ok(Type::Handle(name))
492            }
493
494            // tuple<T, U, ...>
495            Some((_span, Token::Tuple)) => {
496                let types = parse_list(
497                    tokens,
498                    Token::LessThan,
499                    Token::GreaterThan,
500                    |_docs, tokens| Type::parse(tokens),
501                )?;
502                Ok(Type::Tuple(types))
503            }
504
505            Some((_span, Token::Unit)) => Ok(Type::Unit),
506            Some((_span, Token::Bool)) => Ok(Type::Bool),
507            Some((_span, Token::String_)) => Ok(Type::String),
508
509            // list<T>
510            Some((_span, Token::List)) => {
511                tokens.expect(Token::LessThan)?;
512                let ty = Type::parse(tokens)?;
513                tokens.expect(Token::GreaterThan)?;
514                Ok(Type::List(Box::new(ty)))
515            }
516
517            // option<T>
518            Some((_span, Token::Option_)) => {
519                tokens.expect(Token::LessThan)?;
520                let ty = Type::parse(tokens)?;
521                tokens.expect(Token::GreaterThan)?;
522                Ok(Type::Option(Box::new(ty)))
523            }
524
525            // expected<T, E>
526            Some((_span, Token::Expected)) => {
527                tokens.expect(Token::LessThan)?;
528                let ok = Box::new(Type::parse(tokens)?);
529                tokens.expect(Token::Comma)?;
530                let err = Box::new(Type::parse(tokens)?);
531                tokens.expect(Token::GreaterThan)?;
532                Ok(Type::Expected(Expected { ok, err }))
533            }
534
535            // future<T>
536            Some((_span, Token::Future)) => {
537                tokens.expect(Token::LessThan)?;
538                let ty = Box::new(Type::parse(tokens)?);
539                tokens.expect(Token::GreaterThan)?;
540                Ok(Type::Future(ty))
541            }
542
543            // stream<T, Z>
544            Some((_span, Token::Stream)) => {
545                tokens.expect(Token::LessThan)?;
546                let element = Box::new(Type::parse(tokens)?);
547                tokens.expect(Token::Comma)?;
548                let end = Box::new(Type::parse(tokens)?);
549                tokens.expect(Token::GreaterThan)?;
550                Ok(Type::Stream(Stream { element, end }))
551            }
552
553            // `foo`
554            Some((span, Token::Id)) => Ok(Type::Name(Id {
555                name: tokens.parse_id(span)?.into(),
556                span,
557            })),
558            // `@foo`
559            Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
560                name: tokens.parse_explicit_id(span)?.into(),
561                span,
562            })),
563
564            other => Err(err_expected(tokens, "a type", other).into()),
565        }
566    }
567}
568
569impl<'a> Interface<'a> {
570    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> Result<Self> {
571        tokens.expect(Token::Interface)?;
572        let name = parse_id(tokens)?;
573        tokens.expect(Token::LeftBrace)?;
574        let mut items = Vec::new();
575        loop {
576            let docs = parse_docs(tokens)?;
577            if tokens.eat(Token::RightBrace)? {
578                break;
579            }
580            items.push(Item::parse(tokens, docs)?);
581        }
582        Ok(Interface { docs, name, items })
583    }
584}
585
586fn parse_list<'a, T>(
587    tokens: &mut Tokenizer<'a>,
588    start: Token,
589    end: Token,
590    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> Result<T>,
591) -> Result<Vec<T>> {
592    tokens.expect(start)?;
593    let mut items = Vec::new();
594    loop {
595        // get docs before we skip them to try to eat the end token
596        let docs = parse_docs(tokens)?;
597
598        // if we found an end token then we're done
599        if tokens.eat(end)? {
600            break;
601        }
602
603        let item = parse(docs, tokens)?;
604        items.push(item);
605
606        // if there's no trailing comma then this is required to be the end,
607        // otherwise we go through the loop to try to get another item
608        if !tokens.eat(Token::Comma)? {
609            tokens.expect(end)?;
610            break;
611        }
612    }
613    Ok(items)
614}
615
616fn err_expected(
617    tokens: &Tokenizer<'_>,
618    expected: &'static str,
619    found: Option<(Span, Token)>,
620) -> Error {
621    match found {
622        Some((span, token)) => Error {
623            span,
624            msg: format!("expected {}, found {}", expected, token.describe()),
625        },
626        None => Error {
627            span: Span {
628                start: u32::try_from(tokens.input().len()).unwrap(),
629                end: u32::try_from(tokens.input().len()).unwrap(),
630            },
631            msg: format!("expected {}, found eof", expected),
632        },
633    }
634}
635
636#[derive(Debug)]
637struct Error {
638    span: Span,
639    msg: String,
640}
641
642impl fmt::Display for Error {
643    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644        self.msg.fmt(f)
645    }
646}
647
648impl std::error::Error for Error {}
649
650pub fn rewrite_error(err: &mut anyhow::Error, file: &str, contents: &str) {
651    let parse = match err.downcast_mut::<Error>() {
652        Some(err) => err,
653        None => return lex::rewrite_error(err, file, contents),
654    };
655    let msg = highlight_err(
656        parse.span.start as usize,
657        Some(parse.span.end as usize),
658        file,
659        contents,
660        &parse.msg,
661    );
662    *err = anyhow::anyhow!("{}", msg);
663}
664
665fn highlight_err(
666    start: usize,
667    end: Option<usize>,
668    file: &str,
669    input: &str,
670    err: impl fmt::Display,
671) -> String {
672    let (line, col) = linecol_in(start, input);
673    let snippet = input.lines().nth(line).unwrap_or("");
674    let mut msg = format!(
675        "\
676{err}
677     --> {file}:{line}:{col}
678      |
679 {line:4} | {snippet}
680      | {marker:>0$}",
681        col + 1,
682        file = file,
683        line = line + 1,
684        col = col + 1,
685        err = err,
686        snippet = snippet,
687        marker = "^",
688    );
689    if let Some(end) = end {
690        if let Some(s) = input.get(start..end) {
691            for _ in s.chars().skip(1) {
692                msg.push('-');
693            }
694        }
695    }
696    return msg;
697
698    fn linecol_in(pos: usize, text: &str) -> (usize, usize) {
699        let mut cur = 0;
700        // Use split_terminator instead of lines so that if there is a `\r`,
701        // it is included in the offset calculation. The `+1` values below
702        // account for the `\n`.
703        for (i, line) in text.split_terminator('\n').enumerate() {
704            if cur + line.len() + 1 > pos {
705                return (i, pos - cur);
706            }
707            cur += line.len() + 1;
708        }
709        (text.lines().count(), 0)
710    }
711}