📄 t_parse.c
字号:
// Emacs style mode select -*- C++ -*-//----------------------------------------------------------------------------//// $Id: t_parse.c,v 1.4 2001/05/03 21:22:25 hurdler Exp $//// Copyright(C) 2000 Simon Howard//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//// $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...//////--------------------------------------------------------------------------//// Parsing.//// Takes lines of code, or groups of lines and runs them.// The main core of FraggleScript//// By Simon Howard////----------------------------------------------------------------------------/* includes ************************/#include <stdio.h>#include <stdarg.h>#include "command.h"#include "doomtype.h"#include "doomdef.h"#include "doomstat.h"#include "s_sound.h"#include "w_wad.h"#include "z_zone.h"#include "t_parse.h"#include "t_prepro.h"#include "t_spec.h"#include "t_oper.h"#include "t_vari.h"#include "t_func.h"void parse_script();void parse_data(char *data, char *end);svalue_t evaluate_expression(int start, int stop);mobj_t *trigger_obj; // object which triggered scriptchar *tokens[T_MAXTOKENS];tokentype_t tokentype[T_MAXTOKENS];int num_tokens = 0;int script_debug = false;script_t *current_script; // the current scriptsvalue_t nullvar = { svt_int, {0} }; // null var for empty returnint killscript; // when set to true, stop the script quicklysection_t *prev_section; // the section from the previous statement/************ Divide into tokens **************/char *linestart; // start of linechar *rover; // current point reached in script // inline for speed#define isnum(c) ( ((c)>='0' && (c)<='9') || (c)=='.' ) // isop: is an 'operator' character, eg '=', '%'#define isop(c) !( ( (c)<='Z' && (c)>='A') || ( (c)<='z' && (c)>='a') || \ ( (c)<='9' && (c)>='0') || ( (c)=='_') ) // for simplicity:#define tt (tokentype[num_tokens-1])#define tok (tokens[num_tokens-1])section_t *current_section; // the section (if any) found in parsing the lineint bracetype; // bracket_open or bracket_closestatic void add_char(char c);// next_token: end this token, go onto the nextstatic void next_token(){ if(tok[0] || tt==string) { num_tokens++; tokens[num_tokens-1] = tokens[num_tokens-2] + strlen(tokens[num_tokens-2]) + 1; tok[0] = 0; } // get to the next token, ignoring spaces, newlines, // useless chars, comments etc while(1) { // empty whitespace if(*rover && (*rover==' ' || *rover<32)) { while((*rover==' ' || *rover<32) && *rover) rover++; } // end-of-script? if(!*rover) { if(tokens[0][0]) { CONS_Printf("%s %i %i\n", tokens[0], rover-current_script->data, current_script->len); // line contains text, but no semicolon: an error script_error("missing ';'\n"); } // empty line, end of command-list return; } // 11/8 comments moved to new preprocessor break; // otherwise } if(num_tokens>1 && *rover == '(' && tokentype[num_tokens-2] == name) tokentype[num_tokens-2] = function; if(*rover == '{' || *rover == '}') { if(*rover == '{') { bracetype = bracket_open; current_section = find_section_start(rover); } else // closing brace { bracetype = bracket_close; current_section = find_section_end(rover); } if(!current_section) { script_error("section not found!\n"); return; } } else if(*rover == ':') // label { // ignore the label : reset num_tokens = 1; tokens[0][0] = 0; tt = name; rover++; // ignore } else if(*rover == '\"') { tt = string; if(tokentype[num_tokens-2] == string) num_tokens--; // join strings rover++; } else { tt = isop(*rover) ? operator : isnum(*rover) ? number : name; }}// return an escape sequence (prefixed by a '\')// do not use all C escape sequencesstatic char escape_sequence(char c){ if(c == 'n') return '\n'; if(c == '\\') return '\\'; if(c == '"') return '"'; if(c == '?') return '?'; if(c == 'a') return '\a'; // alert beep if(c == 't') return '\t'; //tab// if(c == 'z') return *FC_TRANS; // translucent toggle // font colours if(c >= '0' && c <= '9') return 128 + (c-'0'); return c;}// add_char: add one character to the current tokenstatic void add_char(char c){ char *out = tok + strlen(tok); *out++ = c; *out = 0;}// get_tokens.// Take a string, break it into tokens.// individual tokens are stored inside the tokens[] array// tokentype is also used to hold the type for each token:// name: a piece of text which starts with an alphabet letter.// probably a variable name. Some are converted into// function types later on in find_brackets// number: a number. like '12' or '1337'// operator: an operator such as '&&' or '+'. All FraggleScript// operators are either one character, or two character// (if 2 character, 2 of the same char or ending in '=')// string: a text string that was enclosed in quote "" marks in// the original text// unset: shouldn't ever end up being set really.// function: a function name (found in second stage parsing)void get_tokens(char *s){ rover = s; num_tokens = 1; tokens[0][0] = 0; tt = name; current_section = NULL; // default to no section found next_token(); linestart = rover; // save the start if(*rover) while(1) { if(killscript) return; if(current_section) { // a { or } section brace has been found break; // stop parsing now } else if(tt != string) { if(*rover == ';') break; // check for end of command ';' } switch(tt) { case unset: case string: while(*rover != '\"') // dedicated loop for speed { if(*rover == '\\') // escape sequences { rover++; add_char(escape_sequence(*rover)); } else add_char(*rover); rover++; } rover++; next_token(); // end of this token continue; case operator: // all 2-character operators either end in '=' or // are 2 of the same character // do not allow 2-characters for brackets '(' ')' // which are still being considered as operators // operators are only 2-char max, do not need // a seperate loop if((*tok && *rover != '=' && *rover!=*tok) || *tok == '(' || *tok == ')') { // end of operator next_token(); continue; } add_char(*rover); break; case number: // add while number chars are read while(isnum(*rover)) // dedicated loop add_char(*rover++); next_token(); continue; case name: // add the chars while(!isop(*rover)) // dedicated loop add_char(*rover++); next_token(); continue; default: break; // shut up compiler } rover++; } // check for empty last token if(!tok[0]) { num_tokens = num_tokens - 1; } rover++;}void print_tokens() // DEBUG{ int i; for(i=0; i<num_tokens; i++) { CONS_Printf("\n'%s' \t\t --", tokens[i]); switch(tokentype[i]) { case string: CONS_Printf("string"); break; case operator: CONS_Printf("operator"); break; case name: CONS_Printf("name"); break; case number: CONS_Printf("number"); break; case unset : CONS_Printf("duh"); break; case function: CONS_Printf("function name"); break; } } CONS_Printf("\n"); if(current_section) CONS_Printf("current section: offset %i\n", (int)(current_section->start-current_script->data) );}// run_script//// the function called by t_script.cvoid run_script(script_t *script){ // set current script current_script = script; // start at the beginning of the script rover = current_script->data; current_script->lastiftrue = false; parse_script(); // run it}void continue_script(script_t *script, char *continue_point){ current_script = script; // continue from place specified rover = continue_point; parse_script(); // run }void parse_script(){ // check for valid rover if(rover < current_script->data || rover > current_script->data+current_script->len) { script_error("parse_script: trying to continue from point" "outside script!\n"); return; } trigger_obj = current_script->trigger; // set trigger parse_data(current_script->data, current_script->data+current_script->len); // dont clear global vars! if(current_script->scriptnum != -1) clear_variables(current_script); // free variables current_script->lastiftrue = false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -