nargo-parser 0.0.0

Nargo parser component
Documentation
use crate::{ParseState, ScriptParser};
use nargo_ir::{JsExpr, JsProgram, JsStmt, Trivia};
use nargo_types::{Position, Result, Span};
use oak_core::{parser::ParseSession, tree::RedTree, Parser, SourceText};
use oak_typescript::{TypeScriptElementType, TypeScriptLanguage, TypeScriptParser};

/// 基于 oak-typescript 的脚本解析器
pub struct OakTypeScriptParser;

impl ScriptParser for OakTypeScriptParser {
    fn parse(&self, state: &mut ParseState, _lang: &str) -> Result<JsProgram> {
        let source = SourceText::new(state.cursor.source.to_string());
        let language = TypeScriptLanguage::default();
        let parser = TypeScriptParser::new(&language);
        let mut session = ParseSession::default();
        let parse_output = parser.parse(&source, &[], &mut session);

        // 将 green 树转换为 red 树,获取包含位置信息的 AST
        let green_node = parse_output.result.map_err(|e| nargo_types::Error::parse_error(format!("TypeScript parsing error: {:?}", e), Span::default()))?;
        let red_tree = RedTree::new(green_node);

        // 转换 oak-typescript 的解析结果为项目的 IR 格式
        let program = self.convert_to_ir(&red_tree, &source);
        Ok(program)
    }
}

impl OakTypeScriptParser {
    /// 将 oak-typescript 的解析结果转换为项目的 IR 格式
    fn convert_to_ir(&self, tree: &RedTree<'_, TypeScriptLanguage>, source: &SourceText) -> JsProgram {
        let mut body = Vec::new();
        self.convert_node(tree, source, &mut body);

        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) } };

        JsProgram { body, span, trivia: Trivia::default() }
    }

    /// 转换单个节点
    fn convert_node(&self, tree: &RedTree<'_, TypeScriptLanguage>, source: &SourceText, result: &mut Vec<JsStmt>) {
        match tree {
            RedTree::Node(node) => {
                match node.element_type() {
                    _ => {
                        // 处理所有节点类型
                        // 暂时添加一个空的表达式语句
                        let span = Span { start: Position::new(1, 1, node.span().start as u32), end: Position::new(1, 1, node.span().end as u32) };
                        result.push(JsStmt::Expr(JsExpr::Other("".to_string(), Span::default(), Trivia::default()), span, Trivia::default()));
                    }
                }
            }
            RedTree::Leaf(_) => {
                // 叶子节点已经在父节点中处理
            }
        }
    }
}