Skip to main content

parser/
pattern.rs

1use anyhow::{Result, anyhow};
2use dynamic::Dynamic;
3use smol_str::SmolStr;
4
5use super::{Parser, Span, Type, expr::Expr};
6
7#[derive(Debug, Clone)]
8pub struct Pattern {
9    pub kind: PatternKind,
10    pub span: Span,
11}
12
13#[derive(Debug, Clone)]
14pub enum PatternKind {
15    Wildcard,
16    Var { idx: u32, ty: Type },
17    Ident { name: SmolStr, ty: Type },
18    Literal(Dynamic),
19    Tuple(Vec<Pattern>),
20    List { elems: Vec<Pattern>, has_rest: bool },
21    Member(Box<Pattern>, SmolStr),
22    Idx(Box<Pattern>, Expr),
23}
24
25impl Pattern {
26    pub fn new(kind: PatternKind, span: Span) -> Self {
27        Self { kind, span }
28    }
29
30    pub fn var(&self) -> Option<u32> {
31        if let PatternKind::Var { idx, .. } = &self.kind { Some(*idx) } else { None }
32    }
33
34    pub fn expr(&self) -> Result<Expr> {
35        if let PatternKind::Var { idx, .. } = &self.kind { Ok(Expr::new(super::expr::ExprKind::Var(*idx), self.span)) } else { Err(anyhow!("不是变量")) }
36    }
37}
38
39impl Parser {
40    pub fn pattern(&mut self) -> Result<Pattern> {
41        self.whitespace()?;
42        let start = self.current_pos();
43        if self.just("_").is_ok() {
44            Ok(Pattern::new(PatternKind::Wildcard, self.span_from(start)))
45        } else if self.just("(").is_ok() {
46            Ok(Pattern::new(PatternKind::Tuple(crate::parse_list!(self, Vec::new(), b')', b',', self.pattern()?)), self.span_from(start)))
47        } else if self.just("[").is_ok() {
48            Ok(Pattern::new(PatternKind::List { elems: crate::parse_list!(self, Vec::new(), b']', b',', self.pattern()?), has_rest: false }, self.span_from(start)))
49        } else if let Ok(text) = self.string() {
50            Ok(Pattern::new(PatternKind::Literal(Dynamic::String(text)), self.span_from(start)))
51        } else if let Ok((name, ty)) = self.ident_typed() {
52            Ok(Pattern::new(PatternKind::Ident { name, ty }, self.span_from(start)))
53        } else {
54            Err(anyhow!("无效的模式 {:?}", String::from_utf8_lossy(&self.buf[self.pos..])))
55        }
56    }
57}