Skip to main content

nargo_parser/
oak_script_parser.rs

1use crate::{ParseState, ScriptParser};
2use nargo_ir::{JsExpr, JsProgram, JsStmt, Trivia};
3use nargo_types::{Position, Result, Span};
4use oak_core::{parser::ParseSession, tree::RedTree, Parser, SourceText};
5use oak_typescript::{TypeScriptElementType, TypeScriptLanguage, TypeScriptParser};
6
7/// 基于 oak-typescript 的脚本解析器
8pub struct OakTypeScriptParser;
9
10impl ScriptParser for OakTypeScriptParser {
11    fn parse(&self, state: &mut ParseState, _lang: &str) -> Result<JsProgram> {
12        let source = SourceText::new(state.cursor.source.to_string());
13        let language = TypeScriptLanguage::default();
14        let parser = TypeScriptParser::new(&language);
15        let mut session = ParseSession::default();
16        let parse_output = parser.parse(&source, &[], &mut session);
17
18        // 将 green 树转换为 red 树,获取包含位置信息的 AST
19        let green_node = parse_output.result.map_err(|e| nargo_types::Error::parse_error(format!("TypeScript parsing error: {:?}", e), Span::default()))?;
20        let red_tree = RedTree::new(green_node);
21
22        // 转换 oak-typescript 的解析结果为项目的 IR 格式
23        let program = self.convert_to_ir(&red_tree, &source);
24        Ok(program)
25    }
26}
27
28impl OakTypeScriptParser {
29    /// 将 oak-typescript 的解析结果转换为项目的 IR 格式
30    fn convert_to_ir(&self, tree: &RedTree<'_, TypeScriptLanguage>, source: &SourceText) -> JsProgram {
31        let mut body = Vec::new();
32        self.convert_node(tree, source, &mut body);
33
34        let span = if let RedTree::Node(node) = tree { Span { start: Position::new(1, 1, node.span().start as u32), end: Position::new(1, 1, node.span().end as u32) } } else { Span { start: Position::new(1, 1, 0), end: Position::new(1, 1, 0) } };
35
36        JsProgram { body, span, trivia: Trivia::default() }
37    }
38
39    /// 转换单个节点
40    fn convert_node(&self, tree: &RedTree<'_, TypeScriptLanguage>, source: &SourceText, result: &mut Vec<JsStmt>) {
41        match tree {
42            RedTree::Node(node) => {
43                match node.element_type() {
44                    _ => {
45                        // 处理所有节点类型
46                        // 暂时添加一个空的表达式语句
47                        let span = Span { start: Position::new(1, 1, node.span().start as u32), end: Position::new(1, 1, node.span().end as u32) };
48                        result.push(JsStmt::Expr(JsExpr::Other("".to_string(), Span::default(), Trivia::default()), span, Trivia::default()));
49                    }
50                }
51            }
52            RedTree::Leaf(_) => {
53                // 叶子节点已经在父节点中处理
54            }
55        }
56    }
57}