14
14
#include " SimpleTokenizer.h"
15
15
16
16
std::unordered_set<TokenType> entities = {
17
- TokenType::STMT, TokenType::READ, TokenType::PRINT,
18
- TokenType::CALL, TokenType::WHILE, TokenType::IF,
19
- TokenType::ASSIGN, TokenType::VARIABLE, TokenType::CONSTANT,
20
- TokenType::PROCEDURE,
21
- };
17
+ TokenType::STMT, TokenType::PROG_LINE, TokenType::READ,
18
+ TokenType::PRINT, TokenType::CALL, TokenType::WHILE,
19
+ TokenType::IF, TokenType::ASSIGN, TokenType::VARIABLE,
20
+ TokenType::CONSTANT, TokenType::PROCEDURE};
22
21
23
22
std::unordered_set<TokenType> attributeNames = {
24
23
TokenType::PROCNAME, TokenType::VARNAME, TokenType::VALUE,
@@ -132,6 +131,16 @@ std::unordered_map<TokenType, std::vector<std::unordered_set<TokenType>>>
132
131
}
133
132
134
133
}};
134
+ std::unordered_map<AttributeRefType, std::unordered_set<TokenType>> attributes =
135
+ {
136
+ {AttributeRefType::PROCNAME, {TokenType::PROCEDURE, TokenType::CALL}},
137
+ {AttributeRefType::VARNAME,
138
+ {TokenType::VARIABLE, TokenType::READ, TokenType::PRINT}},
139
+ {AttributeRefType::VALUE, {TokenType::CONSTANT}},
140
+ {AttributeRefType::STATEMENT_NUM,
141
+ {TokenType::STMT, TokenType::READ, TokenType::PRINT, TokenType::CALL,
142
+ TokenType::WHILE, TokenType::IF, TokenType::ASSIGN}},
143
+ };
135
144
136
145
template <class T > bool contains (std::unordered_set<T> set, T item) {
137
146
return set.find (item) != set.end ();
@@ -384,20 +393,23 @@ std::unordered_map<TokenType, AttributeRefType> tokenTypeToAttributeRefType{
384
393
{TokenType::STATEMENT_NUM, AttributeRefType::STATEMENT_NUM}};
385
394
386
395
Element PqlParser::getElem () {
387
- auto nextToken = getNextExpectedToken (TokenType::SYNONYM);
388
- getDeclarationForSynonym (nextToken);
389
- Element result{nextToken.value , AttributeRefType::NONE};
390
- if (it != end && it->type == TokenType::DOT) {
391
- getNextExpectedToken (TokenType::DOT);
392
- const auto nextToken = getNextToken ();
393
- // TODO: store attribute names
394
- if (!contains (attributeNames, nextToken.type )) {
395
- throw " ERROR: Expected next token to be an attribute name but attribute "
396
- " name not found" ;
397
- }
398
- result.refType = tokenTypeToAttributeRefType[nextToken.type ];
396
+ auto synonym = getNextExpectedToken (TokenType::SYNONYM);
397
+ const auto declaration = getDeclarationForSynonym (synonym);
398
+ if (it == end || it->type != TokenType::DOT) {
399
+ return Element{synonym.value , AttributeRefType::NONE};
400
+ }
401
+ getNextExpectedToken (TokenType::DOT);
402
+ const auto nextToken = getNextToken ();
403
+ if (!contains (attributeNames, nextToken.type )) {
404
+ throw " ERROR: Expected next token to be an attribute name but attribute "
405
+ " name not found" ;
399
406
}
400
- return result;
407
+ const auto refType = tokenTypeToAttributeRefType[nextToken.type ];
408
+ const auto acceptableEntityTypes = attributes[refType];
409
+ if (acceptableEntityTypes.find (declaration) == acceptableEntityTypes.end ()) {
410
+ throw " ERROR: Declaration not found in acceptable entity types" ;
411
+ }
412
+ return Element{synonym.value , refType};
401
413
}
402
414
403
415
void PqlParser::parseWithClause () {
@@ -415,7 +427,13 @@ void PqlParser::parseAttributeCompare() {
415
427
const auto secondRef = getRef ();
416
428
// TODO: Perform check on attribute compare to check if ref is valid, and to
417
429
// check if at least one is an elem
418
- // TODO: Check if reference can be of type null
430
+ if (firstRef.referenceType == ReferenceType::RAW_VALUE &&
431
+ secondRef.referenceType == ReferenceType::RAW_VALUE) {
432
+ if (firstRef.pqlToken .type != secondRef.pqlToken .type ) {
433
+ throw " ERROR: Expecting string to compare with string or number to "
434
+ " compare with number" ;
435
+ }
436
+ }
419
437
pq.withs .push_back ({firstRef, secondRef});
420
438
}
421
439
0 commit comments