Skip to content

Commit c661589

Browse files
committed
[parser] Clean up behaviour regarding dictionaries and #ifdef.
1 parent 06f9a32 commit c661589

File tree

5 files changed

+68
-31
lines changed

5 files changed

+68
-31
lines changed

changes.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ Changed Behaviour
5858
for now, due to their orientation being poorly defined.
5959
- An age-old bug in the inbuilt `f_enneper` isosurface function has been
6060
fixed; the function now results in the originally intended shape.
61+
- The `defined()` pseudo-function now returns `true` (while printing a
62+
warning) if applied to reserved words. The `#ifdef` and `#ifndef` directives
63+
also behave accordingly.
6164

6265
New Features
6366
------------

source/parser/parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ typedef unsigned short SymTableEntryRefCount;
104104

105105
// Special symbol tables
106106
enum {
107-
SYM_TABLE_RESERVED = 0, // reserved words
108-
SYM_TABLE_GLOBAL, // identifiers declared using #declare (or #local in top-level file), #function, #macro, etc.
107+
SYM_TABLE_GLOBAL = 0, ///< Identifiers declared using #declare (or #local in top-level file), #function, #macro, etc.
109108
};
110109

111110
/// Structure holding information about a symbol

source/parser/parser_tokenizer.cpp

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,14 @@ void Parser::Get_Token ()
357357
break;
358358

359359
default:
360-
Write_Token(mToken.raw);
360+
if (parseRawIdentifiers || (mToken.raw.isPseudoIdentifier && (!Parsing_Directive || Inside_Ifdef)))
361+
Read_Symbol(mToken.raw);
362+
else
363+
{
364+
if (mToken.raw.isReservedWord && Inside_Ifdef)
365+
Warning("Trying to test whether a reserved keyword is defined. Test result may not be what you expect.");
366+
Write_Token(mToken.raw);
367+
}
361368
break;
362369
}
363370
}
@@ -448,28 +455,26 @@ void Parser::Read_Symbol(const RawToken& rawToken)
448455
RawToken nextRawToken;
449456
bool haveNextRawToken;
450457

451-
/* If its a reserved keyword, write it and return */
452-
Temp_Entry = Find_Symbol(SYM_TABLE_RESERVED, rawToken.lexeme.text.c_str());
453-
if (Temp_Entry != nullptr)
458+
if (rawToken.isReservedWord && !parseRawIdentifiers)
454459
{
455-
POV_PARSER_ASSERT(false);
460+
// Normally, this function shouldn't be called with reserved words.
461+
// Exceptions are a few keywords that behave like identifiers in certain contexts,
462+
// such as `global` and `local` which may behave like dictionaries.
463+
POV_PARSER_ASSERT(rawToken.isPseudoIdentifier);
456464

457-
if (!Parsing_Directive && (Temp_Entry->Token_Number == LOCAL_TOKEN))
465+
if (rawToken.id == LOCAL_TOKEN)
458466
{
467+
POV_PARSER_ASSERT(!Parsing_Directive || Inside_Ifdef);
459468
pseudoDictionary = Table_Index;
460469
}
461-
else if (!Parsing_Directive && (Temp_Entry->Token_Number == GLOBAL_TOKEN))
470+
else if (rawToken.id == GLOBAL_TOKEN)
462471
{
472+
POV_PARSER_ASSERT(!Parsing_Directive || Inside_Ifdef);
463473
pseudoDictionary = SYM_TABLE_GLOBAL;
464474
}
465-
else if (Inside_Ifdef)
466-
{
467-
Warning("Tried to test whether a reserved keyword is defined. Test result may not be what you expect.");
468-
}
469475
else
470476
{
471-
Write_Token (Temp_Entry->Token_Number, rawToken);
472-
return;
477+
POV_PARSER_ASSERT(false);
473478
}
474479
}
475480

@@ -490,7 +495,7 @@ void Parser::Read_Symbol(const RawToken& rawToken)
490495
{
491496
/* Search tables from newest to oldest */
492497
int firstIndex = Table_Index;
493-
int lastIndex = SYM_TABLE_RESERVED+1; // index SYM_TABLE_RESERVED is reserved for reserved words, not identifiers
498+
int lastIndex = SYM_TABLE_GLOBAL;
494499
for (Local_Index = firstIndex; Local_Index >= lastIndex; Local_Index--)
495500
{
496501
/* See if it's a previously declared identifier. */
@@ -628,11 +633,19 @@ void Parser::Read_Symbol(const RawToken& rawToken)
628633
table = Tables [pseudoDictionary];
629634
pseudoDictionary = -1;
630635

631-
if (!haveNextRawToken || (nextRawToken.lexeme.category != Lexeme::kOther) ||
636+
if (!haveNextRawToken ||
637+
(nextRawToken.lexeme.category != Lexeme::kOther) ||
632638
((nextRawToken.lexeme.text != "[") && (nextRawToken.lexeme.text != ".")))
633639
{
634-
Get_Token(); // ensures the error is reported at the right token
635-
Expectation_Error("'[' or '.'");
640+
if (Inside_Ifdef)
641+
{
642+
Warning("Trying to test whether a reserved keyword is defined. Test result may not be what you expect.");
643+
}
644+
else
645+
{
646+
Get_Token(); // ensures the error is reported at the right token
647+
Expectation_Error("'[' or '.'");
648+
}
636649
}
637650
}
638651
else
@@ -2079,14 +2092,7 @@ void Parser::init_sym_tables()
20792092
{
20802093
int i;
20812094

2082-
Add_Sym_Table();
2083-
2084-
for (i = 0; Reserved_Words[i].Token_Name != nullptr; i++)
2085-
{
2086-
Add_Symbol(SYM_TABLE_RESERVED,Reserved_Words[i].Token_Name,Reserved_Words[i].Token_Number);
2087-
}
2088-
2089-
Add_Sym_Table();
2095+
Add_Sym_Table(); // global symbols
20902096
}
20912097

20922098
Parser::SYM_TABLE *Parser::Create_Sym_Table (bool copyNames)
@@ -2289,7 +2295,7 @@ SYM_ENTRY *Parser::Add_Symbol (int Index,const char *Name,TokenId Number)
22892295
{
22902296
SYM_ENTRY *New;
22912297

2292-
New = Create_Entry (Name, Number, (Index != SYM_TABLE_RESERVED));
2298+
New = Create_Entry(Name, Number, true);
22932299
Add_Entry(Index,New);
22942300

22952301
return(New);

source/parser/rawtokenizer.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ TokenId RawToken::GetTokenId() const
7979
//******************************************************************************
8080

8181
RawTokenizer::KnownWordInfo::KnownWordInfo() :
82-
id(int(NOT_A_TOKEN))
82+
id(int(NOT_A_TOKEN)),
83+
expressionId(NOT_A_TOKEN),
84+
isReservedWord(false),
85+
isPseudoIdentifier(false)
8386
{}
8487

8588
//******************************************************************************
@@ -93,8 +96,11 @@ RawTokenizer::RawTokenizer() :
9396
continue;
9497
if (strchr(i->Token_Name, ' ') != nullptr)
9598
continue;
96-
mKnownWords[i->Token_Name].id = i->Token_Number;
97-
mKnownWords[i->Token_Name].expressionId = GetExpressionId(i->Token_Number);
99+
KnownWordInfo& knownWord = mKnownWords[i->Token_Name];
100+
knownWord.id = i->Token_Number;
101+
knownWord.expressionId = GetExpressionId(i->Token_Number);
102+
knownWord.isReservedWord = true;
103+
knownWord.isPseudoIdentifier = ((knownWord.id == GLOBAL_TOKEN) || (knownWord.id == LOCAL_TOKEN));
98104
}
99105
}
100106

@@ -142,6 +148,8 @@ bool RawTokenizer::GetNextDirective(RawToken& token)
142148
token.id = TokenId::HASH_TOKEN;
143149
token.expressionId = TokenId::HASH_TOKEN;
144150
token.value = nullptr;
151+
token.isReservedWord = false;
152+
token.isPseudoIdentifier = false;
145153

146154
return true;
147155
}
@@ -160,6 +168,8 @@ bool RawTokenizer::ProcessWordLexeme(RawToken& token)
160168
token.id = i.id;
161169
token.expressionId = i.expressionId;
162170
token.value = nullptr;
171+
token.isReservedWord = i.isReservedWord;
172+
token.isPseudoIdentifier = i.isPseudoIdentifier;
163173

164174
return true;
165175
}
@@ -174,6 +184,9 @@ bool RawTokenizer::ProcessFloatLiteralLexeme(RawToken& token)
174184
if (sscanf(token.lexeme.text.c_str(), POV_DBL_FORMAT_STRING, &token.floatValue) == 0)
175185
return false;
176186

187+
token.isReservedWord = false;
188+
token.isPseudoIdentifier = false;
189+
177190
return true;
178191
}
179192

@@ -292,6 +305,8 @@ bool RawTokenizer::ProcessStringLiteralLexeme(RawToken& token)
292305
}
293306

294307
token.value = pValue;
308+
token.isReservedWord = false;
309+
token.isPseudoIdentifier = false;
295310

296311
return true;
297312
}
@@ -386,6 +401,8 @@ bool RawTokenizer::ProcessOtherLexeme(RawToken& token)
386401
token.id = int(tokenId);
387402
token.expressionId = GetExpressionId(tokenId);
388403
token.value = nullptr;
404+
token.isReservedWord = false;
405+
token.isPseudoIdentifier = false;
389406

390407
return true;
391408
}
@@ -405,6 +422,8 @@ bool RawTokenizer::ProcessSignatureLexeme(RawToken& token)
405422
token.id = int(tokenId);
406423
token.expressionId = GetExpressionId(tokenId);
407424
token.value = nullptr;
425+
token.isReservedWord = false;
426+
token.isPseudoIdentifier = false;
408427

409428
return true;
410429
}

source/parser/rawtokenizer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ struct RawToken
146146
/// _cooked tokenizer_ to carry the value of the identifier.
147147
ConstValuePtr value;
148148

149+
/// Whether the token is a reserved word.
150+
/// @note
151+
/// This flag is _not_ set for operators.
152+
bool isReservedWord : 1;
153+
154+
/// Whether the token is a keyword with identifier-like properties.
155+
bool isPseudoIdentifier : 1;
156+
149157
/// Helper function to get the token ID.
150158
/// For identifiers, this function returns @ref IDENTIFIER_TOKEN. For all
151159
/// other tokens, this function returns @ref id as a @ref TokenId value.
@@ -230,6 +238,8 @@ class RawTokenizer
230238
{
231239
int id;
232240
TokenId expressionId;
241+
bool isReservedWord : 1;
242+
bool isPseudoIdentifier : 1;
233243
KnownWordInfo();
234244
};
235245

0 commit comments

Comments
 (0)