Bläddra i källkod

Hacked a demo C# class parser for neikeq.

Juan Linietsky 9 år sedan
förälder
incheckning
4613cb7874
1 ändrade filer med 399 tillägg och 1 borttagningar
  1. 399 1
      bin/tests/test_math.cpp

+ 399 - 1
bin/tests/test_math.cpp

@@ -40,12 +40,376 @@
 #include "scene/resources/texture.h"
 #include "vmap.h"
 #include "os/os.h"
+#include "os/file_access.h"
 
 #include "method_ptrcall.h"
 
 namespace TestMath {
 
 
+class GetClassAndNamespace {
+
+	String code;
+	int idx;
+	int line;
+	String error_str;
+	bool error;
+	Variant value;
+
+	String class_name;
+
+	enum Token {
+		TK_BRACKET_OPEN,
+		TK_BRACKET_CLOSE,
+		TK_CURLY_BRACKET_OPEN,
+		TK_CURLY_BRACKET_CLOSE,
+		TK_PERIOD,
+		TK_COLON,
+		TK_COMMA,
+		TK_SYMBOL,
+		TK_IDENTIFIER,
+		TK_STRING,
+		TK_NUMBER,
+		TK_EOF,
+		TK_ERROR
+	};
+
+
+	Token get_token() {
+
+		while (true) {
+			switch(code[idx]) {
+
+				case '\n': {
+
+					line++;
+					idx++;
+					break;
+				};
+				case 0: {
+					return TK_EOF;
+
+				} break;
+				case '{': {
+
+					idx++;
+					return TK_CURLY_BRACKET_OPEN;
+				};
+				case '}': {
+
+					idx++;
+					return TK_CURLY_BRACKET_CLOSE;
+				};
+				case '[': {
+
+					idx++;
+					return TK_BRACKET_OPEN;
+				};
+				case ']': {
+
+					idx++;
+					return TK_BRACKET_CLOSE;
+				};
+				case ':': {
+
+					idx++;
+					return TK_COLON;
+				};
+				case ',': {
+
+					idx++;
+					return TK_COMMA;
+				};
+				case '.': {
+
+					idx++;
+					return TK_PERIOD;
+				};
+				case '#': {
+					//compiler directive
+					while(code[idx]!='\n' && code[idx]!=0) {
+						idx++;
+					}
+					continue;
+				} break;
+				case '/': {
+
+
+					switch(code[idx+1]) {
+						case '*': { // block comment
+
+							idx+=2;
+							while(true) {
+								if (code[idx]==0) {
+									error_str="Unterminated comment";
+									error=true;
+									return TK_ERROR;
+								} if (code[idx]=='*' &&code[idx+1]=='/') {
+
+									idx+=2;
+									break;
+								} if (code[idx]=='\n') {
+									line++;
+								}
+
+								idx++;
+							}
+
+						} break;
+						case '/': { // line comment skip
+
+							while(code[idx]!='\n' && code[idx]!=0) {
+								idx++;
+							}
+
+						} break;
+						default: {
+							value="/";
+							idx++;
+							return TK_SYMBOL;
+						}
+
+					}
+
+					continue; // a comment
+				} break;
+				case '\'':
+				case '"': {
+
+					CharType begin_str = code[idx];
+					idx++;
+					String tk_string=String();
+					while(true) {
+						if (code[idx]==0) {
+							error_str="Unterminated String";
+							error=true;
+							return TK_ERROR;
+						} else if (code[idx]==begin_str) {
+							idx++;
+							break;
+						} else if (code[idx]=='\\') {
+							//escaped characters...
+							idx++;
+							CharType next = code[idx];
+							if (next==0) {
+								error_str="Unterminated String";
+								error=true;
+								return TK_ERROR;
+							}
+							CharType res=0;
+
+							switch(next) {
+
+								case 'b': res=8; break;
+								case 't': res=9; break;
+								case 'n': res=10; break;
+								case 'f': res=12; break;
+								case 'r': res=13; break;
+									/* too much, not needed for now
+								case 'u': {
+									//hexnumbarh - oct is deprecated
+
+
+									for(int j=0;j<4;j++) {
+										CharType c = code[idx+j+1];
+										if (c==0) {
+											r_err_str="Unterminated String";
+											return ERR_PARSE_ERROR;
+										}
+										if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
+
+											r_err_str="Malformed hex constant in string";
+											return ERR_PARSE_ERROR;
+										}
+										CharType v;
+										if (c>='0' && c<='9') {
+											v=c-'0';
+										} else if (c>='a' && c<='f') {
+											v=c-'a';
+											v+=10;
+										} else if (c>='A' && c<='F') {
+											v=c-'A';
+											v+=10;
+										} else {
+											ERR_PRINT("BUG");
+											v=0;
+										}
+
+										res<<=4;
+										res|=v;
+
+
+									}
+									idx+=4; //will add at the end anyway
+
+
+								} break;*/
+								case '\"': res='\"'; break;
+								case '\\': res='\\'; break;
+								//case '/': res='/'; break;
+								default: {
+									res = next;
+									//r_err_str="Invalid escape sequence";
+									//return ERR_PARSE_ERROR;
+								} break;
+							}
+
+							tk_string+=res;
+
+						} else {
+							if (code[idx]=='\n')
+								line++;
+							tk_string+=code[idx];
+						}
+						idx++;
+					}
+
+					value=tk_string;
+
+					return TK_STRING;
+
+				} break;
+				default: {
+
+					if (code[idx]<=32) {
+						idx++;
+						break;
+					}
+
+					if ( (code[idx]>=33 && code[idx]<=47) || (code[idx]>=58 && code[idx]<=64) || (code[idx]>=91 && code[idx]<=96) || (code[idx]>=123 && code[idx]<=127)){
+						value=String::chr(code[idx]);
+						idx++;
+						return TK_SYMBOL;
+					}
+
+					if (code[idx]=='-' || (code[idx]>='0' && code[idx]<='9')) {
+						//a number
+						const CharType *rptr;
+						double number = String::to_double(&code[idx],&rptr);
+						idx+=(rptr - &code[idx]);
+						value=number;
+						return TK_NUMBER;
+
+					} else if ((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) {
+
+						String id;
+
+						while((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) {
+
+							id+=code[idx];
+							idx++;
+						}
+
+						value=id;
+						return TK_IDENTIFIER;
+					} else {
+						error_str="Unexpected character.";
+						error=true;
+						return TK_ERROR;
+					}
+				}
+
+			}
+		}
+	}
+
+public:
+	Error parse(const String& p_code,const String& p_known_class_name=String()) {
+
+		code=p_code;
+		idx=0;
+		line=0;
+		error_str=String();
+		error=false;
+		value=Variant();
+		class_name=String();
+
+		bool use_next_class=false;
+		Token tk = get_token();
+
+		Map<int,String> namespace_stack;
+		int curly_stack=0;
+
+
+		while(!error || tk!=TK_EOF) {
+
+			if (tk==TK_BRACKET_OPEN) {
+				tk = get_token();
+				if (tk==TK_IDENTIFIER && String(value)=="ScriptClass") {
+					if (get_token()==TK_BRACKET_CLOSE) {
+						use_next_class=true;
+					}
+				}
+			} else if (tk==TK_IDENTIFIER && String(value)=="class") {
+				tk = get_token();
+				if (tk==TK_IDENTIFIER) {
+					String name = value;
+					if (use_next_class || p_known_class_name==name) {
+						for (Map<int,String>::Element *E=namespace_stack.front();E;E=E->next()) {
+							class_name+=E->get()+".";
+						}
+						class_name+=String(value);
+						break;
+					}
+				}
+
+			} else if (tk==TK_IDENTIFIER && String(value)=="namespace") {
+				String name;
+				int at_level = curly_stack;
+				while(true) {
+					tk = get_token();
+					if (tk==TK_IDENTIFIER) {
+						name+=String(value);
+					}
+
+					tk = get_token();
+					if (tk==TK_PERIOD) {
+						name+=".";
+					} else if (tk==TK_CURLY_BRACKET_OPEN) {
+						curly_stack++;
+						break;
+					} else {
+						break; //whathever else
+					}
+
+				}
+
+				if (name!=String()) {
+					namespace_stack[at_level]=name;
+				}
+
+			} else if (tk==TK_CURLY_BRACKET_OPEN) {
+				curly_stack++;
+			} else if (tk==TK_CURLY_BRACKET_CLOSE) {
+				curly_stack--;
+				if (namespace_stack.has(curly_stack)) {
+					namespace_stack.erase(curly_stack);
+				}
+			}
+
+			tk = get_token();
+		}
+
+		if (error)
+			return ERR_PARSE_ERROR;
+
+
+
+		return OK;
+
+	}
+
+	String get_error() {
+		return error_str;
+	}
+
+	String get_class() {
+		return class_name;
+	}
+
+};
+
+
 void test_vec(Plane p_vec) {
 
 
@@ -113,7 +477,41 @@ uint32_t ihash3( uint32_t a)
 
 MainLoop* test() {
 
-	print_line(itos(Math::step_decimals( 0.0001 )));
+
+	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]);
+
+	GetClassAndNamespace getclass;
+	if (getclass.parse(code)) {
+		print_line("Parse error: "+getclass.get_error());
+	} else {
+		print_line("Found class: "+getclass.get_class());
+	}
+
 	return NULL;
 
 	{