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