-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds lambda rule and lambda rule parser.
- Loading branch information
1 parent
d2feb29
commit d95d1a2
Showing
8 changed files
with
391 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#include "wayfire/parser/lambda_rule_parser.hpp" | ||
|
||
#include <iostream> | ||
#include <memory> | ||
#include <stdexcept> | ||
#include <string> | ||
|
||
#include "wayfire/lexer/lexer.hpp" | ||
#include "wayfire/parser/condition_parser.hpp" | ||
#include "wayfire/rule/lambda_rule.hpp" | ||
|
||
namespace wf | ||
{ | ||
|
||
std::shared_ptr<lambda_rule_t> lambda_rule_parser_t::parse(const std::string &text, lambda_t if_lambda, lambda_t else_lambda) | ||
{ | ||
lexer_t lexer(text); | ||
return parse(lexer, if_lambda, else_lambda); | ||
} | ||
|
||
std::shared_ptr<lambda_rule_t> lambda_rule_parser_t::parse(lexer_t &lexer, lambda_t if_lambda, lambda_t else_lambda) | ||
{ | ||
std::string signal; | ||
std::shared_ptr<condition_t> condition; | ||
|
||
try | ||
{ | ||
// Expect the first symbol to be the 'on' keyword. | ||
auto symbol = lexer.parse_symbol(); | ||
if ((symbol.type != symbol_t::type_t::KEYWORD) || (get_string(symbol.value) != "on")) | ||
{ | ||
throw std::runtime_error("Lambda rule parser error. Expected 'on' keyword."); | ||
} | ||
|
||
// Expect a signal next. | ||
symbol = lexer.parse_symbol(); | ||
if (symbol.type != symbol_t::type_t::SIGNAL) | ||
{ | ||
throw std::runtime_error("Lambda rule parser error. Expected signal."); | ||
} | ||
signal = get_string(symbol.value); | ||
|
||
// Expect the 'if' keyword next. | ||
symbol = lexer.parse_symbol(); | ||
if ((symbol.type != symbol_t::type_t::KEYWORD) || (get_string(symbol.value) != "if")) | ||
{ | ||
throw std::runtime_error("Lambda rule parser error. Expected 'if' keyword."); | ||
} | ||
|
||
// Delegate to logical condition parser. | ||
condition = condition_parser_t().parse(lexer); | ||
|
||
// Expect the lexer to be at the end - 1. | ||
lexer.parse_symbol(); | ||
symbol = lexer.parse_symbol(); | ||
if (symbol.type != symbol_t::type_t::END) | ||
{ | ||
std::string error = "Lambda rule parser error. Unexpected symbol: "; | ||
error.append(to_string(symbol)); | ||
throw std::runtime_error(error); | ||
} | ||
} | ||
catch (std::runtime_error &e) | ||
{ | ||
std::cout << "Malformed input:" << std::endl; | ||
std::cout << lexer.text() << std::endl; | ||
std::string pad; | ||
auto pos = lexer.current_symbol_position(); | ||
for (std::size_t i = 0; i < pos; ++i) | ||
{ | ||
pad.append(" "); | ||
} | ||
pad.append("^ "); | ||
std::cout << pad << e.what() << std::endl; | ||
} | ||
|
||
auto rule = std::make_shared<lambda_rule_t>(signal, condition); | ||
if (rule != nullptr) | ||
{ | ||
rule->setIfLambda(if_lambda); | ||
rule->setElseLambda(else_lambda); | ||
} | ||
return rule; | ||
} | ||
|
||
} // End namespace wf. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#ifndef LAMBDA_RULE_PARSER_HPP | ||
#define LAMBDA_RULE_PARSER_HPP | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
#include "wayfire/rule/lambda_rule.hpp" | ||
|
||
namespace wf | ||
{ | ||
|
||
class lexer_t; | ||
|
||
/** | ||
* @brief The lambda_rule_parser_t class will parse a rule_t from a lexer_t instance. | ||
*/ | ||
class lambda_rule_parser_t | ||
{ | ||
public: | ||
/** | ||
* @brief parse Convenience method. Takes the text and makes a lexer_t instance which is then used to parse the lambda_rule_t. | ||
* | ||
* This method is convenient, but not recommended if you have multiple rules to parse. In the multiple rules case, | ||
* it is smarter to make 1 lexer_t instance outside and reset it to a new text, thus reusing the lexer_t instance. | ||
* Reuse is good for the environment! | ||
* | ||
* This method will throw std::runtime_error in case the text is malformed. | ||
* | ||
* @param[in] text The text to parse a lambda_rule_t from. | ||
* @param[in] if_lambda The lambda method to execute if the condition holds. | ||
* @param[in] else_lambda The lambda method to execute if the condition does not hold. | ||
* | ||
* @return The parsed rule. | ||
*/ | ||
std::shared_ptr<lambda_rule_t> parse(const std::string &text, lambda_t if_lambda, lambda_t else_lambda); | ||
|
||
/** | ||
* @brief parse Takes the lexer_t instance and parses a lambda_rule_t from it. | ||
* | ||
* This method will throw std::runtime_error incase the lexer_t instance has malformed text in it. | ||
* | ||
* @param[in] lexer The lexer_t instance to parse the lambda_rule_t from. | ||
* @param[in] if_lambda The lambda method to execute if the condition holds. | ||
* @param[in] else_lambda The lambda method to execute if the condition does not hold. | ||
* | ||
* @return Shared pointer to the lambda_rule_t instance parsed from the text. | ||
*/ | ||
std::shared_ptr<lambda_rule_t> parse(lexer_t &lexer, lambda_t if_lambda, lambda_t else_lambda); | ||
}; | ||
|
||
} // End namespace wf, | ||
|
||
#endif // LAMBDA_RULE_PARSER_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include "wayfire/rule/lambda_rule.hpp" | ||
#include "wayfire/condition/condition.hpp" | ||
#include <cstddef> | ||
#include <functional> | ||
#include <memory> | ||
#include <sstream> | ||
#include <string> | ||
|
||
namespace wf | ||
{ | ||
|
||
lambda_rule_t::lambda_rule_t(const std::string &signal, std::shared_ptr<condition_t> condition) : | ||
_signal(signal), _condition(condition) | ||
{ | ||
} | ||
|
||
void lambda_rule_t::setIfLambda(lambda_t if_lambda) | ||
{ | ||
_if_lambda = if_lambda; | ||
} | ||
|
||
void lambda_rule_t::setElseLambda(lambda_t else_lambda) | ||
{ | ||
_else_lambda = else_lambda; | ||
} | ||
|
||
bool lambda_rule_t::apply(const std::string &signal, access_interface_t &access, void *argument) | ||
{ | ||
if ((signal.empty()) || (_condition == nullptr) || (_if_lambda == nullptr)) | ||
{ | ||
return true; | ||
} | ||
|
||
bool error = false; | ||
if (signal == _signal) | ||
{ | ||
auto check_result = _condition->evaluate(access, error); | ||
if (!error) | ||
{ | ||
if (check_result) | ||
{ | ||
error = _if_lambda(argument); | ||
} | ||
else | ||
{ | ||
if (_else_lambda != nullptr) | ||
{ | ||
error = _else_lambda(argument); | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
return error; | ||
} | ||
|
||
std::string lambda_rule_t::to_string() const | ||
{ | ||
std::string out = "lambda rule: [signal: "; | ||
out.append(_signal).append(", condition: "); | ||
if (_condition) | ||
{ | ||
out.append(_condition->to_string()); | ||
} | ||
else | ||
{ | ||
out.append("nullptr"); | ||
} | ||
out.append(", if_lambda: "); | ||
if (_if_lambda) | ||
{ | ||
auto uint_ptr = reinterpret_cast<std::uintptr_t>(&_if_lambda); | ||
std::stringstream ss; | ||
ss << "0x" << std::hex << uint_ptr; | ||
out.append(ss.str()); | ||
} | ||
else | ||
{ | ||
out.append("nullptr"); | ||
} | ||
out.append(", else_lambda: "); | ||
if (_else_lambda) | ||
{ | ||
auto uint_ptr = reinterpret_cast<std::uintptr_t>(&_else_lambda); | ||
std::stringstream ss; | ||
ss << "0x" << std::hex << uint_ptr; | ||
out.append(ss.str()); | ||
} | ||
else | ||
{ | ||
out.append("nullptr"); | ||
} | ||
out.append("]"); | ||
return out; | ||
} | ||
|
||
} // End namespace wf. |
Oops, something went wrong.