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:
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

View File

@ -107,38 +107,135 @@ namespace cs
class LogicalEval
{
private:
// stmt -> (stmt) | expr | (expr)
// expr -> ident && ident | ident || ident
// ident -> lit | !lit
enum class TokenType
{
AND, // &&
OR, // ||
NOT, // !
IDENT, // literal
OPEN, // (
CLOSE // )
};
struct Token {
struct Token
{
TokenType type;
std::optional<std::string> value;
};
std::vector<Token> tokens;
size_t m_index = 0;
public:
void processString(const std::string& str)
static inline bool isSpecial(char c)
{
size_t index = 0;
while (index < str.size())
return c == '&' || c == '|' || c == '!' || c == '(' || c == ')' || std::isspace(c);
}
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++];
if (c == '&' || c == '|'){
} else if (c == '!') {
} else if (c == '(') {
tokens.emplace_back(TokenType::OPEN);
} else if (c == ')') {
tokens.emplace_back(TokenType::CLOSE);
char c = consume();
// ignore whitespace
if (isspace(c))
continue;
switch (c)
{
case '&':
if (consume() != '&')
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: