- Fixed: The check arrays for BlockThingsIterators were not properly
freed and each iterator allocated a new one as a result. - Split the Xlat parser context class into a generic part that can be used for other Lemon-based parsers in the future and a smaller Xlat-specific part. SVN r892 (trunk)
This commit is contained in:
parent
17816dcadd
commit
3a14dab2e8
8 changed files with 691 additions and 476 deletions
|
|
@ -41,9 +41,21 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "info.h"
|
||||
#include "gi.h"
|
||||
#include "parsecontext.h"
|
||||
#include "xlat_parser.h"
|
||||
#include "xlat.h"
|
||||
|
||||
|
||||
// Token types not used in the grammar
|
||||
enum
|
||||
{
|
||||
XLAT_INCLUDE=128,
|
||||
XLAT_STRING,
|
||||
};
|
||||
|
||||
DEFINE_TOKEN_TRANS(XLAT_)
|
||||
|
||||
|
||||
static FString LastTranslator;
|
||||
TAutoGrowArray<FLineTrans> SimpleLineTranslations;
|
||||
FBoomTranslator Boomish[MAX_BOOMISH];
|
||||
|
|
@ -51,27 +63,6 @@ int NumBoomish;
|
|||
TAutoGrowArray<FSectorTrans> SectorTranslations;
|
||||
TArray<FSectorMask> SectorMasks;
|
||||
|
||||
// Token types not used in the grammar
|
||||
enum
|
||||
{
|
||||
INCLUDE=128,
|
||||
STRING,
|
||||
};
|
||||
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
int Value;
|
||||
char Sym[80];
|
||||
};
|
||||
|
||||
union XlatToken
|
||||
{
|
||||
int val;
|
||||
char sym[80];
|
||||
char string[80];
|
||||
Symbol *symval;
|
||||
};
|
||||
|
||||
struct SpecialArgs
|
||||
{
|
||||
|
|
@ -105,49 +96,11 @@ struct ParseBoomArg
|
|||
};
|
||||
|
||||
|
||||
struct XlatParseContext
|
||||
struct XlatParseContext : public FParseContext
|
||||
{
|
||||
TArray<Symbol> symbols;
|
||||
int SourceLine;
|
||||
const char *SourceFile;
|
||||
int EnumVal;
|
||||
|
||||
XlatParseContext()
|
||||
XlatParseContext(void *parser, ParseFunc parse, int *tt)
|
||||
: FParseContext(parser, parse, tt)
|
||||
{
|
||||
SourceLine = 0;
|
||||
SourceFile = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void AddSym (char *sym, int val)
|
||||
{
|
||||
Symbol syme;
|
||||
syme.Value = val;
|
||||
strncpy (syme.Sym, sym, 79);
|
||||
syme.Sym[79]=0;
|
||||
symbols.Push(syme);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
bool FindSym (char *sym, Symbol **val)
|
||||
{
|
||||
for(unsigned i=0;i<symbols.Size(); i++)
|
||||
{
|
||||
if (strcmp (symbols[i].Sym, sym) == 0)
|
||||
{
|
||||
*val = &symbols[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -159,303 +112,43 @@ struct XlatParseContext
|
|||
{
|
||||
static const char tokens[][10] =
|
||||
{
|
||||
"include", "define", "enum",
|
||||
"arg5", "arg4", "arg3", "arg2", "flags", "lineid", "tag",
|
||||
"sector", "bitmask", "nobitmask", "clear"
|
||||
|
||||
"arg2", "arg3", "arg4", "arg5", "bitmask", "clear",
|
||||
"define", "enum", "flags", "include", "lineid",
|
||||
"nobitmask", "sector", "tag"
|
||||
};
|
||||
static const short types[] =
|
||||
{
|
||||
INCLUDE, DEFINE, ENUM,
|
||||
ARG5, ARG4, ARG3, ARG2, FLAGS, TAG, TAG,
|
||||
SECTOR, BITMASK, NOBITMASK, CLEAR
|
||||
XLAT_ARG2, XLAT_ARG3, XLAT_ARG4, XLAT_ARG5, XLAT_BITMASK, XLAT_CLEAR,
|
||||
XLAT_DEFINE, XLAT_ENUM, XLAT_FLAGS, XLAT_INCLUDE, XLAT_TAG,
|
||||
XLAT_NOBITMASK, XLAT_SECTOR, XLAT_TAG,
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = sizeof(tokens)/sizeof(tokens[0])-1; i >= 0; i--)
|
||||
{
|
||||
if (strcmp (tok, tokens[i]) == 0)
|
||||
{
|
||||
*type = types[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int min = 0, max = sizeof(tokens)/sizeof(tokens[0]) - 1;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
int GetToken (char *&sourcep, XlatToken *yylval)
|
||||
{
|
||||
char token[80];
|
||||
int toksize;
|
||||
int c;
|
||||
|
||||
loop:
|
||||
while (isspace (c = *sourcep++) && c != 0)
|
||||
while (min <= max)
|
||||
{
|
||||
if (c == '\n')
|
||||
SourceLine++;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (isdigit (c))
|
||||
{
|
||||
int buildup = c - '0';
|
||||
if (c == '0')
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (tok, tokens[mid]);
|
||||
if (lexval == 0)
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == 'x' || c == 'X')
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (isdigit (c))
|
||||
{
|
||||
buildup = (buildup<<4) + c - '0';
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
buildup = (buildup<<4) + c - 'a' + 10;
|
||||
}
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
buildup = (buildup<<4) + c - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcep--;
|
||||
yylval->val = buildup;
|
||||
return NUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcep--;
|
||||
}
|
||||
*type = types[mid];
|
||||
return true;
|
||||
}
|
||||
while (isdigit (c = *sourcep++))
|
||||
else if (lexval > 0)
|
||||
{
|
||||
buildup = buildup*10 + c - '0';
|
||||
}
|
||||
sourcep--;
|
||||
yylval->val = buildup;
|
||||
return NUM;
|
||||
}
|
||||
if (isalpha (c))
|
||||
{
|
||||
int buildup = 0;
|
||||
|
||||
token[0] = c;
|
||||
toksize = 1;
|
||||
while (toksize < 79 && (isalnum (c = *sourcep++) || c == '_'))
|
||||
{
|
||||
token[toksize++] = c;
|
||||
}
|
||||
token[toksize] = 0;
|
||||
if (toksize == 79 && isalnum (c))
|
||||
{
|
||||
while (isalnum (c = *sourcep++))
|
||||
;
|
||||
}
|
||||
sourcep--;
|
||||
if (FindToken (token, &buildup))
|
||||
{
|
||||
return buildup;
|
||||
}
|
||||
if (FindSym (token, &yylval->symval))
|
||||
{
|
||||
return SYMNUM;
|
||||
}
|
||||
if ((yylval->val = P_FindLineSpecial(token)) != 0)
|
||||
{
|
||||
return NUM;
|
||||
}
|
||||
strcpy (yylval->sym, token);
|
||||
return SYM;
|
||||
}
|
||||
if (c == '/')
|
||||
{
|
||||
c = *sourcep++;;
|
||||
if (c == '*')
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
while ((c = *sourcep++) != '*' && c != 0)
|
||||
{
|
||||
if (c == '\n')
|
||||
SourceLine++;
|
||||
}
|
||||
if (c == 0)
|
||||
return 0;
|
||||
if ((c = *sourcep++) == '/')
|
||||
goto loop;
|
||||
if (c == 0)
|
||||
return 0;
|
||||
sourcep--;
|
||||
}
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
while ((c = *sourcep++) != '\n' && c != 0)
|
||||
;
|
||||
if (c == '\n')
|
||||
SourceLine++;
|
||||
else if (c == EOF)
|
||||
return 0;
|
||||
goto loop;
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcep--;
|
||||
return DIVIDE;
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
if (c == '"')
|
||||
{
|
||||
int tokensize = 0;
|
||||
while ((c = *sourcep++) != '"' && c != 0)
|
||||
{
|
||||
yylval->string[tokensize++] = c;
|
||||
}
|
||||
yylval->string[tokensize] = 0;
|
||||
return STRING;
|
||||
}
|
||||
if (c == '|')
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == '=')
|
||||
return OR_EQUAL;
|
||||
sourcep--;
|
||||
return OR;
|
||||
}
|
||||
if (c == '<')
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == '<')
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == '=')
|
||||
{
|
||||
return LSHASSIGN;
|
||||
}
|
||||
sourcep--;
|
||||
return 0;
|
||||
}
|
||||
c--;
|
||||
return 0;
|
||||
}
|
||||
if (c == '>')
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == '>')
|
||||
{
|
||||
c = *sourcep++;
|
||||
if (c == '=')
|
||||
{
|
||||
return RSHASSIGN;
|
||||
}
|
||||
sourcep--;
|
||||
return 0;
|
||||
}
|
||||
c--;
|
||||
return 0;
|
||||
}
|
||||
switch (c)
|
||||
{
|
||||
case '^': return XOR;
|
||||
case '&': return AND;
|
||||
case '-': return MINUS;
|
||||
case '+': return PLUS;
|
||||
case '*': return MULTIPLY;
|
||||
case '(': return LPAREN;
|
||||
case ')': return RPAREN;
|
||||
case ',': return COMMA;
|
||||
case '{': return LBRACE;
|
||||
case '}': return RBRACE;
|
||||
case '=': return EQUALS;
|
||||
case ';': return SEMICOLON;
|
||||
case ':': return COLON;
|
||||
case '[': return LBRACKET;
|
||||
case ']': return RBRACKET;
|
||||
default: return 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int PrintError (const char *s)
|
||||
{
|
||||
if (SourceFile != NULL)
|
||||
Printf ("%s, line %d: %s\n", SourceFile, SourceLine, s);
|
||||
else
|
||||
Printf ("%s\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#include "xlat_parser.c"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ParseXlatLump(const char *lumpname, void *pParser, XlatParseContext *context)
|
||||
{
|
||||
int tokentype;
|
||||
int SavedSourceLine = context->SourceLine;
|
||||
const char *SavedSourceFile = context->SourceFile;
|
||||
XlatToken token;
|
||||
|
||||
int lumpno = Wads.CheckNumForFullName(lumpname, true);
|
||||
|
||||
if (lumpno == -1)
|
||||
{
|
||||
Printf ("%s, line %d: Lump '%s' not found\n", context->SourceFile, context->SourceLine, lumpname);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the lump into a buffer and add a 0-terminator
|
||||
int lumplen = Wads.LumpLength(lumpno);
|
||||
char *lumpdata = new char[lumplen+1];
|
||||
Wads.ReadLump(lumpno, lumpdata);
|
||||
lumpdata[lumplen] = 0;
|
||||
|
||||
context->SourceLine = 0;
|
||||
context->SourceFile = lumpname;
|
||||
|
||||
char *sourcep = lumpdata;
|
||||
while ( (tokentype = context->GetToken(sourcep, &token)) )
|
||||
{
|
||||
// It is much easier to handle include statements outside the main parser.
|
||||
if (tokentype == INCLUDE)
|
||||
{
|
||||
if (context->GetToken(sourcep, &token) != STRING)
|
||||
{
|
||||
Printf("%s, line %d: Include: String parameter expected\n", context->SourceFile, context->SourceLine);
|
||||
return;
|
||||
}
|
||||
ParseXlatLump(token.string, pParser, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
XlatParse(pParser, tokentype, token, context);
|
||||
}
|
||||
}
|
||||
delete [] lumpdata;
|
||||
context->SourceLine = SavedSourceLine;
|
||||
context->SourceFile = SavedSourceFile;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
@ -476,10 +169,10 @@ void P_LoadTranslator(const char *lumpname)
|
|||
|
||||
void *pParser = XlatParseAlloc(malloc);
|
||||
|
||||
XlatParseContext context;
|
||||
XlatParseContext context(pParser, XlatParse, TokenTrans);
|
||||
|
||||
ParseXlatLump(lumpname, pParser, &context);
|
||||
XlatToken tok;
|
||||
context.ParseLump(lumpname);
|
||||
FParseToken tok;
|
||||
tok.val=0;
|
||||
XlatParse(pParser, 0, tok, &context);
|
||||
XlatParseFree(pParser, free);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue