Skip to main content

sequoia_seq/
parser.rs

1use crate::error::SeqError;
2use crate::ir::{
3    BinOp, CompParam, ComponentDef, DeferredDecl, DeferredKind, FnParam, ImportDecl, LengthVal,
4    MatchPat, SeqApp, SeqArg, SeqExpr, SeqExprKind, SeqFile, SeqFn, SeqMatchArm, SeqNode, SeqStmt,
5    SeqValue, SeqWindow, StateDecl, StyleDecl, ThemeName, UnOp, Visibility,
6};
7
8pub fn parse(file: &str, src: &str) -> Result<SeqApp, SeqError> {
9    let seq = parse_seq_file(file, src)?;
10    let mut app = seq
11        .app
12        .ok_or_else(|| SeqError::new(file, 1, 1, "brak bloku `app Nazwa { }`"))?;
13    app.components = seq.components;
14    app.imports = seq.imports;
15    Ok(app)
16}
17
18pub fn parse_seq_file(file: &str, src: &str) -> Result<SeqFile, SeqError> {
19    let mut p = Parser::new(file, src);
20    p.parse_seq_file()
21}
22
23const MAX_NESTING_DEPTH: usize = 256;
24
25fn is_single_value_expr(kind: &SeqExprKind) -> bool {
26    matches!(
27        kind,
28        SeqExprKind::Int(_)
29            | SeqExprKind::Float(_)
30            | SeqExprKind::Str(_)
31            | SeqExprKind::Bool(_)
32            | SeqExprKind::Var(_)
33            | SeqExprKind::Field { .. }
34            | SeqExprKind::Unary { .. }
35            | SeqExprKind::Call { .. }
36            | SeqExprKind::Array(_)
37    )
38}
39
40struct Parser<'a> {
41    file: &'a str,
42    chars: Vec<char>,
43    pos: usize,
44    line: usize,
45    col: usize,
46    depth: usize,
47}
48
49impl<'a> Parser<'a> {
50    fn new(file: &'a str, src: &str) -> Self {
51        Self {
52            file,
53            chars: src.chars().collect(),
54            pos: 0,
55            line: 1,
56            col: 1,
57            depth: 0,
58        }
59    }
60
61    fn err(&self, line: usize, col: usize, message: impl Into<String>) -> SeqError {
62        SeqError::new(self.file, line, col, message)
63    }
64
65    fn peek(&self) -> Option<char> {
66        self.chars.get(self.pos).copied()
67    }
68
69    fn bump(&mut self) -> Option<char> {
70        let c = self.chars.get(self.pos).copied()?;
71        self.pos += 1;
72        if c == '\n' {
73            self.line += 1;
74            self.col = 1;
75        } else {
76            self.col += 1;
77        }
78        Some(c)
79    }
80
81    fn skip_trivia(&mut self) {
82        loop {
83            match self.peek() {
84                Some(c) if c == ' ' || c == '\t' || c == '\r' || c == '\n' => {
85                    self.bump();
86                }
87                Some('/') if self.chars.get(self.pos + 1) == Some(&'/') => {
88                    while !matches!(self.peek(), None | Some('\n')) {
89                        self.bump();
90                    }
91                }
92                _ => break,
93            }
94        }
95    }
96
97    fn loc(&mut self) -> (usize, usize) {
98        self.skip_trivia();
99        (self.line, self.col)
100    }
101
102    fn eat(&mut self, c: char) -> bool {
103        self.skip_trivia();
104        if self.peek() == Some(c) {
105            self.bump();
106            true
107        } else {
108            false
109        }
110    }
111
112    fn expect(&mut self, c: char, what: &str) -> Result<(), SeqError> {
113        let (line, col) = self.loc();
114        if self.peek() == Some(c) {
115            self.bump();
116            Ok(())
117        } else {
118            Err(self.err(line, col, format!("oczekiwano {what}")))
119        }
120    }
121
122    fn ident(&mut self) -> Result<(String, usize, usize), SeqError> {
123        let (line, col) = self.loc();
124        let start = self.pos;
125        match self.peek() {
126            Some(c) if c.is_ascii_alphabetic() || c == '_' => {
127                self.bump();
128            }
129            _ => return Err(self.err(line, col, "oczekiwano identyfikatora")),
130        }
131        while matches!(self.peek(), Some(c) if c.is_ascii_alphanumeric() || c == '_') {
132            self.bump();
133        }
134        Ok((self.chars[start..self.pos].iter().collect(), line, col))
135    }
136
137    fn number(&mut self) -> Result<(f32, usize, usize), SeqError> {
138        let (line, col) = self.loc();
139        let start = self.pos;
140        if self.peek() == Some('-') {
141            self.bump();
142        }
143        let mut digits = 0;
144        while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
145            self.bump();
146            digits += 1;
147        }
148        if self.peek() == Some('.') {
149            self.bump();
150            while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
151                self.bump();
152                digits += 1;
153            }
154        }
155        if digits == 0 {
156            return Err(self.err(line, col, "oczekiwano liczby"));
157        }
158        let text: String = self.chars[start..self.pos].iter().collect();
159        text.parse::<f32>()
160            .map(|v| (v, line, col))
161            .map_err(|_| self.err(line, col, format!("bad number '{text}'")))
162    }
163
164    fn string(&mut self) -> Result<(String, usize, usize), SeqError> {
165        let (line, col) = self.loc();
166        if self.peek() != Some('"') {
167            return Err(self.err(line, col, "expected string in quotation marks"));
168        }
169        self.bump();
170        let mut out = String::new();
171        loop {
172            match self.bump() {
173                None => return Err(self.err(line, col, "unclosed string")),
174                Some('"') => break,
175                Some('\\') => match self.bump() {
176                    Some('"') => out.push('"'),
177                    Some('\\') => out.push('\\'),
178                    Some('n') => out.push('\n'),
179                    Some('t') => out.push('\t'),
180                    Some(c) => {
181                        return Err(self.err(self.line, self.col, format!("bad escape '\\{c}'")));
182                    }
183                    None => return Err(self.err(line, col, "unclosed string")),
184                },
185                Some(c) => out.push(c),
186            }
187        }
188        Ok((out, line, col))
189    }
190
191    fn color(&mut self) -> Result<(String, usize, usize), SeqError> {
192        let (line, col) = self.loc();
193        debug_assert_eq!(self.peek(), Some('#'));
194        self.bump();
195        let start = self.pos;
196        while matches!(self.peek(), Some(c) if c.is_ascii_hexdigit()) {
197            self.bump();
198        }
199        let hex: String = self.chars[start..self.pos].iter().collect();
200        if hex.len() != 6 && hex.len() != 8 {
201            return Err(self.err(line, col, "kolor to #RRGGBB lub #RRGGBBAA"));
202        }
203        Ok((hex, line, col))
204    }
205
206    fn parse_seq_file(&mut self) -> Result<SeqFile, SeqError> {
207        let mut app: Option<SeqApp> = None;
208        let mut components: Vec<ComponentDef> = Vec::new();
209        let mut imports: Vec<ImportDecl> = Vec::new();
210        loop {
211            self.skip_trivia();
212            if self.peek().is_none() {
213                break;
214            }
215            let (kw, line, col) = self.ident()?;
216            match kw.as_str() {
217                "app" => {
218                    if app.is_some() {
219                        return Err(self.err(line, col, "drugi blok `app` (dozwolony jeden)"));
220                    }
221                    app = Some(self.app_rest(line, col)?);
222                }
223                "import" => {
224                    let (path, _, _) = self.string()?;
225                    imports.push(ImportDecl { path, line });
226                }
227                "pub" => {
228                    let (kw2, l2, c2) = self.ident()?;
229                    if kw2 != "component" {
230                        return Err(self.err(l2, c2, "`pub` tylko przed `component`"));
231                    }
232                    components.push(self.component_rest(line, Visibility::Pub)?);
233                }
234                "component" => {
235                    components.push(self.component_rest(line, Visibility::Priv)?);
236                }
237                _ => {
238                    return Err(self.err(line, col, "oczekiwano `app`, `component` albo `import`"));
239                }
240            }
241        }
242        if app.is_none() && components.is_empty() && imports.is_empty() {
243            return Err(self.err(
244                1,
245                1,
246                "pusty plik: oczekiwano `app`, `component` albo `import`",
247            ));
248        }
249        Ok(SeqFile {
250            imports,
251            components,
252            app,
253        })
254    }
255
256    fn app_rest(&mut self, line: usize, col: usize) -> Result<SeqApp, SeqError> {
257        let (name, _, _) = self.ident()?;
258        let _ = name;
259        self.expect('{', "'{' po `app Nazwa`")?;
260        let mut app = SeqApp {
261            title: String::new(),
262            size: (0.0, 0.0),
263            theme: ThemeName::Dark,
264            windows: Vec::new(),
265            deferred: Vec::new(),
266            styles: Vec::new(),
267            components: Vec::new(),
268            states: Vec::new(),
269            fns: Vec::new(),
270            imports: Vec::new(),
271            app_line: line,
272            has_title: false,
273            has_size: false,
274        };
275        loop {
276            self.skip_trivia();
277            if self.peek() == Some('}') {
278                self.bump();
279                break;
280            }
281            if self.peek().is_none() {
282                return Err(self.err(self.line, self.col, "unclosed `app` block"));
283            }
284            self.app_item(&mut app)?;
285        }
286        if !app.has_title {
287            return Err(self.err(line, col, "app wymaga `title: \"...\"`"));
288        }
289        if !app.has_size {
290            return Err(self.err(line, col, "app wymaga `size: (W, H)`"));
291        }
292        if app.windows.is_empty() {
293            return Err(self.err(line, col, "app wymaga min. 1 bloku `window`"));
294        }
295        Ok(app)
296    }
297
298    fn component_rest(
299        &mut self,
300        line: usize,
301        visibility: Visibility,
302    ) -> Result<ComponentDef, SeqError> {
303        let (name, _, _) = self.ident()?;
304        self.expect('(', "'(' po nazwie component")?;
305        let mut params = Vec::new();
306        loop {
307            self.skip_trivia();
308            if self.eat(')') {
309                break;
310            }
311            let (pname, pline, _) = self.ident()?;
312            self.expect(':', "':' po nazwie parametru")?;
313            let (pty, _, _) = self.ident()?;
314            params.push(CompParam {
315                name: pname,
316                line: pline,
317                ty: pty,
318            });
319            if !self.eat(',') {
320                self.expect(')', "')' po parametrach `component`")?;
321                break;
322            }
323        }
324        self.expect('{', "'{' after `component` header")?;
325        let mut body = Vec::new();
326        loop {
327            self.skip_trivia();
328            if self.peek() == Some('}') {
329                self.bump();
330                break;
331            }
332            if self.peek().is_none() {
333                return Err(self.err(self.line, self.col, "unclosed `component` block"));
334            }
335            body.push(self.node()?);
336        }
337        if body.is_empty() {
338            return Err(self.err(line, 1, "component requires at least 1 node"));
339        }
340        Ok(ComponentDef {
341            name,
342            line,
343            params,
344            body,
345            visibility,
346            file: self.file.to_string(),
347        })
348    }
349
350    fn app_item(&mut self, app: &mut SeqApp) -> Result<(), SeqError> {
351        let (kw, line, col) = self.ident()?;
352        match kw.as_str() {
353            "title" => {
354                self.expect(':', "':' po `title`")?;
355                let (s, _, _) = self.string()?;
356                app.title = s;
357                app.has_title = true;
358            }
359            "size" => {
360                self.expect(':', "':' po `size`")?;
361                app.size = self.size_tuple()?;
362                app.has_size = true;
363            }
364            "theme" => {
365                self.expect(':', "':' po `theme`")?;
366                app.theme = self.theme_name()?;
367            }
368            "window" => {
369                let w = self.window(line)?;
370                app.windows.push(w);
371            }
372            "prop" => {
373                let (name, _, _) = self.ident()?;
374                self.expect(':', "':' po nazwie prop")?;
375                let (ty, _, _) = self.ident()?;
376                app.deferred.push(DeferredDecl {
377                    kind: DeferredKind::Prop,
378                    name,
379                    line,
380                    sig: vec![ty],
381                });
382            }
383            "on" => {
384                let (name, _, _) = self.ident()?;
385                self.expect('(', "'(' po nazwie on")?;
386                let mut sig = Vec::new();
387                loop {
388                    self.skip_trivia();
389                    if self.eat(')') {
390                        break;
391                    }
392                    let (_, _, _) = self.ident()?;
393                    self.expect(':', "':' po nazwie parametru")?;
394                    let (ty, _, _) = self.ident()?;
395                    sig.push(ty);
396                    if !self.eat(',') {
397                        self.expect(')', "')' po parametrach `on`")?;
398                        break;
399                    }
400                }
401                app.deferred.push(DeferredDecl {
402                    kind: DeferredKind::On,
403                    name,
404                    line,
405                    sig,
406                });
407            }
408            "state" => {
409                let (name, _, _) = self.ident()?;
410                self.expect(':', "':' po nazwie state")?;
411                let ty = self.fn_type()?;
412                self.expect('=', "'=' po typie state")?;
413                let init = self.state_literal()?;
414                self.eat(';');
415                app.states.push(StateDecl {
416                    name,
417                    line,
418                    ty,
419                    init,
420                });
421            }
422            "fn" => {
423                let f = self.fn_decl(line)?;
424                app.fns.push(f);
425            }
426            "style" => {
427                let (name, _, _) = self.ident()?;
428                self.expect(':', "':' po nazwie stylu")?;
429                let (target, _, _) = self.ident()?;
430                let mut base = None;
431                let (save_pos, save_line, save_col) = (self.pos, self.line, self.col);
432                if let Ok((w, _, _)) = self.ident() {
433                    if w == "extends" {
434                        let (b, _, _) = self.ident()?;
435                        base = Some(b);
436                    } else {
437                        (self.pos, self.line, self.col) = (save_pos, save_line, save_col);
438                    }
439                } else {
440                    (self.pos, self.line, self.col) = (save_pos, save_line, save_col);
441                }
442                self.expect('{', "'{' po `style Nazwa: Typ`")?;
443                let args = self.style_args()?;
444                self.expect('}', "'}' po polach stylu")?;
445                app.styles.push(StyleDecl {
446                    name,
447                    line,
448                    target,
449                    base,
450                    args,
451                });
452            }
453            "component" => {
454                return Err(self.err(line, col, "blok component poza `app` (definiuj obok `app`)"));
455            }
456            "import" => {
457                return Err(self.err(
458                    line,
459                    col,
460                    "`import` tylko na poziomie pliku (poza blokiem `app`)",
461                ));
462            }
463            "pub" => {
464                return Err(self.err(
465                    line,
466                    col,
467                    "`pub` tylko przed `component` (poza blokiem `app`)",
468                ));
469            }
470            _ => {
471                return Err(self.err(
472                    line,
473                    col,
474                    format!(
475                        "nieznany element app '{kw}' (title/size/theme/window/prop/on/state/fn/style)"
476                    ),
477                ));
478            }
479        }
480        Ok(())
481    }
482
483    fn state_literal(&mut self) -> Result<SeqExpr, SeqError> {
484        self.skip_trivia();
485        let (line, col) = (self.line, self.col);
486        match self.peek() {
487            Some('"') => {
488                let (s, _, _) = self.string()?;
489                Ok(SeqExpr {
490                    line,
491                    kind: SeqExprKind::Str(s),
492                })
493            }
494            Some(c) if c == '-' || c.is_ascii_digit() => {
495                let (n, int, _, _) = self.number_expr()?;
496                Ok(SeqExpr {
497                    line,
498                    kind: if int {
499                        SeqExprKind::Int(n as i64)
500                    } else {
501                        SeqExprKind::Float(n)
502                    },
503                })
504            }
505            _ => {
506                let (id, _, _) = self.ident()?;
507                match id.as_str() {
508                    "true" => Ok(SeqExpr {
509                        line,
510                        kind: SeqExprKind::Bool(true),
511                    }),
512                    "false" => Ok(SeqExpr {
513                        line,
514                        kind: SeqExprKind::Bool(false),
515                    }),
516                    "None" => Ok(SeqExpr {
517                        line,
518                        kind: SeqExprKind::Var("None".to_string()),
519                    }),
520                    other => Err(self.err(
521                        line,
522                        col,
523                        format!(
524                            "state '{other}': initial value is literal (number/string/true/false)"
525                        ),
526                    )),
527                }
528            }
529        }
530    }
531
532    fn fn_decl(&mut self, line: usize) -> Result<SeqFn, SeqError> {
533        let (name, _, _) = self.ident()?;
534        self.expect('(', "'(' po nazwie funkcji")?;
535        let mut params = Vec::new();
536        loop {
537            self.skip_trivia();
538            if self.eat(')') {
539                break;
540            }
541            let mut mutable = false;
542            let (first, first_line, _) = self.ident()?;
543            let pname;
544            let pline;
545            if first == "mut" {
546                mutable = true;
547                let (n, l, _) = self.ident()?;
548                pname = n;
549                pline = l;
550            } else {
551                pname = first;
552                pline = first_line;
553            }
554            self.expect(':', "':' po nazwie parametru funkcji")?;
555            let ty = self.fn_type()?;
556            params.push(FnParam {
557                name: pname,
558                mutable,
559                line: pline,
560                ty,
561            });
562            if !self.eat(',') {
563                self.expect(')', "')' po parametrach funkcji")?;
564                break;
565            }
566        }
567        let mut ret = None;
568        if self.eat_arrow() {
569            ret = Some(self.fn_type()?);
570        }
571        let body = self.fn_block("funkcji")?;
572        Ok(SeqFn {
573            name,
574            line,
575            params,
576            ret,
577            body,
578        })
579    }
580
581    fn fn_type(&mut self) -> Result<String, SeqError> {
582        self.skip_trivia();
583        if self.peek() == Some('O') {
584            let save = (self.pos, self.line, self.col);
585            if let Ok((id, _, _)) = self.ident()
586                && id == "Option"
587            {
588                self.skip_trivia();
589                if self.eat('<') {
590                    let inner = self.fn_type()?;
591                    self.skip_trivia();
592                    self.expect('>', "'>' po typie Option")?;
593                    return Ok(format!("Option<{}>", inner));
594                }
595            } else {
596                (self.pos, self.line, self.col) = save;
597            }
598            (self.pos, self.line, self.col) = save;
599        }
600        if self.eat('(') {
601            let mut parts = vec![self.fn_type()?];
602            while self.eat(',') {
603                parts.push(self.fn_type()?);
604            }
605            self.expect(')', "')' po typie krotki")?;
606            Ok(format!("({})", parts.join(",")))
607        } else {
608            let (id, _, _) = self.ident()?;
609            Ok(id)
610        }
611    }
612
613    fn eat_arrow(&mut self) -> bool {
614        let save = (self.pos, self.line, self.col);
615        self.skip_trivia();
616        if self.peek() == Some('-') && self.chars.get(self.pos + 1) == Some(&'>') {
617            self.bump();
618            self.bump();
619            true
620        } else {
621            (self.pos, self.line, self.col) = save;
622            false
623        }
624    }
625
626    fn fn_block(&mut self, what: &str) -> Result<Vec<SeqStmt>, SeqError> {
627        self.depth += 1;
628        if self.depth > MAX_NESTING_DEPTH {
629            self.depth -= 1;
630            return Err(self.err(
631                self.line,
632                self.col,
633                format!("nesting too deep (limit {MAX_NESTING_DEPTH} levels)"),
634            ));
635        }
636        let result = self.fn_block_inner(what);
637        self.depth -= 1;
638        result
639    }
640
641    fn fn_block_inner(&mut self, what: &str) -> Result<Vec<SeqStmt>, SeqError> {
642        self.expect('{', format!("'{{' w ciele {what}").as_str())?;
643        let mut out = Vec::new();
644        loop {
645            self.skip_trivia();
646            if self.peek() == Some('}') {
647                self.bump();
648                break;
649            }
650            if self.peek().is_none() {
651                return Err(self.err(self.line, self.col, format!("unclosed block {what}")));
652            }
653            let stmt = self.fn_stmt()?;
654            if let Some(stmt) = stmt {
655                out.push(stmt);
656            }
657        }
658        Ok(out)
659    }
660
661    fn fn_stmt(&mut self) -> Result<Option<SeqStmt>, SeqError> {
662        self.skip_trivia();
663        if self.eat(';') {
664            return Ok(None);
665        }
666        let (kw, line, col) = self.ident()?;
667        match kw.as_str() {
668            "let" | "mut" => {
669                let (name, _, _) = self.ident()?;
670                self.expect('=', "'=' po nazwie zmiennej")?;
671                let value = self.fn_expr()?;
672                self.expect(';', "';' po `let`/`mut`")?;
673                Ok(Some(SeqStmt::Let {
674                    name,
675                    mutable: kw == "mut",
676                    value,
677                    line,
678                }))
679            }
680            "if" => Ok(Some(self.if_rest(line)?)),
681            "for" => {
682                let (var, _, _) = self.ident()?;
683                let (in_kw, l2, c2) = self.ident()?;
684                if in_kw != "in" {
685                    return Err(self.err(l2, c2, "'in' after loop variable `for x in rows`"));
686                }
687                let (source, _, _) = self.ident()?;
688                let body = self.fn_block("for loop")?;
689                Ok(Some(SeqStmt::For {
690                    var,
691                    source,
692                    body,
693                    line,
694                }))
695            }
696            "match" => self.match_rest(line),
697            "return" => {
698                self.skip_trivia();
699                let value = if self.peek() == Some(';') {
700                    None
701                } else {
702                    Some(self.fn_expr()?)
703                };
704                self.expect(';', "';' po `return`")?;
705                Ok(Some(SeqStmt::Return { value, line }))
706            }
707            _ => {
708                if self.eat_eq() {
709                    let value = self.fn_expr()?;
710                    self.expect(';', "';' po przypisaniu")?;
711                    return Ok(Some(SeqStmt::Assign {
712                        name: kw,
713                        value,
714                        line,
715                    }));
716                }
717                let base = SeqExpr {
718                    line,
719                    kind: SeqExprKind::Var(kw),
720                };
721                let expr = self.fn_postfix(base)?;
722                if matches!(expr.kind, SeqExprKind::Var(_) | SeqExprKind::Field { .. }) {
723                    return Err(self.err(
724                        line,
725                        col,
726                        "an expression as a statement is a function call (e.g. `connect();`)",
727                    ));
728                }
729                self.expect(';', "';' po instrukcji")?;
730                Ok(Some(SeqStmt::Expr(expr)))
731            }
732        }
733    }
734
735    fn if_rest(&mut self, line: usize) -> Result<SeqStmt, SeqError> {
736        self.expect('(', "'(' po `if`")?;
737        let cond = self.fn_expr()?;
738        self.expect(')', "')' po warunku `if`")?;
739        let then = self.fn_block("branch `if`")?;
740        let mut elifs = Vec::new();
741        let mut els = None;
742        loop {
743            if !self.peek_keyword("else") {
744                break;
745            }
746            let _ = self.ident();
747            if self.peek_keyword("if") {
748                let _ = self.ident();
749                self.expect('(', "'(' po `else if`")?;
750                let cond = self.fn_expr()?;
751                self.expect(')', "')' po warunku `else if`")?;
752                let body = self.fn_block("branch `else if`")?;
753                elifs.push((cond, body));
754            } else {
755                els = Some(self.fn_block("branch `else`")?);
756                break;
757            }
758        }
759        Ok(SeqStmt::If {
760            cond,
761            then,
762            elifs,
763            els,
764            line,
765        })
766    }
767
768    fn match_rest(&mut self, line: usize) -> Result<Option<SeqStmt>, SeqError> {
769        let value = self.fn_expr()?;
770        self.expect('{', "'{' after `match`")?;
771        let mut arms = Vec::new();
772        loop {
773            self.skip_trivia();
774            if self.peek() == Some('}') {
775                self.bump();
776                break;
777            }
778            if self.peek().is_none() {
779                return Err(self.err(self.line, self.col, "unclosed `match` block"));
780            }
781            let (aline, acol) = (self.line, self.col);
782            let pattern = match self.peek() {
783                Some('"') => MatchPat::Str(self.string()?.0),
784                Some(c) if c == '-' || c.is_ascii_digit() => {
785                    let (n, int, _, _) = self.number_expr()?;
786                    if !int {
787                        return Err(self.err(aline, acol, "match pattern is integer"));
788                    }
789                    #[allow(clippy::cast_possible_truncation)]
790                    MatchPat::Int(n as i64)
791                }
792                _ => {
793                    let (id, _, _) = self.ident()?;
794                    match id.as_str() {
795                        "true" => MatchPat::Bool(true),
796                        "false" => MatchPat::Bool(false),
797                        "_" => MatchPat::Wildcard,
798                        other => {
799                            return Err(self.err(
800                                aline,
801                                acol,
802                                format!(
803                                    "wzorzec match to \"tekst\"/liczba/true/false/_, nie '{other}'"
804                                ),
805                            ));
806                        }
807                    }
808                }
809            };
810            self.expect('=', "'=' we wzorcu match (`wzorzec => { ... }`)")?;
811            self.expect('>', "'>' we wzorcu match (`wzorzec => { ... }`)")?;
812            let body = self.fn_block("branch `match`")?;
813            arms.push(SeqMatchArm {
814                pattern,
815                body,
816                line: aline,
817            });
818            self.eat(',');
819        }
820        Ok(Some(SeqStmt::Match { value, arms, line }))
821    }
822
823    fn eat_eq(&mut self) -> bool {
824        let save = (self.pos, self.line, self.col);
825        self.skip_trivia();
826        if self.peek() == Some('=') && self.chars.get(self.pos + 1) != Some(&'=') {
827            self.bump();
828            true
829        } else {
830            (self.pos, self.line, self.col) = save;
831            false
832        }
833    }
834
835    fn peek_keyword(&mut self, kw: &str) -> bool {
836        let save = (self.pos, self.line, self.col);
837        let ok = matches!(self.ident(), Ok((w, _, _)) if w == kw);
838        (self.pos, self.line, self.col) = save;
839        ok
840    }
841
842    fn number_expr(&mut self) -> Result<(f64, bool, usize, usize), SeqError> {
843        let (line, col) = self.loc();
844        let start = self.pos;
845        if self.peek() == Some('-') {
846            self.bump();
847        }
848        let mut digits = 0;
849        while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
850            self.bump();
851            digits += 1;
852        }
853        let mut int = true;
854        if self.peek() == Some('.') {
855            int = false;
856            self.bump();
857            while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
858                self.bump();
859                digits += 1;
860            }
861        }
862        if digits == 0 {
863            return Err(self.err(line, col, "oczekiwano liczby"));
864        }
865        let text: String = self.chars[start..self.pos].iter().collect();
866        text.parse::<f64>()
867            .map(|v| (v, int, line, col))
868            .map_err(|_| self.err(line, col, format!("bad number '{text}'")))
869    }
870
871    fn peek_paren_trivia(&mut self) -> bool {
872        self.skip_trivia();
873        self.peek() == Some('(')
874    }
875
876    fn fn_or(&mut self) -> Result<SeqExpr, SeqError> {
877        let mut lhs = self.fn_and()?;
878        loop {
879            if !self.eat_op("||") {
880                break;
881            }
882            let line = self.line;
883            let rhs = self.fn_and()?;
884            lhs = SeqExpr {
885                line,
886                kind: SeqExprKind::Binary {
887                    op: BinOp::Or,
888                    lhs: Box::new(lhs),
889                    rhs: Box::new(rhs),
890                },
891            };
892        }
893        Ok(lhs)
894    }
895
896    fn fn_and(&mut self) -> Result<SeqExpr, SeqError> {
897        let mut lhs = self.fn_eq()?;
898        loop {
899            if !self.eat_op("&&") {
900                break;
901            }
902            let line = self.line;
903            let rhs = self.fn_eq()?;
904            lhs = SeqExpr {
905                line,
906                kind: SeqExprKind::Binary {
907                    op: BinOp::And,
908                    lhs: Box::new(lhs),
909                    rhs: Box::new(rhs),
910                },
911            };
912        }
913        Ok(lhs)
914    }
915
916    fn fn_eq(&mut self) -> Result<SeqExpr, SeqError> {
917        let mut lhs = self.fn_cmp()?;
918        loop {
919            let op = if self.eat_op("==") {
920                BinOp::Eq
921            } else if self.eat_op("!=") {
922                BinOp::Ne
923            } else {
924                break;
925            };
926            let line = self.line;
927            let rhs = self.fn_cmp()?;
928            lhs = SeqExpr {
929                line,
930                kind: SeqExprKind::Binary {
931                    op,
932                    lhs: Box::new(lhs),
933                    rhs: Box::new(rhs),
934                },
935            };
936        }
937        Ok(lhs)
938    }
939
940    fn fn_cmp(&mut self) -> Result<SeqExpr, SeqError> {
941        let mut lhs = self.fn_add()?;
942        loop {
943            let op = if self.eat_op("<=") {
944                BinOp::Le
945            } else if self.eat_op(">=") {
946                BinOp::Ge
947            } else if self.eat_op("<") {
948                BinOp::Lt
949            } else if self.eat_op(">") {
950                BinOp::Gt
951            } else {
952                break;
953            };
954            let line = self.line;
955            let rhs = self.fn_add()?;
956            lhs = SeqExpr {
957                line,
958                kind: SeqExprKind::Binary {
959                    op,
960                    lhs: Box::new(lhs),
961                    rhs: Box::new(rhs),
962                },
963            };
964        }
965        Ok(lhs)
966    }
967
968    fn fn_add(&mut self) -> Result<SeqExpr, SeqError> {
969        let mut lhs = self.fn_mul()?;
970        loop {
971            let op = if self.eat_op("+") {
972                BinOp::Add
973            } else if self.eat_op("-") {
974                BinOp::Sub
975            } else {
976                break;
977            };
978            let line = self.line;
979            let rhs = self.fn_mul()?;
980            lhs = SeqExpr {
981                line,
982                kind: SeqExprKind::Binary {
983                    op,
984                    lhs: Box::new(lhs),
985                    rhs: Box::new(rhs),
986                },
987            };
988        }
989        Ok(lhs)
990    }
991
992    fn fn_mul(&mut self) -> Result<SeqExpr, SeqError> {
993        let mut lhs = self.fn_unary()?;
994        loop {
995            let op = if self.eat_op("*") {
996                BinOp::Mul
997            } else if self.eat_op("/") {
998                BinOp::Div
999            } else if self.eat_op("%") {
1000                BinOp::Rem
1001            } else {
1002                break;
1003            };
1004            let line = self.line;
1005            let rhs = self.fn_unary()?;
1006            lhs = SeqExpr {
1007                line,
1008                kind: SeqExprKind::Binary {
1009                    op,
1010                    lhs: Box::new(lhs),
1011                    rhs: Box::new(rhs),
1012                },
1013            };
1014        }
1015        Ok(lhs)
1016    }
1017
1018    fn fn_unary(&mut self) -> Result<SeqExpr, SeqError> {
1019        self.skip_trivia();
1020        let (line, _) = (self.line, self.col);
1021        if self.eat_op("!") {
1022            let expr = self.fn_unary()?;
1023            return Ok(SeqExpr {
1024                line,
1025                kind: SeqExprKind::Unary {
1026                    op: UnOp::Not,
1027                    expr: Box::new(expr),
1028                },
1029            });
1030        }
1031        if self.eat_op("-") {
1032            let expr = self.fn_unary()?;
1033            return Ok(SeqExpr {
1034                line,
1035                kind: SeqExprKind::Unary {
1036                    op: UnOp::Neg,
1037                    expr: Box::new(expr),
1038                },
1039            });
1040        }
1041        let primary = self.fn_primary()?;
1042        self.fn_postfix(primary)
1043    }
1044
1045    fn fn_postfix(&mut self, mut base: SeqExpr) -> Result<SeqExpr, SeqError> {
1046        loop {
1047            if self.eat('.') {
1048                self.skip_trivia();
1049                let (name, nline) = if matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
1050                    let nline = self.line;
1051                    let start = self.pos;
1052                    while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
1053                        self.bump();
1054                    }
1055                    (
1056                        self.chars[start..self.pos].iter().collect::<String>(),
1057                        nline,
1058                    )
1059                } else {
1060                    let (name, line, _) = self.ident()?;
1061                    (name, line)
1062                };
1063                if self.peek_paren_trivia() {
1064                    self.expect('(', "'(' po metodzie")?;
1065                    let args = self.fn_call_args()?;
1066                    let mut all = vec![base];
1067                    all.extend(args);
1068                    base = SeqExpr {
1069                        line: nline,
1070                        kind: SeqExprKind::Call { name, args: all },
1071                    };
1072                } else {
1073                    let SeqExprKind::Var(var) = base.kind else {
1074                        return Err(self.err(
1075                            nline,
1076                            self.col,
1077                            "field only on loop variable (e.g. `x.id`)",
1078                        ));
1079                    };
1080                    base = SeqExpr {
1081                        line: nline,
1082                        kind: SeqExprKind::Field {
1083                            base: var,
1084                            field: name,
1085                        },
1086                    };
1087                }
1088            } else if self.peek_paren_trivia() {
1089                self.skip_trivia();
1090                let line = self.line;
1091                self.expect('(', "'(' po nazwie funkcji")?;
1092                let args = self.fn_call_args()?;
1093                let SeqExprKind::Var(name) = base.kind else {
1094                    return Err(self.err(line, self.col, "you can call a function by name"));
1095                };
1096                base = SeqExpr {
1097                    line,
1098                    kind: SeqExprKind::Call { name, args },
1099                };
1100            } else {
1101                break;
1102            }
1103        }
1104        Ok(base)
1105    }
1106
1107    fn fn_call_args(&mut self) -> Result<Vec<SeqExpr>, SeqError> {
1108        let mut args = Vec::new();
1109        self.skip_trivia();
1110        if self.eat(')') {
1111            return Ok(args);
1112        }
1113        args.push(self.fn_expr()?);
1114        loop {
1115            if !self.eat(',') {
1116                break;
1117            }
1118            self.skip_trivia();
1119            if self.eat(')') {
1120                return Ok(args);
1121            }
1122            args.push(self.fn_expr()?);
1123        }
1124        self.expect(')', "')' after call arguments")?;
1125        Ok(args)
1126    }
1127
1128    fn fn_primary(&mut self) -> Result<SeqExpr, SeqError> {
1129        self.depth += 1;
1130        if self.depth > MAX_NESTING_DEPTH {
1131            self.depth -= 1;
1132            return Err(self.err(
1133                self.line,
1134                self.col,
1135                format!("nesting too deep (limit {MAX_NESTING_DEPTH} levels)"),
1136            ));
1137        }
1138        let result = self.fn_primary_inner();
1139        self.depth -= 1;
1140        result
1141    }
1142
1143    fn fn_primary_inner(&mut self) -> Result<SeqExpr, SeqError> {
1144        self.skip_trivia();
1145        let (line, col) = (self.line, self.col);
1146        match self.peek() {
1147            Some('"') => {
1148                let (s, _, _) = self.string()?;
1149                Ok(SeqExpr {
1150                    line,
1151                    kind: SeqExprKind::Str(s),
1152                })
1153            }
1154            Some(c) if c.is_ascii_digit() => {
1155                let (n, int, _, _) = self.number_expr()?;
1156                Ok(SeqExpr {
1157                    line,
1158                    kind: if int {
1159                        #[allow(clippy::cast_possible_truncation)]
1160                        SeqExprKind::Int(n as i64)
1161                    } else {
1162                        SeqExprKind::Float(n)
1163                    },
1164                })
1165            }
1166            Some('(') => {
1167                self.bump();
1168                let first = self.fn_expr()?;
1169                self.skip_trivia();
1170                if self.eat(',') {
1171                    let mut items = vec![first];
1172                    loop {
1173                        self.skip_trivia();
1174                        if self.eat(')') {
1175                            break;
1176                        }
1177                        items.push(self.fn_expr()?);
1178                        if !self.eat(',') {
1179                            self.expect(')', "')' po krotce `(a, b)`")?;
1180                            break;
1181                        }
1182                    }
1183                    Ok(SeqExpr {
1184                        line,
1185                        kind: SeqExprKind::Tuple(items),
1186                    })
1187                } else {
1188                    self.expect(')', "')' after the expression in brackets")?;
1189                    Ok(first)
1190                }
1191            }
1192            Some('[') => {
1193                self.bump();
1194                let mut items = Vec::new();
1195                self.skip_trivia();
1196                if !self.eat(']') {
1197                    loop {
1198                        items.push(self.fn_expr()?);
1199                        self.skip_trivia();
1200                        if self.eat(']') {
1201                            break;
1202                        }
1203                        self.expect(',', "',' or ']' in list `[a, b]`")?;
1204                        self.skip_trivia();
1205                        if self.eat(']') {
1206                            break;
1207                        }
1208                    }
1209                }
1210                Ok(SeqExpr {
1211                    line,
1212                    kind: SeqExprKind::Array(items),
1213                })
1214            }
1215            Some('_') => Err(self.err(line, col, "`_` only as `match` pattern")),
1216            _ => {
1217                let (id, _, _) = self.ident()?;
1218                Ok(SeqExpr {
1219                    line,
1220                    kind: match id.as_str() {
1221                        "true" => SeqExprKind::Bool(true),
1222                        "false" => SeqExprKind::Bool(false),
1223                        _ => SeqExprKind::Var(id),
1224                    },
1225                })
1226            }
1227        }
1228    }
1229
1230    fn eat_op(&mut self, s: &str) -> bool {
1231        self.skip_trivia();
1232        for (i, c) in s.chars().enumerate() {
1233            if self.chars.get(self.pos + i) != Some(&c) {
1234                return false;
1235            }
1236        }
1237        for _ in s.chars() {
1238            self.bump();
1239        }
1240        true
1241    }
1242
1243    fn fn_expr(&mut self) -> Result<SeqExpr, SeqError> {
1244        self.fn_ternary()
1245    }
1246
1247    fn fn_ternary(&mut self) -> Result<SeqExpr, SeqError> {
1248        let cond = self.fn_or()?;
1249        if !self.eat_op("?") {
1250            return Ok(cond);
1251        }
1252        let line = self.line;
1253        let then = self.fn_expr()?;
1254        self.expect(':', "':' in conditional expression `condition ? a : b`")?;
1255        let els = self.fn_ternary()?;
1256        Ok(SeqExpr {
1257            line,
1258            kind: SeqExprKind::Ternary {
1259                cond: Box::new(cond),
1260                then: Box::new(then),
1261                els: Box::new(els),
1262            },
1263        })
1264    }
1265
1266    fn theme_name(&mut self) -> Result<ThemeName, SeqError> {
1267        let (line, col) = self.loc();
1268        match self.peek() {
1269            Some('"') => {
1270                let (s, _, _) = self.string()?;
1271                match s.as_str() {
1272                    "dark" => Ok(ThemeName::Dark),
1273                    "light" => Ok(ThemeName::Light),
1274                    _ => Ok(ThemeName::File(s)),
1275                }
1276            }
1277            _ => {
1278                let (id, _, _) = self.ident()?;
1279                match id.as_str() {
1280                    "dark" => Ok(ThemeName::Dark),
1281                    "light" => Ok(ThemeName::Light),
1282                    _ => Err(self.err(line, col, "theme to dark/light albo \"plik-tokens.json\"")),
1283                }
1284            }
1285        }
1286    }
1287
1288    fn size_tuple(&mut self) -> Result<(f32, f32), SeqError> {
1289        self.expect('(', "'(' przed rozmiarem")?;
1290        let (w, _, _) = self.number()?;
1291        self.expect(',', "',' between W and H")?;
1292        let (h, _, _) = self.number()?;
1293        self.expect(')', "')' po rozmiarze")?;
1294        if !(w.is_finite() && h.is_finite() && w > 0.0 && h > 0.0) {
1295            let (l, c) = (self.line, self.col);
1296            return Err(self.err(l, c, "size must be positive and finite"));
1297        }
1298        Ok((w, h))
1299    }
1300
1301    fn style_args(&mut self) -> Result<Vec<SeqArg>, SeqError> {
1302        let mut args = Vec::new();
1303        loop {
1304            self.skip_trivia();
1305            if self.peek() == Some('}') {
1306                break;
1307            }
1308            if self.peek().is_none() {
1309                return Err(self.err(self.line, self.col, "unclosed `style` block"));
1310            }
1311            let (name, line, _) = self.ident()?;
1312            self.expect(':', format!("':' po polu stylu '{name}'").as_str())?;
1313            let value = self.value()?;
1314            args.push(SeqArg { name, line, value });
1315
1316            self.eat(',');
1317        }
1318        Ok(args)
1319    }
1320
1321    fn window(&mut self, line: usize) -> Result<SeqWindow, SeqError> {
1322        let (name, _, _) = self.ident()?;
1323        let mut size = None;
1324        if self.eat('(') {
1325            let (kw, l, c) = self.ident()?;
1326            if kw != "size" {
1327                return Err(self.err(l, c, "w nawiasie window dozwolone tylko `size: (W, H)`"));
1328            }
1329            self.expect(':', "':' po `size`")?;
1330            size = Some(self.size_tuple()?);
1331            self.expect(')', "')' po `window Nazwa (...)`")?;
1332        }
1333        self.expect('{', "'{' after `window` header")?;
1334        let mut nodes = Vec::new();
1335        loop {
1336            self.skip_trivia();
1337            if self.peek() == Some('}') {
1338                self.bump();
1339                break;
1340            }
1341            if self.peek().is_none() {
1342                return Err(self.err(self.line, self.col, "unclosed `window` block"));
1343            }
1344            nodes.push(self.node()?);
1345        }
1346        Ok(SeqWindow {
1347            name,
1348            line,
1349            size,
1350            nodes,
1351        })
1352    }
1353
1354    fn node(&mut self) -> Result<SeqNode, SeqError> {
1355        self.depth += 1;
1356        if self.depth > MAX_NESTING_DEPTH {
1357            self.depth -= 1;
1358            return Err(self.err(
1359                self.line,
1360                self.col,
1361                format!("nesting too deep (limit {MAX_NESTING_DEPTH} levels)"),
1362            ));
1363        }
1364        let result = self.node_inner();
1365        self.depth -= 1;
1366        result
1367    }
1368
1369    fn node_inner(&mut self) -> Result<SeqNode, SeqError> {
1370        let (kind, line, _) = self.ident()?;
1371        let mut label = None;
1372        let mut args = Vec::new();
1373
1374        if self.eat('(') {
1375            self.skip_trivia();
1376            if self.peek() == Some('"') {
1377                let (s, _, _) = self.string()?;
1378                label = Some(s);
1379                self.skip_trivia();
1380                if self.eat(',') {
1381                    self.skip_trivia();
1382                    if self.peek() != Some(')') {
1383                        args = self.named_args()?;
1384                    }
1385                }
1386            } else if self.peek() != Some(')') {
1387                args = self.named_args()?;
1388            }
1389            self.expect(')', "')' po atrybutach")?;
1390        }
1391        let mut children = Vec::new();
1392        if self.eat('{') {
1393            loop {
1394                self.skip_trivia();
1395                if self.peek() == Some('}') {
1396                    self.bump();
1397                    break;
1398                }
1399                if self.peek().is_none() {
1400                    return Err(self.err(self.line, self.col, "unclosed children block `{ }`"));
1401                }
1402                children.push(self.node()?);
1403            }
1404        }
1405        Ok(SeqNode {
1406            kind,
1407            line,
1408            label,
1409            args,
1410            children,
1411        })
1412    }
1413
1414    fn named_args(&mut self) -> Result<Vec<SeqArg>, SeqError> {
1415        let mut args = Vec::new();
1416        loop {
1417            let (name, line, _) = self.ident()?;
1418            self.expect(':', format!("':' po atrybucie '{name}'").as_str())?;
1419            let value = self.value()?;
1420            args.push(SeqArg { name, line, value });
1421            if !self.eat(',') {
1422                break;
1423            }
1424            self.skip_trivia();
1425            if self.peek() == Some(')') {
1426                break;
1427            }
1428        }
1429        Ok(args)
1430    }
1431
1432    fn peek_paren(&self) -> bool {
1433        let mut i = self.pos;
1434        while let Some(&c) = self.chars.get(i) {
1435            if c == ' ' || c == '\t' || c == '\r' || c == '\n' {
1436                i += 1;
1437            } else {
1438                return c == '(';
1439            }
1440        }
1441        false
1442    }
1443
1444    fn value(&mut self) -> Result<SeqValue, SeqError> {
1445        self.depth += 1;
1446        if self.depth > MAX_NESTING_DEPTH {
1447            self.depth -= 1;
1448            return Err(self.err(
1449                self.line,
1450                self.col,
1451                format!("nesting too deep (limit {MAX_NESTING_DEPTH} levels)"),
1452            ));
1453        }
1454        let result = self.value_inner();
1455        self.depth -= 1;
1456        result.map(SeqValue::fold_exprs)
1457    }
1458
1459    fn value_inner(&mut self) -> Result<SeqValue, SeqError> {
1460        self.skip_trivia();
1461        match self.peek() {
1462            Some('#') => {
1463                let (hex, _, _) = self.color()?;
1464                return Ok(SeqValue::Color(hex));
1465            }
1466            Some('{') => return self.callback(),
1467            _ => {}
1468        }
1469        let save = (self.pos, self.line, self.col);
1470        let starts_paren = self.peek() == Some('(');
1471        if let Ok(expr) = self.fn_expr()
1472            && self.value_end()
1473        {
1474            let expr = if starts_paren && is_single_value_expr(&expr.kind) {
1475                SeqExpr {
1476                    line: expr.line,
1477                    kind: SeqExprKind::Tuple(vec![expr]),
1478                }
1479            } else {
1480                expr
1481            };
1482            return Ok(SeqValue::Expr(expr));
1483        }
1484        (self.pos, self.line, self.col) = save;
1485        self.value_literal()
1486    }
1487
1488    fn value_end(&mut self) -> bool {
1489        self.skip_trivia();
1490        matches!(
1491            self.peek(),
1492            None | Some(',') | Some(')') | Some(']') | Some('}')
1493        )
1494    }
1495
1496    fn value_literal(&mut self) -> Result<SeqValue, SeqError> {
1497        self.skip_trivia();
1498        Ok(match self.peek() {
1499            Some('"') => {
1500                let (s, _, _) = self.string()?;
1501                SeqValue::Str(s)
1502            }
1503            Some(c) if c == '-' || c.is_ascii_digit() => {
1504                let (n, _, _) = self.number()?;
1505                SeqValue::Num(n)
1506            }
1507            Some('#') => {
1508                let (hex, _, _) = self.color()?;
1509                SeqValue::Color(hex)
1510            }
1511            Some('{') => return self.callback(),
1512            Some('(') => {
1513                self.bump();
1514                let mut items = vec![self.value()?];
1515                while self.eat(',') {
1516                    self.skip_trivia();
1517                    if self.peek() == Some(')') {
1518                        break;
1519                    }
1520                    items.push(self.value()?);
1521                }
1522                self.expect(')', "')' po krotce `(a, b)`")?;
1523                SeqValue::Tuple(items)
1524            }
1525            Some('[') => {
1526                self.bump();
1527                let mut items = vec![self.value()?];
1528                while self.eat(',') {
1529                    self.skip_trivia();
1530                    if self.peek() == Some(']') {
1531                        break;
1532                    }
1533                    items.push(self.value()?);
1534                }
1535                self.expect(']', "']' after list `[a, b]`")?;
1536                SeqValue::Array(items)
1537            }
1538            _ => {
1539                let (id, _, _) = self.ident()?;
1540                match id.as_str() {
1541                    "true" => SeqValue::Bool(true),
1542                    "false" => SeqValue::Bool(false),
1543                    "fit" => SeqValue::Length(LengthVal::Fit),
1544
1545                    "fill" if self.peek_paren() => {
1546                        return self.length_paren(LengthVal::Fill, "fill(waga)");
1547                    }
1548                    "px" if self.peek_paren() => {
1549                        return self.length_paren(LengthVal::Px, "px(liczba)");
1550                    }
1551                    "percent" if self.peek_paren() => {
1552                        return self.length_paren(LengthVal::Percent, "percent(liczba)");
1553                    }
1554                    "dynamic" => {
1555                        self.expect('(', "'(' po `dynamic`")?;
1556                        let (name, _, _) = self.ident()?;
1557                        self.expect(')', "')' po `dynamic(nazwa)`")?;
1558                        SeqValue::Dynamic(name)
1559                    }
1560                    "theme" => {
1561                        self.expect('.', "'.' po `theme` (theme.pole)")?;
1562                        let (field, _, _) = self.ident()?;
1563                        SeqValue::Theme(field)
1564                    }
1565                    "env" => {
1566                        self.expect('.', "'.' po `env` (env.nazwa)")?;
1567                        let (field, _, _) = self.ident()?;
1568                        SeqValue::Env(field)
1569                    }
1570                    "item" => {
1571                        self.expect('.', "'.' po `item` (item.pole)")?;
1572                        let (field, _, _) = self.ident()?;
1573                        SeqValue::ItemField(field)
1574                    }
1575                    _ => SeqValue::Ident(id),
1576                }
1577            }
1578        })
1579    }
1580
1581    fn length_paren(&mut self, f: fn(f32) -> LengthVal, what: &str) -> Result<SeqValue, SeqError> {
1582        self.expect('(', format!("'(' — {what}").as_str())?;
1583        let (n, _, _) = self.number()?;
1584        self.expect(')', format!("')' — {what}").as_str())?;
1585        Ok(SeqValue::Length(f(n)))
1586    }
1587
1588    fn callback(&mut self) -> Result<SeqValue, SeqError> {
1589        debug_assert_eq!(self.peek(), Some('{'));
1590        self.bump();
1591        self.skip_trivia();
1592        let (action, _, _) = self.ident()?;
1593        self.expect('(', "'(' po nazwie callbacku")?;
1594        let mut args = Vec::new();
1595        self.skip_trivia();
1596        if self.peek() != Some(')') {
1597            args.push(self.value()?);
1598            while self.eat(',') {
1599                self.skip_trivia();
1600                if self.peek() == Some(')') {
1601                    break;
1602                }
1603                args.push(self.value()?);
1604            }
1605        }
1606        self.expect(')', "')' po argumencie callbacku")?;
1607        self.skip_trivia();
1608        if self.peek() == Some('}') {
1609            self.bump();
1610        } else {
1611            let (l, c) = (self.line, self.col);
1612            return Err(self.err(l, c, "'}' po callbacku `{ akcja() }`"));
1613        }
1614        Ok(SeqValue::Callback { action, args })
1615    }
1616}