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 "name" => {
405 self.bump();
406 let value = self.value()?;
407 if kind != BlockKind::Table {
408 self.diags.push(Diagnostic::error(
409 value.span,
410 "`name` は `table` にしか書けない",
411 ));
412 }
413 Ok(Member::Name(value))
414 }
415 "column" => {
416 self.bump();
417 let name = self.expect_ident("カラム名")?;
418 let attrs = self.attrs()?;
419 Ok(Member::Column(Column { name, attrs }))
420 }
421 "pk" => {
422 self.bump();
423 Ok(Member::Pk(self.name_list("列名")?))
424 }
425 "index" => {
426 self.bump();
427 let columns = self.name_list("列名")?;
428 let unique = if self.at_keyword("unique") {
429 self.bump();
430 true
431 } else {
432 false
433 };
434 Ok(Member::Index(Index { columns, unique }))
435 }
436 "use" => {
437 self.bump();
438 Ok(Member::Use(self.expect_ident("mixin名")?))
439 }
440 "override" => {
441 self.bump();
442 let name = self.expect_ident("カラム名")?;
443 let attrs = self.attrs()?;
444 if attrs.is_empty() {
445 let span = name.span;
446 return Err(self.error(span, "`override` には属性が1つ以上必要"));
447 }
448 Ok(Member::Override(Override { name, attrs }))
449 }
450 "except" => {
451 self.bump();
452 if self.at_keyword("index") {
453 self.bump();
454 Ok(Member::ExceptIndex(self.name_list("列名")?))
455 } else {
456 Ok(Member::Except(self.name_list("カラム名")?))
457 }
458 }
459 "belongs_to" => self.relation(RelationKind::BelongsTo),
460 "unique_belongs_to" => self.relation(RelationKind::UniqueBelongsTo),
461 "has_many" => self.relation(RelationKind::HasMany),
462 "has_one" => self.relation(RelationKind::HasOne),
463 other => {
464 let span = self.span();
465 Err(self.error(span, format!("宣言文にならないキーワード `{other}`")))
466 }
467 }
468 }
469
470 fn relation(&mut self, kind: RelationKind) -> PResult<Member> {
471 self.bump();
472 let target = self.expect_ident("参照先の語")?;
473 let mut rel = Relation {
474 kind,
475 target,
476 fk: None,
477 alias: None,
478 via: None,
479 comment: None,
480 };
481 while let Tok::Ident(key) = self.peek().clone() {
482 if *self.peek_at(1) != Tok::Eq {
483 break;
484 }
485 let key_span = self.span();
486 self.bump();
487 self.bump();
488 if !RELATION_KEYS.contains(&key.as_str()) {
489 self.diags.push(Diagnostic::error(
490 key_span,
491 format!(
492 "`{}` に書けない属性キー `{key}`。使えるのは {}",
493 kind.keyword(),
494 RELATION_KEYS.join(" / ")
495 ),
496 ));
497 }
498 let duplicated = match key.as_str() {
499 "alias" => {
500 let value = self.value()?;
501 rel.alias.replace(value).is_some()
502 }
503 "fk" => {
504 let value = self.expect_string("列名(文字列)")?;
505 rel.fk.replace(value).is_some()
506 }
507 "comment" => {
508 let value = self.expect_string("コメント(文字列)")?;
509 rel.comment.replace(value).is_some()
510 }
511 _ => {
512 let value = self.expect_string("列名(文字列)")?;
513 rel.via.replace(value).is_some()
514 }
515 };
516 if duplicated {
517 self.diags.push(Diagnostic::error(
518 key_span,
519 format!("`{key}` が重複している"),
520 ));
521 }
522 }
523 if rel.fk.is_some() && !kind.owns_fk() {
524 let span = rel.fk.as_ref().map(|f| f.span).unwrap_or(rel.target.span);
525 self.diags.push(Diagnostic::error(
526 span,
527 format!("`{}` に `fk=` は書けない", kind.keyword()),
528 ));
529 }
530 if rel.via.is_some() && kind.owns_fk() {
531 let span = rel.via.as_ref().map(|v| v.span).unwrap_or(rel.target.span);
532 self.diags.push(Diagnostic::error(
533 span,
534 format!("`{}` に `via=` は書けない", kind.keyword()),
535 ));
536 }
537 if rel.comment.is_some() && !kind.owns_fk() {
538 let span = rel
539 .comment
540 .as_ref()
541 .map(|c| c.span)
542 .unwrap_or(rel.target.span);
543 self.diags.push(Diagnostic::error(
544 span,
545 format!(
546 "`{}` は列を作らないので `comment=` は書けない",
547 kind.keyword()
548 ),
549 ));
550 }
551 Ok(Member::Relation(rel))
552 }
553
554 fn attrs(&mut self) -> PResult<Vec<Attr>> {
555 let mut attrs = Vec::new();
556 while let Tok::Ident(key) = self.peek().clone() {
557 if *self.peek_at(1) != Tok::Eq {
558 break;
559 }
560 let key_span = self.span();
561 self.bump();
562 self.bump();
563 if !ATTR_KEYS.contains(&key.as_str()) {
564 self.diags.push(Diagnostic::error(
565 key_span,
566 format!(
567 "知らない属性キー `{key}`。使えるのは {}",
568 ATTR_KEYS.join(" / ")
569 ),
570 ));
571 }
572 let value = self.value()?;
573 attrs.push(Attr {
574 key: Spanned::new(key, key_span),
575 value,
576 });
577 }
578 Ok(attrs)
579 }
580
581 fn name_list(&mut self, what: &str) -> PResult<Vec<Name>> {
583 if self.eat(&Tok::LBracket) {
584 let mut names = Vec::new();
585 loop {
586 if self.at(&Tok::RBracket) {
587 break;
588 }
589 names.push(self.expect_ident(what)?);
590 if !self.eat(&Tok::Comma) {
591 break;
592 }
593 }
594 self.expect(Tok::RBracket)?;
595 if names.is_empty() {
596 let span = self.prev_span();
597 return Err(self.error(span, format!("{what} が空")));
598 }
599 Ok(names)
600 } else {
601 Ok(vec![self.expect_ident(what)?])
602 }
603 }
604
605 fn blueprint_block(&mut self) -> PResult<Blueprint> {
608 let start = self.expect_ident("`blueprint`")?.span;
609 let name = self.expect_ident("blueprint名")?;
610 let mut params = Vec::new();
611 while matches!(self.peek(), Tok::Ident(_)) {
612 params.push(self.expect_ident("引数名")?);
613 }
614
615 if self.expect(Tok::LBrace).is_err() {
616 self.recover_block();
617 return Err(Bail);
618 }
619 let mut tables = Vec::new();
620 loop {
621 self.skip_newlines();
622 if self.at(&Tok::RBrace) || self.at(&Tok::Eof) {
623 break;
624 }
625 if self.at_keyword("table") {
626 match self.table_block() {
627 Ok(t) => tables.push(t),
628 Err(Bail) => self.recover_line(),
629 }
630 } else {
631 let span = self.span();
632 let found = self.peek().describe();
633 self.diags.push(Diagnostic::error(
634 span,
635 format!("blueprint 内に書けるのは `table` のみ。{found} が来た"),
636 ));
637 self.recover_line();
638 }
639 }
640 let end = self.expect(Tok::RBrace).unwrap_or(self.prev_span());
641 Ok(Blueprint {
642 name,
643 params,
644 tables,
645 span: start.join(end),
646 })
647 }
648
649 fn macro_call(&mut self) -> PResult<MacroCall> {
652 let name = self.expect_ident("マクロ名")?;
653 let start = name.span;
654 self.expect(Tok::LParen)?;
655 let mut args = Vec::new();
656 let mut table_name = None;
657 let mut comment = None;
658 loop {
659 if self.at(&Tok::RParen) {
660 break;
661 }
662 if matches!(self.peek(), Tok::Ident(_)) && *self.peek_at(1) == Tok::Eq {
664 let key = self.expect_ident("キー")?;
665 self.expect(Tok::Eq)?;
666 let duplicated = match key.value.as_str() {
667 "name" => table_name.replace(self.value()?).is_some(),
668 "comment" => comment
669 .replace(self.expect_string("コメント(文字列)")?)
670 .is_some(),
671 other => {
672 self.diags.push(Diagnostic::error(
673 key.span,
674 format!("知らないキー `{other}`。使えるのは name / comment"),
675 ));
676 self.value()?;
677 false
678 }
679 };
680 if duplicated {
681 self.diags.push(Diagnostic::error(
682 key.span,
683 format!("`{}` が重複している", key.value),
684 ));
685 }
686 } else {
687 args.push(self.expect_ident("引数")?);
688 }
689 if !self.eat(&Tok::Comma) {
690 break;
691 }
692 }
693 let end = self.expect(Tok::RParen)?;
694 Ok(MacroCall {
695 name,
696 args,
697 table_name,
698 comment,
699 span: start.join(end),
700 })
701 }
702
703 fn value(&mut self) -> PResult<Spanned<Value>> {
706 let start = self.span();
707 match self.peek().clone() {
708 Tok::Str(s) => {
709 let span = self.bump().span;
710 Ok(Spanned::new(Value::Str(s), span))
711 }
712 Tok::Num(n) => {
713 let span = self.bump().span;
714 Ok(Spanned::new(Value::Num(n), span))
715 }
716 Tok::Eval(body) => {
717 let span = self.bump().span;
718 Ok(Spanned::new(Value::Eval(body), span))
719 }
720 Tok::LBracket => {
721 let items = self.value_list()?;
722 let span = start.join(self.prev_span());
723 Ok(Spanned::new(Value::List(items), span))
724 }
725 Tok::Ident(name) => {
726 if *self.peek_at(1) == Tok::LParen {
727 let call_name = self.expect_ident("関数名")?;
728 if !VALUE_FNS.contains(&name.as_str()) {
729 self.diags.push(Diagnostic::error(
730 call_name.span,
731 format!(
732 "値の位置で使える関数は {} のみ。`{name}` は使えない",
733 VALUE_FNS.join(" / ")
734 ),
735 ));
736 }
737 self.expect(Tok::LParen)?;
738 let mut args = Vec::new();
739 loop {
740 if self.at(&Tok::RParen) {
741 break;
742 }
743 args.push(self.value()?);
744 if !self.eat(&Tok::Comma) {
745 break;
746 }
747 }
748 let end = self.expect(Tok::RParen)?;
749 Ok(Spanned::new(
750 Value::Call {
751 name: call_name,
752 args,
753 },
754 start.join(end),
755 ))
756 } else {
757 let span = self.bump().span;
758 Ok(Spanned::new(Value::Ident(name), span))
759 }
760 }
761 other => {
762 let span = self.span();
763 let found = other.describe();
764 Err(self.error(span, format!("値が必要。{found} が来た")))
765 }
766 }
767 }
768
769 fn value_list(&mut self) -> PResult<Vec<Name>> {
771 self.expect(Tok::LBracket)?;
772 let mut items = Vec::new();
773 loop {
774 self.skip_newlines();
775 if self.at(&Tok::RBracket) || self.at(&Tok::Eof) {
776 break;
777 }
778 items.push(self.expect_ident("リスト要素")?);
779 self.skip_newlines();
780 if !self.eat(&Tok::Comma) {
781 break;
782 }
783 }
784 self.skip_newlines();
785 self.expect(Tok::RBracket)?;
786 Ok(items)
787 }
788}