boolean expressions

main
Brett 2023-08-21 19:09:23 -04:00
parent aaf29c5fe7
commit 54ac0acd55
2 changed files with 116 additions and 16 deletions

View File

@ -19,6 +19,9 @@ namespace cs
public: public:
LexerSyntaxError(): std::runtime_error("Invalid template syntax. EOF occurred before template was fully processed!") LexerSyntaxError(): std::runtime_error("Invalid template syntax. EOF occurred before template was fully processed!")
{} {}
explicit LexerSyntaxError(const std::string& err): std::runtime_error(err)
{}
}; };
class LexerSearchFailure : public std::runtime_error class LexerSearchFailure : public std::runtime_error

View File

@ -107,38 +107,135 @@ namespace cs
class LogicalEval class LogicalEval
{ {
private: private:
// stmt -> (stmt) | expr | (expr)
// expr -> ident && ident | ident || ident
// ident -> lit | !lit
enum class TokenType enum class TokenType
{ {
AND, // && AND, // &&
OR, // || OR, // ||
NOT, // ! NOT, // !
IDENT, // literal
OPEN, // ( OPEN, // (
CLOSE // ) CLOSE // )
}; };
struct Token { struct Token
{
TokenType type; TokenType type;
std::optional<std::string> value; std::optional<std::string> value;
}; };
std::vector<Token> tokens;
size_t m_index = 0; static inline bool isSpecial(char c)
public:
void processString(const std::string& str)
{ {
size_t index = 0; return c == '&' || c == '|' || c == '!' || c == '(' || c == ')' || std::isspace(c);
while (index < str.size()) }
std::vector<Token> tokens;
size_t t_index = 0;
size_t s_index = 0;
std::string str;
inline bool hasNextToken()
{
return t_index < tokens.size();
}
inline Token& peekToken()
{
return tokens[t_index];
}
inline Token& consumeToken()
{
return tokens[t_index++];
}
inline bool hasNext()
{
return s_index < str.size();
}
inline char peek()
{
return str[s_index];
}
inline char consume()
{
return str[s_index++];
}
public:
explicit LogicalEval(std::string str): str(std::move(str))
{
processString();
}
void processString()
{
while (hasNext())
{ {
char c = str[index++]; char c = consume();
if (c == '&' || c == '|'){ // ignore whitespace
if (isspace(c))
} else if (c == '!') { continue;
switch (c)
} else if (c == '(') { {
tokens.emplace_back(TokenType::OPEN); case '&':
} else if (c == ')') { if (consume() != '&')
tokens.emplace_back(TokenType::CLOSE); throw LexerSyntaxError("Unable to parse logical expression. Found single '&' missing second '&'");
tokens.emplace_back(TokenType::AND);
break;
case '|':
if (consume() != '|')
throw LexerSyntaxError("Unable to parse logical expression. Found single '|' missing second '|'");
tokens.emplace_back(TokenType::OR);
break;
case '!':
tokens.emplace_back(TokenType::NOT);
break;
case '(':
tokens.emplace_back(TokenType::OPEN);
break;
case ')':
tokens.emplace_back(TokenType::CLOSE);
break;
default:
std::string token;
while (hasNext() && !isSpecial(peek()))
token += consume();
tokens.emplace_back(TokenType::IDENT, token);
break;
} }
} }
} }
static inline bool isEmpty(const std::string& token, const RuntimeContext& context)
{
return !context.contains(token) || context.at(token).empty();
}
bool factor(const RuntimeContext& context)
{
if (!hasNextToken())
throw LexerSyntaxError("Processing boolean factor but no token was found!");
}
bool term(const RuntimeContext& context)
{
}
bool expr(const RuntimeContext& context)
{
}
bool eval(const RuntimeContext& context)
{
}
}; };
public: public: