2006-08-12 09:52:37 -07:00
|
|
|
%{
|
|
|
|
/*
|
|
|
|
* 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.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;
|
2006-08-19 06:26:11 -07:00
|
|
|
case VAL_STRING:
|
|
|
|
return STRING_VAR;
|
|
|
|
break;
|
2006-08-12 09:52:37 -07:00
|
|
|
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;
|
2006-08-19 06:26:11 -07:00
|
|
|
case VAL_STRING:
|
|
|
|
return STRING_CONSTANT;
|
|
|
|
break;
|
2006-08-12 09:52:37 -07:00
|
|
|
default:
|
|
|
|
if (object)
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
//debug(LOG_SCRIPT, "scriptGetConstToken: OBJ_CONSTANT");
|
2006-08-12 09:52:37 -07:00
|
|
|
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
|
2006-08-19 06:26:11 -07:00
|
|
|
object = asScrTypeTab[psFunc->type - VAL_USERTYPESTART].accessType == AT_OBJECT;
|
2006-08-12 09:52:37 -07:00
|
|
|
|
|
|
|
if (object)
|
|
|
|
{
|
|
|
|
return OBJ_FUNC;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (psFunc->type)
|
|
|
|
{
|
|
|
|
case VAL_BOOL:
|
|
|
|
return BOOL_FUNC;
|
|
|
|
break;
|
|
|
|
case VAL_INT:
|
|
|
|
// case VAL_FLOAT:
|
|
|
|
return NUM_FUNC;
|
|
|
|
break;
|
2006-08-19 06:26:11 -07:00
|
|
|
case VAL_STRING:
|
|
|
|
return STRING_FUNC;
|
|
|
|
break;
|
2006-08-12 09:52:37 -07:00
|
|
|
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
|
|
|
|
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;
|
2006-08-19 06:26:11 -07:00
|
|
|
case VAL_STRING:
|
2006-08-12 09:52:37 -07:00
|
|
|
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;
|
2006-08-19 06:26:11 -07:00
|
|
|
return return RET;
|
|
|
|
function return FUNCTION;
|
|
|
|
|
|
|
|
/* function return FUNCTION;*/
|
|
|
|
/* cond return COND; */
|
2006-08-12 09:52:37 -07:00
|
|
|
|
|
|
|
|
|
|
|
public { scr_lval.stype = ST_PUBLIC; return STORAGE; }
|
|
|
|
private { scr_lval.stype = ST_PRIVATE; return STORAGE; }
|
2006-08-15 11:38:51 -07:00
|
|
|
local { scr_lval.stype = ST_LOCAL; return STORAGE; }
|
2006-08-12 09:52:37 -07:00
|
|
|
while return WHILE;
|
|
|
|
if return IF;
|
|
|
|
else return ELSE;
|
|
|
|
exit return EXIT;
|
|
|
|
pause return PAUSE;
|
|
|
|
|
|
|
|
/* Match to type key words */
|
2006-08-19 06:26:11 -07:00
|
|
|
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; }
|
2006-08-12 09:52:37 -07:00
|
|
|
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; }
|
2006-08-19 06:26:11 -07:00
|
|
|
/*float { ais_lval.tval = VAL_FLOAT; return TYPE; }*/
|
2006-08-12 09:52:37 -07:00
|
|
|
/* 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 */
|
2006-08-19 06:26:11 -07:00
|
|
|
[a-zA-Z_][0-9_a-zA-Z_]* {
|
|
|
|
debug(LOG_SCRIPT, "looking up '%s'", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
/* See if this identifier has been defined as a type */
|
|
|
|
if (scriptLookUpType(scr_text, &scr_lval.tval))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a type", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return TYPE;
|
|
|
|
}
|
|
|
|
/* See if this identifier has been defined as a variable */
|
|
|
|
else if (scriptLookUpVariable(scr_text, &scr_lval.vSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a var", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return scriptGetVarToken(scr_lval.vSymbol);
|
|
|
|
}
|
|
|
|
/* See if this identifier has been defined as a constant */
|
|
|
|
else if (scriptLookUpConstant(scr_text, &scr_lval.cSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a constant", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return scriptGetConstToken(scr_lval.cSymbol);
|
|
|
|
}
|
|
|
|
/* See if this identifier has been defined as a function */
|
|
|
|
else if (scriptLookUpFunction(scr_text, &scr_lval.fSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a function", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return scriptGetFuncToken(scr_lval.fSymbol);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See if this identifier has been defined as a custom function */
|
|
|
|
else if (scriptLookUpCustomFunction(scr_text, &scr_lval.eSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a cust func", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return scriptGetCustomFuncToken(scr_lval.eSymbol);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (scriptLookUpTrigger(scr_text, &scr_lval.tSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a trigger", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return TRIG_SYM;
|
|
|
|
}
|
|
|
|
else if (scriptLookUpEvent(scr_text, &scr_lval.eSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is an event", scr_text);
|
|
|
|
|
2006-08-12 09:52:37 -07:00
|
|
|
return EVENT_SYM;
|
|
|
|
}
|
|
|
|
else if (scriptLookUpCallback(scr_text, &scr_lval.cbSymbol))
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is a callback", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return CALLBACK_SYM;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "'%s' is an ident", scr_text);
|
|
|
|
|
2006-08-12 09:52:37 -07:00
|
|
|
strcpy(aText[currText], scr_text);
|
|
|
|
scr_lval.sval = aText[currText];
|
|
|
|
currText = (currText + 1) % TEXT_BUFFERS;
|
|
|
|
return IDENT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Match quoted text */
|
|
|
|
\" { BEGIN QUOTE; }
|
|
|
|
<QUOTE>\" { BEGIN 0; }
|
|
|
|
<QUOTE>[^\"\n]* {
|
|
|
|
strcpy(aText[currText], scr_text);
|
|
|
|
scr_lval.sval = aText[currText];
|
|
|
|
currText = (currText + 1) % TEXT_BUFFERS;
|
2006-08-19 06:26:11 -07:00
|
|
|
debug(LOG_SCRIPT, "%s is QTEXT", scr_text);
|
2006-08-12 09:52:37 -07:00
|
|
|
return QTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip white space */
|
|
|
|
[ \t\n\x0d\x0a] ;
|
|
|
|
|
|
|
|
/* Strip comments */
|
|
|
|
"/*" { inComment=TRUE; BEGIN COMMENT; }
|
|
|
|
<COMMENT>"*/" |
|
|
|
|
<COMMENT>"*/"\n { inComment=FALSE; BEGIN 0; }
|
|
|
|
<COMMENT>. |
|
|
|
|
<COMMENT>\n ;
|
|
|
|
|
|
|
|
/* Strip single line comments */
|
|
|
|
"//" { BEGIN SLCOMMENT; }
|
|
|
|
<SLCOMMENT>\n { BEGIN 0; }
|
|
|
|
<SLCOMMENT>[^\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)
|
|
|
|
{
|
2006-08-19 06:26:11 -07:00
|
|
|
DBERROR(("Warning: reached end of file in a comment"));
|
2006-08-12 09:52:37 -07:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|