//bd 20maart2004 //d interpreter #include "d_base.h" // #include "d_error.h" //generic error messaging #include "d_var.h" #include "d_parse.h" #include "d_calc.h" //expression evaluation ////////////////////program flow statements//////////////// void dd_define(int declare) { char a[StringSize],b[StringSize],c; int local; while(1) // scan multiple definitions as declare i=2,a,b,c=2; { dd_expression(a); //this is the variable name local=d_var_locallevel; if(declare==1) //declare at present local level { if(!d_var_value_local(a))d_var_push_local(a,""); } else if(declare==2) //declare global variable { if(!d_var_value(a))d_var_push(a,""); } else //obsolete { if(!d_var_value_any(a))dd_runtime_error("variable %s not declared",a); } c=dd_expression(b); if(!declare && c!='=')dd_syntax_expected("=",b); if(c==',')continue; if(c==';')return; dd_expression(b); //assign at local or global level //printf("%s%s variable %s as %s ",declare?"declare":"assign",local?" local":"",a,b); d_var_push_any(a,b); c=dd_expression(b); if(c==',')continue; if(c==';')return; dd_syntax_expected(", or ;",b); } } void dd_include(S_fifo *rfifo) { char a[StringSize], *e; dd_expression(a); //this is the file name while(dd_expression(NULL)!=';'); //just disregard the remainder of the statement e=d_parse_init(a,0); //an includefile should thus contain one of more statements or statement lists if(e)dd_runtime_error(e,NULL); while(dd_statement(rfifo)); //read statements until eof d_parse_close(); } void dd_return(S_fifo *rfifo) { //result (a) (b) (c) ...; char h[StringSize]; if(!rfifo)dd_runtime_error("result statement outside function body",NULL); while(dd_expression(h)!=';') { S_fifo_write(rfifo,h,1); } } void dd_function(void) { char a[StringSize],hulps[StringSize]; int arguments=-1; //number of required arguments (-1 = free) dd_expression(a); //this is the function call name dd_expression(hulps);if(*hulps)arguments=atoi(hulps); // # of arguments //store start address of statement list sprintf(hulps,"\001%d\002%d\t%s",d_parse_tokenpos(), arguments, d_parse_filename()); d_var_push(a,hulps); dd_skipstatementlist(); } void dd_call_by_name(char *hf,S_fifo *rfifo) { char *a, hulps[StringSize],h2[StringSize],fn[StringSize], *e; S_fifo fifo; int tokenpos,arguments,count=0; S_fifo_init(&fifo); a=d_var_value(hf); //a this is the stored function information if(!a || a[0]!='\001') { dd_runtime_error("call to function %s not previously defined",hf); return; } tokenpos=atoi(a+1); arguments=atoi(Voorbij(a,'\002')); Copy(Voorbij(a,'\t'),fn); count=0; while(dd_argument(count,hulps)) {//read all arguments and put in fifo S_fifo_write(&fifo,hulps,1); count++; } count=0; while(S_fifo_read(&fifo,h2)) {//copy from fifo to function body arguments d_var_locallevel++; sprintf(hulps,"%d",count);d_var_push_local(hulps,h2); //printf("{{%s=%s}}",d_var_local(hulps),h2); d_var_locallevel--; count++; } d_var_locallevel++; d_var_push_int("function.nesting",d_var_locallevel); sprintf(hulps,"%d",count);d_var_push_local("#",hulps); if(arguments>=0 && arguments!=count) dd_runtime_error("function call with wrong number of arguments",NULL); e=d_parse_init(fn,tokenpos); if(e)dd_runtime_error(e,NULL); dd_statement(rfifo); d_parse_close(); d_var_locallevel--; d_var_push_int("function.nesting",d_var_locallevel); } void dd_call(S_fifo *rfifo) //the statement version of a call OBSOLETE! { char h[StringSize]; S_fifo fifo; if(rfifo==NULL) {S_fifo_init(&fifo);rfifo=&fifo;} //result will come in this fifo dd_expression(h); //h is the function call name dd_call_by_name(h,rfifo); //discart returnvalues in a statement call; S_fifo_cleanup(rfifo); // while(S_fifo_read(rfifo,h))printf("returned(%s)",h); //end statement: while(dd_expression(NULL)!=';'); //qualifiers neglected } int dd_conditionoflastif=2; //condition of last if void dd_if(S_fifo *rfifo) { boolean condition=FALSE; //boolean int dd_skipstatementlist(); //predeclaration int dd_statement(); //predeclaration char cond[StringSize]; dd_expression(cond); //execute if condition true //printf("if(%s) evaluates %s",cond,dd_true(cond)?"TRUE":"FALSE"); if(condition=dd_true(cond))dd_statement(rfifo); else dd_skipstatementlist(); dd_conditionoflastif=condition; //to acticipate nest else } void dd_else(S_fifo *rfifo) { int dd_skipstatementlist(); //predeclaration int dd_statement(); //predeclaration if(dd_conditionoflastif==2)dd_syntax_error("else without preceeding if",NULL); if(!dd_conditionoflastif)dd_statement(rfifo); else dd_skipstatementlist(); dd_conditionoflastif=2;//means: there was no last if } void dd_while(S_fifo *rfifo) { int loop; //loop counter int dd_skipstatementlist(); //predeclaration int dd_statement(); //predeclaration char cond[StringSize]; int condpos,statpos; loop=0; do { if(loop==0) { condpos=d_parse_tokenpos(); dd_expression(cond); //execute if condition true statpos=d_parse_tokenpos(); dd_skipstatementlist(); } else { d_parse_init(NULL,condpos); dd_expression(cond); //execute if condition true d_parse_close(); } if(dd_true(cond)) { d_parse_init(NULL,statpos); dd_statement(rfifo); d_parse_close(); } loop++; }while(dd_true(cond)); } //////////////////system statemtns /////////////// void dd_system(void) { //various system level, debugging, etc. call char types[StringSize],h[StringSize]; dd_expression(types); if(Gelijk(types,"variables")) d_var_list(); else dd_syntax_error("%s invalid argument for system statement",types); while(dd_expression(NULL)!=';') {} } ////////////////////////////statement executor/////////////////////// //parse keywords #define DD_UNKNOWN 1 #define DD_ASSIGN 3 #define DD_DECLARE 4 #define DD_INSTANCE 5 #define DD_WHILE 6 #define DD_IF 7 #define DD_ELSE 8 #define DD_INCLUDE 14 #define DD_FUNCTION 16 #define DD_CALL 17 #define DD_SYSTEM 18 #define DD_GLOBAL 19 #define DD_RETURN 21 int dd_parse_keyword(char *a) //allowed keywords at beginning of statement { int i=DD_UNKNOWN; if(Gelijk(a,"{")) i='{'; if(Gelijk(a,"}")) i='}'; if(Gelijk(a,";")) i=';'; if(Gelijk(a,"declare")) i=DD_DECLARE; //declare variable (local!) if(Gelijk(a,"global")) i=DD_DECLARE; //declare global variable if(Gelijk(a,"while")) i=DD_WHILE; if(Gelijk(a,"if")) i=DD_IF; if(Gelijk(a,"else")) i=DD_ELSE; if(Gelijk(a,"include")) i=DD_INCLUDE; if(Gelijk(a,"system")) i=DD_SYSTEM; if(Gelijk(a,"function")) i=DD_FUNCTION; //function declaration if(Gelijk(a,"call")) i=DD_CALL; //non returning function call if(Gelijk(a,"result")) i=DD_RETURN; //result in function call if(Gelijk(a,"")) i=0; return(i); } int dd_statement(S_fifo *rfifo) //parse one statement or a statement list //returns 1(5) at end of statement(-list) , 0 at eof and 2 if } encountered //rfifo is the fifo in which the results of "result" statements are put { int i; char keyword[StringSize]; if(d_parse_preview()=='*') {dd_expression(NULL);} dd_nexttoken(keyword); switch(dd_parse_keyword(keyword)) { case '{': while(i=dd_statement(rfifo),i&&i!=2); return(5); break; case '}': return(2); //end of list reached break; case 0: return(0);break; //end of file case DD_WHILE:dd_while(rfifo);break; case DD_IF:dd_if(rfifo);break; case DD_ELSE:dd_else(rfifo);break; case DD_DECLARE:dd_define(1);break; case DD_GLOBAL:dd_define(2);break; case DD_ASSIGN:dd_define(0);break; case DD_INCLUDE:dd_include(rfifo);break; case DD_FUNCTION:dd_function();break; case DD_CALL:dd_call(NULL);break; case DD_SYSTEM:dd_system();break; case DD_RETURN:dd_return(rfifo);break; case ';':/*dd_syntax_remark("(empty statement)")*/;break; case DD_UNKNOWN: default:dd_syntax_unexpected(d_parse_string);break; } return(1);//normal end of valid statement } int dd_skipstatementlist(void) {//reads stream until closing } int c;int level; level=0; while(c=d_parse_next()) { switch(c) { case'{':level++; break; case'}':level--; if(level==0)return(c); if(level<0){dd_syntax_unexpected("}");return(c);}; break; case';':if(level==0)return(c); //dwz single statement break; } } return(c); } main(int argc,char **argv) { int k; char *e; for(k=0;k