Skip to content

Commit

Permalink
Merge pull request #755 from edge-classic/declarate-scanner
Browse files Browse the repository at this point in the history
Replace EPI Lexer with Declarate-compatible Scanner Class
  • Loading branch information
dashodanger authored Dec 17, 2024
2 parents 98fab61 + 9a01a8e commit 3abd355
Show file tree
Hide file tree
Showing 10 changed files with 1,293 additions and 898 deletions.
86 changes: 44 additions & 42 deletions source_files/ajbsp/bsp_level.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "epi_doomdefs.h"
#include "epi_ename.h"
#include "epi_endian.h"
#include "epi_lexer.h"
#include "epi_scanner.h"
#include "epi_str_util.h"
#include "miniz.h"

Expand Down Expand Up @@ -470,33 +470,33 @@ void GetLinedefs()

/* ----- UDMF reading routines ------------------------- */

void ParseThingField(Thing *thing, const int &key, const std::string &value)
void ParseThingField(Thing *thing, const int &key, epi::Scanner &lex)
{
// Do we need more precision than an int for things? I think this would only
// be an issue if/when polyobjects happen, as I think other thing types are
// ignored - Dasho

if (key == epi::kENameX)
thing->x = RoundToInteger(epi::LexDouble(value));
thing->x = RoundToInteger(lex.state_.decimal);
else if (key == epi::kENameY)
thing->y = RoundToInteger(epi::LexDouble(value));
thing->y = RoundToInteger(lex.state_.decimal);
else if (key == epi::kENameType)
thing->type = epi::LexInteger(value);
thing->type = lex.state_.number;
}

void ParseVertexField(Vertex *vertex, const int &key, const std::string &value)
void ParseVertexField(Vertex *vertex, const int &key, epi::Scanner &lex)
{
if (key == epi::kENameX)
vertex->x_ = epi::LexDouble(value);
vertex->x_ = lex.state_.decimal;
else if (key == epi::kENameY)
vertex->y_ = epi::LexDouble(value);
vertex->y_ = lex.state_.decimal;
}

void ParseSidedefField(Sidedef *side, const int &key, const std::string &value)
void ParseSidedefField(Sidedef *side, const int &key, epi::Scanner &lex)
{
if (key == epi::kENameSector)
{
int num = epi::LexInteger(value);
int num = lex.state_.number;

if (num < 0 || num >= level_sectors.size())
FatalError("AJBSP: illegal sector number #%d\n", (int)num);
Expand All @@ -505,24 +505,24 @@ void ParseSidedefField(Sidedef *side, const int &key, const std::string &value)
}
}

