#!/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;
}