Skip to content

Commit d95a109

Browse files
WhyIsEvery4thYearAlwaysBadWhyIsEvery4thYearAlwaysBad
authored andcommitted
Bundled commit:
* Added raw strings (``). What they contain will be appended to the cmenu cfg. * Fixed captions not being properly written. * when a cmenu with the console display is active, random output will no longer appear. * Console display is now properly displayed. (NOTE: Console cmenus use wait, because con_filter_enable doesn't immediately take affect after change I'll try to find a waitless solution).
1 parent ddcc18e commit d95a109

File tree

6 files changed

+170
-124
lines changed

6 files changed

+170
-124
lines changed

src/commandmenu.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define COMMANDMENU_HPP
33
#include <string>
44
#include <vector>
5-
#include <deque>
5+
#include <variant>
66
#include "compiler.hpp"
77
#include "bind.hpp"
88

@@ -14,7 +14,7 @@ enum class CMenuDisplayType {
1414

1515
struct CommandMenu {
1616
std::string sRawName, sName;
17-
std::vector<Bind> binds;
17+
std::vector<std::variant<Bind, std::string> > Entries;
1818
CMenuDisplayType Display;
1919
CommandMenu();
2020
CommandMenu(const std::string& p_sName);

src/compiler.cpp

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,28 @@ extern std::map<std::string,std::string> KVMap;
1515
std::deque<Token> TokenContainer;
1616
std::deque<Token> ErrorTokens;
1717
// Raw pointer bad, std::variant good.
18-
typedef std::variant<Parser::MenuToken, Parser::KVToken, Parser::BindToken, Parser::ToggleBindToken, Parser::CMenuToken, Parser::CMenuEndToken> MenuToken_t;
18+
typedef std::variant<Parser::MenuToken, Parser::KVToken, Parser::BindToken, Parser::ToggleBindToken, Parser::CMenuToken, Parser::CodeToken, Parser::CMenuEndToken> MenuToken_t;
1919
std::deque<MenuToken_t> CMenuTokens;
2020

2121
extern std::deque<CommandMenu> CMenuContainer; // Made in main.cpp
2222
extern std::vector<std::string> UsedKeys; // made in main.cpp
2323

2424
namespace Parser {
25-
Parser::MenuToken::MenuToken() {
26-
27-
}
28-
29-
Parser::MenuToken::~MenuToken() {
30-
31-
}
32-
33-
Parser::KVToken::KVToken() {
34-
35-
}
36-
25+
Parser::MenuToken::MenuToken() {}
26+
Parser::MenuToken::~MenuToken() {}
27+
Parser::KVToken::KVToken() {}
3728
Parser::KVToken::KVToken(const std::string& ident, const std::string& value)
3829
: Key(ident), Value(value) {
3930
fAttribs=0;
4031
}
41-
32+
Parser::KVToken::~KVToken() {}
4233
Parser::BindToken::BindToken() {}
43-
4434
Parser::BindToken::BindToken(const std::string& p_sName, const std::string& p_sCmdStr, const char& p_fAttributeFlag)
4535
: sName(p_sName), sCmdStr(p_sCmdStr) {fAttribs = p_fAttributeFlag;}
46-
4736
Parser::BindToken::BindToken(const std::string& p_sKey, const std::string& p_sName, const std::string& p_sCmdStr, const char& p_fAttributeFlag)
48-
: sKey(p_sKey), sName(p_sName), sCmdStr(p_sCmdStr) {fAttribs = p_fAttributeFlag; }
49-
37+
: sKey(p_sKey), sName(p_sName), sCmdStr(p_sCmdStr) {fAttribs = p_fAttributeFlag;}
5038
Parser::BindToken::~BindToken() {}
51-
5239
Parser::ToggleBindToken::ToggleBindToken() {}
53-
5440
Parser::ToggleBindToken::ToggleBindToken(const std::string p_names[MAX_TOGGLE_STATES], const std::string p_CmdStrContainer[MAX_TOGGLE_STATES], unsigned short p_iToggleStates, const char& p_fAttributeFlag)
5541
: ToggleStates(p_iToggleStates)
5642
{
@@ -65,7 +51,6 @@ namespace Parser {
6551

6652
fAttribs = p_fAttributeFlag;
6753
}
68-
6954
Parser::ToggleBindToken::ToggleBindToken(const std::string& p_sKey, const std::string p_names[MAX_TOGGLE_STATES], const std::string p_CmdStrContainer[MAX_TOGGLE_STATES], unsigned short p_iToggleStates, const char& p_fAttributeFlag)
7055
: ToggleStates(p_iToggleStates), sKey(p_sKey)
7156
{
@@ -79,25 +64,22 @@ namespace Parser {
7964
}
8065
fAttribs = p_fAttributeFlag;
8166
}
82-
8367
Parser::ToggleBindToken::~ToggleBindToken() {}
84-
8568
Parser::CMenuToken::CMenuToken() {}
86-
8769
Parser::CMenuToken::CMenuToken(const std::string& sName, const char& p_fAttributeFlag)
8870
: sName(sName) {
8971
fAttribs = p_fAttributeFlag;
9072
}
91-
9273
Parser::CMenuToken::CMenuToken(const std::string& p_sKey, const std::string& sName, const char& p_fAttributeFlag)
9374
: sName(sName), sKey(p_sKey) {
9475
fAttribs = p_fAttributeFlag;
9576
}
96-
9777
Parser::CMenuToken::~CMenuToken() {}
98-
78+
Parser::CodeToken::CodeToken() {}
79+
Parser::CodeToken::CodeToken(const std::string& p_sValue)
80+
: sValue(p_sValue) {}
81+
Parser::CodeToken::~CodeToken() {}
9982
Parser::CMenuEndToken::CMenuEndToken() {}
100-
10183
Parser::CMenuEndToken::~CMenuEndToken() {}
10284

10385
/* Parses the tokens from the lexer
@@ -193,9 +175,13 @@ namespace Parser {
193175
if (!(fParserStateFlag & PARSER_STATE_ERRORS_FOUND))
194176
CMenuTokens.push_back(Parser::CMenuToken(token->sValue,((fParserStateFlag & PARSER_STATE_FORMATTED) ? CMTOKATTRIB_FORMATTED : 0) | CMTOKATTRIB_NOEXIT));
195177
fParserStateFlag |= CMTOKATTRIB_FORMATTED;
196-
token+=i;
178+
token += i;
197179
}
198180
break;
181+
case TokenType::RAW_STRING:
182+
CMenuTokens.push_back(Parser::CodeToken(token->sValue));
183+
token++;
184+
break;
199185
case TokenType::IDENTIFIER: // Check for set keymaps
200186
{
201187
// Key Values should never have modifiers.
@@ -247,12 +233,12 @@ namespace Parser {
247233
}
248234
}
249235
if (!(fParserStateFlag & PARSER_STATE_EOF_FOUND)) std::cout<<"warning: EOF not found!\n";
250-
if (ErrorTokens.size()>=1) fParserStateFlag |= PARSER_STATE_ERRORS_FOUND;
236+
if (ErrorTokens.size() >= 1) fParserStateFlag |= PARSER_STATE_ERRORS_FOUND;
251237
return !(fParserStateFlag >> 7 /* Errors Found? */);
252238
}
253239
}
254240

255-
/* Convert menu tokens in TokenContainer into something useful.
241+
/* Convert menu tokens in TokenContainer into cmenus and cfg code (from ``).
256242
* p_iBindCount (unsigned short) stores how many binds were counted
257243
* p_bUsedDisplayFlags (a flag) stores what display types were used. Used to optimize proper closing of CMenu displays.
258244
- 3rd bit: Is the "none" display method used?
@@ -261,7 +247,7 @@ namespace Parser {
261247
262248
Returns true if conversion was successful. If not then it returns false.
263249
*/
264-
bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags) {
250+
bool ParseMenuTokens(unsigned short& p_iBindCount, unsigned char& p_bUsedDisplayFlags, std::string& init_defined_code) {
265251
// Has there been an error? BAIL.
266252
char t_bUsedDisplayFlags = p_bUsedDisplayFlags;
267253
if (ErrorTokens.size()>=1) return false;
@@ -270,7 +256,6 @@ bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags) {
270256

271257
// This variable is in the function scope instead of the switch-case scope, because the end cmenu tokens NEED to remember the attributes of their cmenus.
272258
Parser::CMenuToken CurrentCMenu;
273-
274259
for (auto token = CMenuTokens.begin(); token != CMenuTokens.end(); token++) {
275260
// Automatically resets the KEY KV to prevent other binds from being affected by it.
276261
if (token != CMenuTokens.begin() && !std::holds_alternative<Parser::KVToken>(*(token - 1))) KVMap["KEY"]="";
@@ -315,15 +300,15 @@ bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags) {
315300
if (CMenuStack.size() > 1) {
316301
if (CurrentCMenu.fAttribs & CMTOKATTRIB_BIND_KEYSET) {
317302
if (iDuplicateNumber > 0)
318-
(CMenuStack.begin()+1)->binds.push_back(Bind(CurrentCMenu.sKey,Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName)+'_'+std::to_string(iDuplicateNumber),CurrentCMenu.fAttribs)));
303+
(CMenuStack.begin()+1)->Entries.push_back(Bind(CurrentCMenu.sKey,Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName)+'_'+std::to_string(iDuplicateNumber),CurrentCMenu.fAttribs)));
319304
else
320-
(CMenuStack.begin()+1)->binds.push_back(Bind(CurrentCMenu.sKey,Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName),CurrentCMenu.fAttribs)));
305+
(CMenuStack.begin()+1)->Entries.push_back(Bind(CurrentCMenu.sKey,Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName),CurrentCMenu.fAttribs)));
321306
// Add the keyname to a list of used key names if it isn't already added.
322307
if (std::none_of(UsedKeys.cbegin(),UsedKeys.cend(),[&CurrentCMenu](std::string_view s){ return s == CurrentCMenu.sKey; })) UsedKeys.push_back(CurrentCMenu.sKey);
323308
}
324309
else {
325-
if (iDuplicateNumber>0) (CMenuStack.begin()+1)->binds.push_back(Bind(std::to_string(NumKeyStack.top() % 10),Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName)+'_'+std::to_string(iDuplicateNumber),CurrentCMenu.fAttribs)));
326-
else (CMenuStack.begin()+1)->binds.push_back(Bind(std::to_string(NumKeyStack.top() % 10),Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName),CurrentCMenu.fAttribs)));
310+
if (iDuplicateNumber>0) (CMenuStack.begin()+1)->Entries.push_back(Bind(std::to_string(NumKeyStack.top() % 10),Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName)+'_'+std::to_string(iDuplicateNumber),CurrentCMenu.fAttribs)));
311+
else (CMenuStack.begin()+1)->Entries.push_back(Bind(std::to_string(NumKeyStack.top() % 10),Parser::BindToken(CurrentCMenu.sName,"exec $cmenu_"+formatRaw(CurrentCMenu.sName),CurrentCMenu.fAttribs)));
327312
}
328313
}
329314
if (!(CurrentCMenu.fAttribs & CMTOKATTRIB_BIND_KEYSET) && !NumKeyStack.empty()) NumKeyStack.top()=(NumKeyStack.top()+1);
@@ -346,11 +331,11 @@ bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags) {
346331
CurrentBindToken.sKey = KVMap["KEY"];
347332
assert(CMenuStack.size() > 0);
348333
if (!(CurrentBindToken.fAttribs & CMTOKATTRIB_BIND_KEYSET)) {
349-
CMenuStack.front().binds.push_back(Bind(std::to_string(NumKeyStack.top() % 10),CurrentBindToken));
350-
NumKeyStack.top()=(NumKeyStack.top()+1);
334+
CMenuStack.front().Entries.push_back(Bind(std::to_string(NumKeyStack.top() % 10),CurrentBindToken));
335+
NumKeyStack.top() = (NumKeyStack.top()+1);
351336
}
352337
else {
353-
CMenuStack.front().binds.push_back(Bind(CurrentBindToken.sKey,CurrentBindToken));
338+
CMenuStack.front().Entries.push_back(Bind(CurrentBindToken.sKey,CurrentBindToken));
354339
// Add the keyname to a list of used key names if it isn't already added.
355340
if (std::none_of(UsedKeys.cbegin(),UsedKeys.cend(),[&CurrentBindToken](std::string_view s){ return s == CurrentBindToken.sKey;})) UsedKeys.push_back(CurrentBindToken.sKey);
356341
}
@@ -362,20 +347,23 @@ bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags) {
362347
CurrentToggleBindToken.sKey = KVMap["KEY"];
363348
assert(CMenuStack.size() > 0);
364349
if (!(CurrentToggleBindToken.fAttribs & CMTOKATTRIB_BIND_KEYSET)) {
365-
CMenuStack.front().binds.push_back(Bind(std::to_string(NumKeyStack.top() % 10),CurrentToggleBindToken));
350+
CMenuStack.front().Entries.push_back(Bind(std::to_string(NumKeyStack.top() % 10),CurrentToggleBindToken));
366351
assert(!NumKeyStack.empty());
367352
NumKeyStack.top()=(NumKeyStack.top()+1);
368353
}
369354
else {
370-
CMenuStack.front().binds.push_back(Bind(CurrentToggleBindToken.sKey,CurrentToggleBindToken));
355+
CMenuStack.front().Entries.push_back(Bind(CurrentToggleBindToken.sKey,CurrentToggleBindToken));
371356
// Add the keyname to a list of used key names if it isn't already added.
372357
if (std::none_of(UsedKeys.cbegin(),UsedKeys.cend(),[&CurrentToggleBindToken](std::string_view s){ return s == CurrentToggleBindToken.sKey;})) UsedKeys.push_back(CurrentToggleBindToken.sKey);
373358
}
374359
p_iBindCount++;
360+
}
361+
else if (std::holds_alternative<Parser::CodeToken>(*token)) {
362+
if (!CMenuStack.empty()) CMenuStack.front().Entries.push_back(std::get<Parser::CodeToken>(*token).sValue);
363+
else if (!CMenuContainer.empty()) CMenuContainer.back().Entries.push_back(std::get<Parser::CodeToken>(*token).sValue);
364+
else init_defined_code += std::get<Parser::CodeToken>(*token).sValue;
375365
}
376-
else {
377-
378-
}
366+
else std::cout << "ParseMenuTokens(): warning: std::variant has invalid type. Not parsing this variant.\n";
379367
}
380368
return true;
381369
}