void ParseLinedefField(Linedef *line, const int &key, const std::string &value)
void ParseLinedefField(Linedef *line, const int &key, epi::Scanner &lex)
{
switch (key)
{
case epi::kENameV1:
line->start = SafeLookupVertex(epi::LexInteger(value));
line->start = SafeLookupVertex(lex.state_.number);
break;
case epi::kENameV2:
line->end = SafeLookupVertex(epi::LexInteger(value));
line->end = SafeLookupVertex(lex.state_.number);
break;
case epi::kENameSpecial:
line->type = epi::LexInteger(value);
line->type = lex.state_.number;
break;
case epi::kENameTwosided:
line->two_sided = epi::LexBoolean(value);
line->two_sided = lex.state_.boolean;
break;
case epi::kENameSidefront: {
int num = epi::LexInteger(value);
int num = lex.state_.number;

if (num < 0 || num >= (int)level_sidedefs.size())
line->right = nullptr;
Expand All @@ -531,7 +531,7 @@ void ParseLinedefField(Linedef *line, const int &key, const std::string &value)
}
break;
case epi::kENameSideback: {
int num = epi::LexInteger(value);
int num = lex.state_.number;

if (num < 0 || num >= (int)level_sidedefs.size())
line->left = nullptr;
Expand All @@ -544,7 +544,7 @@ void ParseLinedefField(Linedef *line, const int &key, const std::string &value)
}
}

void ParseUDMF_Block(epi::Lexer &lex, int cur_type)
void ParseUDMF_Block(epi::Scanner &lex, int cur_type)
{
Vertex *vertex = nullptr;
Thing *thing = nullptr;
Expand Down Expand Up @@ -572,48 +572,48 @@ void ParseUDMF_Block(epi::Lexer &lex, int cur_type)
break;
}

for (;;)
while (lex.TokensLeft())
{
if (lex.Match("}"))
if (lex.CheckToken('}'))
break;

std::string key;
std::string value;

epi::TokenKind tok = lex.Next(key);

if (tok == epi::kTokenEOF)
if (!lex.GetNextToken())
FatalError("AJBSP: Malformed TEXTMAP lump: unclosed block\n");

if (tok != epi::kTokenIdentifier)
if (lex.state_.token != epi::Scanner::kIdentifier)
FatalError("AJBSP: Malformed TEXTMAP lump: missing key\n");

if (!lex.Match("="))
FatalError("AJBSP: Malformed TEXTMAP lump: missing '='\n");
key = lex.state_.string;

tok = lex.Next(value);
if (!lex.CheckToken('='))
FatalError("AJBSP: Malformed TEXTMAP lump: missing '='\n");

if (tok == epi::kTokenEOF || tok == epi::kTokenError || value == "}")
if (!lex.GetNextToken() || lex.state_.token == '}')
FatalError("AJBSP: Malformed TEXTMAP lump: missing value\n");

if (!lex.Match(";"))
value = lex.state_.string;

if (!lex.CheckToken(';'))
FatalError("AJBSP: Malformed TEXTMAP lump: missing ';'\n");

epi::EName key_ename(key, true);

switch (cur_type)
{
case kUDMFVertex:
ParseVertexField(vertex, key_ename.GetIndex(), value);
ParseVertexField(vertex, key_ename.GetIndex(), lex);
break;
case kUDMFThing:
ParseThingField(thing, key_ename.GetIndex(), value);
ParseThingField(thing, key_ename.GetIndex(), lex);
break;
case kUDMFSidedef:
ParseSidedefField(side, key_ename.GetIndex(), value);
ParseSidedefField(side, key_ename.GetIndex(), lex);
break;
case kUDMFLinedef:
ParseLinedefField(line, key_ename.GetIndex(), value);
ParseLinedefField(line, key_ename.GetIndex(), lex);
break;
case kUDMFSector:
default: /* just skip it */
Expand Down Expand Up @@ -644,32 +644,34 @@ void ParseUDMF_Pass(const std::string &data, int pass)
// pass = 2 : sidedefs
// pass = 3 : linedefs

epi::Lexer lex(data);
epi::Scanner lex(data);

for (;;)
while (lex.TokensLeft())
{
std::string section;
epi::TokenKind tok = lex.Next(section);

if (tok == epi::kTokenEOF)
if (!lex.GetNextToken())
return;

if (tok != epi::kTokenIdentifier)
if (lex.state_.token != epi::Scanner::kIdentifier)
{
FatalError("AJBSP: Malformed TEXTMAP lump.\n");
return;
}

section = lex.state_.string;

// ignore top-level assignments
if (lex.Match("="))
if (lex.CheckToken('='))
{
lex.Next(section);
if (!lex.Match(";"))
lex.GetNextToken();
section = lex.state_.string;
if (!lex.CheckToken(';'))
FatalError("AJBSP: Malformed TEXTMAP lump: missing ';'\n");
continue;
}

if (!lex.Match("{"))
if (!lex.CheckToken('{'))
FatalError("AJBSP: Malformed TEXTMAP lump: missing '{'\n");

int cur_type = 0;
Expand Down
110 changes: 45 additions & 65 deletions source_files/edge/m_misc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#include "epi_endian.h"
#include "epi_file.h"
#include "epi_filesystem.h"
#include "epi_lexer.h"
#include "epi_scanner.h"
#include "epi_str_compare.h"
#include "epi_str_util.h"
#include "g_game.h"
Expand Down Expand Up @@ -309,54 +309,78 @@ void ResetDefaults(int dummy, ConsoleVariable *dummy_cvar)
done_first_init = true;
}

static void ParseConfigBlock(epi::Lexer &lex)
static void ParseConfig(const std::string &data, bool check_config_version)
{
for (;;)
epi::Scanner lex(data);

// Check the first line of a config file for the #VERSION entry. If not
// present, assume it is from a version that predates this concept
if (check_config_version)
{
if (!lex.GetNextToken() || lex.state_.token != '#')
{
show_old_config_warning = true;
}

if (!lex.GetNextToken() || lex.state_.token != epi::Scanner::kIdentifier || lex.state_.string != "VERSION")
{
show_old_config_warning = true;
}

if (!lex.GetNextToken() || lex.state_.token != epi::Scanner::kIntConst || lex.state_.number < kInternalConfigVersion)
{
show_old_config_warning = true;
}
}

while (lex.TokensLeft())
{
std::string key;
std::string value;

epi::TokenKind tok = lex.Next(key);
if (!lex.GetNextToken())
FatalError("ParseConfig: error parsing file!\n");

if (key == "/") // CVAR keys will start with this, but we need to discard it
continue;
// Discard leading / for cvars
// Todo: Convert everything to CVARs and then get
// rid of the leading slash
if (lex.state_.token == '/')
{
if (!lex.GetNextToken())
FatalError("ParseConfig: error parsing file!\n");
}

if (tok == epi::kTokenEOF)
return;
key = lex.state_.string;

if (tok == epi::kTokenError)
FatalError("ParseConfig: error parsing file!\n");
LogPrint("%s\n", lex.state_.string.c_str());

tok = lex.Next(value);
if (!lex.GetNextToken())
FatalError("ParseConfig: missing value for key %s!\n", key.c_str());

// The last line of the config writer causes a weird blank key with an
// EOF value, so just return here
if (tok == epi::kTokenEOF)
return;
value = lex.state_.string;

if (tok == epi::kTokenError)
FatalError("ParseConfig: malformed value for key %s!\n", key.c_str());
LogPrint("%s\n", lex.state_.string.c_str());

if (tok == epi::kTokenString)
if (lex.state_.token == epi::Scanner::kStringConst)
{
std::string try_cvar = key;
try_cvar.append(" ").append(value);
TryConsoleCommand(try_cvar.c_str());
}
else if (tok == epi::kTokenNumber)
else if (lex.state_.token == epi::Scanner::kIntConst)
{
for (int i = 0; i < total_defaults; i++)
{
if (0 == epi::StringCompare(key.c_str(), defaults[i].name))
{
if (defaults[i].type == kConfigBoolean)
{
*(bool *)defaults[i].location = epi::LexInteger(value) ? true : false;
*(bool *)defaults[i].location = lex.state_.boolean ? true : false;
}
else /* kConfigInteger and
kConfigKey */
{
*(int *)defaults[i].location = epi::LexInteger(value);
*(int *)defaults[i].location = lex.state_.number;
}
break;
}
Expand All @@ -365,50 +389,6 @@ static void ParseConfigBlock(epi::Lexer &lex)
}
}

static void ParseConfig(const std::string &data, bool check_config_version)
{
epi::Lexer lex(data);

// Check the first line of a config file for the #VERSION entry. If not
// present, assume it is from a version that predates this concept
if (check_config_version)
{
std::string version;
epi::TokenKind tok = lex.Next(version);

if (tok != epi::kTokenSymbol || version != "#")
{
show_old_config_warning = true;
}

tok = lex.Next(version);

if (tok != epi::kTokenIdentifier || version != "version")
{
show_old_config_warning = true;
}

tok = lex.Next(version);

if (tok != epi::kTokenNumber || epi::LexInteger(version) < kInternalConfigVersion)
{
show_old_config_warning = true;
}
}

for (;;)
{
std::string section;
epi::TokenKind tok = lex.Next(section);

if (tok == epi::kTokenEOF)
return;

// process the block
ParseConfigBlock(lex);
}
}

void LoadDefaults(void)
{
// set everything to base values
Expand Down
Loading

0 comments on commit 3abd355

Please sign in to comment.