File size: 3,015 Bytes
9b15797
 
 
 
 
0b272f5
 
9b15797
 
0b272f5
 
9b15797
0b272f5
 
 
 
 
 
9b15797
0b272f5
9b15797
0b272f5
 
9b15797
6c76fe5
 
 
9b15797
 
 
 
 
0b272f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b15797
 
 
0b272f5
9b15797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from tree_sitter import Parser
# tree-sitter-c-sharp pip package provides the C# language.
from tree_sitter_languages import get_language  # helper wrapper (optional)
import re



def parse_csharp(code: str) -> dict:
    """
    Parses a C# script and returns a simple AST-like dict:
    {
        "classes": [
            {
                "name": "Foo",
                "methods": [
                    {"name": "Update", "body": "..."}
                ]
            }
        ]
    }
    """
    result = {"classes": []}

    try:
        # try tree-sitter approach
        from tree_sitter import Parser
        from tree_sitter_c_sharp import CSHARP_LANGUAGE
        parser = Parser()
        parser.set_language(CSHARP_LANGUAGE)
        tree = parser.parse(bytes(code, "utf8"))
        root = tree.root_node

        def traverse(node):
            classes = []
            for child in node.children:
                if child.type == "class_declaration":
                    class_name = None
                    methods = []
                    # get class name
                    for grand in child.children:
                        if grand.type == "identifier":
                            class_name = code[grand.start_byte:grand.end_byte]
                        if grand.type == "method_declaration":
                            method_name = None
                            body = ""
                            for g in grand.children:
                                if g.type == "identifier":
                                    method_name = code[g.start_byte:g.end_byte]
                                if g.type == "block":
                                    body = code[g.start_byte:g.end_byte]
                            methods.append({"name": method_name, "body": body})
                    classes.append({"name": class_name, "methods": methods})
                # recurse into namespaces or other nodes
                classes.extend(traverse(child))
            return classes

        result["classes"] = traverse(root)
        return result

    except Exception:
        # Fallback using regex
        classes = []
        class_matches = re.finditer(r'class\s+(\w+)\s*:\s*MonoBehaviour\s*{', code)
        for m in class_matches:
            cls = m.group(1)
            methods = []
            for mm in re.finditer(r'(void|public)\s+(Start|Update|FixedUpdate)\s*\([^\)]*\)\s*{', code):
                method_name = mm.group(2)
                start = mm.end()
                depth = 1
                i = start
                while i < len(code) and depth > 0:
                    if code[i] == '{':
                        depth += 1
                    elif code[i] == '}':
                        depth -= 1
                    i += 1
                body = code[start:i-1].strip()
                methods.append({"name": method_name, "body": body})
            classes.append({"name": cls, "methods": methods})
        result["classes"] = classes
        return result