Skip to main content

nounsql_core/
parser.rs

1use crate::ast::*;
2use crate::diag::Diagnostic;
3use crate::lexer::{Tok, Token, lex};
4use crate::span::{Span, Spanned};
5
6pub fn parse(src: &str) -> (Document, Vec<Diagnostic>) {
7    let (tokens, mut diags) = lex(src);
8    let mut parser = Parser {
9        tokens,
10        pos: 0,
11        diags: Vec::new(),
12    };
13    let doc = parser.document();
14    diags.append(&mut parser.diags);
15    (doc, diags)
16}
17
18/// 文の解析に失敗したことを表す。行末まで読み飛ばして回復する。
19struct Bail;
20type PResult<T> = Result<T, Bail>;
21
22const ATTR_KEYS: &[&str] = &["type", "null", "default", "on_update", "comment"];
23
24/// `nouns` の行で使えるキー。
25const NOUN_KEYS: &[&str] = &["singular", "plural", "short"];
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27enum BlockKind {
28    Table,
29    Mixin,
30}
31
32const RELATION_KEYS: &[&str] = &["fk", "alias", "via", "comment"];
33const VALUE_FNS: &[&str] = &["noun", "singular", "plural"];
34
35struct Parser {
36    tokens: Vec<Token>,
37    pos: usize,
38    diags: Vec<Diagnostic>,
39}
40
41impl Parser {
42    // ---------- トークン操作 ----------
43
44    fn peek(&self) -> &Tok {
45        &self.tokens[self.pos].value
46    }
47
48    fn peek_at(&self, n: usize) -> &Tok {
49        let i = (self.pos + n).min(self.tokens.len() - 1);
50        &self.tokens[i].value
51    }
52
53    fn span(&self) -> Span {
54        self.tokens[self.pos].span
55    }
56
57    fn prev_span(&self) -> Span {
58        self.tokens[self.pos.saturating_sub(1)].span
59    }
60
61    fn bump(&mut self) -> Token {
62        let tok = self.tokens[self.pos].clone();
63        if self.pos + 1 < self.tokens.len() {
64            self.pos += 1;
65        }
66        tok
67    }
68
69    fn at(&self, tok: &Tok) -> bool {
70        self.peek() == tok
71    }
72
73    fn eat(&mut self, tok: &Tok) -> bool {
74        if self.at(tok) {
75            self.bump();
76            true
77        } else {
78            false
79        }
80    }
81
82    fn at_keyword(&self, kw: &str) -> bool {
83        matches!(self.peek(), Tok::Ident(s) if s == kw)
84    }
85
86    fn error(&mut self, span: Span, msg: impl Into<String>) -> Bail {
87        self.diags.push(Diagnostic::error(span, msg));
88        Bail
89    }
90
91    fn expect(&mut self, tok: Tok) -> PResult<Span> {
92        if self.at(&tok) {
93            Ok(self.bump().span)
94        } else {
95            let span = self.span();
96            let found = self.peek().describe();
97            Err(self.error(span, format!("{} が必要。{} が来た", tok.describe(), found)))
98        }
99    }
100
101    fn expect_ident(&mut self, what: &str) -> PResult<Name> {
102        match self.peek().clone() {
103            Tok::Ident(name) => {
104                let span = self.bump().span;
105                Ok(Spanned::new(name, span))
106            }
107            other => {
108                let span = self.span();
109                Err(self.error(span, format!("{what} が必要。{} が来た", other.describe())))
110            }
111        }
112    }
113
114    fn expect_string(&mut self, what: &str) -> PResult<Spanned<String>> {
115        match self.peek().clone() {
116            Tok::Str(s) => {
117                let span = self.bump().span;
118                Ok(Spanned::new(s, span))
119            }
120            other => {
121                let span = self.span();
122                Err(self.error(span, format!("{what} が必要。{} が来た", other.describe())))
123            }
124        }
125    }
126
127    fn skip_newlines(&mut self) {
128        while self.at(&Tok::Newline) {
129            self.bump();
130        }
131    }
132
133    /// 行末まで読み飛ばす。1行1文なので、これで次の文から再開できる。
134    fn recover_line(&mut self) {
135        while !matches!(self.peek(), Tok::Newline | Tok::Eof | Tok::RBrace) {
136            self.bump();
137        }
138    }
139
140    /// 対応する `}` まで読み飛ばす。
141    fn recover_block(&mut self) {
142        let mut depth = 0usize;
143        loop {
144            match self.peek() {
145                Tok::Eof => return,
146                Tok::LBrace => depth += 1,
147                Tok::RBrace => {
148                    self.bump();
149                    if depth == 0 {
150                        return;
151                    }
152                    depth -= 1;
153                    continue;
154                }
155                _ => {}
156            }
157            self.bump();
158        }
159    }
160
161    /// 文の終わり(改行 / `}` / EOF)を要求する。
162    fn end_of_statement(&mut self) -> PResult<()> {
163        match self.peek() {
164            Tok::Newline | Tok::Eof | Tok::RBrace => Ok(()),
165            other => {
166                let span = self.span();
167                let found = other.describe();
168                Err(self.error(span, format!("1行1文。行末が必要だが {found} が来た")))
169            }
170        }
171    }
172
173    // ---------- トップレベル ----------
174
175    fn document(&mut self) -> Document {
176        let mut doc = Document::default();
177        loop {
178            self.skip_newlines();
179            if self.at(&Tok::Eof) {
180                break;
181            }
182            if self.item(&mut doc).is_err() {
183                self.recover_line();
184            }
185        }
186        doc
187    }
188
189    fn item(&mut self, doc: &mut Document) -> PResult<()> {
190        let Tok::Ident(kw) = self.peek().clone() else {
191            let span = self.span();
192            let found = self.peek().describe();
193            return Err(self.error(span, format!("トップレベルに書けない: {found}")));
194        };
195        match kw.as_str() {
196            "naming" | "constraints" => {
197                let block = self.config_block()?;
198                let slot = if kw == "naming" {
199                    &mut doc.naming
200                } else {
201                    &mut doc.constraints
202                };
203                if let Some(prev) = slot {
204                    let span = block.name.span;
205                    let prev_span = prev.name.span;
206                    self.diags.push(
207                        Diagnostic::error(span, format!("`{kw}` ブロックが重複している"))
208                            .with_label(prev_span, "最初の定義"),
209                    );
210                } else {
211                    *slot = Some(block);
212                }
213                Ok(())
214            }
215            "nouns" => {
216                let block = self.nouns_block()?;
217                if let Some(prev) = &doc.nouns {
218                    let prev_span = prev.span;
219                    self.diags.push(
220                        Diagnostic::error(block.span, "`nouns` ブロックが重複している")
221                            .with_label(prev_span, "最初の定義"),
222                    );
223                } else {
224                    doc.nouns = Some(block);
225                }
226                Ok(())
227            }
228            "mixin" => {
229                let m = self.mixin_block()?;
230                doc.mixins.push(m);
231                Ok(())
232            }
233            "table" => {
234                let t = self.table_block()?;
235                doc.tables.push(t);
236                Ok(())
237            }
238            "blueprint" => {
239                let b = self.blueprint_block()?;
240                doc.blueprints.push(b);
241                Ok(())
242            }
243            "associate" | "apply_blueprint" => {
244                let m = self.macro_call()?;
245                doc.macros.push(m);
246                self.end_of_statement()
247            }
248            other => {
249                let span = self.span();
250                Err(self.error(span, format!("トップレベルに書けないキーワード `{other}`")))
251            }
252        }
253    }
254
255    // ---------- 設定ブロック ----------
256
257    fn config_block(&mut self) -> PResult<ConfigBlock> {
258        let name = self.expect_ident("ブロック名")?;
259        let start = name.span;
260        if self.expect(Tok::LBrace).is_err() {
261            self.recover_block();
262            return Err(Bail);
263        }
264        let mut entries = Vec::new();
265        loop {
266            self.skip_newlines();
267            if self.at(&Tok::RBrace) || self.at(&Tok::Eof) {
268                break;
269            }
270            match self.assign() {
271                Ok(a) => {
272                    entries.push(a);
273                    if self.end_of_statement().is_err() {
274                        self.recover_line();
275                    }
276                }
277                Err(Bail) => self.recover_line(),
278            }
279        }
280        let end = self.expect(Tok::RBrace).unwrap_or(self.prev_span());
281        Ok(ConfigBlock {
282            name,
283            entries,
284            span: start.join(end),
285        })
286    }
287
288    fn assign(&mut self) -> PResult<Assign> {
289        let key = self.expect_ident("設定キー")?;
290        self.expect(Tok::Eq)?;
291        let value = self.value()?;
292        Ok(Assign { key, value })
293    }
294
295    fn nouns_block(&mut self) -> PResult<NounsBlock> {
296        let start = self.expect_ident("`nouns`")?.span;
297        if self.expect(Tok::LBrace).is_err() {
298            self.recover_block();
299            return Err(Bail);
300        }
301        let mut entries = Vec::new();
302        loop {
303            self.skip_newlines();
304            if self.at(&Tok::RBrace) || self.at(&Tok::Eof) {
305                break;
306            }
307            match self.noun_entry() {
308                Ok(e) => {
309                    entries.push(e);
310                    if self.end_of_statement().is_err() {
311                        self.recover_line();
312                    }
313                }
314                Err(Bail) => self.recover_line(),
315            }
316        }
317        let end = self.expect(Tok::RBrace).unwrap_or(self.prev_span());
318        Ok(NounsBlock {
319            entries,
320            span: start.join(end),
321        })
322    }
323
324    fn noun_entry(&mut self) -> PResult<Noun> {
325        let id = self.expect_ident("名詞の識別子")?;
326        let mut noun = Noun {
327            id,
328            singular: None,
329            plural: None,
330            short: None,
331            comment: None,
332        };
333        while let Tok::Ident(key) = self.peek().clone() {
334            if *self.peek_at(1) != Tok::Eq {
335                break;
336            }
337            let key_span = self.span();
338            self.bump();
339            self.bump();
340            let word = self.noun_word()?;
341            let slot = match key.as_str() {
342                "singular" => Some(&mut noun.singular),
343                "plural" => Some(&mut noun.plural),
344                "short" => Some(&mut noun.short),
345                _ => None,
346            };
347            match slot {
348                Some(slot) => {
349                    if slot.is_some() {
350                        self.diags.push(Diagnostic::error(
351                            key_span,
352                            format!("`{key}` が重複している"),
353                        ));
354                    }
355                    *slot = Some(word);
356                }
357                None => self.diags.push(Diagnostic::error(
358                    key_span,
359                    format!(
360                        "知らない名詞のキー `{key}`。使えるのは {}",
361                        NOUN_KEYS.join(" / ")
362                    ),
363                )),
364            }
365        }
366        if matches!(self.peek(), Tok::Str(_)) {
367            noun.comment = Some(self.expect_string("説明")?);
368        }
369        Ok(noun)
370    }
371
372    /// 語形。識別子でも文字列でも書ける。
373    fn noun_word(&mut self) -> PResult<Name> {
374        match self.peek().clone() {
375            Tok::Str(s) => {
376                let span = self.bump().span;
377                Ok(Spanned::new(s, span))
378            }
379            _ => self.expect_ident("語形"),
380        }
381    }
382
383    // ---------- mixin / table ----------
384
385    fn mixin_block(&mut self) -> PResult<Mixin> {
386        let start = self.expect_ident("`mixin`")?.span;
387        let name = self.expect_ident("mixin名")?;
388        let (members, end) = self.member_block(BlockKind::Mixin)?;
389        Ok(Mixin {
390            name,
391            members,
392            span: start.join(end),
393        })
394    }
395
396    fn table_block(&mut self) -> PResult<Table> {
397        let start = self.expect_ident("`table`")?.span;
398        let name = self.expect_ident("テーブル名")?;
399        let (members, end) = self.member_block(BlockKind::Table)?;
400        Ok(Table {
401            name,
402            members,
403            span: start.join(end),
404        })
405    }
406
407    fn member_block(&mut self, kind: BlockKind) -> PResult<(Vec<Spanned<Member>>, Span)> {
408        if self.expect(Tok::LBrace).is_err() {
409            self.recover_block();
410            return Err(Bail);
411        }
412        let mut members = Vec::new();
413        loop {
414            self.skip_newlines();
415            if self.at(&Tok::RBrace) || self.at(&Tok::Eof) {
416                break;
417            }
418            let start = self.span();
419            match self.member(kind) {
420                Ok(m) => {
421                    let span = start.join(self.prev_span());
422                    members.push(Spanned::new(m, span));
423                    if self.end_of_statement().is_err() {
424                        self.recover_line();
425                    }
426                }
427                Err(Bail) => self.recover_line(),
428            }
429        }
430        let end = self.expect(Tok::RBrace).unwrap_or(self.prev_span());
431        Ok((members, end))
432    }
433
434    fn member(&mut self, kind: BlockKind) -> PResult<Member> {
435        let Tok::Ident(kw) = self.peek().clone() else {
436            let span = self.span();
437            let found = self.peek().describe();
438            return Err(self.error(span, format!("宣言文が必要。{found} が来た")));
439        };
440        match kw.as_str() {
441            "comment" => {
442                self.bump();
443                let text = self.expect_string("コメント(文字列)")?;
444                if kind != BlockKind::Table {
445                    self.diags.push(Diagnostic::error(
446                        text.span,
447                        "`comment` は `table` にしか書けない",
448                    ));
449                }
450                Ok(Member::Comment(text))
451            }
452            "name" => {
453                self.bump();
454                let value = self.value()?;
455                if kind != BlockKind::Table {
456                    self.diags.push(Diagnostic::error(
457                        value.span,
458                        "`name` は `table` にしか書けない",
459                    ));
460                }
461                Ok(Member::Name(value))
462            }
463            "column" => {
464                self.bump();
465                let name = self.expect_ident("カラム名")?;
466                let attrs = self.attrs()?;
467                Ok(Member::Column(Column { name, attrs }))
468            }
469            "pk" => {
470                self.bump();
471                Ok(Member::Pk(self.name_list("列名")?))
472            }
473            "index" => {
474                self.bump();
475                let columns = self.name_list("列名")?;
476                let unique = if self.at_keyword("unique") {
477                    self.bump();
478                    true
479                } else {
480                    false
481                };
482                Ok(Member::Index(Index { columns, unique }))
483            }
484            "use" => {
485                self.bump();
486                Ok(Member::Use(self.expect_ident("mixin名")?))
487            }
488            "override" => {
489                self.bump();
490                let name = self.expect_ident("カラム名")?;
491                let attrs = self.attrs()?;
492                if attrs.is_empty() {
493                    let span = name.span;
494                    return Err(self.error(span, "`override` には属性が1つ以上必要"));
495                }
496                Ok(Member::Override(Override { name, attrs }))
497            }
498            "except" => {
499                self.bump();
500                if self.at_keyword("index") {
501                    self.bump();
502                    Ok(Member::ExceptIndex(self.name_list("列名")?))
503                } else {
504                    Ok(Member::Except(self.name_list("カラム名")?))
505                }
506            }
507            "belongs_to" => self.relation(RelationKind::BelongsTo),
508            "unique_belongs_to" => self.relation(RelationKind::UniqueBelongsTo),
509            "has_many" => self.relation(RelationKind::HasMany),
510            "has_one" => self.relation(RelationKind::HasOne),
511            other => {
512                let span = self.span();
513                Err(self.error(span, format!("宣言文にならないキーワード `{other}`")))
514            }
515        }
516    }
517
518    fn relation(&mut self, kind: RelationKind) -> PResult<Member> {
519        self.bump();
520        let target = self.expect_ident("参照先の語")?;
521        let mut rel = Relation {
522            kind,
523            target,
524            fk: None,
525            alias: None,
526            via: None,
527            comment: None,
528        };
529        while let Tok::Ident(key) = self.peek().clone() {
530            if *self.peek_at(1) != Tok::Eq {
531                break;
532            }
533            let key_span = self.span();
534            self.bump();
535            self.bump();
536            if !RELATION_KEYS.contains(&key.as_str()) {
537                self.diags.push(Diagnostic::error(
538                    key_span,
539                    format!(
540                        "`{}` に書けない属性キー `{key}`。使えるのは {}",
541                        kind.keyword(),
542                        RELATION_KEYS.join(" / ")
543                    ),
544                ));
545            }
546            let duplicated = match key.as_str() {
547                "alias" => {
548                    let value = self.value()?;
549                    rel.alias.replace(value).is_some()
550                }
551                "fk" => {
552                    let value = self.expect_string("列名(文字列)")?;
553                    rel.fk.replace(value).is_some()
554                }
555                "comment" => {
556                    let value = self.expect_string("コメント(文字列)")?;
557                    rel.comment.replace(value).is_some()
558                }
559                _ => {
560                    let value = self.expect_string("列名(文字列)")?;
561                    rel.via.replace(value).is_some()
562                }
563            };
564            if duplicated {
565                self.diags.push(Diagnostic::error(
566                    key_span,
567                    format!("`{key}` が重複している"),
568                ));
569            }
570        }
571        if rel.fk.is_some() && !kind.owns_fk() {
572            let span = rel.fk.as_ref().map(|f| f.span).unwrap_or(rel.target.span);
573            self.diags.push(Diagnostic::error(
574                span,
575                format!("`{}` に `fk=` は書けない", kind.keyword()),
576            ));
577        }
578        if rel.via.is_some() && kind.owns_fk() {
579            let span = rel.via.as_ref().map(|v| v.span).unwrap_or(rel.target.span);
580            self.diags.push(Diagnostic::error(
581                span,
582                format!("`{}` に `via=` は書けない", kind.keyword()),
583            ));
584        }
585        if rel.comment.is_some() && !kind.owns_fk() {
586            let span = rel
587                .comment
588                .as_ref()
589                .map(|c| c.span)
590                .unwrap_or(rel.target.span);
591            self.diags.push(Diagnostic::error(
592                span,
593                format!(
594                    "`{}` は列を作らないので `comment=` は書けない",
595                    kind.keyword()
596                ),
597            ));
598        }
599        Ok(Member::Relation(rel))
600    }
601
602    fn attrs(&mut self) -> PResult<Vec<Attr>> {
603        let mut attrs = Vec::new();
604        while let Tok::Ident(key) = self.peek().clone() {
605            if *self.peek_at(1) != Tok::Eq {
606                break;
607            }
608            let key_span = self.span();
609            self.bump();
610            self.bump();
611            if !ATTR_KEYS.contains(&key.as_str()) {
612                self.diags.push(Diagnostic::error(
613                    key_span,
614                    format!(
615                        "知らない属性キー `{key}`。使えるのは {}",
616                        ATTR_KEYS.join(" / ")
617                    ),
618                ));
619            }
620            let value = self.value()?;
621            attrs.push(Attr {
622                key: Spanned::new(key, key_span),
623                value,
624            });
625        }
626        Ok(attrs)
627    }
628
629    /// `名前` または `[名前, ...]`
630    fn name_list(&mut self, what: &str) -> PResult<Vec<Name>> {
631        if self.eat(&Tok::LBracket) {
632            let mut names = Vec::new();
633            loop {
634                if self.at(&Tok::RBracket) {
635                    break;
636                }
637                names.push(self.expect_ident(what)?);
638                if !self.eat(&Tok::Comma) {
639                    break;
640                }
641            }
642            self.expect(Tok::RBracket)?;
643            if names.is_empty() {
644                let span = self.prev_span();
645                return Err(self.error(span, format!("{what} が空")));
646            }
647            Ok(names)
648        } else {
649            Ok(vec![self.expect_ident(what)?])
650        }
651    }
652
653    // ---------- blueprint ----------
654
655    fn blueprint_block(&mut self) -> PResult<Blueprint> {
656        let start = self.expect_ident("`blueprint`")?.span;
657        let name = self.expect_ident("blueprint名")?;
658        let mut params = Vec::new();
659        while matches!(self.peek(), Tok::Ident(_)) {
660            params.push(self.expect_ident("引数名")?);
661        }
662
663        if self.expect(Tok::LBrace).is_err() {
664            self.recover_block();
665            return Err(Bail);
666        }
667        let mut tables = Vec::new();
668        loop {
669            self.skip_newlines();
670            if self.at(&Tok::RBrace) || self.at(&Tok::Eof) {
671                break;
672            }
673            if self.at_keyword("table") {
674                match self.table_block() {
675                    Ok(t) => tables.push(t),
676                    Err(Bail) => self.recover_line(),
677                }
678            } else {
679                let span = self.span();
680                let found = self.peek().describe();
681                self.diags.push(Diagnostic::error(
682                    span,
683                    format!("blueprint 内に書けるのは `table` のみ。{found} が来た"),
684                ));
685                self.recover_line();
686            }
687        }
688        let end = self.expect(Tok::RBrace).unwrap_or(self.prev_span());
689        Ok(Blueprint {
690            name,
691            params,
692            tables,
693            span: start.join(end),
694        })
695    }
696
697    // ---------- マクロ ----------
698
699    fn macro_call(&mut self) -> PResult<MacroCall> {
700        let name = self.expect_ident("マクロ名")?;
701        let start = name.span;
702        self.expect(Tok::LParen)?;
703        let mut args = Vec::new();
704        let mut table_name = None;
705        let mut comment = None;
706        loop {
707            if self.at(&Tok::RParen) {
708                break;
709            }
710            // `キー=値` は名前付き、それ以外は位置引数。
711            if matches!(self.peek(), Tok::Ident(_)) && *self.peek_at(1) == Tok::Eq {
712                let key = self.expect_ident("キー")?;
713                self.expect(Tok::Eq)?;
714                let duplicated = match key.value.as_str() {
715                    "name" => table_name.replace(self.value()?).is_some(),
716                    "comment" => comment
717                        .replace(self.expect_string("コメント(文字列)")?)
718                        .is_some(),
719                    other => {
720                        self.diags.push(Diagnostic::error(
721                            key.span,
722                            format!("知らないキー `{other}`。使えるのは name / comment"),
723                        ));
724                        self.value()?;
725                        false
726                    }
727                };
728                if duplicated {
729                    self.diags.push(Diagnostic::error(
730                        key.span,
731                        format!("`{}` が重複している", key.value),
732                    ));
733                }
734            } else {
735                args.push(self.expect_ident("引数")?);
736            }
737            if !self.eat(&Tok::Comma) {
738                break;
739            }
740        }
741        let end = self.expect(Tok::RParen)?;
742        Ok(MacroCall {
743            name,
744            args,
745            table_name,
746            comment,
747            span: start.join(end),
748        })
749    }
750
751    // ---------- 値 ----------
752
753    fn value(&mut self) -> PResult<Spanned<Value>> {
754        let start = self.span();
755        match self.peek().clone() {
756            Tok::Str(s) => {
757                let span = self.bump().span;
758                Ok(Spanned::new(Value::Str(s), span))
759            }
760            Tok::Num(n) => {
761                let span = self.bump().span;
762                Ok(Spanned::new(Value::Num(n), span))
763            }
764            Tok::Eval(body) => {
765                let span = self.bump().span;
766                Ok(Spanned::new(Value::Eval(body), span))
767            }
768            Tok::LBracket => {
769                let items = self.value_list()?;
770                let span = start.join(self.prev_span());
771                Ok(Spanned::new(Value::List(items), span))
772            }
773            Tok::Ident(name) => {
774                if *self.peek_at(1) == Tok::LParen {
775                    let call_name = self.expect_ident("関数名")?;
776                    if !VALUE_FNS.contains(&name.as_str()) {
777                        self.diags.push(Diagnostic::error(
778                            call_name.span,
779                            format!(
780                                "値の位置で使える関数は {} のみ。`{name}` は使えない",
781                                VALUE_FNS.join(" / ")
782                            ),
783                        ));
784                    }
785                    self.expect(Tok::LParen)?;
786                    let mut args = Vec::new();
787                    loop {
788                        if self.at(&Tok::RParen) {
789                            break;
790                        }
791                        args.push(self.value()?);
792                        if !self.eat(&Tok::Comma) {
793                            break;
794                        }
795                    }
796                    let end = self.expect(Tok::RParen)?;
797                    Ok(Spanned::new(
798                        Value::Call {
799                            name: call_name,
800                            args,
801                        },
802                        start.join(end),
803                    ))
804                } else {
805                    let span = self.bump().span;
806                    Ok(Spanned::new(Value::Ident(name), span))
807                }
808            }
809            other => {
810                let span = self.span();
811                let found = other.describe();
812                Err(self.error(span, format!("値が必要。{found} が来た")))
813            }
814        }
815    }
816
817    /// リストは要素の途中で改行できる。
818    fn value_list(&mut self) -> PResult<Vec<Name>> {
819        self.expect(Tok::LBracket)?;
820        let mut items = Vec::new();
821        loop {
822            self.skip_newlines();
823            if self.at(&Tok::RBracket) || self.at(&Tok::Eof) {
824                break;
825            }
826            items.push(self.expect_ident("リスト要素")?);
827            self.skip_newlines();
828            if !self.eat(&Tok::Comma) {
829                break;
830            }
831        }
832        self.skip_newlines();
833        self.expect(Tok::RBracket)?;
834        Ok(items)
835    }
836}