wxml_parser_rs/parser/
mod.rs1use serde_json::Value;
2
3mod ast_builder;
4mod cursor;
5mod error;
6mod eslint;
7mod scanner;
8pub mod ir;
9mod script;
10mod serialize;
11mod syntax;
12
13use cursor::Cursor;
14use ir::{NodeIr, ParsedProgram};
15pub(crate) use serialize::{serialize_program, serialize_program_to_string};
16
17pub use eslint::{parse_for_eslint_json, parse_for_eslint_json_string};
18
19pub(crate) struct Parser<'a> {
20 pub(crate) src: &'a str,
21 pub(crate) bytes: &'a [u8],
22 pub(crate) i: usize,
23 pub(crate) line: usize,
24 pub(crate) col: usize,
25 pub(crate) errors: Vec<ir::ParseErrorIr>,
26 pub(crate) emit_script_program: bool,
27}
28
29impl<'a> Parser<'a> {
30 fn new_with_mode(src: &'a str, emit_script_program: bool) -> Self {
31 Self {
32 src,
33 bytes: src.as_bytes(),
34 i: 0,
35 line: 1,
36 col: 1,
37 errors: vec![],
38 emit_script_program,
39 }
40 }
41
42 #[inline(always)]
43 pub(crate) fn is_name_char(c: u8) -> bool {
44 c.is_ascii_alphanumeric() || matches!(c, b':' | b'_' | b'-' | b'.')
45 }
46
47 pub(crate) fn parse_name(&mut self) -> Option<&'a str> {
48 let start = self.i;
49 self.skip_ascii_while(Self::is_name_char);
50 if self.i > start {
51 Some(self.safe_slice(start, self.i))
52 } else {
53 None
54 }
55 }
56}
57
58pub fn parse_json(code: &str) -> Value {
59 parse_json_with_mode(code, false)
60}
61
62pub fn parse_json_string(code: &str) -> String {
66 serialize_program_to_string(&parse_program_with_mode(code, false))
67}
68
69pub(crate) fn parse_json_with_mode(code: &str, emit_script_program: bool) -> Value {
70 serialize_program(parse_program_with_mode(code, emit_script_program))
71}
72
73pub fn parse_program_with_mode(code: &str, emit_script_program: bool) -> ParsedProgram<'_> {
74 if code.is_empty() {
75 return ParsedProgram {
76 body: vec![],
77 comment_indices: vec![],
78 errors: vec![],
79 end_line: 0,
80 end_col: 0,
81 code_len: 0,
82 };
83 }
84
85 let mut p = Parser::new_with_mode(code, emit_script_program);
86 let body = p.parse_document();
87
88 let comment_indices = body
89 .iter()
90 .enumerate()
91 .filter_map(|(idx, n)| {
92 if matches!(n, NodeIr::Comment { .. }) {
93 Some(idx)
94 } else {
95 None
96 }
97 })
98 .collect();
99
100 ParsedProgram {
101 body,
102 comment_indices,
103 errors: p.errors,
104 end_line: p.line,
105 end_col: p.col,
106 code_len: code.len(),
107 }
108}
109
110#[allow(dead_code)]
111fn _keep_cursor(_c: Cursor) {}