leo_parser_rowan/parser/
grammar.rs1use super::{Parse, Parser};
23use crate::{lexer::lex, syntax_kind::SyntaxKind::*};
24
25pub fn parse_file(source: &str) -> Parse {
29 let (tokens, _lex_errors) = lex(source);
30 let mut parser = Parser::new(source, &tokens);
31
32 let root = parser.start();
33 parser.parse_file_items();
34 root.complete(&mut parser, ROOT);
35
36 parser.finish()
37}
38
39pub fn parse_expression_entry(source: &str) -> Parse {
41 let (tokens, _lex_errors) = lex(source);
42 let mut parser = Parser::new(source, &tokens);
43
44 let root = parser.start();
45 parser.parse_expr();
46 root.complete(&mut parser, ROOT);
47
48 parser.finish()
49}
50
51pub fn parse_module_entry(source: &str) -> Parse {
53 let (tokens, _lex_errors) = lex(source);
54 let mut parser = Parser::new(source, &tokens);
55
56 let root = parser.start();
57 parser.parse_module_items();
58 root.complete(&mut parser, ROOT);
59
60 parser.finish()
61}
62
63pub fn parse_statement_entry(source: &str) -> Parse {
65 let (tokens, _lex_errors) = lex(source);
66 let mut parser = Parser::new(source, &tokens);
67
68 let root = parser.start();
69 parser.parse_stmt();
70 root.complete(&mut parser, ROOT);
71
72 parser.finish()
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use expect_test::{Expect, expect};
79
80 fn check_file(input: &str, expect: Expect) {
81 let parse = parse_file(input);
82 let output = format!("{:#?}", parse.syntax());
83 expect.assert_eq(&output);
84 }
85
86 #[test]
87 fn parse_file_empty() {
88 check_file("", expect![[r#"
89 ROOT@0..0
90 "#]]);
91 }
92
93 #[test]
94 fn parse_file_trivial() {
95 check_file("program test.aleo { }", expect![[r#"
96 ROOT@0..21
97 PROGRAM_DECL@0..21
98 KW_PROGRAM@0..7 "program"
99 WHITESPACE@7..8 " "
100 IDENT@8..12 "test"
101 DOT@12..13 "."
102 KW_ALEO@13..17 "aleo"
103 WHITESPACE@17..18 " "
104 L_BRACE@18..19 "{"
105 WHITESPACE@19..20 " "
106 R_BRACE@20..21 "}"
107 "#]]);
108 }
109
110 fn check_module(input: &str, expect: Expect) {
111 let parse = parse_module_entry(input);
112 let output = format!("{:#?}", parse.syntax());
113 expect.assert_eq(&output);
114 }
115
116 fn check_module_no_errors(input: &str) {
117 let parse = parse_module_entry(input);
118 if !parse.errors().is_empty() {
119 for err in parse.errors() {
120 eprintln!("error at {:?}: {}", err.range, err.message);
121 }
122 eprintln!("tree:\n{:#?}", parse.syntax());
123 panic!("module parse had {} error(s)", parse.errors().len());
124 }
125 }
126
127 #[test]
128 fn parse_module_empty() {
129 check_module("", expect![[r#"
130 ROOT@0..0
131 "#]]);
132 }
133
134 #[test]
135 fn parse_module_const() {
136 check_module_no_errors("const X: u32 = 32u32;");
137 }
138
139 #[test]
140 fn parse_module_struct() {
141 check_module_no_errors("struct Data { values: u32, }");
142 }
143
144 #[test]
145 fn parse_module_inline_fn() {
146 check_module_no_errors("inline helper() -> u32 { return 0u32; }");
147 }
148
149 #[test]
150 fn parse_module_mixed_items() {
151 check_module_no_errors(
152 "const X: u32 = 3;\n\
153 struct Data { values: u32, }\n\
154 inline helper() -> u32 { return 0u32; }",
155 );
156 }
157
158 #[test]
159 fn parse_module_with_comments() {
160 check_module_no_errors(
163 "// --- Next Module: dep.leo --- //\n\
164 const X: u32 = 32u32;\n\
165 // --- Next Module: dep/inner.leo --- //\n\
166 const Y: u32 = 64u32;",
167 );
168 }
169
170 #[test]
171 fn parse_file_with_module_sections() {
172 let source = "\
174program test.aleo {
175 transition foo() -> u32 { return 0u32; }
176}
177
178// --- Next Module: dep.leo --- //
179
180const X: u32 = 32u32;
181
182// --- Next Module: dep/inner.leo --- //
183
184const Y: u32 = 64u32;";
185
186 let parse = parse_file(source);
187 if !parse.errors().is_empty() {
188 for err in parse.errors() {
189 eprintln!("error at {:?}: {}", err.range, err.message);
190 }
191 eprintln!("tree:\n{:#?}", parse.syntax());
192 panic!("file parse had {} error(s)", parse.errors().len());
193 }
194 }
195}