parseSource ====================== .. js:function:: function parseSource(fs, file_name) ソースファイルの構文解析 ソース ^^^^^^ .. code-block:: js function parseSource(fs, file_name) { var source_file = new SourceFile(file_name); SourceFiles.push(source_file); fs.mkdirsSync('../docs/api/' + file_name); console.log(file_name); var buf = fs.readFileSync(file_name + ".js"); var str = buf.toString().replace(/\r\n/g, "\n").replace(/\t/g, " ").replace(/[ ]+$/g, ""); var class_name = null; var class_indent = -1; var current_class = null; var current_fnc = null; var comment_start = null; var comment_indent; var comment = null; var prev_comment = null; var lines = str.split('\n'); for (var line_idx = 0; line_idx < lines.length; line_idx++) { if (prev_comment != null) { comment = prev_comment; prev_comment = null; } else { comment = null; } var line = lines[line_idx]; if (line.trim().length == 0) { // 空行の場合 if (source_file.comment == null && comment != null) { source_file.comment = comment; } continue; } var indent = SkipSpace(line, 0); if (comment_start != null) { if (line.startsWith("*/", indent)) { prev_comment = lines.slice(comment_start + 1, line_idx).map(x => x.substring(comment_indent)).join("\n"); comment_start = null; } continue; } if (line.startsWith("class", indent)) { // クラスの場合 var pos = SkipSpace(line, indent + 5); [pos, class_name] = SkipName(line, pos); pos = SkipSpace(line, pos); var super_class_name = null; if (line.startsWith("extends", pos)) { pos = SkipSpace(line, pos + 7); [pos, super_class_name] = SkipName(line, pos); } current_class = new Class(source_file, comment, indent, class_name, super_class_name); source_file.classes.push(current_class); Classes.push(current_class); } else if (line.startsWith("/**", indent) || line.startsWith("/*", indent)) { // ブロックコメントの場合 var s = line.trim(); if (s.endsWith("*/")) { comment_indent = 0; prev_comment = s.substring(2, s.length - 2); } else { comment_indent = indent; comment_start = line_idx; } } else if (line.startsWith("//", indent)) { // 行コメントの場合 prev_comment = line.substring(indent + 2).trim(); } else if (line.startsWith("function", indent)) { // 関数の場合 var pos = SkipSpace(line, indent + 8); var fnc_name; [pos, fnc_name] = SkipName(line, pos); current_fnc = new Function(comment, line_idx, line, indent, false, fnc_name, null); source_file.functions.push(current_fnc); } else if (line.startsWith("constructor", indent)) { // コンストラクタの場合 current_fnc = new Function(comment, line_idx, line, indent, false, "constructor", current_class); current_class.methods.push(current_fnc); } else if (line.startsWith("var", indent)) { // 変数の場合 } else if (line.startsWith("}", indent)) { // ブロックの終わりの場合 if (current_class != null && current_class.indent == indent) { current_class = null; } else if (current_fnc != null && current_fnc.indent == indent) { current_fnc.body = " " + lines.slice(current_fnc.startLineIdx, line_idx + 1).join("\n "); current_fnc = null; } } else { if (current_class != null && current_class.indent + 4 == indent && current_fnc == null) { // クラス定義の中で、クラス定義の直下のインデントで、関数定義の中でない場合 var pos, fnc_name, is_generator = false; if (line[indent] == "*") { // ジェネレーターの場合 is_generator = true; pos = SkipSpace(line, indent + 1); } else { // ジェネレーターでない場合 pos = indent; } [pos, fnc_name] = SkipName(line, pos); current_fnc = new Function(comment, line_idx, line, indent, is_generator, fnc_name, current_class); current_class.methods.push(current_fnc); } } } }