1use crate::{Lexer, Node, Parse, SyntaxKind, Token, YulLanguage};
2use core::iter::Peekable;
3use rowan::{Checkpoint, GreenNodeBuilder, Language};
4
5pub struct Parser<'a> {
7 lexer: Peekable<Lexer<'a>>,
8 builder: GreenNodeBuilder<'static>,
9}
10
11impl<'a> Parser<'a> {
12 pub fn new(input: &'a str) -> Self {
13 let mut parser = Self {
14 lexer: Lexer::new(input).peekable(),
15 builder: GreenNodeBuilder::new(),
16 };
17 parser.start_node(Node::root());
18 parser
19 }
20
21 pub fn finish(mut self) -> Parse {
23 if self.peek().is_some() {
24 self.start_node(Node::Error);
25 while self.peek().is_some() {
26 self.bump();
27 }
28 self.finish_node();
29 }
30 self.finish_node();
31 Parse::new(self.builder.finish())
32 }
33
34 pub fn peek_is(&mut self, token: Token) -> bool {
36 self.peek().map_or(false, |peek| peek == token)
37 }
38
39 pub fn peek_is_not(&mut self, token: Token) -> bool {
41 self.peek().map_or(false, |peek| peek != token)
42 }
43
44 pub fn peek(&mut self) -> Option<Token> {
46 self.lexer.peek().map(|(token, _)| *token)
47 }
48
49 pub fn token(&mut self, token: Token) {
51 if self.peek() == Some(token) {
52 self.bump();
53 } else {
54 self.start_node(Node::Error);
55 if self.peek().is_some() {
56 self.bump();
57 }
58 self.finish_node();
59 }
61 self.skip_insignificant();
62 }
63
64 pub fn error(&mut self) {
66 self.start_node(Node::error());
67 self.bump();
68 self.skip_insignificant();
69 self.finish_node();
70 }
71
72 pub fn skip_insignificant(&mut self) {
74 while !self.peek().as_ref().map_or(true, Token::is_significant) {
75 self.bump()
76 }
77 }
78
79 pub fn bump(&mut self) {
84 let (token, text) = self.lexer.next().unwrap();
85 self.add_token(token, text);
86 }
87
88 pub fn checkpoint(&self) -> Checkpoint {
90 self.builder.checkpoint()
91 }
92
93 pub fn start_node_at(&mut self, checkpoint: Checkpoint, node: Node) {
96 let kind = SyntaxKind::Node(node);
97 self.builder
98 .start_node_at(checkpoint, YulLanguage::kind_to_raw(kind));
99 }
100
101 pub fn start_node(&mut self, node: Node) {
103 let kind = SyntaxKind::Node(node);
104 self.builder.start_node(YulLanguage::kind_to_raw(kind));
105 }
106
107 pub fn finish_node(&mut self) {
109 self.builder.finish_node();
110 }
111
112 pub fn add_token(&mut self, token: Token, slice: &str) {
114 let kind = SyntaxKind::Token(token);
115 self.builder
116 .token(YulLanguage::kind_to_raw(kind), slice.into());
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use serde_json::json;
124
125 #[test]
126 fn parse_nothing() {
127 let parser = Parser::new("");
128 let parse = parser.finish();
129 assert_eq!(parse.debug_tree(), "Root@0..0");
130 }
131
132 #[test]
133 fn parse_number() {
134 let mut parser = Parser::new("123");
135 parser.token(Token::LiteralInt);
136 let parse = parser.finish();
137 assert_eq!(
138 serde_json::to_value(&parse).unwrap(),
139 json!({
140 "kind": "Root",
141 "text_range": [0, 3],
142 "children": [{
143 "kind": "LiteralInt",
144 "text_range": [0, 3],
145 "text": "123"
146 }]
147 })
148 );
149 }
150}