src/compiler.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#define FL_DISPLAY_CONSOLE (1<<1)
2525
#define FL_DISPLAY_CAPTION (1<<2)
2626

27-
bool ParseMenuTokens(unsigned short& p_iBindCount, char& p_bUsedDisplayFlags);
27+
// Summary in compiler.cpp definition.
28+
bool ParseMenuTokens(unsigned short& p_iBindCount, unsigned char& p_bUsedDisplayFlags, std::string& init_defined_code);
2829
namespace Parser {
2930
struct MenuToken {
3031
char fAttribs=0; // Attribute flag.
@@ -36,6 +37,7 @@ namespace Parser {
3637
std::string Key, Value;
3738
KVToken();
3839
KVToken(const std::string& ident, const std::string& value);
40+
~KVToken();
3941
};
4042
// Bind
4143
struct BindToken : public MenuToken {
@@ -65,6 +67,14 @@ namespace Parser {
6567
CMenuToken(const std::string& p_sKey, const std::string& sName, const char& p_fAttributeFlag);
6668
~CMenuToken();
6769
};
70+
71+
// Raw code
72+
struct CodeToken : public MenuToken {
73+
std::string sValue;
74+
CodeToken();
75+
CodeToken(const std::string& p_sValue);
76+
~CodeToken();
77+
};
6878
// CMenu end
6979
struct CMenuEndToken : public MenuToken {
7080
CMenuEndToken();

src/lex.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ extern std::deque<Parser::MenuToken*> CMenuTokens;
1414

1515
// Convert to a safer string format for file and caption names.
1616
std::string formatRaw(std::string p_sInStr) {
17-
// Remove punctation and nonascii characters
18-
p_sInStr.erase(std::remove_if(p_sInStr.begin(), p_sInStr.end(), [](char c){return std::ispunct(c) || !isascii(c);}), p_sInStr.end());
17+
// Remove punctation and unicode characters.
18+
p_sInStr.erase(std::remove_if(p_sInStr.begin(), p_sInStr.end(), [](char c){ return std::ispunct(c) || !isascii(c); }), p_sInStr.end());
1919
// and replace spaces with underscores
2020
std::replace(p_sInStr.begin(), p_sInStr.end(), ' ', '_');
2121
// replace uppercase with lower case
@@ -32,7 +32,7 @@ namespace Lexer {
3232
}
3333
// Convert string to token stream. Returns true if successful and false if an error occurs.
3434
bool Tokenize(const std::string_view& p_sInStr) {
35-
bool bErrorsFound=false, bInBlockComment=false;
35+
bool bErrorsFound=false;
3636
std::string t_sStrTemp;
3737
for (auto str_it = p_sInStr.begin(); str_it < p_sInStr.end(); )
3838
{
@@ -100,19 +100,21 @@ namespace Lexer {
100100
}
101101
break;
102102
// strings
103+
case '`':
103104
case '\"':
104105
{
105-
std::string_view::iterator end_quote_it = std::find(str_it + 1, p_sInStr.end(), '\"');
106+
std::string_view::iterator end_quote_it = std::find(str_it + 1, p_sInStr.end(), *str_it);
106107
// New lines or carriage returns cannot be in strings. (As in ASCII values 10 and 13, not the C-style escapes though those arent interpreted.)
107108
if (end_quote_it >= p_sInStr.end()
108109
|| std::any_of(str_it, end_quote_it, [](char c){return c == '\n' || c == '\r'; })) {
109-
ErrorTokens.push_back(Token(iLineNum,iLineColumn,TokenType::COMPILER_ERROR,"error: String not properly closed with '\"'."));
110+
ErrorTokens.push_back(Token(iLineNum,iLineColumn,TokenType::COMPILER_ERROR,"error: String not properly closed with "));
111+
ErrorTokens.back().sValue += *str_it + '.';
110112
str_it = p_sInStr.end();
111113
iLineColumn++;
112114
}
113115
else {
114116
// Line column and number for strings should be located at the beginning '"'.
115-
TokenContainer.push_back(Token(iLineNum, iLineColumn, TokenType::STRING, std::string(str_it + 1, end_quote_it)));
117+
TokenContainer.push_back(Token(iLineNum, iLineColumn, (*str_it == '\"' ? TokenType::STRING : TokenType::RAW_STRING), std::string(str_it + 1, end_quote_it)));
116118
unsigned long long lambda_char_pos = p_sInStr.length();
117119
std::for_each(str_it, end_quote_it, [lambda_char_pos, iLineColumn](char c) mutable -> void {
118120
lambda_char_pos++;

0 commit comments

Comments
 (0)