Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
libcommon: Derived HexLex (class) from Hexen's script parser
A (common) lexical analyzer for Hexen definition/script syntaxes. Todo: Cleanup
- Loading branch information
1 parent
e1efab8
commit 29e810a
Showing
7 changed files
with
305 additions
and
409 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** @file hexlex.h Laxical analyzer for Hexen definition/script syntax. | ||
* | ||
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
* @authors Copyright © 2007-2013 Daniel Swanson <danij@dengine.net> | ||
* @authors Copyright © 1999 Activision | ||
* | ||
* @par License | ||
* GPL: http://www.gnu.org/licenses/gpl.html | ||
* | ||
* <small>This program 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. This program 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 this program; if not, write to the Free | ||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
* 02110-1301 USA</small> | ||
*/ | ||
|
||
#ifndef LIBCOMMON_HEXLEX_H | ||
#define LIBCOMMON_HEXLEX_H | ||
|
||
#include "common.h" | ||
|
||
/** | ||
* Lexical analyzer for Hexen definition/script syntax. | ||
*/ | ||
class HexLex | ||
{ | ||
public: | ||
HexLex(); | ||
~HexLex(); | ||
|
||
/** | ||
* Prepare a new script for parsing. It is assumed that the @a script data | ||
* remains available until parsing is completed (or the script is replaced). | ||
* | ||
* @param script The script source to be parsed. | ||
* @param sourcePath Used to identify the script in log messages. A copy is made. | ||
*/ | ||
void parse(Str const *script, Str const *sourcePath); | ||
|
||
bool readToken(); | ||
|
||
Str const *token(); | ||
|
||
void unreadToken(); | ||
|
||
Str const *mustGetString(); | ||
int mustGetNumber(); | ||
|
||
int lineNumber() const; | ||
|
||
void scriptError(); | ||
void scriptError(char const *message); | ||
|
||
private: | ||
void checkOpen(); | ||
bool atEnd(); | ||
|
||
Str _sourcePath; ///< Used to identify the source in error messages. | ||
|
||
Str const *_script; ///< The start of the script being parsed. | ||
int _readPos; ///< Current read position. | ||
int _lineNumber; | ||
|
||
Str _token; | ||
int _tokenAsNumber; | ||
bool _alreadyGot; | ||
bool _multiline; ///< @c true= current token spans multiple lines. | ||
}; | ||
|
||
#endif // LIBCOMMON_HEXLEX_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
/** @file hexlex.cpp Hexen definition/script syntax. | ||
* | ||
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
* @authors Copyright © 2007-2013 Daniel Swanson <danij@dengine.net> | ||
* @authors Copyright © 1999 Activision | ||
* | ||
* @par License | ||
* GPL: http://www.gnu.org/licenses/gpl.html | ||
* | ||
* <small>This program 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. This program 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 this program; if not, write to the Free | ||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
* 02110-1301 USA</small> | ||
*/ | ||
|
||
#include "hexlex.h" | ||
#include <cstdlib> | ||
#include <cstdio> | ||
#include <cstring> | ||
|
||
#define T_COMMENT ';' ///< Single-line comment. | ||
#define T_QUOTE '"' | ||
|
||
void HexLex::checkOpen() | ||
{ | ||
if(!_script) Con_Error("RavHexParser: No script to parse!"); | ||
} | ||
|
||
bool HexLex::atEnd() | ||
{ | ||
checkOpen(); | ||
return (_readPos >= Str_Length(_script)); | ||
} | ||
|
||
HexLex::HexLex() | ||
: _script(0) | ||
, _readPos(0) | ||
, _lineNumber(0) | ||
, _tokenAsNumber(0) | ||
, _alreadyGot(false) | ||
, _multiline(false) | ||
{ | ||
Str_InitStd(&_sourcePath); | ||
Str_InitStd(&_token); | ||
} | ||
|
||
HexLex::~HexLex() | ||
{ | ||
Str_Free(&_sourcePath); | ||
Str_Free(&_token); | ||
} | ||
|
||
void HexLex::parse(Str const *script, Str const *sourcePath) | ||
{ | ||
_script = script; | ||
|
||
if(!sourcePath) | ||
{ | ||
Str_Clear(&_sourcePath); | ||
} | ||
else | ||
{ | ||
Str_Copy(&_sourcePath, sourcePath); | ||
} | ||
|
||
Str_Clear(&_token); | ||
_readPos = 0; | ||
_lineNumber = 1; | ||
_alreadyGot = false; | ||
} | ||
|
||
bool HexLex::readToken() | ||
{ | ||
checkOpen(); | ||
if(_alreadyGot) | ||
{ | ||
_alreadyGot = false; | ||
return true; | ||
} | ||
|
||
_multiline = false; | ||
|
||
if(atEnd()) | ||
{ | ||
return false; | ||
} | ||
|
||
bool foundToken = false; | ||
while(!foundToken) | ||
{ | ||
while(Str_At(_script, _readPos) <= ' ') | ||
{ | ||
if(atEnd()) | ||
{ | ||
return false; | ||
} | ||
|
||
if(Str_At(_script, _readPos++) == '\n') | ||
{ | ||
_lineNumber++; | ||
_multiline = true; | ||
} | ||
} | ||
|
||
if(atEnd()) | ||
{ | ||
return false; | ||
} | ||
|
||
if(Str_At(_script, _readPos) != T_COMMENT) | ||
{ | ||
// Found a token | ||
foundToken = true; | ||
} | ||
else | ||
{ | ||
// Skip comment. | ||
while(Str_At(_script, _readPos++) != '\n') | ||
{ | ||
if(atEnd()) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
_lineNumber++; | ||
_multiline = true; | ||
} | ||
} | ||
|
||
Str_Clear(&_token); | ||
if(Str_At(_script, _readPos) == T_QUOTE) | ||
{ | ||
// Quoted string. | ||
_readPos++; | ||
while(Str_At(_script, _readPos) != T_QUOTE) | ||
{ | ||
Str_AppendChar(&_token, Str_At(_script, _readPos++)); | ||
if(atEnd()) | ||
{ | ||
break; | ||
} | ||
} | ||
_readPos++; | ||
} | ||
else | ||
{ | ||
// Normal string. | ||
while(Str_At(_script, _readPos) > ' ' && | ||
Str_At(_script, _readPos) != T_COMMENT) | ||
{ | ||
Str_AppendChar(&_token, Str_At(_script, _readPos++)); | ||
if(atEnd()) | ||
{ | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
Str const *HexLex::mustGetString() | ||
{ | ||
if(!readToken()) | ||
{ | ||
scriptError("Missing string"); | ||
} | ||
return &_token; | ||
} | ||
|
||
int HexLex::mustGetNumber() | ||
{ | ||
checkOpen(); | ||
|
||
if(!readToken()) | ||
{ | ||
scriptError("Missing integer"); | ||
} | ||
|
||
char *stopper; | ||
_tokenAsNumber = strtol(Str_Text(&_token), &stopper, 0); | ||
if(*stopper != 0) | ||
{ | ||
Con_Error("RavHexParser: Bad numeric constant \"%s\".\n" | ||
"File: \"%s\", Line: %i", | ||
Str_Text(&_token), F_PrettyPath(Str_Text(&_sourcePath)), _lineNumber); | ||
} | ||
|
||
return _tokenAsNumber; | ||
} | ||
|
||
/// @note Assumes there is a valid string in sc_String. | ||
void HexLex::unreadToken() | ||
{ | ||
_alreadyGot = true; | ||
} | ||
|
||
Str const *HexLex::token() | ||
{ | ||
return &_token; | ||
} | ||
|
||
int HexLex::lineNumber() const | ||
{ | ||
return _lineNumber; | ||
} | ||
|
||
void HexLex::scriptError(char const *message) | ||
{ | ||
Con_Error("RavHexParser: Error in script \"%s\" on line #%i.\n%s", | ||
F_PrettyPath(Str_Text(&_sourcePath)), _lineNumber, message); | ||
} | ||
|
||
void HexLex::scriptError() | ||
{ | ||
AutoStr *msg = Str_Appendf(AutoStr_NewStd(), "Unexpected token '%s'", Str_Text(&_token)); | ||
scriptError(Str_Text(msg)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.