static void _parser_show_class(const GDScriptParser::ClassNode *p_class, int p_indent, const Vector<String> &p_code) { if (p_indent == 0 && (String(p_class->extends_file) != "" || p_class->extends_class.size())) { _print_indent(p_indent, _parser_extends(p_class)); print_line("\n"); } for (int i = 0; i < p_class->subclasses.size(); i++) { const GDScriptParser::ClassNode *subclass = p_class->subclasses[i]; String line = "class " + subclass->name; if (String(subclass->extends_file) != "" || subclass->extends_class.size()) line += " " + _parser_extends(subclass); line += ":"; _print_indent(p_indent, line); _parser_show_class(subclass, p_indent + 1, p_code); print_line("\n"); } for (int i = 0; i < p_class->constant_expressions.size(); i++) { const GDScriptParser::ClassNode::Constant &constant = p_class->constant_expressions[i]; _print_indent(p_indent, "const " + String(constant.identifier) + "=" + _parser_expr(constant.expression)); } for (int i = 0; i < p_class->variables.size(); i++) { const GDScriptParser::ClassNode::Member &m = p_class->variables[i]; _print_indent(p_indent, "var " + String(m.identifier)); } print_line("\n"); for (int i = 0; i < p_class->static_functions.size(); i++) { _parser_show_function(p_class->static_functions[i], p_indent); print_line("\n"); } for (int i = 0; i < p_class->functions.size(); i++) { if (String(p_class->functions[i]->name) == "_init") { _parser_show_function(p_class->functions[i], p_indent, p_class->initializer); } else _parser_show_function(p_class->functions[i], p_indent); print_line("\n"); } //_parser_show_function(p_class->initializer,p_indent); print_line("\n"); }
MainLoop *test(TestType p_type) { List<String> cmdlargs = OS::get_singleton()->get_cmdline_args(); if (cmdlargs.empty()) { //try editor! return NULL; } String test = cmdlargs.back()->get(); FileAccess *fa = FileAccess::open(test, FileAccess::READ); if (!fa) { ERR_EXPLAIN("Could not open file: " + test); ERR_FAIL_V(NULL); } Vector<uint8_t> buf; int flen = fa->get_len(); buf.resize(fa->get_len() + 1); fa->get_buffer(buf.ptrw(), flen); buf.write[flen] = 0; String code; code.parse_utf8((const char *)&buf[0]); Vector<String> lines; int last = 0; for (int i = 0; i <= code.length(); i++) { if (code[i] == '\n' || code[i] == 0) { lines.push_back(code.substr(last, i - last)); last = i + 1; } } if (p_type == TEST_TOKENIZER) { GDScriptTokenizerText tk; tk.set_code(code); int line = -1; while (tk.get_token() != GDScriptTokenizer::TK_EOF) { String text; if (tk.get_token() == GDScriptTokenizer::TK_IDENTIFIER) text = "'" + tk.get_token_identifier() + "' (identifier)"; else if (tk.get_token() == GDScriptTokenizer::TK_CONSTANT) { Variant c = tk.get_token_constant(); if (c.get_type() == Variant::STRING) text = "\"" + String(c) + "\""; else text = c; text = text + " (" + Variant::get_type_name(c.get_type()) + " constant)"; } else if (tk.get_token() == GDScriptTokenizer::TK_ERROR) text = "ERROR: " + tk.get_token_error(); else if (tk.get_token() == GDScriptTokenizer::TK_NEWLINE) text = "newline (" + itos(tk.get_token_line()) + ") + indent: " + itos(tk.get_token_line_indent()); else if (tk.get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC) text = "'" + String(GDScriptFunctions::get_func_name(tk.get_token_built_in_func())) + "' (built-in function)"; else text = tk.get_token_name(tk.get_token()); if (tk.get_token_line() != line) { int from = line + 1; line = tk.get_token_line(); for (int i = from; i <= line; i++) { int l = i - 1; if (l >= 0 && l < lines.size()) { print_line("\n" + itos(i) + ": " + lines[l] + "\n"); } } } print_line("\t(" + itos(tk.get_token_column()) + "): " + text); tk.advance(); } } if (p_type == TEST_PARSER) { GDScriptParser parser; Error err = parser.parse(code); if (err) { print_line("Parse Error:\n" + itos(parser.get_error_line()) + ":" + itos(parser.get_error_column()) + ":" + parser.get_error()); memdelete(fa); return NULL; } const GDScriptParser::Node *root = parser.get_parse_tree(); ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, NULL); const GDScriptParser::ClassNode *cnode = static_cast<const GDScriptParser::ClassNode *>(root); _parser_show_class(cnode, 0, lines); } if (p_type == TEST_COMPILER) { GDScriptParser parser; Error err = parser.parse(code); if (err) { print_line("Parse Error:\n" + itos(parser.get_error_line()) + ":" + itos(parser.get_error_column()) + ":" + parser.get_error()); memdelete(fa); return NULL; } GDScript *script = memnew(GDScript); GDScriptCompiler gdc; err = gdc.compile(&parser, script); if (err) { print_line("Compile Error:\n" + itos(gdc.get_error_line()) + ":" + itos(gdc.get_error_column()) + ":" + gdc.get_error()); memdelete(script); return NULL; } Ref<GDScript> gds = Ref<GDScript>(script); Ref<GDScript> current = gds; while (current.is_valid()) { print_line("** CLASS **"); _disassemble_class(current, lines); current = current->get_base(); } } else if (p_type == TEST_BYTECODE) { Vector<uint8_t> buf = GDScriptTokenizerBuffer::parse_code_string(code); String dst = test.get_basename() + ".gdc"; FileAccess *fw = FileAccess::open(dst, FileAccess::WRITE); fw->store_buffer(buf.ptr(), buf.size()); memdelete(fw); } memdelete(fa); return NULL; }