/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 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. Warzone 2100 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 Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ %{ /* * script.l * * Script file lexer. */ #include "lib/framework/frame.h" #include "interp.h" #include "parse.h" #include "script.h" /* Get the Yacc definitions */ #include "script_parser.tab.h" /* Maximum length for any TEXT value */ #ifndef YYLMAX #define YYLMAX 255 #endif /* Store for any string values */ static STRING aText[TEXT_BUFFERS][YYLMAX]; static UDWORD currText=0; // Note if we are in a comment static BOOL inComment = FALSE; /* Pointer to the input buffer */ static char *pInputBuffer = NULL; static char *pEndBuffer = NULL; #define YY_INPUT(buf, result, max_size) \ if (pInputBuffer != pEndBuffer) { \ buf[0] = *(pInputBuffer++); result = 1; \ } else { \ buf[0] = EOF; result = YY_NULL; \ } #undef scr_getc #define scr_getc() (pInputBuffer != pEndBuffer ? *(pInputBuffer++) : EOF) /* Get the token type for a variable symbol */ SDWORD scriptGetVarToken(VAR_SYMBOL *psVar) { BOOL object; // See if this is an object pointer if (!asScrTypeTab || psVar->type < VAL_USERTYPESTART) { object = FALSE; } else { object = asScrTypeTab[psVar->type - VAL_USERTYPESTART].accessType == AT_OBJECT; } if (psVar->storage == ST_OBJECT) { /* This is an object member variable */ if (object) { return OBJ_OBJVAR; } else { switch (psVar->type) { case VAL_BOOL: return BOOL_OBJVAR; break; case VAL_INT: // case VAL_FLOAT: return NUM_OBJVAR; break; default: return USER_OBJVAR; break; } } } else if (psVar->dimensions > 0) { /* This is an array variable */ if (object) { return OBJ_ARRAY; } else { switch (psVar->type) { case VAL_BOOL: return BOOL_ARRAY; break; case VAL_INT: // case VAL_FLOAT: return NUM_ARRAY; break; default: return VAR_ARRAY; break; } } } else { /* This is a standard variable */ if (object) { return OBJ_VAR; } else { switch (psVar->type) { case VAL_BOOL: return BOOL_VAR; break; case VAL_INT: // case VAL_FLOAT: return NUM_VAR; break; case VAL_STRING: return STRING_VAR; break; default: return VAR; break; } } } } /* Get the token type for a constant symbol */ SDWORD scriptGetConstToken(CONST_SYMBOL *psConst) { BOOL object; // See if this is an object constant if (!asScrTypeTab || psConst->type < VAL_USERTYPESTART) { object = FALSE; } else { object = asScrTypeTab[psConst->type - VAL_USERTYPESTART].accessType == AT_OBJECT; } switch (psConst->type) { case VAL_BOOL: return BOOL_CONSTANT; break; case VAL_INT: // case VAL_FLOAT: return NUM_CONSTANT; break; case VAL_STRING: return STRING_CONSTANT; break; default: if (object) { //debug(LOG_SCRIPT, "scriptGetConstToken: OBJ_CONSTANT"); return OBJ_CONSTANT; } else { return USER_CONSTANT; } break; } } /* Get the token type for a function symbol */ SDWORD scriptGetFuncToken(FUNC_SYMBOL *psFunc) { BOOL object; // See if this is an object pointer if(psFunc->type >= VAL_USERTYPESTART) { object = asScrTypeTab[psFunc->type - VAL_USERTYPESTART].accessType == AT_OBJECT; if (object) { return OBJ_FUNC; } } switch (psFunc->type) { case VAL_BOOL: return BOOL_FUNC; break; case VAL_INT: // case VAL_FLOAT: return NUM_FUNC; break; case VAL_STRING: return STRING_FUNC; break; case VAL_VOID: return FUNC; break; default: return USER_FUNC; break; } } /* Get the token type for a custom function symbol */ SDWORD scriptGetCustomFuncToken(EVENT_SYMBOL *psFunc) { BOOL object; // See if this is an object pointer if (!asScrTypeTab || psFunc->retType < VAL_USERTYPESTART) { object = FALSE; } else { object = asScrTypeTab[psFunc->retType - VAL_USERTYPESTART].accessType == AT_OBJECT; } if (object) { return OBJ_FUNC_CUST; } else { switch (psFunc->retType) { case VAL_BOOL: return BOOL_FUNC_CUST; break; case VAL_INT: // case VAL_FLOAT: return NUM_FUNC_CUST; break; case VAL_STRING: return STRING_FUNC_CUST; break; case VAL_VOID: return VOID_FUNC_CUST; break; default: return USER_FUNC_CUST; break; } } } %} %option prefix="scr_" %option nounput %option yylineno %x COMMENT %x SLCOMMENT %x QUOTE %% /* Match to key words */ /*begin return START;*/ /*end return END;*/ wait return WAIT; every return EVERY; trigger return TRIGGER; event return EVENT; inactive return INACTIVE; init return INITIALISE; link return LINK; ref return REF; return return RET; function return FUNCTION; /* function return FUNCTION;*/ /* cond return COND; */ public { scr_lval.stype = ST_PUBLIC; return STORAGE; } private { scr_lval.stype = ST_PRIVATE; return STORAGE; } local { scr_lval.stype = ST_LOCAL; return STORAGE; } while return WHILE; if return IF; else return ELSE; exit return EXIT; pause return PAUSE; /* Match to type key words */ void { scr_lval.tval = VAL_VOID; return TYPE; } VOID { scr_lval.tval = VAL_VOID; return TYPE; } string { scr_lval.tval = VAL_STRING; return TYPE; } STRING { scr_lval.tval = VAL_STRING; return TYPE; } bool { scr_lval.tval = VAL_BOOL; return TYPE; } BOOL { scr_lval.tval = VAL_BOOL; return TYPE; } int { scr_lval.tval = VAL_INT; return TYPE; } INT { scr_lval.tval = VAL_INT; return TYPE; } /*float { ais_lval.tval = VAL_FLOAT; return TYPE; }*/ /* string type isn't implemented yet */ /* string { ais_lval.tval = VAL_STRING; return TYPE; } */ /* object { scr_lval.tval = VAL_OBJECT; return TYPE; } */ /* Match boolean values */ TRUE { scr_lval.bval = TRUE; return BOOLEAN_T; } true { scr_lval.bval = TRUE; return BOOLEAN_T; } FALSE { scr_lval.bval = FALSE; return BOOLEAN_T; } false { scr_lval.bval = FALSE; return BOOLEAN_T; } /* Match boolean operators */ "==" return BOOLEQUAL; "!=" return NOTEQUAL; ">=" return GREATEQUAL; "<=" return LESSEQUAL; ">" return GREATER; "<" return LESS; and return _AND; AND return _AND; or return _OR; OR return _OR; not return _NOT; NOT return _NOT; /* Match floating point numbers */ /*-?[0-9]*"."[0-9]+ { scr_lval.fval = (float)atof(scr_text); return FLOAT; }*/ /* Match integer numbers */ -?[0-9]+ { scr_lval.ival = atol(scr_text); return INTEGER; } /* Match identifiers */ [a-zA-Z_][0-9_a-zA-Z_]* { #ifdef DEBUG_SCRIPT debug(LOG_SCRIPT, "looking up '%s'", scr_text); #endif /* See if this identifier has been defined as a type */ if (scriptLookUpType(scr_text, &scr_lval.tval)) { //debug(LOG_SCRIPT, "'%s' is a type", scr_text); return TYPE; } /* See if this identifier has been defined as a variable */ else if (scriptLookUpVariable(scr_text, &scr_lval.vSymbol)) { //debug(LOG_SCRIPT, "'%s' is a var", scr_text); return scriptGetVarToken(scr_lval.vSymbol); } /* See if this identifier has been defined as a constant */ else if (scriptLookUpConstant(scr_text, &scr_lval.cSymbol)) { //debug(LOG_SCRIPT, "'%s' is a constant", scr_text); return scriptGetConstToken(scr_lval.cSymbol); } /* See if this identifier has been defined as a function */ else if (scriptLookUpFunction(scr_text, &scr_lval.fSymbol)) { //debug(LOG_SCRIPT, "'%s' is a function", scr_text); return scriptGetFuncToken(scr_lval.fSymbol); } /* See if this identifier has been defined as a custom function */ else if (scriptLookUpCustomFunction(scr_text, &scr_lval.eSymbol)) { //debug(LOG_SCRIPT, "'%s' is a cust func", scr_text); return scriptGetCustomFuncToken(scr_lval.eSymbol); } else if (scriptLookUpTrigger(scr_text, &scr_lval.tSymbol)) { //debug(LOG_SCRIPT, "'%s' is a trigger", scr_text); return TRIG_SYM; } else if (scriptLookUpEvent(scr_text, &scr_lval.eSymbol)) { //debug(LOG_SCRIPT, "'%s' is an event", scr_text); return EVENT_SYM; } else if (scriptLookUpCallback(scr_text, &scr_lval.cbSymbol)) { //debug(LOG_SCRIPT, "'%s' is a callback", scr_text); return CALLBACK_SYM; } else { #ifdef DEBUG_SCRIPT debug(LOG_SCRIPT, "'%s' is an ident", scr_text); #endif strcpy(aText[currText], scr_text); scr_lval.sval = aText[currText]; currText = (currText + 1) % TEXT_BUFFERS; return IDENT; } } /* Match quoted text */ \" { BEGIN QUOTE; } \" { BEGIN 0; } [^\"\n]* { strcpy(aText[currText], scr_text); scr_lval.sval = aText[currText]; currText = (currText + 1) % TEXT_BUFFERS; //debug(LOG_SCRIPT, "%s is QTEXT", scr_text); return QTEXT; } /* Skip white space */ [ \t\n\x0d\x0a] ; /* Strip comments */ "/*" { inComment=TRUE; BEGIN COMMENT; } "*/" | "*/"\n { inComment=FALSE; BEGIN 0; } . | \n ; /* Strip single line comments */ "//" { BEGIN SLCOMMENT; } \n { BEGIN 0; } [^\n]* ; /* Match anything that's been missed and pass it as a char */ . return scr_text[0]; %% /* Set the current input buffer for the lexer */ void scriptSetInputBuffer(char *pBuffer, UDWORD size) { pInputBuffer = pBuffer; pEndBuffer = pBuffer + size; /* Reset the lexer in case it's been used before */ scr__flush_buffer( YY_CURRENT_BUFFER ); } void scriptGetErrorData(int *pLine, char **ppText) { *pLine = scr_lineno; *ppText = scr_text; } int scr_wrap(void) { if (inComment) { debug( LOG_ERROR, "Warning: reached end of file in a comment" ); abort(); } return 1; }