Example #1
0
int GDScriptLanguage::find_function(const String& p_function,const String& p_code) const {

	GDTokenizerText tokenizer;
	tokenizer.set_code(p_code);
	int indent=0;
	while(tokenizer.get_token()!=GDTokenizer::TK_EOF && tokenizer.get_token()!=GDTokenizer::TK_ERROR) {

		if (tokenizer.get_token()==GDTokenizer::TK_NEWLINE) {
			indent=tokenizer.get_token_line_indent();
		}
		//print_line("TOKEN: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));
		if (indent==0 && tokenizer.get_token()==GDTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1)==GDTokenizer::TK_IDENTIFIER) {

			String identifier = tokenizer.get_token_identifier(1);
			if (identifier==p_function) {
				return tokenizer.get_token_line();
			}
		}
		tokenizer.advance();
		//print_line("NEXT: "+String(GDTokenizer::get_token_name(tokenizer.get_token())));

	}
	return -1;
}
Example #2
0
Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String& p_code) {

	Vector<uint8_t> buf;


	Map<StringName,int> identifier_map;
	HashMap<Variant,int,VariantHasher> constant_map;
	Map<uint32_t,int> line_map;
	Vector<uint32_t> token_array;

	GDTokenizerText tt;
	tt.set_code(p_code);
	int line=-1;
	int col=0;

	while(true) {

		if (tt.get_token_line()!=line) {

			line=tt.get_token_line();
			line_map[line]=token_array.size();
		}

		uint32_t token=tt.get_token();
		switch(tt.get_token()) {

			case TK_IDENTIFIER: {
				StringName id = tt.get_token_identifier();
				if (!identifier_map.has(id)) {
					int idx = identifier_map.size();
					identifier_map[id]=idx;
				}
				token|=identifier_map[id]<<TOKEN_BITS;
			} break;
			case TK_CONSTANT: {

				Variant c = tt.get_token_constant();
				if (!constant_map.has(c)) {
					int idx = constant_map.size();
					constant_map[c]=idx;
				}
				token|=constant_map[c]<<TOKEN_BITS;
			} break;
			case TK_BUILT_IN_TYPE: {

				token|=tt.get_token_type()<<TOKEN_BITS;
			} break;
			case TK_BUILT_IN_FUNC: {

				token|=tt.get_token_built_in_func()<<TOKEN_BITS;

			} break;
			case TK_NEWLINE: {

				token|=tt.get_token_line_indent()<<TOKEN_BITS;
			} break;
			case TK_ERROR: {

				ERR_FAIL_V(Vector<uint8_t>());
			} break;
			default: {}

		};

		token_array.push_back(token);

		if (tt.get_token()==TK_EOF)
			break;
		tt.advance();

	}

	//reverse maps

	Map<int,StringName> rev_identifier_map;
	for(Map<StringName,int>::Element *E=identifier_map.front();E;E=E->next()) {
		rev_identifier_map[E->get()]=E->key();
	}

	Map<int,Variant> rev_constant_map;
	const Variant *K =NULL;
	while((K=constant_map.next(K))) {
		rev_constant_map[constant_map[*K]]=*K;
	}

	Map<int,uint32_t> rev_line_map;
	for(Map<uint32_t,int>::Element *E=line_map.front();E;E=E->next()) {
		rev_line_map[E->get()]=E->key();
	}

	//save header
	buf.resize(24);
	buf[0]='G';
	buf[1]='D';
	buf[2]='S';
	buf[3]='C';
	encode_uint32(BYTECODE_VERSION,&buf[4]);
	encode_uint32(identifier_map.size(),&buf[8]);
	encode_uint32(constant_map.size(),&buf[12]);
	encode_uint32(line_map.size(),&buf[16]);
	encode_uint32(token_array.size(),&buf[20]);

	//save identifiers

	for(Map<int,StringName>::Element *E=rev_identifier_map.front();E;E=E->next()) {

		CharString cs = String(E->get()).utf8();
		int len = cs.length()+1;
		int extra = 4-(len%4);
		if (extra==4)
			extra=0;

		uint8_t ibuf[4];
		encode_uint32(len+extra,ibuf);
		for(int i=0;i<4;i++) {
			buf.push_back(ibuf[i]);
		}
		for(int i=0;i<len;i++) {
			buf.push_back(cs[i]^0xb6);
		}
		for(int i=0;i<extra;i++) {
			buf.push_back(0^0xb6);
		}
	}

	for(Map<int,Variant>::Element *E=rev_constant_map.front();E;E=E->next()) {

		int len;
		Error err = encode_variant(E->get(),NULL,len);
		ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
		int pos=buf.size();
		buf.resize(pos+len);
		encode_variant(E->get(),&buf[pos],len);
	}

	for(Map<int,uint32_t>::Element *E=rev_line_map.front();E;E=E->next()) {

		uint8_t ibuf[8];
		encode_uint32(E->key(),&ibuf[0]);
		encode_uint32(E->get(),&ibuf[4]);
		for(int i=0;i<8;i++)
			buf.push_back(ibuf[i]);
	}

	for(int i=0;i<token_array.size();i++) {

		uint32_t token = token_array[i];

		if (token&~TOKEN_MASK) {
			uint8_t buf4[4];
			encode_uint32(token_array[i]|TOKEN_BYTE_MASK,&buf4[0]);
			for(int j=0;j<4;j++) {
				buf.push_back(buf4[j]);
			}
		} else {
			buf.push_back(token);
		}
	}

	return buf;

}
Example #3
0
MainLoop* test(TestType p_test) {

	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[0],flen);
	buf[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_test==TEST_TOKENIZER) {

		GDTokenizerText tk;
		tk.set_code(code);
		int line=-1;
		while(tk.get_token()!=GDTokenizer::TK_EOF) {


			String text;
			if (tk.get_token()==GDTokenizer::TK_IDENTIFIER)
				text="'"+tk.get_token_identifier()+"' (identifier)";
			else if (tk.get_token()==GDTokenizer::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()==GDTokenizer::TK_ERROR)
				text="ERROR: "+tk.get_token_error();
			else if (tk.get_token()==GDTokenizer::TK_NEWLINE)
				text="newline ("+itos(tk.get_token_line())+") + indent: "+itos(tk.get_token_line_indent());
			else if (tk.get_token()==GDTokenizer::TK_BUILT_IN_FUNC)
				text="'"+String(GDFunctions::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_test==TEST_PARSER) {


		GDParser 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 GDParser::Node* root = parser.get_parse_tree();
		ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,NULL);
		const GDParser::ClassNode *cnode=static_cast<const GDParser::ClassNode*>(root);

		_parser_show_class(cnode,0,lines);

	}

	if (p_test==TEST_COMPILER) {


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

		GDCompiler 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_test==TEST_BYTECODE) {

		Vector<uint8_t> buf = GDTokenizerBuffer::parse_code_string(code);
		String dst = test.basename()+".gdc";
		FileAccess *fw = FileAccess::open(dst,FileAccess::WRITE);
		fw->store_buffer(buf.ptr(),buf.size());
		memdelete(fw);
	}


#if 0
	Parser parser;
	Error err = parser.parse(code);
	if (err) {
		print_line("error:"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
	} else {
		print_line("Parse O-K!");
	}
#endif



	memdelete(fa);

	return NULL;
}