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
18struct Bail;
20type PResult<T> = Result<T, Bail>;
21
22const ATTR_KEYS: &[&str] = &["type", "null", "default", "on_update", "comment"];
23
24const 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 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 fn recover_line(&mut self) {
135 while !matches!(self.peek(), Tok::Newline | Tok::Eof | Tok::RBrace) {
136 self.bump();
137 }
138 }
139
140 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 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 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 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 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 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 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 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 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 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 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 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}