1use std::borrow::Cow;
2
3use mical_cli_syntax::{GreenNode, SyntaxError, SyntaxKind, token::TokenStream};
4use rowan::{GreenNodeBuilder, TextRange};
5
6mod event;
7mod grammar;
8mod parser;
9mod token_set;
10
11use event::Event;
12use parser::Parser;
13
14pub fn parse<'s>(token_stream: impl TokenStream<'s>) -> (GreenNode, Vec<SyntaxError>) {
15 let source = token_stream.source();
16 let events = {
17 let mut parser = Parser::new(token_stream);
18 grammar::source_file(&mut parser);
19 parser.finish()
20 };
21 let mut builder = NodeBuilder::new(source);
22 for event in events {
56 match event {
57 Event::StartNode { kind } => builder.start_node(kind),
58 Event::FinishNode => builder.finish_node(),
59 Event::Token { kind, len } => builder.token(kind, len),
60 Event::Error { message } => builder.error(message),
61 }
62 }
63 builder.finish()
64}
65
66struct NodeBuilder<'s> {
67 source: &'s str,
68 builder: GreenNodeBuilder<'s>,
69 errors: Vec<SyntaxError>,
70 offset: u32,
71}
72
73impl<'s> NodeBuilder<'s> {
74 fn new(source: &'s str) -> Self {
75 NodeBuilder { source, builder: GreenNodeBuilder::new(), errors: Vec::new(), offset: 0 }
76 }
77
78 fn start_node(&mut self, kind: SyntaxKind) {
79 self.builder.start_node(kind.into());
80 }
81
82 fn finish_node(&mut self) {
83 self.builder.finish_node();
84 }
85
86 fn token(&mut self, kind: SyntaxKind, len: u32) {
87 let text = &self.source[(self.offset as usize)..(self.offset + len) as usize];
88 self.builder.token(kind.into(), text);
89 self.offset += len;
90 }
91
92 fn error(&mut self, message: impl Into<Cow<'static, str>>) {
93 let range = TextRange::empty(self.offset.into());
94 self.errors.push(SyntaxError::new(message, range));
95 }
96
97 fn finish(self) -> (GreenNode, Vec<SyntaxError>) {
98 (self.builder.finish(), self.errors)
99 }
100}