- demoted the SWCustom parser to the primitive Hexen interface after finding out that this is all the Build parser can do.

This also meant I had to add symbol support to the old style number parsers.
This commit is contained in:
Christoph Oelckers 2020-09-12 10:23:47 +02:00
parent e0ae87e973
commit 89316aea33
4 changed files with 139 additions and 70 deletions

View file

@ -61,7 +61,7 @@ int32_t scriptfile_getnumber(scriptfile *sf, int32_t *num)
{ {
char *p = sf->textptr; char *p = sf->textptr;
skipovertoken(sf); skipovertoken(sf);
Printf("Error on line %s:%d: expecting int32_t, got \"%s\"\n",sf->filename,scriptfile_getlinum(sf,sf->ltextptr),p); Printf("Error on line %s:%d: expecting int, got \"%s\"\n",sf->filename,scriptfile_getlinum(sf,sf->ltextptr),p);
return -2; return -2;
} }
return 0; return 0;

View file

@ -505,6 +505,7 @@ bool FScanner::ScanString (bool tokens)
const char *marker, *tok; const char *marker, *tok;
bool return_val; bool return_val;
ParseError = false;
CheckOpen(); CheckOpen();
if (AlreadyGot) if (AlreadyGot)
{ {
@ -545,7 +546,7 @@ bool FScanner::GetString ()
return ScanString (false); return ScanString (false);
} }
//========================================================================== //============================================ ==============================
// //
// FScanner :: MustGetString // FScanner :: MustGetString
// //
@ -723,7 +724,7 @@ bool FScanner::CheckToken (int token, bool evaluate)
// //
//========================================================================== //==========================================================================
bool FScanner::GetNumber () bool FScanner::GetNumber (bool evaluate)
{ {
char *stopper; char *stopper;
@ -740,6 +741,19 @@ bool FScanner::GetNumber ()
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX); Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
if (*stopper != 0) if (*stopper != 0)
{ {
if (evaluate && symbols.CountUsed())
{
auto sym = symbols.CheckKey(String);
if (sym && sym->tokenType == TK_IntConst)
{
BigNumber = sym->Number;
Number = (int)sym->Number;
Float = sym->Float;
// String will retain the actual symbol name.
return true;
}
}
ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String); ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String);
} }
} }
@ -758,9 +772,9 @@ bool FScanner::GetNumber ()
// //
//========================================================================== //==========================================================================
void FScanner::MustGetNumber () void FScanner::MustGetNumber (bool evaluate)
{ {
if (GetNumber() == false) if (GetNumber(evaluate) == false)
{ {
ScriptError ("Missing integer (unexpected end of file)."); ScriptError ("Missing integer (unexpected end of file).");
} }
@ -775,7 +789,7 @@ void FScanner::MustGetNumber ()
// //
//========================================================================== //==========================================================================
bool FScanner::CheckNumber () bool FScanner::CheckNumber (bool evaluate)
{ {
char *stopper; char *stopper;
@ -797,6 +811,19 @@ bool FScanner::CheckNumber ()
Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX); Number = (int)BigNumber;// clamp<int64_t>(BigNumber, 0, UINT_MAX);
if (*stopper != 0) if (*stopper != 0)
{ {
if (evaluate && symbols.CountUsed())
{
auto sym = symbols.CheckKey(String);
if (sym && sym->tokenType == TK_IntConst)
{
BigNumber = sym->Number;
Number = (int)sym->Number;
Float = sym->Float;
// String will retain the actual symbol name.
return true;
}
}
UnGet(); UnGet();
return false; return false;
} }
@ -818,7 +845,7 @@ bool FScanner::CheckNumber ()
// //
//========================================================================== //==========================================================================
bool FScanner::CheckFloat () bool FScanner::CheckFloat (bool evaluate)
{ {
char *stopper; char *stopper;
@ -833,6 +860,20 @@ bool FScanner::CheckFloat ()
Float = strtod (String, &stopper); Float = strtod (String, &stopper);
if (*stopper != 0) if (*stopper != 0)
{ {
if (evaluate && symbols.CountUsed())
{
auto sym = symbols.CheckKey(String);
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
{
BigNumber = sym->Number;
Number = (int)sym->Number;
Float = sym->Float;
// String will retain the actual symbol name.
return true;
}
}
UnGet(); UnGet();
return false; return false;
} }
@ -851,7 +892,7 @@ bool FScanner::CheckFloat ()
// //
//========================================================================== //==========================================================================
bool FScanner::GetFloat () bool FScanner::GetFloat (bool evaluate)
{ {
char *stopper; char *stopper;
@ -861,6 +902,19 @@ bool FScanner::GetFloat ()
Float = strtod (String, &stopper); Float = strtod (String, &stopper);
if (*stopper != 0) if (*stopper != 0)
{ {
if (evaluate && symbols.CountUsed())
{
auto sym = symbols.CheckKey(String);
if (sym && sym->tokenType == TK_IntConst && sym->tokenType != TK_FloatConst)
{
BigNumber = sym->Number;
Number = (int)sym->Number;
Float = sym->Float;
// String will retain the actual symbol name.
return true;
}
}
ScriptError ("SC_GetFloat: Bad numeric constant \"%s\".", String); ScriptError ("SC_GetFloat: Bad numeric constant \"%s\".", String);
} }
Number = (int)Float; Number = (int)Float;
@ -878,9 +932,9 @@ bool FScanner::GetFloat ()
// //
//========================================================================== //==========================================================================
void FScanner::MustGetFloat () void FScanner::MustGetFloat (bool evaluate)
{ {
if (GetFloat() == false) if (GetFloat(evaluate) == false)
{ {
ScriptError ("Missing floating-point number (unexpected end of file)."); ScriptError ("Missing floating-point number (unexpected end of file).");
} }
@ -1115,6 +1169,12 @@ void FScanner::ScriptError (const char *message, ...)
va_end (arglist); va_end (arglist);
} }
if (NoFatalErrors)
{
Printf(TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
AlreadyGot ? AlreadyGotLine : Line, composed.GetChars());
return;
}
I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(), I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
AlreadyGot? AlreadyGotLine : Line, composed.GetChars()); AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
} }

View file

@ -82,6 +82,7 @@ public:
void SetCMode(bool cmode); void SetCMode(bool cmode);
void SetNoOctals(bool cmode) { NoOctals = cmode; } void SetNoOctals(bool cmode) { NoOctals = cmode; }
void SetNoFatalErrors(bool cmode) { NoFatalErrors = cmode; }
void SetEscape(bool esc); void SetEscape(bool esc);
void SetStateMode(bool stately); void SetStateMode(bool stately);
void DisableStateOptions(); void DisableStateOptions();
@ -108,13 +109,13 @@ public:
bool CheckToken(int token, bool evaluate = false); bool CheckToken(int token, bool evaluate = false);
bool CheckTokenId(ENamedName id); bool CheckTokenId(ENamedName id);
bool GetNumber(); bool GetNumber(bool evaluate = false);
void MustGetNumber(); void MustGetNumber(bool evaluate = false);
bool CheckNumber(); bool CheckNumber(bool evaluate = false);
bool GetFloat(); bool GetFloat(bool evaluate = false);
void MustGetFloat(); void MustGetFloat(bool evaluate = false);
bool CheckFloat(); bool CheckFloat(bool evaluate = false);
double *LookupConstant(FName name) double *LookupConstant(FName name)
{ {
@ -148,6 +149,7 @@ public:
double Float; double Float;
int Line; int Line;
bool End; bool End;
bool ParseError = false;
bool Crossed; bool Crossed;
int LumpNum; int LumpNum;
FString ScriptName; FString ScriptName;
@ -176,6 +178,7 @@ protected:
int LastGotLine; int LastGotLine;
bool CMode; bool CMode;
bool NoOctals = false; bool NoOctals = false;
bool NoFatalErrors = false;
uint8_t StateMode; uint8_t StateMode;
bool StateOptions; bool StateOptions;
bool Escape; bool Escape;

View file

@ -463,6 +463,8 @@ void LoadCustomInfoFromScript(const char *filename)
sc.OpenLumpNum(lump); sc.OpenLumpNum(lump);
sc.SetNoOctals(true); sc.SetNoOctals(true);
sc.SetCMode(true);
sc.SetNoFatalErrors(true);
// predefine constants for some stuff to give convenience and eliminate the need for a 'define' directive // predefine constants for some stuff to give convenience and eliminate the need for a 'define' directive
sc.AddSymbol("INV_ARMOR", 1+InvDecl_Armor); sc.AddSymbol("INV_ARMOR", 1+InvDecl_Armor);
@ -484,61 +486,60 @@ void LoadCustomInfoFromScript(const char *filename)
} }
MapRecord* curMap = nullptr; MapRecord* curMap = nullptr;
while (sc.GetToken()) while (sc.GetString())
{ {
sc.TokenMustBe(TK_Identifier);
switch (cm_transtok(sc.String, cm_tokens, cm_numtokens)) switch (cm_transtok(sc.String, cm_tokens, cm_numtokens))
{ {
case CM_MAP: case CM_MAP:
{ {
sc.MustGetValue(false, true); sc.MustGetNumber(true);
int mapno = sc.Number; int mapno = sc.ParseError? -1 : sc.Number;
curMap = FindMapByLevelNum(mapno); curMap = FindMapByLevelNum(mapno);
if (!curMap) if (!curMap)
{ {
curMap = AllocateMap(); curMap = AllocateMap();
curMap->levelNumber = mapno; curMap->levelNumber = mapno;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_map_tokens, cm_map_numtokens)) switch (cm_transtok(sc.String, cm_map_tokens, cm_map_numtokens))
{ {
case CM_FILENAME: case CM_FILENAME:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
curMap->SetFileName(sc.String); curMap->SetFileName(sc.String);
break; break;
} }
case CM_SONG: case CM_SONG:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
curMap->music = sc.String; curMap->music = sc.String;
break; break;
} }
case CM_TITLE: case CM_TITLE:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
curMap->SetName(sc.String); curMap->SetName(sc.String);
break; break;
} }
case CM_BESTTIME: case CM_BESTTIME:
{ {
sc.MustGetValue(false); sc.MustGetNumber();
curMap->designerTime = sc.Number; curMap->designerTime = sc.Number;
break; break;
} }
case CM_PARTIME: case CM_PARTIME:
{ {
sc.MustGetValue(false); sc.MustGetNumber();
curMap->parTime = sc.Number; curMap->parTime = sc.Number;
break; break;
} }
case CM_CDATRACK: case CM_CDATRACK:
{ {
sc.MustGetValue(false); sc.MustGetNumber();
curMap->cdSongId = sc.Number; curMap->cdSongId = sc.Number;
break; break;
} }
@ -554,31 +555,32 @@ void LoadCustomInfoFromScript(const char *filename)
{ {
int curep; int curep;
sc.MustGetValue(false, true); sc.MustGetNumber();
curep = sc.Number; curep = sc.Number;
if ((unsigned)--curep >= 2u) if (sc.ParseError) curep = -1;
else if ((unsigned)--curep >= 2u)
{ {
sc.ScriptMessage("Episode number %d not in range 1-2\n", curep + 1); sc.ScriptMessage("Episode number %d not in range 1-2\n", curep + 1);
curep = -1; curep = -1;
break; break;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_episode_tokens, cm_episode_numtokens)) switch (cm_transtok(sc.String, cm_episode_tokens, cm_episode_numtokens))
{ {
case CM_TITLE: case CM_TITLE:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (curep != -1) gVolumeNames[curep] = sc.String; if (curep != -1) gVolumeNames[curep] = sc.String;
break; break;
} }
case CM_SUBTITLE: case CM_SUBTITLE:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (curep != -1) gVolumeSubtitles[curep] = sc.String; if (curep != -1) gVolumeSubtitles[curep] = sc.String;
break; break;
} }
@ -593,8 +595,9 @@ void LoadCustomInfoFromScript(const char *filename)
case CM_SKILL: case CM_SKILL:
{ {
int curskill; int curskill;
sc.MustGetValue(false, true); sc.MustGetNumber();
curskill = sc.Number; curskill = sc.Number;
if (sc.ParseError) curskill = -1;
if ((unsigned)--curskill >= 4u) if ((unsigned)--curskill >= 4u)
{ {
sc.ScriptMessage("Skill number %d not in range 1-4 on line %s:%d\n", curskill + 1); sc.ScriptMessage("Skill number %d not in range 1-4 on line %s:%d\n", curskill + 1);
@ -602,15 +605,15 @@ void LoadCustomInfoFromScript(const char *filename)
break; break;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_skill_tokens, cm_skill_numtokens)) switch (cm_transtok(sc.String, cm_skill_tokens, cm_skill_numtokens))
{ {
case CM_TITLE: case CM_TITLE:
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (curskill != -1) gSkillNames[curskill] = sc.String; if (curskill != -1) gSkillNames[curskill] = sc.String;
break; break;
} }
@ -625,10 +628,10 @@ void LoadCustomInfoFromScript(const char *filename)
case CM_COOKIE: case CM_COOKIE:
{ {
int fc = 0; int fc = 0;
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (fc < MAX_FORTUNES) if (fc < MAX_FORTUNES)
{ {
quoteMgr.InitializeQuote(QUOTE_COOKIE + fc, sc.String); quoteMgr.InitializeQuote(QUOTE_COOKIE + fc, sc.String);
@ -640,10 +643,10 @@ void LoadCustomInfoFromScript(const char *filename)
case CM_GOTKEY: case CM_GOTKEY:
{ {
int fc = 0; int fc = 0;
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (fc < MAX_KEYS) if (fc < MAX_KEYS)
{ {
quoteMgr.InitializeQuote(QUOTE_KEYMSG + fc, sc.String); quoteMgr.InitializeQuote(QUOTE_KEYMSG + fc, sc.String);
@ -655,10 +658,10 @@ void LoadCustomInfoFromScript(const char *filename)
case CM_NEEDKEY: case CM_NEEDKEY:
{ {
int fc = 0; int fc = 0;
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_StringConst, true); sc.MustGetString();
if (fc < MAX_KEYS) if (fc < MAX_KEYS)
{ {
quoteMgr.InitializeQuote(QUOTE_DOORMSG + fc, sc.String); quoteMgr.InitializeQuote(QUOTE_DOORMSG + fc, sc.String);
@ -673,9 +676,10 @@ void LoadCustomInfoFromScript(const char *filename)
FString name; FString name;
int amt = -1; int amt = -1;
sc.MustGetValue(false, true); sc.MustGetNumber();
in = sc.Number; in = sc.Number;
if (sc.ParseError) in = -1;
if ((unsigned)--in >= (unsigned)InvDecl_TOTAL) if ((unsigned)--in >= (unsigned)InvDecl_TOTAL)
{ {
sc.ScriptMessage("Inventory item number %d not in range 1-%d\n", in, InvDecl_TOTAL); sc.ScriptMessage("Inventory item number %d not in range 1-%d\n", in, InvDecl_TOTAL);
@ -683,10 +687,10 @@ void LoadCustomInfoFromScript(const char *filename)
break; break;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_inventory_tokens, cm_inventory_numtokens)) switch (cm_transtok(sc.String, cm_inventory_tokens, cm_inventory_numtokens))
{ {
case CM_TITLE: case CM_TITLE:
@ -694,7 +698,7 @@ void LoadCustomInfoFromScript(const char *filename)
name = sc.String; name = sc.String;
break; break;
case CM_AMOUNT: case CM_AMOUNT:
sc.MustGetValue(false, true); sc.MustGetNumber();
amt = sc.Number; amt = sc.Number;
break; break;
default: default:
@ -720,9 +724,10 @@ void LoadCustomInfoFromScript(const char *filename)
int maxammo = -1, damagemin = -1, damagemax = -1, pickup = -1, wpickup = -1; int maxammo = -1, damagemin = -1, damagemax = -1, pickup = -1, wpickup = -1;
int in,id; int in,id;
sc.MustGetValue(false, true); sc.MustGetNumber();
in = sc.Number; in = sc.Number;
if (sc.ParseError) in = -1;
if ((unsigned)--in >= (unsigned)SIZ(weaponmap)) if ((unsigned)--in >= (unsigned)SIZ(weaponmap))
{ {
sc.ScriptMessage("Error: weapon number %d not in range 1-%d", in+1, (int)SIZ(weaponmap)); sc.ScriptMessage("Error: weapon number %d not in range 1-%d", in+1, (int)SIZ(weaponmap));
@ -730,10 +735,10 @@ void LoadCustomInfoFromScript(const char *filename)
break; break;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_weapons_tokens, cm_weapons_numtokens)) switch (cm_transtok(sc.String, cm_weapons_tokens, cm_weapons_numtokens))
{ {
case CM_TITLE: case CM_TITLE:
@ -745,23 +750,23 @@ void LoadCustomInfoFromScript(const char *filename)
ammo = sc.String; ammo = sc.String;
break; break;
case CM_MAXAMMO: case CM_MAXAMMO:
sc.MustGetValue(false, true); sc.MustGetNumber();
maxammo = sc.Number; maxammo = sc.Number;
break; break;
case CM_DAMAGEMIN: case CM_DAMAGEMIN:
sc.MustGetValue(false, true); sc.MustGetNumber();
damagemin = sc.Number; damagemin = sc.Number;
break; break;
case CM_DAMAGEMAX: case CM_DAMAGEMAX:
sc.MustGetValue(false, true); sc.MustGetNumber();
damagemax = sc.Number; damagemax = sc.Number;
break; break;
case CM_AMOUNT: case CM_AMOUNT:
sc.MustGetValue(false, true); sc.MustGetNumber();
pickup = sc.Number; pickup = sc.Number;
break; break;
case CM_WEAPON: case CM_WEAPON:
sc.MustGetValue(false, true); sc.MustGetNumber();
wpickup = sc.Number; wpickup = sc.Number;
break; break;
default: default:
@ -801,18 +806,19 @@ void LoadCustomInfoFromScript(const char *filename)
int trak = -1; int trak = -1;
int curtheme; int curtheme;
sc.MustGetValue(false, true); sc.MustGetNumber();
curtheme = sc.Number; curtheme = sc.Number;
if ((unsigned)--curtheme >= 6u) if (sc.ParseError) curtheme = -1;
if ((unsigned)--curtheme >= 6u)
{ {
sc.ScriptMessage("Theme number %d not in range 1-6", curtheme+1); sc.ScriptMessage("Theme number %d not in range 1-6", curtheme+1);
curtheme = -1; curtheme = -1;
} }
sc.MustGetToken('{'); if (sc.CheckString("{"))
while (!sc.CheckToken('}')) while (!sc.CheckString("}"))
{ {
sc.MustGetToken(TK_Identifier); sc.MustGetString();
switch (cm_transtok(sc.String, cm_theme_tokens, cm_theme_numtokens)) switch (cm_transtok(sc.String, cm_theme_tokens, cm_theme_numtokens))
{ {
case CM_SONG: case CM_SONG:
@ -820,7 +826,7 @@ void LoadCustomInfoFromScript(const char *filename)
name = sc.String; name = sc.String;
break; break;
case CM_CDATRACK: case CM_CDATRACK:
sc.MustGetValue(false, true); sc.MustGetNumber();
trak = sc.Number; trak = sc.Number;
break; break;
default: default: