Hacked a demo C# class parser for neikeq.
This commit is contained in:
parent
913925f106
commit
4613cb7874
|
@ -40,12 +40,376 @@
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
#include "vmap.h"
|
#include "vmap.h"
|
||||||
#include "os/os.h"
|
#include "os/os.h"
|
||||||
|
#include "os/file_access.h"
|
||||||
|
|
||||||
#include "method_ptrcall.h"
|
#include "method_ptrcall.h"
|
||||||
|
|
||||||
namespace TestMath {
|
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) {
|
void test_vec(Plane p_vec) {
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +477,41 @@ uint32_t ihash3( uint32_t a)
|
||||||
|
|
||||||
MainLoop* test() {
|
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;
|
return NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue