parseSource¶
-
function parseSource
(fs, file_name)¶ ソースファイルの構文解析
ソース¶
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);
}
}
}
}