#!/usr/local/bin/lpc -Cstay /* Hubbes inkrementella lpc frontend - hilfe */ /* todo: * return (void)1; will give me problems. * strstr(string,string *) -> return first occurance of first string... * */ #!define catch(X) ((X),0) #pragma all_inline /* #define DEBUG */ mapping variables=([]); string *functions=({}); string *function_names=({}); mapping query_variables() { return variables; } /* do nothing */ object eval(string f) { string program,file; object o; program="#pragma unpragma_strict_types\n#pragma all_inline\n"+ "void create() { expunge(); }\n"+ "static object ___hilfe=previous_object();\n"+ "void write(mixed s) { efun::write(stringp(s)?s:sprintf(\"%O\",s)); }\n"+ "static mapping ___variables=___hilfe->query_variables();\n"+ implode(map_array(m_indices(variables),lambda(string f) { return sprintf("mixed %s=___variables[\"%s\"];",f,f); }),"\n")+ "\nmapping query_variables() { return ([\n"+ implode(map_array(m_indices(variables),lambda(string f) { return sprintf(" \"%s\":%s,",f,f); }),"\n")+ "\n ]);\n}\n"+ implode(functions,"\n")+"\n"+ f+"\n"; #ifdef DEBUG write("program:"+program); #endif if(catch(file=make_object(program))) return 0; o=clone_object(file); update(file); return o; } string input=""; string skipwhite(string f) { while(sscanf(f,"%*[ \r\n\t]%s",f) && sscanf(f,"/*%*s*/%s",f)); return f; } int find_next_comma(string s) { int e, p, q; for(e=0;e<strlen(s);e++) { switch(s[e]) { case '"': for(e++;s[e]!='"';e++) { switch(s[e]) { case 0: return 0; case '\\': e++; break; } } break; case '{': case '(': case '[': p++; break; case ',': if(!p) return e; break; case '/': if(s[e+1]=='*') while(s[e-1..e]!="*/" && e<strlen(s)) e++; break; case '}': case ')': case ']': p--; if(p<0) { write("Syntax errror.\n"); input=""; return 0; } break; } } return 0; } string get_name(string f) { int e,d; f=skipwhite(f); if(sscanf(f,"*%s",f)) f=skipwhite(f); sscanf(f,"%[a-zA-Z0-9_]",f); return f; } string first_word=0; int pos=0; int parenthese_level=0; int in_comment=0; int in_string=0; int in_quote=0; int eq_pos=-1; int do_parse(); mixed parse_function(string s); mixed parse_statement(string s); void set_buffer(string s,int parsing) { input=s; first_word=0; pos=-1; parenthese_level=0; in_comment=0; in_quote=0; in_string=0; eq_pos=-1; if(!parsing) do_parse(); } void clean_buffer() { set_buffer("",0); } void add_buffer(string s) { input+=s; do_parse(); } void cut_buffer(int where) { int old,new; old=strlen(input); input=skipwhite(input[where..old-1]); new=strlen(input); if(where>1) first_word=0; pos-=old-new; if(pos<0) pos=0; eq_pos-=old-new; if(eq_pos<0) eq_pos=-1; #ifdef DEBUG write("CUT input = "+code_value(input,1)+" pos="+pos+"\n"); #endif } int do_parse() { string tmp; if(pos<0) pos=0; for(;pos<strlen(input);pos++) { if(in_quote) { in_quote=0; continue; } if(!first_word) { int d; d=input[pos]; if(d==' ' && !pos) { cut_buffer(1); continue; } if((d<'a' || d>'z') && (d<'A' || d>'Z') && (d<'0' || d>'9') && d!='_') { first_word=input[0..pos-1]; #ifdef DEBUG write("First = "+code_value(first_word)+" pos="+pos+"\n"); write("input = "+code_value(input)+"\n"); #endif switch(first_word) { case "quit": write("Exiting.\n"); exit(1); case ".": clean_buffer(); write("Input buffer flushed.\n"); break; case "new": this_object()->__INIT(); break; case "dump": sum_arrays(lambda(string var,mixed foo) { write(sprintf("%-15s:%s\n",var,sprintf("%O",foo))); }, m_indices(variables), m_values(variables)); cut_buffer(4); } } } switch(input[pos]) { case '\\': in_quote=1; break; case '=': if(in_string || in_comment || parenthese_level || eq_pos!=-1) break; eq_pos=pos; break; case '"': if(in_comment) break; in_string=!in_string; break; case '{': case '(': case '[': if(in_string || in_comment) break; parenthese_level++; break; case '}': case ')': case ']': if(in_string || in_comment) break; if(--parenthese_level<0) { write("Syntax error.\n"); clean_buffer(); return 0; } if(!parenthese_level && input[pos]=='}') { if(tmp=parse_function(input[0..pos])) { cut_buffer(pos+1); if(stringp(tmp)) set_buffer(tmp+input,1); } } break; case ';': if(in_string || in_comment || parenthese_level) break; if(tmp=parse_statement(input[0..pos])) { cut_buffer(pos+1); if(stringp(tmp)) set_buffer(tmp+input,1); } break; case '*': if(in_string || in_comment) break; if(input[pos-1]=='/') in_comment=1; break; case '/': if(in_string) break; if(input[pos-1]=='*') in_comment=0; break; } } if(pos>strlen(input)) pos=strlen(input); return -1; } mixed parse_function(string fun) { string name,a,b; object foo; mixed c; #ifdef DEBUG write("Parsing block ("+first_word+")\n"); #endif switch(first_word) { case "if": case "for": case "do": case "while": case "foreach": /* parse loop */ if(foo=eval("___Foo4711() { "+fun+" ; }\n")) { if(c=catch(foo->___Foo4711())) { write("error during evaluation: "+c); }else{ write("Ok.\n"); variables=foo->query_variables(); } } return 1; case "int": case "void": case "object": case "mapping": case "string": case "list": case "float": case "mixed": /* parse function */ if(eq_pos!=-1) break; /* it's a variable */ sscanf(fun,first_word+"%s",name); name=get_name(name); if(sscanf(fun,"%s"+name+"%s(",c,c) && skipwhite(c)=="") { int i; if((i=member_array(name,function_names))!=-1) { b=functions[i]; functions[i]=fun; if(!eval("")) functions[i]=b; }else{ if(eval(fun)) { functions+=({fun}); function_names+=({name}); } } return 1; } } } mixed parse_statement(string ex) { string a,b,name; mixed c; object foo; int e; #ifdef DEBUG write("Parsing statement ("+first_word+")\n"); #endif switch(first_word) { case "if": case "for": case "do": case "while": case "foreach": /* parse loop */ if(foo=eval("___Foo4711() { "+ex+" ; }\n")) { if(c=catch(foo->___Foo4711())) { write("error during evaluation: "+c); }else{ write("Ok.\n"); variables=foo->query_variables(); } } return 1; case "int": case "void": case "object": case "mapping": case "string": case "list": case "float": case "mixed": /* parse variable def. */ sscanf(ex,first_word+"%s",b); b=skipwhite(b); name=get_name(b); #ifdef DEBUG write("Variable def.\n"); #endif if(name=="") { return 1; }else{ string f; variables[name]=0; if(sscanf(ex,"%s"+name+"%s=%s",c,f,c)==3 && skipwhite(f)=="") { #ifdef DEBUG write("Variable def. with assign. ("+name+")\n"); #endif if(e=find_next_comma(c)) return name+"="+c[0..e-1]+";\n"+ first_word+" "+c[e+1..strlen(c)-1]; else return name+"="+c; #ifdef DEBUG write("Input buffer = '"+input+"'\n"); #endif }else{ sscanf(b,"%s"+name+"%s",b,b); sscanf(b,",%s",b); return first_word+" "+b; } } return 1; default: /* parse expressions */ a="___Foo4711() { return (mixed)("+ex[0..strlen(ex)-2]+"); }\n"; if(foo=eval(a)) { if(c=catch(a=sprintf("%O",foo->___Foo4711()))) { write("error during evaluation: "+c); }else{ write("Result: "+a+"\n"); variables=foo->query_variables(); } } return 1; } } void stdin(string s) { string *tmp,a,b,c,f,name; int e,d; object foo; #ifdef DEBUG write(save_object()); write("input: "+code_value(s,1)+"\n"); #endif s=skipwhite(s); if(s[0..1]==".\n") { clean_buffer(); write("Input buffer flushed.\n"); s=s[2..strlen(s)-1]; } add_buffer(s); if(!strlen(input)) write("> "); } void main(int argc,string *argv) { write("LPC"+version()+ " Running Hilfe v1.1 (Hubbe's Incremental LPC FrontEnd)\n"); write("> "); } int signal(int s) { if(s==4) { clean_buffer(); if(sizeof(previous_objects())>1) throw("**Break"); else write("**Break\n"); } return 1; }