1use std::error::Error;
8use std::fmt;
9
10#[derive(Debug)]
11pub enum SyntaxError {
13 ParsingError(ParsingError),
15 AssumptionError(String),
17}
18
19impl From<ParsingError> for SyntaxError {
20 fn from(error: ParsingError) -> Self {
21 SyntaxError::ParsingError(error)
22 }
23}
24
25impl fmt::Display for SyntaxError {
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 write!(f, "{}", self)
28 }
29}
30
31impl std::error::Error for SyntaxError {}
32
33#[derive(PartialEq, Debug)]
36pub enum ErrorCode {
37 UnterminatedNormalString,
38 UnterminatedExtendedString,
39 UnterminatedMultiLineComment,
40 UnexpectedClosingDelimiter,
41 DelimiterMismatch,
42 PotentialErroneousClosingDelimiterFollowedByComment,
43 UnclosedDelimiter,
44 BadAssumption,
45}
46
47impl fmt::Display for ErrorCode {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 write!(f, "{}", self)
50 }
51}
52
53#[derive(Debug)]
57pub struct ParsingError {
58 pub error_code: ErrorCode,
59 pub error_message: String,
60}
61
62impl fmt::Display for ParsingError {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 write!(f, "({}): {}", self.error_code, self.error_message)
65 }
66}
67
68impl Error for ParsingError {}
69
70impl ParsingError {
71 #[inline]
76 pub fn new(
77 code: &[u8],
78 start_index: usize,
79 end_index: usize,
80 error_code: ErrorCode,
81 error_message: &str,
82 ) -> ParsingError {
83 #![allow(unused_variables, unused_assignments)]
86
87 let code = String::from_utf8_lossy(code);
90
91 let error_message = String::from(error_message);
92
93 let si = start_index;
94
95 let mut sl = 0;
96
97 let mut sc = 0;
98
99 let ei = end_index;
100 let mut el = 0;
101 let mut ec = 0;
102
103 {
106 let mut code_index = 0;
107 let mut line_index = 0;
108 let mut column_index = 0;
109
110 let mut count = 2;
111
112 for c in code.chars() {
113 if count == 0 {
114 break;
115 }
116
117 if si == code_index {
118 sl = line_index;
121 sc = column_index;
122
123 count -= 1;
124 }
125
126 if ei == code_index {
127 el = line_index;
128 ec = column_index;
129
130 count -= 1;
131 }
132
133 code_index += 1;
136
137 if c == '\n' {
138 line_index += 1;
139 column_index = 0;
140 } else {
141 column_index += 1;
142 }
143 }
144 }
145
146 let lines: Vec<&str> = code.split("\n").collect();
147
148 let mut msg: Vec<String> = Vec::new();
149
150 let end_line_number_string = format!("{}", el + 1);
151
152 let mut gutter_size = 0;
153 gutter_size = std::cmp::max(gutter_size, end_line_number_string.len());
154
155 let e_line = lines.get(el).unwrap();
156
157 msg.push(String::from(""));
158 msg.push(format!(" {} | {}", end_line_number_string, e_line));
159 msg.push(format!(
160 " {} | {}^",
161 " ".repeat(gutter_size),
162 " ".repeat(ec)
163 ));
164
165 msg.push(String::from(""));
166 msg.push(format!("{}", error_message));
167
168 let error_message = msg.join("\n");
169
170 ParsingError {
171 error_code,
172 error_message,
173 }
174 }
175}
176
177#[derive(Debug, PartialEq, Clone, Copy)]
181pub enum TokenId {
182 Whitespace = 2,
183
184 Word = 7,
185
186 RoundBracketOpen = 10,
187 RoundBracketClose = 11,
188 CurlyBracketOpen = 12,
189 CurlyBracketClose = 14,
190 SquareBracketOpen = 15,
191 SquareBracketClose = 16,
192
193 StringNormal = 21,
194 StringExtended = 22,
195
196 CommentSingleLine = 31,
197
198 CommentMultiLine = 32,
199}
200
201#[derive(Debug, PartialEq)]
204enum State {
205 Undetermined,
206 Whitespace,
207
208 CommentAmbiguous,
209 CommentSingleLine,
210 CommentMultiLine,
211
212 StringAmbiguous,
213 StringNormal,
214 StringExtendedConfig, StringExtendedBody, StringExtendedEnd, Word,
219}
220
221#[derive(Clone, Debug)]
227pub struct Token {
228 pub id: TokenId,
230 pub index: usize,
232 pub length: usize,
234}
235
236impl Token {
237 #[inline]
239 pub fn new(id: TokenId, index: usize, length: usize) -> Token {
240 Token { id, index, length }
241 }
242
243 #[inline]
245 pub fn get_lexeme<'a>(self: &Self, code: &'a str) -> &'a str {
246 let i = self.index;
247 let j = self.index + self.length;
248
249 let x = &code[i..j];
250
251 x
252 }
253}
254
255const DEBUG: bool = false;
259
260#[allow(dead_code)]
265const HAS_ISSUE_132: bool = true;
266
267pub fn tokenize(
271 code: &str,
272 include_comments: bool,
273 include_whitespace: bool,
274) -> Result<Vec<Token>, SyntaxError> {
275 let code = code.as_bytes();
276
277 if DEBUG {
278 println!("{}", "-".repeat(80));
279
280 let code = std::str::from_utf8(code).unwrap();
281 println!("Code: [{}]", code);
282 }
283
284 let mut tokens: Vec<Token> = Vec::new();
285
286 let mut token_id = TokenId::Whitespace;
287 let mut token_index = 0;
288 let mut token_length = 0;
289
290 let mut state: State = State::Undetermined;
291
292 let mut attempting_to_close_comment = false;
293 let mut attempting_to_open_comment = false;
294
295 let mut start_semicolon_count = 0;
296 let mut end_semicolon_count = 0;
297
298 let mut start_double_quote_count = 0;
305 let mut end_double_quote_count = 0;
306
307 let mut multi_line_comment_stack = Vec::new();
308
309 let mut pc = b'a';
311
312 'code_loop: for (code_index, c) in code.iter().enumerate() {
318 let c = *c;
319
320 let mut no_progress_iter = 0;
321
322 if DEBUG {
325 if code_index > 0 {
326 println!("> State = {:?} (end)", state);
328 }
329
330 println!("{}", "-".repeat(80));
331 println!("i = {}, c = [{}]", code_index, c);
332 }
333
334 'decision_loop: loop {
337 if DEBUG {
338 if no_progress_iter == 0 {
339 println!("> State = {:?} (start)", state);
340 } else {
341 println!("> State = {:?}", state);
342 }
343 }
344
345 {
346 no_progress_iter += 1;
349
350 if no_progress_iter == 3 {
351 return Err(SyntaxError::AssumptionError(
352 "No progress while tokenizing.".to_string(),
353 ));
354 }
355 }
356
357 match &state {
358 State::Undetermined => {
359 if c.is_ascii_whitespace() {
363 pc = c;
364
365 token_id = TokenId::Whitespace;
366 token_index = code_index;
367 token_length = 1;
368
369 state = State::Whitespace;
370
371 continue 'code_loop;
372 } else if c == b'(' {
373 pc = c;
374
375 token_id = TokenId::RoundBracketOpen;
376 token_index = code_index;
377 token_length = 1;
378
379 tokens.push(Token::new(token_id, token_index, token_length));
380
381 continue 'code_loop;
382 } else if c == b')' {
383 pc = c;
384
385 token_id = TokenId::RoundBracketClose;
386 token_index = code_index;
387 token_length = 1;
388
389 tokens.push(Token::new(token_id, token_index, token_length));
392
393 continue 'code_loop;
394 } else if c == b'[' {
395 pc = c;
396
397 token_id = TokenId::SquareBracketOpen;
398 token_index = code_index;
399 token_length = 1;
400
401 tokens.push(Token::new(token_id, token_index, token_length));
402
403 continue 'code_loop;
404 } else if c == b']' {
405 pc = c;
406
407 token_id = TokenId::SquareBracketClose;
408 token_index = code_index;
409 token_length = 1;
410
411 tokens.push(Token::new(token_id, token_index, token_length));
412
413 continue 'code_loop;
414 } else if c == b'{' {
415 pc = c;
416
417 token_id = TokenId::CurlyBracketOpen;
418 token_index = code_index;
419 token_length = 1;
420
421 tokens.push(Token::new(token_id, token_index, token_length));
422
423 continue 'code_loop;
424 } else if c == b'}' {
425 pc = c;
426
427 token_id = TokenId::CurlyBracketClose;
428 token_index = code_index;
429 token_length = 1;
430
431 tokens.push(Token::new(token_id, token_index, token_length));
432
433 continue 'code_loop;
434 } else if c == b'"' {
435 pc = c;
436
437 start_double_quote_count = 1;
438
439 token_index = code_index;
440 token_length = 1;
441
442 state = State::StringAmbiguous;
443
444 continue 'code_loop;
445 } else if c == b';' {
446 if pc == b')' {
448 return Err(SyntaxError::ParsingError(ParsingError::new(
449 code,
450 code_index,
451 code_index,
452 ErrorCode::PotentialErroneousClosingDelimiterFollowedByComment,
453 "Unterminated potential erroneous closing delimiter followed by comment",
454 )));
455 }
456
457 pc = c;
458
459 token_index = code_index;
460 token_length = 1;
461
462 start_semicolon_count = 1;
463
464 state = State::CommentAmbiguous;
465
466 continue 'code_loop;
467 } else {
468 pc = c;
469
470 token_id = TokenId::Word;
471 token_index = code_index;
472 token_length = 1;
473
474 state = State::Word;
475
476 continue 'code_loop;
477 }
478 }
479 State::Whitespace => {
480 if c.is_ascii_whitespace() {
481 token_length += 1;
482
483 continue 'code_loop;
484 } else {
485 if include_whitespace {
487 tokens.push(Token::new(token_id, token_index, token_length));
488 }
489
490 state = State::Undetermined;
491
492 continue 'decision_loop;
493 }
494 }
495 State::CommentAmbiguous => {
496 if c == b';' {
503 token_length += 1;
506 start_semicolon_count += 1;
507
508 continue 'code_loop;
509 } else if c == b'(' {
510 multi_line_comment_stack.push(start_semicolon_count);
512
513 token_length += 1;
514
515 token_id = TokenId::CommentMultiLine;
516 state = State::CommentMultiLine;
517
518 attempting_to_open_comment = false;
519 attempting_to_close_comment = false;
520
521 continue 'code_loop;
522 } else if c == b'\n' {
523 token_id = TokenId::CommentSingleLine;
526
527 if include_comments {
528 tokens.push(Token::new(token_id, token_index, token_length));
529 }
530
531 state = State::Undetermined;
532
533 continue 'decision_loop;
534 } else {
535 token_length += 1;
538
539 token_id = TokenId::CommentSingleLine;
540
541 state = State::CommentSingleLine;
542
543 continue 'code_loop;
544 }
545 }
546 State::CommentSingleLine => {
547 if c == b'\n' {
558 if include_comments {
560 tokens.push(Token::new(token_id, token_index, token_length));
561 }
562
563 state = State::Undetermined;
564
565 continue 'decision_loop;
566 } else {
567 token_length += 1;
568
569 continue 'code_loop;
570 }
571 }
572 State::CommentMultiLine => {
573 if DEBUG {
586 let s: Vec<String> = (&multi_line_comment_stack)
587 .into_iter()
588 .map(|n| format!("{}{{", ";".repeat(*n)))
589 .collect();
590
591 println!(" Stack: {:?}", s);
592
593 if attempting_to_open_comment {
594 println!(" Opening?: {}", ";".repeat(start_semicolon_count));
595 } else if attempting_to_close_comment {
596 println!(" Closing?: ){}", ";".repeat(end_semicolon_count));
597 }
598 }
599
600 if attempting_to_open_comment {
603 if c == b';' {
604 start_semicolon_count += 1;
606 token_length += 1;
607
608 continue 'code_loop;
609 } else if c == b'(' {
610 attempting_to_open_comment = false;
611 token_length += 1;
613
614 multi_line_comment_stack.push(start_semicolon_count);
615
616 continue 'code_loop;
617 } else {
618 attempting_to_open_comment = false;
620
621 continue 'decision_loop;
622 }
623 } else if attempting_to_close_comment {
624 if c == b';' {
625 end_semicolon_count += 1;
626
627 token_length += 1;
628
629 continue 'code_loop;
630 } else {
631 if end_semicolon_count == 0 {
632 attempting_to_close_comment = false;
639
640 continue 'decision_loop;
641 } else {
642 attempting_to_close_comment = false;
651
652 let mut pop_off_stack = false;
655 let mut match_index = 0;
656
657 'stack_loop: for (i, stack_semicolon_count) in
659 multi_line_comment_stack.iter().enumerate().rev()
660 {
661 if end_semicolon_count < *stack_semicolon_count {
662 attempting_to_close_comment = false;
676
677 if DEBUG {
678 println!(" Dropped!");
679 }
680
681 continue 'decision_loop;
682 } else if end_semicolon_count == *stack_semicolon_count {
683 pop_off_stack = true;
693 match_index = i;
694
695 if DEBUG {
696 println!(" Matched!");
697 }
698
699 break 'stack_loop;
700 }
701 }
702
703 if pop_off_stack {
704 while multi_line_comment_stack.len() > match_index {
725 multi_line_comment_stack.pop();
726
727 if DEBUG {
728 println!(" Pop!");
729 }
730 }
731
732 if multi_line_comment_stack.len() == 0 {
736 if include_comments {
739 tokens.push(Token::new(
740 token_id,
741 token_index,
742 token_length,
743 ));
744 }
745
746 state = State::Undetermined;
747
748 continue 'decision_loop;
749 }
750 }
751
752 attempting_to_close_comment = false;
753
754 continue 'decision_loop;
755 }
756 }
757 } else {
758 if c == b';' {
759 token_length += 1;
760
761 attempting_to_open_comment = true;
762 start_semicolon_count = 1;
763
764 continue 'code_loop;
765 } else if c == b')' {
766 token_length += 1;
767
768 attempting_to_close_comment = true;
769 end_semicolon_count = 0;
770
771 continue 'code_loop;
772 } else {
773 token_length += 1;
774
775 continue 'code_loop;
776 }
777 }
778
779 }
781 State::StringAmbiguous => {
782 if c == b'"' {
787 token_length += 1;
788 start_double_quote_count += 1;
789
790 continue 'code_loop;
791 } else {
792 if start_double_quote_count == 1 {
793 token_length += 1;
795
796 pc = c;
797
798 token_id = TokenId::StringNormal;
799
800 state = State::StringNormal;
801
802 continue 'code_loop;
803 } else if start_double_quote_count == 2 {
804 token_id = TokenId::StringNormal;
807
808 tokens.push(Token::new(token_id, token_index, token_length));
809
810 state = State::Undetermined;
811
812 continue 'decision_loop;
813 } else {
814 token_id = TokenId::StringExtended;
816
817 state = State::StringExtendedConfig;
818
819 continue 'decision_loop;
822 }
823 }
824 }
825 State::StringNormal => {
826 token_length += 1;
827
828 if c == b'"' && pc != b'\\' {
829 tokens.push(Token::new(token_id, token_index, token_length));
831
832 state = State::Undetermined;
833 } else {
834 pc = c;
835 }
836
837 continue 'code_loop;
838 }
839 State::StringExtendedConfig => {
840 token_length += 1;
841
842 if c == b'.' || c == b',' {
843 state = State::StringExtendedBody;
846 }
847
848 continue 'code_loop;
849 }
850 State::StringExtendedBody => {
851 token_length += 1;
852
853 if c == b'.' || c == b',' {
854 end_double_quote_count = 0;
856
857 state = State::StringExtendedEnd;
858 }
859
860 continue 'code_loop;
861 }
862 State::StringExtendedEnd => {
863 if c == b'"' {
864 token_length += 1;
865 end_double_quote_count += 1;
866
867 if end_double_quote_count == start_double_quote_count {
868 tokens.push(Token::new(token_id, token_index, token_length));
870
871 state = State::Undetermined
872 }
873 } else if c == b'.' || c == b',' {
874 token_length += 1;
875 end_double_quote_count = 0;
876 } else {
877 token_length += 1;
878 state = State::StringExtendedBody;
879 }
880
881 continue 'code_loop;
882 }
883 State::Word => {
884 if c.is_ascii_whitespace()
889 || c == b'('
890 || c == b')'
891 || c == b'['
892 || c == b']'
893 || c == b'{'
894 || c == b'}'
895 || c == b'"'
896 || c == b';'
897 {
898 tokens.push(Token::new(token_id, token_index, token_length));
900
901 state = State::Undetermined;
902
903 continue 'decision_loop;
904 } else {
905 token_length += 1;
906 continue 'code_loop;
907 }
908 }
909 }
910 }
911 }
912
913 if DEBUG {
914 println!("> State = {:?} (end)", state);
916 println!("{}", "-".repeat(80));
917 }
918
919 match &state {
920 State::Undetermined => { }
921 State::Whitespace => {
922 if include_whitespace {
923 tokens.push(Token::new(token_id, token_index, token_length));
924 }
925 }
926 State::CommentAmbiguous => {
927 token_id = TokenId::CommentSingleLine;
929
930 if include_comments {
931 tokens.push(Token::new(token_id, token_index, token_length));
932 }
933 }
934 State::CommentSingleLine => {
935 if include_comments {
936 tokens.push(Token::new(token_id, token_index, token_length));
937 }
938 }
939 State::CommentMultiLine => {
940 let mut ok = false;
941
942 if attempting_to_close_comment {
946 if end_semicolon_count > 0 {
947 let mut pop_off_stack = false;
948 let mut match_index = 0;
949
950 'leftover_stack_loop: for (i, stack_semicolon_count) in
951 multi_line_comment_stack.iter().enumerate().rev()
952 {
953 if end_semicolon_count < *stack_semicolon_count {
954 break 'leftover_stack_loop;
955 } else if end_semicolon_count == *stack_semicolon_count {
956 pop_off_stack = true;
957 match_index = i;
958
959 break 'leftover_stack_loop;
960 }
961 }
962
963 if pop_off_stack {
964 while multi_line_comment_stack.len() > match_index {
965 multi_line_comment_stack.pop();
966 }
967
968 if multi_line_comment_stack.len() == 0 {
969 ok = true;
970
971 if include_comments {
972 tokens.push(Token::new(token_id, token_index, token_length));
973 }
974 }
975 }
976 }
977 }
978
979 if !ok {
983 return Err(SyntaxError::ParsingError(ParsingError::new(
986 code,
987 token_index,
988 code.len(),
989 ErrorCode::UnterminatedMultiLineComment,
990 "Unterminated multiline comment",
991 )));
992 }
993 }
994 State::StringAmbiguous => {
995 if start_double_quote_count == 1 {
996 return Err(SyntaxError::ParsingError(ParsingError::new(
998 code,
999 token_index,
1000 code.len(),
1001 ErrorCode::UnterminatedNormalString,
1002 "Unterminated normal string",
1003 )));
1004 } else if start_double_quote_count == 2 {
1005 token_id = TokenId::StringNormal;
1006 tokens.push(Token::new(token_id, token_index, token_length));
1008 } else {
1009 return Err(SyntaxError::ParsingError(ParsingError::new(
1011 code,
1012 token_index,
1013 code.len(),
1014 ErrorCode::UnterminatedExtendedString,
1015 "Unterminated extended string",
1016 )));
1017 }
1018 }
1019 State::StringNormal => {
1020 return Err(SyntaxError::ParsingError(ParsingError::new(
1022 code,
1023 token_index,
1024 code.len(),
1025 ErrorCode::UnterminatedNormalString,
1026 "Unterminated normal string",
1027 )));
1028 }
1029 State::StringExtendedConfig | State::StringExtendedBody | State::StringExtendedEnd => {
1030 return Err(SyntaxError::ParsingError(ParsingError::new(
1032 code,
1033 token_index,
1034 code.len(),
1035 ErrorCode::UnterminatedExtendedString,
1036 "Unterminated extended string",
1037 )));
1038 }
1039 State::Word => {
1040 tokens.push(Token::new(token_id, token_index, token_length));
1041 }
1042 }
1043
1044 Ok(tokens)
1045}
1046
1047#[derive(Debug)]
1051pub enum ParseNode {
1052 Token(Token),
1053 List(ParseNodeList),
1054}
1055
1056#[derive(Debug)]
1058pub struct ParseNodeList {
1059 pub index: usize,
1061 pub length: usize,
1063 pub children: Vec<ParseNode>,
1065}
1066
1067impl ParseNodeList {
1068 #[inline]
1070 fn new(index: usize) -> ParseNodeList {
1071 ParseNodeList {
1072 index,
1073 length: 0,
1074 children: Vec::new(),
1075 }
1076 }
1077
1078 fn add_child_length(&mut self, child: ParseNode) -> () {
1079 match &child {
1080 ParseNode::Token(token) => self.length += token.length,
1081 ParseNode::List(parse_node_list) => self.length += parse_node_list.length,
1082 }
1083 }
1084
1085 fn add_child(&mut self, child: ParseNode) -> () {
1086 match &child {
1087 ParseNode::Token(token) => self.length += token.length,
1088 ParseNode::List(parse_node_list) => self.length += parse_node_list.length,
1089 }
1090 self.children.push(child);
1091 }
1092}
1093
1094pub fn parse(
1096 code: &str,
1097 include_comments: bool,
1098 include_whitespace: bool,
1099 include_list_delimiters: bool,
1100) -> Result<Vec<ParseNode>, SyntaxError> {
1101 let tokens: Vec<Token>;
1102
1103 match tokenize(code, include_comments, include_whitespace) {
1104 Err(parsing_error) => {
1105 return Err(parsing_error);
1106 }
1107 Ok(result_tokens) => {
1108 tokens = result_tokens;
1109 }
1110 }
1111
1112 let mut parse_node_list_stack = Vec::new();
1113
1114 parse_node_list_stack.push(ParseNodeList::new(0));
1115
1116 let mut open_bracket_token_stack = Vec::new();
1117
1118 fn brackets_match(open_bracket: TokenId, close_bracket: TokenId) -> Result<bool, SyntaxError> {
1119 match open_bracket {
1120 TokenId::RoundBracketOpen => match close_bracket {
1121 TokenId::RoundBracketClose => return Ok(true),
1122 TokenId::CurlyBracketClose => return Ok(false),
1123 TokenId::SquareBracketClose => return Ok(false),
1124 _ => {
1125 return Err(SyntaxError::AssumptionError(
1126 "Logic error in brackets_match (1).".to_string(),
1127 ))
1128 }
1129 },
1130 TokenId::CurlyBracketOpen => match close_bracket {
1131 TokenId::RoundBracketClose => return Ok(false),
1132 TokenId::CurlyBracketClose => return Ok(true),
1133 TokenId::SquareBracketClose => return Ok(false),
1134 _ => {
1135 return Err(SyntaxError::AssumptionError(
1136 "Logic error in brackets_match (2).".to_string(),
1137 ))
1138 }
1139 },
1140 TokenId::SquareBracketOpen => match close_bracket {
1141 TokenId::RoundBracketClose => return Ok(false),
1142 TokenId::CurlyBracketClose => return Ok(false),
1143 TokenId::SquareBracketClose => return Ok(true),
1144 _ => {
1145 return Err(SyntaxError::AssumptionError(
1146 "Logic error in brackets_match (3).".to_string(),
1147 ))
1148 }
1149 },
1150 _ => {
1151 return Err(SyntaxError::AssumptionError(
1152 "Logic error in brackets_match (4).".to_string(),
1153 ))
1154 }
1155 }
1156 }
1157
1158 for token in tokens {
1159 match token.id {
1160 TokenId::Whitespace => {
1161 let parse_node_list = parse_node_list_stack.last_mut().unwrap();
1162
1163 if include_comments {
1164 parse_node_list.add_child(ParseNode::Token(token));
1165 } else {
1166 parse_node_list.add_child_length(ParseNode::Token(token));
1167 }
1168 }
1169 TokenId::CommentSingleLine | TokenId::CommentMultiLine => {
1170 let parse_node_list = parse_node_list_stack.last_mut().unwrap();
1171
1172 if include_comments {
1173 parse_node_list.add_child(ParseNode::Token(token));
1174 } else {
1175 parse_node_list.add_child_length(ParseNode::Token(token));
1176 }
1177 }
1178 TokenId::Word | TokenId::StringNormal | TokenId::StringExtended => {
1179 parse_node_list_stack
1180 .last_mut()
1181 .unwrap()
1182 .add_child(ParseNode::Token(token));
1183 }
1184 TokenId::RoundBracketOpen | TokenId::SquareBracketOpen | TokenId::CurlyBracketOpen => {
1185 parse_node_list_stack.push(ParseNodeList::new(token.index));
1187
1188 if include_list_delimiters {
1189 parse_node_list_stack
1190 .last_mut()
1191 .unwrap()
1192 .add_child(ParseNode::Token(token.clone()));
1193 }
1194
1195 open_bracket_token_stack.push(token);
1196 }
1197 TokenId::RoundBracketClose
1198 | TokenId::SquareBracketClose
1199 | TokenId::CurlyBracketClose => {
1200 match open_bracket_token_stack.pop() {
1202 None => {
1203 let parsing_error = ParsingError::new(
1206 code.as_bytes(),
1207 0,
1208 0,
1209 ErrorCode::UnexpectedClosingDelimiter,
1210 "Unexpected closing delimiter",
1211 );
1212
1213 return Err(SyntaxError::ParsingError(parsing_error));
1214 }
1215 Some(open_bracket) => {
1216 if brackets_match(open_bracket.id, token.id)? {
1217 if include_list_delimiters {
1218 parse_node_list_stack
1219 .last_mut()
1220 .unwrap()
1221 .add_child(ParseNode::Token(token));
1222 }
1223
1224 let parse_node_level = parse_node_list_stack.pop().unwrap();
1225
1226 parse_node_list_stack
1227 .last_mut()
1228 .unwrap()
1229 .add_child(ParseNode::List(parse_node_level));
1230 } else {
1231 let parsing_error = ParsingError::new(
1234 code.as_bytes(),
1235 0,
1236 0,
1237 ErrorCode::DelimiterMismatch,
1238 "Delimiter mismatch",
1239 );
1240
1241 return Err(SyntaxError::ParsingError(parsing_error));
1242 }
1243 }
1244 }
1245 }
1246 }
1247 }
1248
1249 if parse_node_list_stack.len() != 1 {
1250 let parsing_error = ParsingError::new(
1253 code.as_bytes(),
1254 0,
1255 0,
1256 ErrorCode::UnclosedDelimiter,
1257 "Unclosed delimiter mismatch",
1258 );
1259
1260 return Err(SyntaxError::ParsingError(parsing_error));
1261 }
1262
1263 let parse_trees = parse_node_list_stack.pop().unwrap().children;
1264
1265 return Ok(parse_trees);
1266}
1267
1268#[cfg(test)]
1269mod test_tokenizer {
1270 use super::tokenize as original_tokenize;
1271 use super::*;
1272
1273 #[inline]
1274 fn tokenize(code: &str) -> Result<Vec<Token>, SyntaxError> {
1275 return original_tokenize(code, true, true);
1276 }
1277
1278 #[inline]
1280 fn assert_eq_code_and_tokens_length(code: &str, tokens: &Vec<Token>) {
1281 let m = code.len();
1282
1283 let mut n = 0;
1284
1285 for token in tokens {
1286 n += token.length;
1287 }
1288
1289 assert_eq!(m, n);
1290 }
1291
1292 fn assert_code_is_ok(code: &str) {
1293 let tokenization_result = tokenize(code);
1294 match tokenization_result {
1295 Ok(_) => (),
1296 Err(syntax_error) => match syntax_error {
1297 SyntaxError::ParsingError(parsing_error) => panic!(parsing_error.error_message),
1298 SyntaxError::AssumptionError(error_message) => panic!(error_message),
1299 },
1300 }
1301 }
1302
1303 fn assert_code_is_not_ok(code: &str) {
1304 let tokenization_result = tokenize(code);
1305 match tokenization_result {
1306 Ok(_) => {
1307 panic!();
1308 }
1309 Err(_) => (),
1310 }
1311 }
1312
1313 #[test]
1316 fn test_misc() {
1317 assert_code_is_ok("");
1318 assert_code_is_ok(" ");
1319
1320 if HAS_ISSUE_132 {
1321 assert_code_is_not_ok(");");
1322 assert_code_is_not_ok(";(););");
1323
1324 assert_code_is_ok(";();");
1325 assert_code_is_ok(";(;(););");
1326 assert_code_is_ok(";(;(;();););");
1327
1328 assert_code_is_ok(";;();;");
1329
1330 assert_code_is_ok(";;(;;();;);;");
1332
1333 assert_code_is_not_ok(";(;;();;););");
1334 }
1335 }
1336
1337 #[test]
1338 fn test_icelandic_name() {
1339 assert_code_is_ok(r#"(var name "DavÃð")"#)
1340 }
1341
1342 #[test]
1343 fn test_whitespace() {
1344 {
1345 let code = r#" "#;
1346
1347 let tokenization_result = tokenize(code);
1348 let tokens = tokenization_result.unwrap();
1349
1350 assert_eq_code_and_tokens_length(code, &tokens);
1351
1352 assert!(tokens.len() == 1);
1353
1354 let token = &tokens[0];
1355
1356 assert!(token.id == TokenId::Whitespace);
1357 assert!(token.index == 0);
1358 assert!(token.length == 1);
1359 }
1360 }
1361
1362 #[test]
1363 fn test_word() {
1364 {
1365 let code = r#"hallo"#;
1366
1367 let tokenization_result = tokenize(code);
1368 let tokens = tokenization_result.unwrap();
1369
1370 assert_eq_code_and_tokens_length(code, &tokens);
1371
1372 assert!(tokens.len() == 1);
1373
1374 let token = &tokens[0];
1375
1376 assert!(token.id == TokenId::Word);
1377 assert!(token.index == 0);
1378 assert!(token.length == 5);
1379 }
1380 }
1381
1382 #[test]
1383 fn test_round_bracket_open() {
1384 {
1385 let code = r#"()"#;
1386
1387 let tokenization_result = tokenize(code);
1388 let tokens = tokenization_result.unwrap();
1389
1390 assert_eq_code_and_tokens_length(code, &tokens);
1391
1392 assert!(tokens.len() == 2);
1393
1394 let token = &tokens[0];
1395
1396 assert!(token.id == TokenId::RoundBracketOpen);
1397 assert!(token.index == 0);
1398 assert!(token.length == 1);
1399 }
1400 }
1401
1402 #[test]
1403 fn test_round_bracket_close() {
1404 {
1405 let code = r#"()"#;
1406
1407 let tokenization_result = tokenize(code);
1408 let tokens = tokenization_result.unwrap();
1409
1410 assert_eq_code_and_tokens_length(code, &tokens);
1411
1412 assert!(tokens.len() == 2);
1413
1414 let token = &tokens[1];
1415
1416 assert!(token.id == TokenId::RoundBracketClose);
1417 assert!(token.index == 1);
1418 assert!(token.length == 1);
1419 }
1420 }
1421
1422 #[test]
1423 fn test_curly_bracket_open() {
1424 {
1425 let code = r#"{}"#;
1426
1427 let tokenization_result = tokenize(code);
1428 let tokens = tokenization_result.unwrap();
1429
1430 assert_eq_code_and_tokens_length(code, &tokens);
1431
1432 assert!(tokens.len() == 2);
1433
1434 let token = &tokens[0];
1435
1436 assert!(token.id == TokenId::CurlyBracketOpen);
1437 assert!(token.index == 0);
1438 assert!(token.length == 1);
1439 }
1440 }
1441
1442 #[test]
1443 fn test_curly_bracket_close() {
1444 {
1445 let code = r#"{}"#;
1446
1447 let tokenization_result = tokenize(code);
1448 let tokens = tokenization_result.unwrap();
1449
1450 assert_eq_code_and_tokens_length(code, &tokens);
1451
1452 assert!(tokens.len() == 2);
1453
1454 let token = &tokens[1];
1455
1456 assert!(token.id == TokenId::CurlyBracketClose);
1457 assert!(token.index == 1);
1458 assert!(token.length == 1);
1459 }
1460 }
1461
1462 #[test]
1463 fn test_square_bracket_open() {
1464 {
1465 let code = r#"[]"#;
1466
1467 let tokenization_result = tokenize(code);
1468 let tokens = tokenization_result.unwrap();
1469
1470 assert_eq_code_and_tokens_length(code, &tokens);
1471
1472 assert!(tokens.len() == 2);
1473
1474 let token = &tokens[0];
1475
1476 assert!(token.id == TokenId::SquareBracketOpen);
1477 assert!(token.index == 0);
1478 assert!(token.length == 1);
1479 }
1480 }
1481
1482 #[test]
1483 fn test_suqare_bracket_close() {
1484 {
1485 let code = r#"[]"#;
1486
1487 let tokenization_result = tokenize(code);
1488 let tokens = tokenization_result.unwrap();
1489
1490 assert_eq_code_and_tokens_length(code, &tokens);
1491
1492 assert!(tokens.len() == 2);
1493
1494 let token = &tokens[1];
1495
1496 assert!(token.id == TokenId::SquareBracketClose);
1497 assert!(token.index == 1);
1498 assert!(token.length == 1);
1499 }
1500 }
1501
1502 #[test]
1503 fn test_string_normal() {
1504 {
1505 let code = r#""hallo""#;
1506
1507 let tokenization_result = tokenize(code);
1508 let tokens = tokenization_result.unwrap();
1509
1510 assert_eq_code_and_tokens_length(code, &tokens);
1511
1512 assert!(tokens.len() == 1);
1513
1514 let token = &tokens[0];
1515
1516 assert!(token.id == TokenId::StringNormal);
1517 assert!(token.index == 0);
1518 assert!(token.length == 7);
1519 }
1520 }
1521
1522 #[test]
1523 fn test_string_extended() {
1524 {
1525 let code = r#"""".hallo.""""#;
1526
1527 let tokenization_result = tokenize(code);
1528 let tokens = tokenization_result.unwrap();
1529
1530 assert_eq_code_and_tokens_length(code, &tokens);
1531
1532 assert!(tokens.len() == 1);
1533
1534 let token = &tokens[0];
1535
1536 assert!(token.id == TokenId::StringExtended);
1537 assert!(token.index == 0);
1538 assert!(token.length == 13);
1539 }
1540 {
1541 let code = r#"""",hallo.""""#;
1542
1543 let tokenization_result = tokenize(code);
1544 let tokens = tokenization_result.unwrap();
1545
1546 assert_eq_code_and_tokens_length(code, &tokens);
1547
1548 assert!(tokens.len() == 1);
1549
1550 let token = &tokens[0];
1551
1552 assert!(token.id == TokenId::StringExtended);
1553 assert!(token.index == 0);
1554 assert!(token.length == 13);
1555 }
1556 {
1557 let code = r#"""".hallo,""""#;
1558
1559 let tokenization_result = tokenize(code);
1560 let tokens = tokenization_result.unwrap();
1561
1562 assert_eq_code_and_tokens_length(code, &tokens);
1563
1564 assert!(tokens.len() == 1);
1565
1566 let token = &tokens[0];
1567
1568 assert!(token.id == TokenId::StringExtended);
1569 assert!(token.index == 0);
1570 assert!(token.length == 13);
1571 }
1572 {
1573 let code = r#"""",hallo,""""#;
1574
1575 let tokenization_result = tokenize(code);
1576 let tokens = tokenization_result.unwrap();
1577
1578 assert_eq_code_and_tokens_length(code, &tokens);
1579
1580 assert!(tokens.len() == 1);
1581
1582 let token = &tokens[0];
1583
1584 assert!(token.id == TokenId::StringExtended);
1585 assert!(token.index == 0);
1586 assert!(token.length == 13);
1587 }
1588 }
1589
1590 #[test]
1591 fn test_comment_single_line() {
1592 {
1593 let code = r#";"#;
1594
1595 let tokenization_result = tokenize(code);
1596 let tokens = tokenization_result.unwrap();
1597
1598 assert_eq_code_and_tokens_length(code, &tokens);
1599
1600 assert!(tokens.len() == 1);
1601
1602 let token = &tokens[0];
1603
1604 assert!(token.id == TokenId::CommentSingleLine);
1605 assert!(token.index == 0);
1606 assert!(token.length == 1);
1607 }
1608 {
1609 let code = r#"; "#;
1610
1611 let tokenization_result = tokenize(code);
1612 let tokens = tokenization_result.unwrap();
1613
1614 assert_eq_code_and_tokens_length(code, &tokens);
1615
1616 assert!(tokens.len() == 1);
1617
1618 let token = &tokens[0];
1619
1620 assert!(token.id == TokenId::CommentSingleLine);
1621 assert!(token.index == 0);
1622 assert!(token.length == 2);
1623 }
1624 {
1625 let code = r#";a"#;
1626
1627 let tokenization_result = tokenize(code);
1628 let tokens = tokenization_result.unwrap();
1629
1630 assert_eq_code_and_tokens_length(code, &tokens);
1631
1632 assert!(tokens.len() == 1);
1633
1634 let token = &tokens[0];
1635
1636 assert!(token.id == TokenId::CommentSingleLine);
1637 assert!(token.index == 0);
1638 assert!(token.length == 2);
1639 }
1640 {
1641 let code = r#"; a"#;
1642
1643 let tokenization_result = tokenize(code);
1644 let tokens = tokenization_result.unwrap();
1645
1646 assert_eq_code_and_tokens_length(code, &tokens);
1647
1648 assert!(tokens.len() == 1);
1649
1650 let token = &tokens[0];
1651
1652 assert!(token.id == TokenId::CommentSingleLine);
1653 assert!(token.index == 0);
1654 assert!(token.length == 3);
1655 }
1656 {
1657 let code = r#";;"#;
1658
1659 let tokenization_result = tokenize(code);
1660 let tokens = tokenization_result.unwrap();
1661
1662 assert_eq_code_and_tokens_length(code, &tokens);
1663
1664 assert!(tokens.len() == 1);
1665
1666 let token = &tokens[0];
1667
1668 assert!(token.id == TokenId::CommentSingleLine);
1669 assert!(token.index == 0);
1670 assert!(token.length == 2);
1671 }
1672 {
1673 let code = r#";;;"#;
1674
1675 let tokenization_result = tokenize(code);
1676 let tokens = tokenization_result.unwrap();
1677
1678 assert_eq_code_and_tokens_length(code, &tokens);
1679
1680 assert!(tokens.len() == 1);
1681
1682 let token = &tokens[0];
1683
1684 assert!(token.id == TokenId::CommentSingleLine);
1685 assert!(token.index == 0);
1686 assert!(token.length == 3);
1687 }
1688 }
1689
1690 #[test]
1691 fn test_comment_multi_line_1() {
1692 assert_code_is_ok(";();");
1693 }
1694
1695 #[test]
1696 fn test_comment_multi_line_2() {
1697 assert_code_is_not_ok(";;();");
1698 }
1699
1700 #[test]
1701 fn test_comment_multi_line_3() {
1702 assert_code_is_not_ok(";();;");
1703 }
1704
1705 #[test]
1706 fn test_comment_multi_line_4() {
1707 assert_code_is_not_ok(";(;;();");
1709 }
1710
1711 #[test]
1712 fn test_comment_multi_line_5() {
1713 let code = r#";();"#;
1714
1715 let tokenization_result = tokenize(code);
1716 let tokens = tokenization_result.unwrap();
1717
1718 assert_eq_code_and_tokens_length(code, &tokens);
1719
1720 assert!(tokens.len() == 1);
1721
1722 let token = &tokens[0];
1723
1724 assert!(token.id == TokenId::CommentMultiLine);
1725 assert!(token.index == 0);
1726 assert!(token.length == 4);
1727 }
1728
1729 #[test]
1730 fn test_comment_multi_line_6() {
1731 let code = r#" ;(;();); "#;
1732
1733 let tokenization_result = tokenize(code);
1734 let tokens = tokenization_result.unwrap();
1735
1736 assert_eq_code_and_tokens_length(code, &tokens);
1737
1738 assert!(tokens.len() == 3);
1739
1740 let token = &tokens[1];
1741
1742 assert!(token.id == TokenId::CommentMultiLine);
1743 assert!(token.index == 1);
1744 assert!(token.length == 8);
1745 }
1746
1747 #[test]
1748 fn test_comment_multi_line_7() {
1749 let code = r#";(;(););"#;
1750
1751 let tokenization_result = tokenize(code);
1752 let tokens = tokenization_result.unwrap();
1753
1754 assert_eq_code_and_tokens_length(code, &tokens);
1755
1756 assert!(tokens.len() == 1);
1757
1758 let token = &tokens[0];
1759
1760 assert!(token.id == TokenId::CommentMultiLine);
1761 assert!(token.index == 0);
1762 assert!(token.length == 8);
1763 }
1764
1765 #[test]
1766 fn test_comment_multi_line_8() {
1767 let code = r#" ;(;(););"#;
1768
1769 let tokenization_result = tokenize(code);
1770 let tokens = tokenization_result.unwrap();
1771
1772 assert_eq_code_and_tokens_length(code, &tokens);
1773
1774 assert!(tokens.len() == 2);
1775
1776 let token = &tokens[1];
1777
1778 assert!(token.id == TokenId::CommentMultiLine);
1779 assert!(token.index == 1);
1780 assert!(token.length == 8);
1781 }
1782
1783 #[test]
1784 fn test_comment_multi_line_9() {
1785 let code = r#";(;();); "#;
1786
1787 let tokenization_result = tokenize(code);
1788 let tokens = tokenization_result.unwrap();
1789
1790 assert_eq_code_and_tokens_length(code, &tokens);
1791
1792 assert!(tokens.len() == 2);
1793
1794 let token = &tokens[0];
1795
1796 assert!(token.id == TokenId::CommentMultiLine);
1797 assert!(token.index == 0);
1798 assert!(token.length == 8);
1799 }
1800
1801 #[test]
1802 fn test_empty_normal_string() {
1803 let code = r#""""#;
1804
1805 let tokenization_result = tokenize(code);
1806 let tokens = tokenization_result.unwrap();
1807
1808 assert_eq_code_and_tokens_length(code, &tokens);
1809
1810 assert!(tokens.len() == 1);
1811
1812 let token = &tokens[0];
1813
1814 assert!(token.id == TokenId::StringNormal);
1815 assert!(token.index == 0);
1816 assert!(token.length == 2);
1817 }
1818
1819 #[test]
1820 fn test_unterminated_normal_string() {
1821 {
1822 let code = r#"""#;
1823 let tokenization_result = tokenize(code);
1824 match tokenization_result {
1825 Err(syntax_error) => match syntax_error {
1826 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1827 parsing_error.error_code,
1828 ErrorCode::UnterminatedNormalString
1829 ),
1830 _ => panic!(),
1831 },
1832 _ => panic!(),
1833 }
1834 }
1835 {
1836 let code = r#""a"#;
1837 let tokenization_result = tokenize(code);
1838
1839 match tokenization_result {
1840 Err(syntax_error) => match syntax_error {
1841 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1842 parsing_error.error_code,
1843 ErrorCode::UnterminatedNormalString
1844 ),
1845 _ => panic!(),
1846 },
1847 _ => panic!(),
1848 }
1849 }
1850 {
1851 let code = r#""a\"#;
1852 let tokenization_result = tokenize(code);
1853
1854 match tokenization_result {
1855 Err(syntax_error) => match syntax_error {
1856 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1857 parsing_error.error_code,
1858 ErrorCode::UnterminatedNormalString
1859 ),
1860 _ => panic!(),
1861 },
1862 _ => panic!(),
1863 }
1864 }
1865 {
1866 let code = r#""a\""#;
1867 let tokenization_result = tokenize(code);
1868
1869 match tokenization_result {
1870 Err(syntax_error) => match syntax_error {
1871 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1872 parsing_error.error_code,
1873 ErrorCode::UnterminatedNormalString
1874 ),
1875 _ => panic!(),
1876 },
1877 _ => panic!(),
1878 }
1879 }
1880 {
1881 let tokenization_result = tokenize(r#""a\"c"#);
1882
1883 match tokenization_result {
1884 Err(syntax_error) => match syntax_error {
1885 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1886 parsing_error.error_code,
1887 ErrorCode::UnterminatedNormalString
1888 ),
1889 _ => panic!(),
1890 },
1891 _ => panic!(),
1892 }
1893 }
1894 }
1895
1896 #[test]
1897 fn test_unterminated_extended_string() {
1898 {
1899 let code = r#"""""#;
1900 let tokenization_result = tokenize(code);
1901
1902 match tokenization_result {
1903 Err(syntax_error) => match syntax_error {
1904 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1905 parsing_error.error_code,
1906 ErrorCode::UnterminatedExtendedString
1907 ),
1908 _ => panic!(),
1909 },
1910 _ => panic!(),
1911 }
1912 }
1913 {
1914 let code = r#""""."#;
1915 let tokenization_result = tokenize(code);
1916
1917 match tokenization_result {
1918 Err(syntax_error) => match syntax_error {
1919 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1920 parsing_error.error_code,
1921 ErrorCode::UnterminatedExtendedString
1922 ),
1923 _ => panic!(),
1924 },
1925 _ => panic!(),
1926 }
1927 }
1928 {
1929 let code = r#"""".""#;
1930 let tokenization_result = tokenize(code);
1931
1932 match tokenization_result {
1933 Err(syntax_error) => match syntax_error {
1934 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1935 parsing_error.error_code,
1936 ErrorCode::UnterminatedExtendedString
1937 ),
1938 _ => panic!(),
1939 },
1940 _ => panic!(),
1941 }
1942 }
1943 {
1944 let code = r#""""."""#;
1945 let tokenization_result = tokenize(code);
1946
1947 match tokenization_result {
1948 Err(syntax_error) => match syntax_error {
1949 SyntaxError::ParsingError(parsing_error) => assert_eq!(
1950 parsing_error.error_code,
1951 ErrorCode::UnterminatedExtendedString
1952 ),
1953 _ => panic!(),
1954 },
1955 _ => panic!(),
1956 }
1957 }
1958 }
1959}
1960
1961#[cfg(test)]
1962mod test_parser {
1963 use super::*;
1964
1965 fn assert_code_is_ok(code: &str) {
1966 let result = parse(code, true, true, true);
1968 match result {
1969 Ok(_) => (),
1970 Err(syntax_error) => match syntax_error {
1971 SyntaxError::ParsingError(parsing_error) => panic!(parsing_error.error_message),
1972 SyntaxError::AssumptionError(error_message) => panic!(error_message),
1973 },
1974 }
1975 }
1976
1977 fn assert_code_is_not_ok(code: &str) {
1978 let result = parse(code, true, true, true);
1980 match result {
1981 Ok(_) => {
1982 panic!();
1983 }
1984 Err(_) => (),
1985 }
1986 }
1987
1988 #[test]
1989 fn test_misc() {
1990 assert_code_is_ok("");
1991 assert_code_is_ok(" ");
1992
1993 assert_code_is_ok("()");
1994
1995 assert_code_is_ok("(())");
1996
1997 assert_code_is_ok("((()))");
1998
1999 assert_code_is_ok("((())())");
2000
2001 assert_code_is_ok("()");
2002 assert_code_is_ok("[]");
2003 assert_code_is_ok("{}");
2004
2005 assert_code_is_ok("(())");
2006 assert_code_is_ok("([])");
2007 assert_code_is_ok("({})");
2008
2009 assert_code_is_ok("[()]");
2010 assert_code_is_ok("[[]]");
2011 assert_code_is_ok("[{}]");
2012
2013 assert_code_is_ok("{()}");
2014 assert_code_is_ok("{[]}");
2015 assert_code_is_ok("{{}}");
2016 }
2017
2018 #[test]
2019 fn test_unexpected_closing_delimiter() {
2020 assert_code_is_not_ok(r#")"#);
2021 assert_code_is_not_ok(r#"]"#);
2022 assert_code_is_not_ok(r#"}"#);
2023 }
2024
2025 #[test]
2026 fn test_delimiter_mismatch() {
2027 assert_code_is_not_ok(r#"(]"#);
2028 assert_code_is_not_ok(r#"(}"#);
2029 assert_code_is_not_ok(r#"[)"#);
2030 assert_code_is_not_ok(r#"[}"#);
2031 assert_code_is_not_ok(r#"{)"#);
2032 assert_code_is_not_ok(r#"{]"#);
2033 }
2034
2035 #[test]
2036 fn test_unclosed_delimiter() {
2037 assert_code_is_not_ok(r#" ( "#);
2038
2039 assert_code_is_not_ok(r#"("#);
2040 assert_code_is_not_ok(r#"["#);
2041 assert_code_is_not_ok(r#"{"#);
2042 }
2043}
2044
2045#[cfg(test)]
2046mod test_lib {
2047 use super::{parse, ParseNode};
2048 use std::error::Error;
2049
2050 fn t1() -> Result<Vec<ParseNode>, Box<dyn Error>> {
2051 let code = " ( hello )) ";
2052
2053 let result = parse(code, false, false, false)?;
2054
2055 Ok(result)
2056 }
2057
2058 #[test]
2059 fn test_1() {
2060 let result = t1();
2061
2062 println!("-> {:?}", result);
2063 }
2064}