kb/
parser.rs

1use super::ast::*;
2use super::lexer::*;
3use super::ArgSpec;
4use super::ArithmeticBinop;
5use super::ArithmeticUnop;
6use super::BasicError;
7use super::Binop;
8use super::Mark;
9use super::RcStr;
10use super::Unop;
11use super::Val;
12use std::collections::HashSet;
13use std::rc::Rc;
14
15type Prec = i64;
16const CMP_PREC: Prec = 100;
17const ADD_PREC: Prec = 120;
18const MUL_PREC: Prec = 160;
19const UNARY_PREC: Prec = 200;
20const POSTFIX_PREC: Prec = 1000;
21
22const KEYWORDS: &[&'static str] = &[
23    "fn", "import", "var", "if", "elif", "else", "end", "is", "not", "and", "or", "in", "yield",
24    "assert", "true", "false", "to",
25    // --------------------- (mostly) legacy all-caps keywords -------------------------
26    "PRINT", "GOTO", "DIM", "LET", "IF", "ELSEIF", "ELSE", "END", "DO", "WHILE", "LOOP", "FUNCTION",
27    "TO", "DISASM", "LEN",
28    // NEXT has been changed from its original meaning
29    //     originally it was for denoting the end of a FOR loop
30    //     now it will instead resume a generator object
31    //       and return a [next-val-or-nil, has-next] pair
32    "NEXT",
33    // --------------------- special ops all-caps keywords -------------------------
34    "APPEND",
35];
36
37pub fn parse(source: &Rc<Source>) -> Result<File, BasicError> {
38    let toks = lex(source)?;
39    let keywords: HashSet<&'static str> = KEYWORDS.iter().map(|s| *s).collect();
40    let mut parser = Parser {
41        source: source.clone(),
42        toks,
43        i: 0,
44        keywords,
45    };
46    let file = parser.file()?;
47    Ok(file)
48}
49
50struct Parser<'a> {
51    source: Rc<Source>,
52    toks: Vec<(Token<'a>, Mark)>,
53    i: usize,
54    keywords: HashSet<&'static str>,
55}
56
57impl<'a> Parser<'a> {
58    fn peek(&self) -> &Token<'a> {
59        &self.toks[self.i].0
60    }
61    fn lookahead(&self, n: usize) -> Option<&Token<'a>> {
62        self.toks.get(self.i + n).map(|pair| &pair.0)
63    }
64    fn mark(&self) -> Mark {
65        self.toks[self.i].1.clone()
66    }
67    fn at<P: Into<Pat<'a>>>(&self, p: P) -> bool {
68        let p = p.into();
69        p.matches(self.peek())
70    }
71    fn gettok(&mut self) -> Token<'a> {
72        self.i += 1;
73        self.toks[self.i - 1].0.clone()
74    }
75    fn expect<'b, P: Into<Pat<'b>>>(&mut self, p: P) -> Result<Token<'a>, BasicError> {
76        let p = p.into();
77        if p.matches(self.peek()) {
78            Ok(self.gettok())
79        } else {
80            Err(BasicError {
81                marks: vec![self.mark()],
82                message: format!("Expected {:?} but got {:?}", p, self.peek()),
83                help: None,
84            })
85        }
86    }
87    fn expect_name(&mut self) -> Result<RcStr, BasicError> {
88        let mark = self.mark();
89        let token = self.expect(Pat::Name)?;
90        let name = token.name_or_keyword().unwrap();
91        if self.keywords.contains(&name) {
92            Err(BasicError {
93                marks: vec![mark],
94                message: format!("Expected name but got keyword"),
95                help: None,
96            })
97        } else {
98            Ok(name.to_owned().into())
99        }
100    }
101    fn expect_label(&mut self) -> Result<RcStr, BasicError> {
102        match self.peek() {
103            Token::Number(x) => {
104                let x = *x;
105                self.gettok();
106                Ok(format!("{}", x).into())
107            }
108            Token::Name(_) => {
109                let name = self.expect_name()?;
110                Ok(name)
111            }
112            _ => Err(BasicError::new(
113                vec![self.mark()],
114                format!("Expected label but got {:?}", self.peek()),
115            )),
116        }
117    }
118    fn consume<P: Into<Pat<'a>>>(&mut self, p: P) -> bool {
119        if self.at(p) {
120            self.gettok();
121            true
122        } else {
123            false
124        }
125    }
126}
127
128impl<'a> Parser<'a> {
129    fn file(&mut self) -> Result<File, BasicError> {
130        let mark = self.mark();
131        let mut imports = Vec::new();
132        let mut funcs = Vec::new();
133        let mut stmts = Vec::new();
134        self.consume_delim();
135        while !self.at(Token::EOF) {
136            match self.peek() {
137                Token::Name("import") => imports.push(self.import_()?),
138                Token::Name("fn") | Token::Name("FUNCTION") | Token::Name("SUB") => {
139                    funcs.push(self.func()?)
140                }
141                _ => stmts.extend(self.maybe_labeled_stmt()?),
142            }
143            self.delim()?;
144        }
145        Ok(File {
146            source: self.source.clone(),
147            imports,
148            funcs,
149            body: Stmt {
150                mark,
151                desc: StmtDesc::Block(stmts),
152            },
153            vars: vec![],
154        })
155    }
156    fn import_(&mut self) -> Result<Import, BasicError> {
157        let mark = self.mark();
158        self.expect(Token::Name("import"))?;
159        let mut module_name = self.expect_name()?;
160        let mut last_part = module_name.clone();
161        while self.consume(Token::Dot) {
162            last_part = self.expect_name()?;
163            module_name = format!("{}.{}", module_name, last_part).into();
164        }
165        if self.consume(Token::Name("as")) {
166            last_part = self.expect_name()?;
167        }
168        Ok(Import {
169            mark,
170            module_name,
171            alias: last_part,
172            unique_name: "".to_owned().into(),
173        })
174    }
175    fn at_end(&mut self) -> bool {
176        self.at(Token::Name("end")) || self.at(Token::Name("END"))
177    }
178    fn at_elif(&mut self) -> bool {
179        self.at(Token::Name("elif")) || self.at(Token::Name("ELSEIF"))
180    }
181    fn at_else(&mut self) -> bool {
182        self.at(Token::Name("else")) || self.at(Token::Name("ELSE"))
183    }
184    fn expect_end(&mut self) -> Result<(), BasicError> {
185        if !self.consume(Token::Name("END")) {
186            self.expect(Token::Name("end"))?;
187        }
188        Ok(())
189    }
190    fn consume_elif(&mut self) -> bool {
191        self.consume(Token::Name("elif")) || self.consume(Token::Name("ELSEIF"))
192    }
193    fn consume_else(&mut self) -> bool {
194        self.consume(Token::Name("else")) || self.consume(Token::Name("ELSE"))
195    }
196    fn func(&mut self) -> Result<FuncDisplay, BasicError> {
197        let mark = self.mark();
198        if !self.consume(Token::Name("FUNCTION")) && !self.consume(Token::Name("SUB")) {
199            self.expect(Token::Name("fn"))?;
200        }
201        let generator = self.consume(Token::Star);
202        let test = if self.consume(Token::LBracket) {
203            let test = self.consume(Token::Name("test"));
204            self.expect(Token::RBracket)?;
205            test
206        } else {
207            false
208        };
209        let name = self.expect_name()?;
210        let argspec = if self.consume(Token::LParen) {
211            let mut req = Vec::new();
212            let mut def = Vec::new();
213            let mut var = None;
214            'fin: loop {
215                // required parameters
216                while self.at(Pat::Name) && self.lookahead(1) != Some(&Token::Eq) {
217                    req.push(self.expect_name()?);
218
219                    // no comma => parameter spec is done
220                    if !self.consume(Token::Comma) {
221                        self.expect(Token::RParen)?;
222                        break 'fin;
223                    }
224                }
225
226                // default parameters
227                while self.at(Pat::Name) {
228                    let name = self.expect_name()?;
229                    self.expect(Token::Eq)?;
230                    let val = self.constexpr()?;
231                    def.push((name, val));
232
233                    // no comma => parameter spec is done
234                    if !self.consume(Token::Comma) {
235                        self.expect(Token::RParen)?;
236                        break 'fin;
237                    }
238                }
239
240                // variadic parameter
241                if self.consume(Token::Star) {
242                    var = Some(self.expect_name()?);
243                }
244
245                self.consume(Token::Comma);
246                self.expect(Token::RParen)?;
247                break;
248            }
249            ArgSpec { req, def, var }
250        } else {
251            ArgSpec::empty()
252        };
253        let body = if self.consume(Token::Eq) {
254            Stmt {
255                mark: mark.clone(),
256                desc: StmtDesc::Return(Some(self.expr(0)?)),
257            }
258        } else {
259            self.block()?
260        };
261        Ok(FuncDisplay {
262            mark,
263            generator,
264            test,
265            short_name: name,
266            argspec,
267            body,
268            vars: vec![],
269            as_var: None,
270        })
271    }
272    fn block(&mut self) -> Result<Stmt, BasicError> {
273        let block = self.block_body()?;
274        self.expect_end()?;
275        Ok(block)
276    }
277    fn block_body(&mut self) -> Result<Stmt, BasicError> {
278        let mark = self.mark();
279        let mut stmts = Vec::new();
280        self.consume_delim();
281        while !self.at_end() && !self.at_elif() && !self.at_else() {
282            let new_stmts = self.maybe_labeled_stmt()?;
283            self.delim()?;
284            stmts.extend(new_stmts);
285        }
286        Ok(Stmt {
287            mark,
288            desc: StmtDesc::Block(stmts),
289        })
290    }
291    fn maybe_labeled_stmt(&mut self) -> Result<Vec<Stmt>, BasicError> {
292        let mut ret = Vec::new();
293
294        // check for
295        //   <label-name> :
296        // style labels
297        match self.peek() {
298            Token::Name(name)
299                if !self.keywords.contains(name) && self.lookahead(1) == Some(&Token::Colon) =>
300            {
301                let mark = self.mark();
302                let label = self.expect_label()?;
303                self.expect(Token::Colon)?;
304                self.consume_delim();
305                ret.push(Stmt {
306                    mark,
307                    desc: StmtDesc::Label(label),
308                })
309            }
310            _ => {}
311        }
312
313        // check for line number labels
314        // we check to see if a Number is immediately followed
315        // by a Name (keyword or otherwise) or open parentheses
316        // if this is not the case, we assume there is no line number
317        if self.peek().number().is_some()
318            && self
319                .lookahead(1)
320                .map(|t| t.name_or_keyword().is_some() || t == &Token::LParen)
321                .unwrap_or(false)
322        {
323            let mark = self.mark();
324            let label = self.expect_label()?;
325            ret.push(Stmt {
326                mark,
327                desc: StmtDesc::Label(label),
328            });
329        }
330
331        ret.push(self.stmt()?);
332
333        Ok(ret)
334    }
335    fn stmt(&mut self) -> Result<Stmt, BasicError> {
336        let mark = self.mark();
337        match self.peek() {
338            Token::Name("PRINT") => {
339                self.gettok();
340                let arg = self.expr(0)?;
341                Ok(Stmt {
342                    mark,
343                    desc: StmtDesc::Print(arg.into()),
344                })
345            }
346            Token::Name("GOTO") => {
347                self.gettok();
348                let label = self.expect_label()?;
349                Ok(Stmt {
350                    mark,
351                    desc: StmtDesc::Goto(label),
352                })
353            }
354            Token::Name("var") | Token::Name("DIM") | Token::Name("LET") => {
355                self.gettok();
356                let lhs = self.expr(0)?;
357                self.expect(Token::Eq)?;
358                self.rhs_assignment(mark, lhs)
359            }
360            Token::Name("if") | Token::Name("IF") => {
361                self.gettok();
362                let mut pairs = Vec::new();
363                let mut other = None;
364                loop {
365                    let cond = self.expr(0)?;
366                    self.delim()?;
367                    let body = self.block_body()?;
368                    pairs.push((cond, body));
369                    if !self.consume_elif() {
370                        if self.consume_else() {
371                            self.delim()?;
372                            other = Some(self.block_body()?.into());
373                        }
374                        self.expect_end()?;
375                        break;
376                    }
377                }
378                Ok(Stmt {
379                    mark,
380                    desc: StmtDesc::If(pairs, other),
381                })
382            }
383            Token::Name("while") => {
384                self.gettok();
385                let cond = self.expr(0)?;
386                self.delim()?;
387                let body = self.block()?;
388                Ok(Stmt {
389                    mark,
390                    desc: StmtDesc::While(cond, body.into()),
391                })
392            }
393            Token::Name("for") => {
394                self.gettok();
395                let target = expr_to_assign_target(self.expr(0)?)?;
396                if self.consume(Token::Name("in")) {
397                    let container = self.expr(0)?;
398                    self.delim()?;
399                    let body = self.block()?;
400                    Ok(Stmt {
401                        mark,
402                        desc: StmtDesc::ForIn(target, container, body.into()),
403                    })
404                } else {
405                    self.expect(Token::Eq)?;
406                    let start = self.expr(0)?;
407                    let inclusive =
408                        if self.consume(Token::Name("TO")) || self.consume(Token::Name("to")) {
409                            true
410                        } else {
411                            self.expect(Token::Dot2)?;
412                            false
413                        };
414                    let end = self.expr(0)?;
415                    let step =
416                        if self.consume(Token::Name("STEP")) || self.consume(Token::Name("step")) {
417                            self.constexpr_number()?
418                        } else {
419                            1.0
420                        };
421                    self.delim()?;
422                    let body = self.block()?;
423                    Ok(Stmt {
424                        mark,
425                        desc: StmtDesc::ForClassic(
426                            target,
427                            start,
428                            end,
429                            inclusive,
430                            step,
431                            body.into(),
432                        ),
433                    })
434                }
435            }
436            Token::Name("assert") => {
437                self.gettok();
438                let cond = self.expr(0)?;
439                Ok(Stmt {
440                    mark,
441                    desc: StmtDesc::Assert(cond),
442                })
443            }
444            Token::Name(name)
445                if !self.keywords.contains(name) && self.lookahead(1) == Some(&Token::Colon) =>
446            {
447                let label = self.expect_label()?;
448                self.expect(Token::Colon)?;
449                Ok(Stmt {
450                    mark,
451                    desc: StmtDesc::Label(label),
452                })
453            }
454            _ => {
455                let expr = self.expr(0)?;
456                if self.consume(Token::Eq) {
457                    self.rhs_assignment(mark, expr)
458                } else {
459                    Ok(Stmt {
460                        mark,
461                        desc: StmtDesc::Expr(expr),
462                    })
463                }
464            }
465        }
466    }
467    fn rhs_assignment(&mut self, mark: Mark, lhs: Expr) -> Result<Stmt, BasicError> {
468        let mut exprs = vec![lhs, self.expr(0)?];
469        while self.consume(Token::Eq) {
470            exprs.push(self.expr(0)?);
471        }
472
473        let target = expr_to_assign_target(exprs.remove(0))?;
474        let rhs = exprs.pop().unwrap();
475        let mut other_targets = Vec::new();
476        for expr in exprs {
477            other_targets.push(expr_to_assign_target(expr)?);
478        }
479
480        Ok(Stmt {
481            mark,
482            desc: StmtDesc::Assign(target, other_targets, rhs.into()),
483        })
484    }
485    fn constexpr(&mut self) -> Result<Val, BasicError> {
486        let expr = self.expr(0)?;
487        let mark = expr.mark;
488        match expr.desc {
489            ExprDesc::Nil => Ok(Val::Nil),
490            ExprDesc::Bool(b) => Ok(Val::Bool(b)),
491            ExprDesc::Number(x) => Ok(Val::Number(x)),
492            ExprDesc::String(x) => Ok(Val::String(x)),
493            _ => Err(BasicError {
494                marks: vec![mark],
495                message: format!("Expected a constant expression here"),
496                help: None,
497            }),
498        }
499    }
500    fn constexpr_number(&mut self) -> Result<f64, BasicError> {
501        let mark = self.mark();
502        match self.constexpr()? {
503            Val::Number(x) => Ok(x),
504            _ => Err(BasicError {
505                marks: vec![mark],
506                message: format!("Expected a constant number here"),
507                help: None,
508            }),
509        }
510    }
511    fn expr(&mut self, prec: Prec) -> Result<Expr, BasicError> {
512        let mut e = self.atom()?;
513        while precof(self.peek()) >= prec {
514            e = self.infix(e)?;
515        }
516        Ok(e)
517    }
518    fn infix(&mut self, e: Expr) -> Result<Expr, BasicError> {
519        let mark = self.mark();
520        let token = self.gettok();
521        match token {
522            Token::Dot => {
523                let attr = self.expect_name()?;
524                Ok(Expr {
525                    mark,
526                    desc: ExprDesc::GetAttr(e.into(), attr),
527                })
528            }
529            Token::LParen => {
530                let mut args = Vec::new();
531                while !self.consume(Token::RParen) {
532                    args.push(self.expr(0)?);
533                    if !self.consume(Token::Comma) {
534                        self.expect(Token::RParen)?;
535                        break;
536                    }
537                }
538                Ok(Expr {
539                    mark,
540                    desc: ExprDesc::CallFunc(e.into(), args),
541                })
542            }
543            Token::Plus
544            | Token::Minus
545            | Token::Star
546            | Token::Slash
547            | Token::Slash2
548            | Token::Percent
549            | Token::Eq2
550            | Token::Ne
551            | Token::LessThan
552            | Token::LessThanOrEqual
553            | Token::GreaterThan
554            | Token::GreaterThanOrEqual => {
555                let op = match token {
556                    Token::Plus => Binop::Arithmetic(ArithmeticBinop::Add),
557                    Token::Minus => Binop::Arithmetic(ArithmeticBinop::Subtract),
558                    Token::Star => Binop::Arithmetic(ArithmeticBinop::Multiply),
559                    Token::Slash => Binop::Arithmetic(ArithmeticBinop::Divide),
560                    Token::Slash2 => Binop::Arithmetic(ArithmeticBinop::TruncDivide),
561                    Token::Percent => Binop::Arithmetic(ArithmeticBinop::Remainder),
562                    Token::Eq2 => Binop::Equal,
563                    Token::Ne => Binop::NotEqual,
564                    Token::LessThan => Binop::LessThan,
565                    Token::LessThanOrEqual => Binop::LessThanOrEqual,
566                    Token::GreaterThan => Binop::GreaterThan,
567                    Token::GreaterThanOrEqual => Binop::GreaterThanOrEqual,
568                    _ => panic!("binop {:?}", token),
569                };
570                let prec = precof(&token);
571                let rhs = self.expr(prec + 1)?;
572                Ok(Expr {
573                    mark,
574                    desc: ExprDesc::Binop(op, e.into(), rhs.into()),
575                })
576            }
577            _ => Err(BasicError {
578                marks: vec![mark],
579                message: format!("Expected infix operator"),
580                help: None,
581            }),
582        }
583    }
584    fn atom(&mut self) -> Result<Expr, BasicError> {
585        let mark = self.mark();
586        match self.peek() {
587            Token::LParen => {
588                self.gettok();
589                let expr = self.expr(0)?;
590                self.expect(Token::RParen)?;
591                Ok(expr)
592            }
593            Token::Number(x) => {
594                let x = *x;
595                self.gettok();
596                Ok(Expr {
597                    mark,
598                    desc: ExprDesc::Number(x),
599                })
600            }
601            Token::String(_) => {
602                let s = self.gettok().string().unwrap();
603                Ok(Expr {
604                    mark,
605                    desc: ExprDesc::String(s.into()),
606                })
607            }
608            Token::RawString(s) => {
609                let desc = ExprDesc::String((*s).into());
610                self.gettok();
611                Ok(Expr { mark, desc })
612            }
613            Token::LBracket => {
614                self.gettok();
615                let mut exprs = Vec::new();
616                while !self.consume(Token::RBracket) {
617                    exprs.push(self.expr(0)?);
618                    if !self.consume(Token::Comma) {
619                        self.expect(Token::RBracket)?;
620                        break;
621                    }
622                }
623                Ok(Expr {
624                    mark,
625                    desc: ExprDesc::List(exprs),
626                })
627            }
628            Token::Minus | Token::Plus => {
629                let tok = self.gettok();
630                let op = match tok {
631                    Token::Minus => Unop::Arithmetic(ArithmeticUnop::Negative),
632                    Token::Plus => Unop::Arithmetic(ArithmeticUnop::Positive),
633                    _ => panic!("parse unop: {:?}", tok),
634                };
635                let expr = self.expr(UNARY_PREC)?;
636                Ok(Expr {
637                    mark,
638                    desc: ExprDesc::Unop(op, expr.into()),
639                })
640            }
641            Token::Name("nil") => {
642                self.gettok();
643                Ok(Expr {
644                    mark,
645                    desc: ExprDesc::Nil,
646                })
647            }
648            Token::Name("true") => {
649                self.gettok();
650                Ok(Expr {
651                    mark,
652                    desc: ExprDesc::Bool(true),
653                })
654            }
655            Token::Name("false") => {
656                self.gettok();
657                Ok(Expr {
658                    mark,
659                    desc: ExprDesc::Bool(false),
660                })
661            }
662            Token::Name("yield") => {
663                self.gettok();
664                let yieldexpr = self.expr(0)?;
665                Ok(Expr {
666                    mark,
667                    desc: ExprDesc::Yield(yieldexpr.into()),
668                })
669            }
670            Token::Name("NEXT") => {
671                self.gettok();
672                self.expect(Token::LParen)?;
673                let genexpr = self.expr(0)?;
674                self.consume(Token::Comma);
675                self.expect(Token::RParen)?;
676                Ok(Expr {
677                    mark,
678                    desc: ExprDesc::Next(genexpr.into()),
679                })
680            }
681            Token::Name("DISASM") => {
682                self.gettok();
683                self.expect(Token::LParen)?;
684                let fexpr = self.expr(0)?;
685                self.consume(Token::Comma);
686                self.expect(Token::RParen)?;
687                Ok(Expr {
688                    mark,
689                    desc: ExprDesc::Disasm(fexpr.into()),
690                })
691            }
692            Token::Name("APPEND") => {
693                self.gettok();
694                self.expect(Token::LParen)?;
695                let listexpr = self.expr(0)?;
696                self.expect(Token::Comma)?;
697                let itemexpr = self.expr(0)?;
698                self.consume(Token::Comma);
699                self.expect(Token::RParen)?;
700                Ok(Expr {
701                    mark,
702                    desc: ExprDesc::Binop(Binop::Append, listexpr.into(), itemexpr.into()),
703                })
704            }
705            Token::Name("LEN") => {
706                self.gettok();
707                self.expect(Token::LParen)?;
708                let expr = self.expr(0)?;
709                self.consume(Token::Comma);
710                self.expect(Token::RParen)?;
711                Ok(Expr {
712                    mark,
713                    desc: ExprDesc::Unop(Unop::Len, expr.into()),
714                })
715            }
716            Token::Name(name) if !self.keywords.contains(name) => {
717                let name = self.expect_name()?;
718                Ok(Expr {
719                    mark,
720                    desc: ExprDesc::GetVar(name),
721                })
722            }
723            Token::Name(name) if self.keywords.contains(name) => Err(BasicError {
724                marks: vec![mark],
725                message: format!("Expected expression but got keyword {:?}", name),
726                help: None,
727            }),
728            _ => Err(BasicError {
729                marks: vec![mark],
730                message: format!("Expected expression but got {:?}", self.peek()),
731                help: None,
732            }),
733        }
734    }
735    fn consume_delim(&mut self) {
736        while self.at(Token::Newline) || self.at(Token::Semicolon) {
737            self.gettok();
738        }
739    }
740    fn at_delim(&self) -> bool {
741        match self.peek() {
742            Token::Name("end") | Token::EOF | Token::Semicolon | Token::Newline => true,
743            _ => false,
744        }
745    }
746    fn delim(&mut self) -> Result<(), BasicError> {
747        if self.at_delim() {
748            self.consume_delim();
749            Ok(())
750        } else {
751            Err(BasicError {
752                marks: vec![self.mark()],
753                message: format!("Expected delimiter but got {:?}", self.peek()),
754                help: None,
755            })
756        }
757    }
758}
759
760fn expr_to_assign_target(expr: Expr) -> Result<AssignTarget, BasicError> {
761    match expr.desc {
762        ExprDesc::GetVar(name) => Ok(AssignTarget {
763            mark: expr.mark,
764            desc: AssignTargetDesc::Name(name),
765        }),
766        ExprDesc::List(exprs) => {
767            let mut targets = Vec::new();
768            for expr in exprs {
769                targets.push(expr_to_assign_target(expr)?);
770            }
771            Ok(AssignTarget {
772                mark: expr.mark,
773                desc: AssignTargetDesc::List(targets),
774            })
775        }
776        _ => Err(BasicError {
777            marks: vec![expr.mark],
778            message: format!("The left hand side is not assignable"),
779            help: Some(
780                concat!(
781                    "An assignable expression is either a name or a list of other assignable ",
782                    "expressions. For example, 'x' or '[a, b, [x, y]]'",
783                )
784                .into(),
785            ),
786        }),
787    }
788}
789
790fn precof<'a>(tok: &Token<'a>) -> Prec {
791    match tok {
792        Token::Name("is")
793        | Token::Eq2
794        | Token::Ne
795        | Token::LessThan
796        | Token::LessThanOrEqual
797        | Token::GreaterThan
798        | Token::GreaterThanOrEqual => CMP_PREC,
799        Token::Minus | Token::Plus => ADD_PREC,
800        Token::Star | Token::Slash | Token::Slash2 | Token::Percent => MUL_PREC,
801        Token::LParen | Token::Dot => POSTFIX_PREC,
802        _ => -1,
803    }
804}
805
806#[derive(Debug, Clone)]
807enum Pat<'a> {
808    Exact(Token<'a>),
809    Keyword(&'a str),
810    Name,
811}
812
813impl<'a> Pat<'a> {
814    fn matches<'b>(&self, tok: &Token<'b>) -> bool {
815        match self {
816            Pat::Exact(t) => t == tok,
817            Pat::Keyword(t) => match tok {
818                Token::Name(name) => t == name,
819                _ => false,
820            },
821            Pat::Name => match tok {
822                Token::Name(_) => true,
823                _ => false,
824            },
825        }
826    }
827}
828
829impl<'a> From<Token<'a>> for Pat<'a> {
830    fn from(t: Token<'a>) -> Pat<'a> {
831        Pat::Exact(t)
832    }
833}
834
835impl<'a> From<&'a str> for Pat<'a> {
836    fn from(s: &'a str) -> Pat<'a> {
837        Pat::Keyword(s)
838    }
839}