mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 07:45:33 +01:00
ExpressionParser: Add support for literals.
This commit is contained in:
parent
5be061e27f
commit
f3192ca06d
@ -29,6 +29,7 @@ enum TokenType
|
|||||||
TOK_NOT,
|
TOK_NOT,
|
||||||
TOK_ADD,
|
TOK_ADD,
|
||||||
TOK_CONTROL,
|
TOK_CONTROL,
|
||||||
|
TOK_LITERAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string OpName(TokenType op)
|
inline std::string OpName(TokenType op)
|
||||||
@ -53,10 +54,10 @@ class Token
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TokenType type;
|
TokenType type;
|
||||||
ControlQualifier qualifier;
|
std::string data;
|
||||||
|
|
||||||
Token(TokenType type_) : type(type_) {}
|
Token(TokenType type_) : type(type_) {}
|
||||||
Token(TokenType type_, ControlQualifier qualifier_) : type(type_), qualifier(qualifier_) {}
|
Token(TokenType type_, std::string data_) : type(type_), data(std::move(data_)) {}
|
||||||
operator std::string() const
|
operator std::string() const
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -78,7 +79,9 @@ public:
|
|||||||
case TOK_ADD:
|
case TOK_ADD:
|
||||||
return "+";
|
return "+";
|
||||||
case TOK_CONTROL:
|
case TOK_CONTROL:
|
||||||
return "Device(" + (std::string)qualifier + ")";
|
return "Device(" + data + ")";
|
||||||
|
case TOK_LITERAL:
|
||||||
|
return '\'' + data + '\'';
|
||||||
case TOK_INVALID:
|
case TOK_INVALID:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -94,38 +97,33 @@ public:
|
|||||||
std::string::iterator it;
|
std::string::iterator it;
|
||||||
|
|
||||||
Lexer(const std::string& expr_) : expr(expr_) { it = expr.begin(); }
|
Lexer(const std::string& expr_) : expr(expr_) { it = expr.begin(); }
|
||||||
bool FetchBacktickString(std::string& value, char otherDelim = 0)
|
|
||||||
|
bool FetchDelimString(std::string& value, char delim)
|
||||||
{
|
{
|
||||||
value = "";
|
value = "";
|
||||||
while (it != expr.end())
|
while (it != expr.end())
|
||||||
{
|
{
|
||||||
char c = *it;
|
char c = *it;
|
||||||
++it;
|
++it;
|
||||||
if (c == '`')
|
if (c == delim)
|
||||||
return false;
|
|
||||||
if (c > 0 && c == otherDelim)
|
|
||||||
return true;
|
return true;
|
||||||
value += c;
|
value += c;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token GetLiteral()
|
||||||
|
{
|
||||||
|
std::string value;
|
||||||
|
FetchDelimString(value, '\'');
|
||||||
|
return Token(TOK_LITERAL, value);
|
||||||
|
}
|
||||||
|
|
||||||
Token GetFullyQualifiedControl()
|
Token GetFullyQualifiedControl()
|
||||||
{
|
{
|
||||||
ControlQualifier qualifier;
|
|
||||||
std::string value;
|
std::string value;
|
||||||
|
FetchDelimString(value, '`');
|
||||||
if (FetchBacktickString(value, ':'))
|
return Token(TOK_CONTROL, value);
|
||||||
{
|
|
||||||
// Found colon, this is the device name
|
|
||||||
qualifier.has_device = true;
|
|
||||||
qualifier.device_qualifier.FromString(value);
|
|
||||||
FetchBacktickString(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
qualifier.control_name = value;
|
|
||||||
|
|
||||||
return Token(TOK_CONTROL, qualifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Token GetBarewordsControl(char c)
|
Token GetBarewordsControl(char c)
|
||||||
@ -172,6 +170,8 @@ public:
|
|||||||
return Token(TOK_NOT);
|
return Token(TOK_NOT);
|
||||||
case '+':
|
case '+':
|
||||||
return Token(TOK_ADD);
|
return Token(TOK_ADD);
|
||||||
|
case '\'':
|
||||||
|
return GetLiteral();
|
||||||
case '`':
|
case '`':
|
||||||
return GetFullyQualifiedControl();
|
return GetFullyQualifiedControl();
|
||||||
default:
|
default:
|
||||||
@ -339,6 +339,35 @@ public:
|
|||||||
operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; }
|
operator std::string() const override { return OpName(op) + "(" + (std::string)(*inner) + ")"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LiteralExpression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit LiteralExpression(const std::string& str)
|
||||||
|
{
|
||||||
|
// If it fails to parse it will just be the default: 0.0
|
||||||
|
TryParse(str, &m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlState GetValue() const override { return m_value; }
|
||||||
|
|
||||||
|
void SetValue(ControlState value) override
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
int CountNumControls() const override { return 1; }
|
||||||
|
|
||||||
|
void UpdateReferences(ControlFinder&) override
|
||||||
|
{
|
||||||
|
// Nothing needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
operator std::string() const override { return '\'' + ValueToString(m_value) + '\''; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ControlState m_value{};
|
||||||
|
};
|
||||||
|
|
||||||
// This class proxies all methods to its either left-hand child if it has bound controls, or its
|
// This class proxies all methods to its either left-hand child if it has bound controls, or its
|
||||||
// right-hand child. Its intended use is for supporting old-style barewords expressions.
|
// right-hand child. Its intended use is for supporting old-style barewords expressions.
|
||||||
class CoalesceExpression : public Expression
|
class CoalesceExpression : public Expression
|
||||||
@ -430,7 +459,15 @@ private:
|
|||||||
switch (tok.type)
|
switch (tok.type)
|
||||||
{
|
{
|
||||||
case TOK_CONTROL:
|
case TOK_CONTROL:
|
||||||
return {ParseStatus::Successful, std::make_unique<ControlExpression>(tok.qualifier)};
|
{
|
||||||
|
ControlQualifier cq;
|
||||||
|
cq.FromString(tok.data);
|
||||||
|
return {ParseStatus::Successful, std::make_unique<ControlExpression>(cq)};
|
||||||
|
}
|
||||||
|
case TOK_LITERAL:
|
||||||
|
{
|
||||||
|
return {ParseStatus::Successful, std::make_unique<LiteralExpression>(tok.data)};
|
||||||
|
}
|
||||||
case TOK_LPAREN:
|
case TOK_LPAREN:
|
||||||
return Paren();
|
return Paren();
|
||||||
default:
|
default:
|
||||||
|
@ -19,6 +19,7 @@ public:
|
|||||||
std::string control_name;
|
std::string control_name;
|
||||||
|
|
||||||
ControlQualifier() : has_device(false) {}
|
ControlQualifier() : has_device(false) {}
|
||||||
|
|
||||||
operator std::string() const
|
operator std::string() const
|
||||||
{
|
{
|
||||||
if (has_device)
|
if (has_device)
|
||||||
@ -26,6 +27,23 @@ public:
|
|||||||
else
|
else
|
||||||
return control_name;
|
return control_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FromString(const std::string& str)
|
||||||
|
{
|
||||||
|
const auto col_pos = str.find_last_of(':');
|
||||||
|
|
||||||
|
has_device = (str.npos != col_pos);
|
||||||
|
if (has_device)
|
||||||
|
{
|
||||||
|
device_qualifier.FromString(str.substr(0, col_pos));
|
||||||
|
control_name = str.substr(col_pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
device_qualifier.FromString("");
|
||||||
|
control_name = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControlFinder
|
class ControlFinder
|
||||||
|
Loading…
x
Reference in New Issue
Block a user