1 // Copyright 2013 Dolphin Emulator Project 2 // Licensed under GPLv2+ 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <map> 8 #include <memory> 9 #include <optional> 10 #include <string> 11 12 #include "InputCommon/ControllerInterface/Device.h" 13 14 namespace ciface::ExpressionParser 15 { 16 enum TokenType 17 { 18 TOK_WHITESPACE, 19 TOK_INVALID, 20 TOK_EOF, 21 TOK_LPAREN, 22 TOK_RPAREN, 23 TOK_NOT, 24 TOK_CONTROL, 25 TOK_LITERAL, 26 TOK_VARIABLE, 27 TOK_BAREWORD, 28 TOK_COMMENT, 29 TOK_HOTKEY, 30 // Binary Ops: 31 TOK_BINARY_OPS_BEGIN, 32 TOK_AND = TOK_BINARY_OPS_BEGIN, 33 TOK_OR, 34 TOK_ADD, 35 TOK_SUB, 36 TOK_MUL, 37 TOK_DIV, 38 TOK_MOD, 39 TOK_ASSIGN, 40 TOK_LTHAN, 41 TOK_GTHAN, 42 TOK_COMMA, 43 TOK_XOR, 44 TOK_BINARY_OPS_END, 45 }; 46 47 class Token 48 { 49 public: 50 TokenType type; 51 std::string data; 52 53 // Position in the input string: 54 std::size_t string_position = 0; 55 std::size_t string_length = 0; 56 57 explicit Token(TokenType type_); 58 Token(TokenType type_, std::string data_); 59 60 bool IsBinaryOperator() const; 61 }; 62 63 enum class ParseStatus 64 { 65 Successful, 66 SyntaxError, 67 EmptyExpression, 68 }; 69 70 class Lexer 71 { 72 public: 73 std::string expr; 74 std::string::iterator it; 75 76 explicit Lexer(std::string expr_); 77 78 ParseStatus Tokenize(std::vector<Token>& tokens); 79 80 private: 81 template <typename F> FetchCharsWhile(F && func)82 std::string FetchCharsWhile(F&& func) 83 { 84 std::string value; 85 while (it != expr.end() && func(*it)) 86 { 87 value += *it; 88 ++it; 89 } 90 return value; 91 } 92 93 std::string FetchDelimString(char delim); 94 std::string FetchWordChars(); 95 Token GetDelimitedLiteral(); 96 Token GetVariable(); 97 Token GetFullyQualifiedControl(); 98 Token GetBareword(char c); 99 Token GetRealLiteral(char c); 100 101 Token PeekToken(); 102 Token NextToken(); 103 }; 104 105 class ControlQualifier 106 { 107 public: 108 bool has_device; 109 Core::DeviceQualifier device_qualifier; 110 std::string control_name; 111 ControlQualifier()112 ControlQualifier() : has_device(false) {} 113 string()114 operator std::string() const 115 { 116 if (has_device) 117 return device_qualifier.ToString() + ":" + control_name; 118 else 119 return control_name; 120 } 121 FromString(const std::string & str)122 void FromString(const std::string& str) 123 { 124 const auto col_pos = str.find_last_of(':'); 125 126 has_device = (str.npos != col_pos); 127 if (has_device) 128 { 129 device_qualifier.FromString(str.substr(0, col_pos)); 130 control_name = str.substr(col_pos + 1); 131 } 132 else 133 { 134 device_qualifier.FromString(""); 135 control_name = str; 136 } 137 } 138 }; 139 140 class ControlEnvironment 141 { 142 public: 143 using VariableContainer = std::map<std::string, ControlState>; 144 ControlEnvironment(const Core::DeviceContainer & container_,const Core::DeviceQualifier & default_,VariableContainer & vars)145 ControlEnvironment(const Core::DeviceContainer& container_, const Core::DeviceQualifier& default_, 146 VariableContainer& vars) 147 : m_variables(vars), container(container_), default_device(default_) 148 { 149 } 150 151 std::shared_ptr<Core::Device> FindDevice(ControlQualifier qualifier) const; 152 Core::Device::Input* FindInput(ControlQualifier qualifier) const; 153 Core::Device::Output* FindOutput(ControlQualifier qualifier) const; 154 ControlState* GetVariablePtr(const std::string& name); 155 156 private: 157 VariableContainer& m_variables; 158 const Core::DeviceContainer& container; 159 const Core::DeviceQualifier& default_device; 160 }; 161 162 class Expression 163 { 164 public: 165 virtual ~Expression() = default; 166 virtual ControlState GetValue() const = 0; 167 virtual void SetValue(ControlState state) = 0; 168 virtual int CountNumControls() const = 0; 169 virtual void UpdateReferences(ControlEnvironment& finder) = 0; 170 }; 171 172 class ParseResult 173 { 174 public: 175 static ParseResult MakeEmptyResult(); 176 static ParseResult MakeSuccessfulResult(std::unique_ptr<Expression>&& expr); 177 static ParseResult MakeErrorResult(Token token, std::string description); 178 179 ParseStatus status; 180 std::unique_ptr<Expression> expr; 181 182 // Used for parse errors: 183 // TODO: This should probably be moved elsewhere: 184 std::optional<Token> token; 185 std::optional<std::string> description; 186 187 private: 188 ParseResult() = default; 189 }; 190 191 ParseResult ParseExpression(const std::string& expr); 192 ParseResult ParseTokens(const std::vector<Token>& tokens); 193 void RemoveInertTokens(std::vector<Token>* tokens); 194 195 } // namespace ciface::ExpressionParser 196