📄 t_parse.c
字号:
void parse_data(char *data, char *end){ char *token_alloc; // allocated memory for tokens killscript = false; // dont kill the script straight away // allocate space for the tokens token_alloc = Z_Malloc(current_script->len + T_MAXTOKENS, PU_STATIC, 0); prev_section = NULL; // clear it while(*rover) // go through the script executing each statement { // past end of script? if(rover > end) break; // reset the tokens before getting the next line tokens[0] = token_alloc; prev_section = current_section; // store from prev. statement // get the line and tokens get_tokens(rover); if(killscript) break; if(!num_tokens) { if(current_section) // no tokens but a brace { // possible } at end of loop: // refer to spec.c spec_brace(); } continue; // continue to next statement } if(script_debug) print_tokens(); // debug run_statement(); // run the statement } Z_Free(token_alloc);}void run_statement(){ // decide what to do with it // NB this stuff is a bit hardcoded: // it could be nicer really but i'm // aiming for speed // if() and while() will be mistaken for functions // during token processing if(tokentype[0] == function) { if(!strcmp(tokens[0], "if")) { current_script->lastiftrue = spec_if() ? true: false; return; } else if(!strcmp(tokens[0], "elseif")) { if(!prev_section || (prev_section->type != st_if && prev_section->type != st_elseif)) { script_error("elseif without if!\n"); return; } current_script->lastiftrue = spec_elseif(current_script->lastiftrue) ? true : false; return; } else if(!strcmp(tokens[0], "else")) { if(!prev_section || (prev_section->type != st_if && prev_section->type != st_elseif)) { script_error("else without if!\n"); return; } spec_else(current_script->lastiftrue); current_script->lastiftrue = true; return; } else if(!strcmp(tokens[0], "while")) { spec_while(); return; } else if(!strcmp(tokens[0], "for")) { spec_for(); return; } } else if(tokentype[0] == name) { // NB: goto is a function so is not here // if a variable declaration, return now if(spec_variable()) return; } // just a plain expression evaluate_expression(0, num_tokens-1);}/***************** Evaluating Expressions ************************/ // find a token, ignoring things in brackets int find_operator(int start, int stop, char *value){ int i; int bracketlevel = 0; for(i=start; i<=stop; i++) { // only interested in operators if(tokentype[i] != operator) continue; // use bracketlevel to check the number of brackets // which we are inside bracketlevel += tokens[i][0]=='(' ? 1 : tokens[i][0]==')' ? -1 : 0; // only check when we are not in brackets if(!bracketlevel && !strcmp(value, tokens[i])) return i; } return -1;} // go through tokens the same as find_operator, but backwardsint find_operator_backwards(int start, int stop, char *value){ int i; int bracketlevel = 0; for(i=stop; i>=start; i--) // check backwards { // operators only if(tokentype[i] != operator) continue; // use bracketlevel to check the number of brackets // which we are inside bracketlevel += tokens[i][0]=='(' ? -1 : tokens[i][0]==')' ? 1 : 0; // only check when we are not in brackets // if we find what we want, return it if(!bracketlevel && !strcmp(value, tokens[i])) return i; } return -1;}// simple_evaluate is used once evalute_expression gets to the level// where it is evaluating just one token// converts number tokens into svalue_ts and returns// the same with string tokens// name tokens are considered to be variables and// attempts are made to find the value of that variable// command tokens are executed (does not return a svalue_t)extern svalue_t nullvar;static svalue_t simple_evaluate(int n){ svalue_t returnvar; svariable_t *var; switch(tokentype[n]) { case string: returnvar.type = svt_string; returnvar.value.s = tokens[n]; return returnvar; case number: if(strchr(tokens[n], '.')) { returnvar.type = svt_fixed; returnvar.value.f = atof(tokens[n]) * FRACUNIT; } else { returnvar.type = svt_int; returnvar.value.i = atoi(tokens[n]); } return returnvar; case name: var = find_variable(tokens[n]); if(!var) { script_error("unknown variable '%s'\n", tokens[n]); return nullvar; } else return getvariablevalue(var); default: return nullvar; }}// pointless_brackets checks to see if there are brackets surrounding// an expression. eg. "(2+4)" is the same as just "2+4"//// because of the recursive nature of evaluate_expression, this function is// neccesary as evaluating expressions such as "2*(2+4)" will inevitably// lead to evaluating "(2+4)"static void pointless_brackets(int *start, int *stop){ int bracket_level, i; // check that the start and end are brackets while(tokens[*start][0] == '(' && tokens[*stop][0] == ')') { bracket_level = 0; // confirm there are pointless brackets.. // if they are, bracket_level will only get to 0 // at the last token // check up to <*stop rather than <=*stop to ignore // the last token for(i = *start; i<*stop; i++) { if(tokentype[i] != operator) continue; // ops only bracket_level += (tokens[i][0] == '('); bracket_level -= (tokens[i][0] == ')'); if(bracket_level == 0) return; // stop if braces stop before end } // move both brackets in *start = *start + 1; *stop = *stop - 1; }}// evaluate_expresion is the basic function used to evaluate// a FraggleScript expression.// start and stop denote the tokens which are to be evaluated.//// works by recursion: it finds operators in the expression// (checking for each in turn), then splits the expression into// 2 parts, left and right of the operator found.// The handler function for that particular operator is then// called, which in turn calls evaluate_expression again to// evaluate each side. When it reaches the level of being asked// to evaluate just 1 token, it calls simple_evaluatesvalue_t evaluate_expression(int start, int stop){ int i, n; if(killscript) return nullvar; // killing the script // possible pointless brackets if(tokentype[start] == operator && tokentype[stop] == operator) pointless_brackets(&start, &stop); if(start == stop) // only 1 thing to evaluate { return simple_evaluate(start); } // go through each operator in order of precedence for(i=0; i<num_operators; i++) { // check backwards for the token. it has to be // done backwards for left-to-right reading: eg so // 5-3-2 is (5-3)-2 not 5-(3-2) if( -1 != (n = (operators[i].direction==forward ? find_operator_backwards : find_operator) (start, stop, operators[i].string)) ) { // CONS_Printf("operator %s, %i-%i-%i\n", operators[count].string, start, n, stop); // call the operator function and evaluate this chunk of tokens return operators[i].handler(start, n, stop); } } if(tokentype[start] == function) return evaluate_function(start, stop); // error ? { char tempstr[1024]=""; for(i=start; i<=stop; i++) sprintf(tempstr,"%s %s", tempstr, tokens[i]); script_error("couldnt evaluate expression: %s\n",tempstr); return nullvar; } }void script_error(char *s, ...){ va_list args; char tempstr[2048]; va_start(args, s); if(killscript) return; //already killing script if(current_script->scriptnum == -1) CONS_Printf("global"); else CONS_Printf("%i", current_script->scriptnum); // find the line number if(rover >= current_script->data && rover <= current_script->data+current_script->len) { int linenum = 1; char *temp; for(temp = current_script->data; temp<linestart; temp++) if(*temp == '\n') linenum++; // count EOLs CONS_Printf(", %i", linenum); } // print the error vsprintf(tempstr, s, args); CONS_Printf(": %s", tempstr); // make a noise S_StartSound(NULL, sfx_pldeth); killscript = true;}//// sf: string value of an svalue_t//char *stringvalue(svalue_t v){ static char buffer[256]; switch(v.type) { case svt_string: return v.value.s; case svt_mobj: return "map object"; case svt_fixed: { double val = ((double)v.value.f / FRACUNIT); sprintf(buffer, "%g", val); return buffer; } case svt_int: default: sprintf(buffer, "%li", v.value.i); return buffer; }}//---------------------------------------------------------------------------//// $Log: t_parse.c,v $// Revision 1.4 2001/05/03 21:22:25 hurdler// remove some warnings//// Revision 1.3 2000/11/04 16:23:44 bpereira// no message//// Revision 1.2 2000/11/03 11:48:40 hurdler// Fix compiling problem under win32 with 3D-Floors and FragglScript (to verify!)//// Revision 1.1 2000/11/02 17:57:28 stroggonmeth// FraggleScript files...//// Revision 1.1.1.1 2000/04/30 19:12:08 fraggle// initial import//////---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -