pattern: Added compound assignment operators

This commit is contained in:
WerWolv 2022-01-29 04:16:32 +01:00
parent a0a39f1c04
commit 75331cda94
3 changed files with 94 additions and 35 deletions

View File

@ -27,7 +27,7 @@ namespace hex::pl {
private: private:
std::optional<ParseError> m_error; std::optional<ParseError> m_error;
TokenIter m_curr; TokenIter m_curr;
TokenIter m_originalPosition; TokenIter m_originalPosition, m_partOriginalPosition;
std::unordered_map<std::string, ASTNode *> m_types; std::unordered_map<std::string, ASTNode *> m_types;
std::vector<TokenIter> m_matchedOptionals; std::vector<TokenIter> m_matchedOptionals;
@ -71,6 +71,7 @@ namespace hex::pl {
ASTNode *parseStringLiteral(); ASTNode *parseStringLiteral();
std::string parseNamespaceResolution(); std::string parseNamespaceResolution();
ASTNode *parseScopeResolution(); ASTNode *parseScopeResolution();
ASTNode *parseRValue();
ASTNode *parseRValue(ASTNodeRValue::Path &path); ASTNode *parseRValue(ASTNodeRValue::Path &path);
ASTNode *parseFactor(); ASTNode *parseFactor();
ASTNode *parseCastExpression(); ASTNode *parseCastExpression();
@ -92,7 +93,8 @@ namespace hex::pl {
ASTNode *parseFunctionDefinition(); ASTNode *parseFunctionDefinition();
ASTNode *parseFunctionVariableDecl(); ASTNode *parseFunctionVariableDecl();
ASTNode *parseFunctionStatement(); ASTNode *parseFunctionStatement();
ASTNode *parseFunctionVariableAssignment(); ASTNode *parseFunctionVariableAssignment(const std::string &lvalue);
ASTNode *parseFunctionVariableCompoundAssignment(const std::string &lvalue);
ASTNode *parseFunctionControlFlowStatement(); ASTNode *parseFunctionControlFlowStatement();
std::vector<ASTNode *> parseStatementBody(); std::vector<ASTNode *> parseStatementBody();
ASTNode *parseFunctionConditional(); ASTNode *parseFunctionConditional();
@ -158,12 +160,29 @@ namespace hex::pl {
return true; return true;
} }
bool partBegin() {
this->m_partOriginalPosition = this->m_curr;
this->m_matchedOptionals.clear();
return true;
}
void reset() { void reset() {
this->m_curr = this->m_originalPosition; this->m_curr = this->m_originalPosition;
} }
void partReset() {
this->m_curr = this->m_partOriginalPosition;
}
bool resetIfFailed(bool value) {
if (!value) reset();
return value;
}
template<Setting S = Normal> template<Setting S = Normal>
bool sequence() { bool sequenceImpl() {
if constexpr (S == Normal) if constexpr (S == Normal)
return true; return true;
else if constexpr (S == Not) else if constexpr (S == Not)
@ -173,17 +192,17 @@ namespace hex::pl {
} }
template<Setting S = Normal> template<Setting S = Normal>
bool sequence(Token::Type type, auto value, auto... args) { bool sequenceImpl(Token::Type type, auto value, auto... args) {
if constexpr (S == Normal) { if constexpr (S == Normal) {
if (!peek(type, value)) { if (!peek(type, value)) {
reset(); partReset();
return false; return false;
} }
this->m_curr++; this->m_curr++;
if (!sequence<Normal>(args...)) { if (!sequenceImpl<Normal>(args...)) {
reset(); partReset();
return false; return false;
} }
@ -194,17 +213,22 @@ namespace hex::pl {
this->m_curr++; this->m_curr++;
if (!sequence<Normal>(args...)) if (!sequenceImpl<Normal>(args...))
return true; return true;
reset(); partReset();
return false; return false;
} else } else
__builtin_unreachable(); __builtin_unreachable();
} }
template<Setting S = Normal> template<Setting S = Normal>
bool oneOf() { bool sequence(Token::Type type, auto value, auto... args) {
return partBegin() && sequenceImpl<S>(type, value, args...);
}
template<Setting S = Normal>
bool oneOfImpl() {
if constexpr (S == Normal) if constexpr (S == Normal)
return false; return false;
else if constexpr (S == Not) else if constexpr (S == Not)
@ -214,19 +238,24 @@ namespace hex::pl {
} }
template<Setting S = Normal> template<Setting S = Normal>
bool oneOf(Token::Type type, auto value, auto... args) { bool oneOfImpl(Token::Type type, auto value, auto... args) {
if constexpr (S == Normal) if constexpr (S == Normal)
return sequence<Normal>(type, value) || oneOf(args...); return sequenceImpl<Normal>(type, value) || oneOfImpl(args...);
else if constexpr (S == Not) else if constexpr (S == Not)
return sequence<Not>(type, value) && oneOf(args...); return sequenceImpl<Not>(type, value) && oneOfImpl(args...);
else else
__builtin_unreachable(); __builtin_unreachable();
} }
bool variant(Token::Type type1, auto value1, Token::Type type2, auto value2) { template<Setting S = Normal>
bool oneOf(Token::Type type, auto value, auto... args) {
return partBegin() && oneOfImpl<S>(type, value, args...);
}
bool variantImpl(Token::Type type1, auto value1, Token::Type type2, auto value2) {
if (!peek(type1, value1)) { if (!peek(type1, value1)) {
if (!peek(type2, value2)) { if (!peek(type2, value2)) {
reset(); partReset();
return false; return false;
} }
} }
@ -236,7 +265,11 @@ namespace hex::pl {
return true; return true;
} }
bool optional(Token::Type type, auto value) { bool variant(Token::Type type1, auto value1, Token::Type type2, auto value2) {
return partBegin() && variantImpl(type1, value1, type2, value2);
}
bool optionalImpl(Token::Type type, auto value) {
if (peek(type, value)) { if (peek(type, value)) {
this->m_matchedOptionals.push_back(this->m_curr); this->m_matchedOptionals.push_back(this->m_curr);
this->m_curr++; this->m_curr++;
@ -245,6 +278,10 @@ namespace hex::pl {
return true; return true;
} }
bool optional(Token::Type type, auto value) {
return partBegin() && optionalImpl(type, value);
}
bool peek(Token::Type type, auto value, i32 index = 0) { bool peek(Token::Type type, auto value, i32 index = 0) {
return this->m_curr[index].type == type && this->m_curr[index] == value; return this->m_curr[index].type == type && this->m_curr[index] == value;
} }

View File

@ -306,6 +306,7 @@ namespace hex::pl {
#define IDENTIFIER hex::pl::Token::Type::Identifier, "" #define IDENTIFIER hex::pl::Token::Type::Identifier, ""
#define STRING hex::pl::Token::Type::String, hex::pl::Token::Literal("") #define STRING hex::pl::Token::Type::String, hex::pl::Token::Literal("")
#define OPERATOR_ANY COMPONENT(Operator, Any)
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration) #define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment) #define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
#define OPERATOR_INHERIT COMPONENT(Operator, Inherit) #define OPERATOR_INHERIT COMPONENT(Operator, Inherit)
@ -341,7 +342,6 @@ namespace hex::pl {
#define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned) #define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned)
#define VALUETYPE_SIGNED COMPONENT(ValueType, Signed) #define VALUETYPE_SIGNED COMPONENT(ValueType, Signed)
#define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint) #define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint)
#define VALUETYPE_INTEGER COMPONENT(ValueType, Integer)
#define VALUETYPE_ANY COMPONENT(ValueType, Any) #define VALUETYPE_ANY COMPONENT(ValueType, Any)
#define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen) #define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen)

View File

@ -2,7 +2,7 @@
#include <optional> #include <optional>
#define MATCHES(x) (begin() && x) #define MATCHES(x) (begin() && resetIfFailed(x))
// Definition syntax: // Definition syntax:
// [A] : Either A or no token // [A] : Either A or no token
@ -87,6 +87,11 @@ namespace hex::pl {
throwParseError("failed to parse scope resolution. Expected 'TypeName::Identifier'"); throwParseError("failed to parse scope resolution. Expected 'TypeName::Identifier'");
} }
ASTNode *Parser::parseRValue() {
ASTNodeRValue::Path path;
return this->parseRValue(path);
}
// <Identifier[.]...> // <Identifier[.]...>
ASTNode *Parser::parseRValue(ASTNodeRValue::Path &path) { ASTNode *Parser::parseRValue(ASTNodeRValue::Path &path) {
if (peek(IDENTIFIER, -1)) if (peek(IDENTIFIER, -1))
@ -136,28 +141,33 @@ namespace hex::pl {
} else if (peek(OPERATOR_SCOPERESOLUTION, 0)) { } else if (peek(OPERATOR_SCOPERESOLUTION, 0)) {
return this->parseScopeResolution(); return this->parseScopeResolution();
} else { } else {
ASTNodeRValue::Path path; return this->parseRValue();
return this->parseRValue(path);
} }
} else if (MATCHES(oneOf(KEYWORD_PARENT, KEYWORD_THIS))) { } else if (MATCHES(oneOf(KEYWORD_PARENT, KEYWORD_THIS))) {
ASTNodeRValue::Path path; return this->parseRValue();
return this->parseRValue(path);
} else if (MATCHES(sequence(OPERATOR_DOLLAR))) { } else if (MATCHES(sequence(OPERATOR_DOLLAR))) {
return new ASTNodeRValue({ "$" }); return new ASTNodeRValue({ "$" });
} else if (MATCHES(oneOf(OPERATOR_ADDRESSOF, OPERATOR_SIZEOF) && sequence(SEPARATOR_ROUNDBRACKETOPEN))) { } else if (MATCHES(oneOf(OPERATOR_ADDRESSOF, OPERATOR_SIZEOF) && sequence(SEPARATOR_ROUNDBRACKETOPEN))) {
auto op = getValue<Token::Operator>(-2); auto op = getValue<Token::Operator>(-2);
if (!MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT, KEYWORD_THIS))) { ASTNode *result = nullptr;
throwParseError("expected rvalue identifier");
if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT, KEYWORD_THIS))) {
result = create(new ASTNodeTypeOperator(op, this->parseRValue()));
} else if (MATCHES(sequence(VALUETYPE_ANY))) {
auto type = getValue<Token::ValueType>(-1);
result = new ASTNodeLiteral(u128(Token::getTypeSize(type)));
} else {
throwParseError("expected rvalue identifier or built-in type");
} }
ASTNodeRValue::Path path;
auto node = create(new ASTNodeTypeOperator(op, this->parseRValue(path)));
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) { if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) {
delete node; delete result;
throwParseError("expected closing parenthesis"); throwParseError("expected closing parenthesis");
} }
return node;
return result;
} else } else
throwParseError("expected value or parenthesis"); throwParseError("expected value or parenthesis");
} }
@ -490,9 +500,13 @@ namespace hex::pl {
ASTNode *statement; ASTNode *statement;
if (MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT))) if (MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT)))
statement = parseFunctionVariableAssignment(); statement = parseFunctionVariableAssignment(getValue<Token::Identifier>(-2).get());
else if (MATCHES(sequence(OPERATOR_DOLLAR, OPERATOR_ASSIGNMENT))) else if (MATCHES(sequence(OPERATOR_DOLLAR, OPERATOR_ASSIGNMENT)))
statement = create(new ASTNodeAssignment("$", parseMathematicalExpression())); statement = parseFunctionVariableAssignment("$");
else if (MATCHES(oneOf(IDENTIFIER) && oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT, OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT, OPERATOR_BITOR, OPERATOR_BITAND, OPERATOR_BITXOR) && sequence(OPERATOR_ASSIGNMENT)))
statement = parseFunctionVariableCompoundAssignment(getValue<Token::Identifier>(-3).get());
else if (MATCHES(oneOf(OPERATOR_DOLLAR) && oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT, OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT, OPERATOR_BITOR, OPERATOR_BITAND, OPERATOR_BITXOR) && sequence(OPERATOR_ASSIGNMENT)))
statement = parseFunctionVariableCompoundAssignment("$");
else if (MATCHES(oneOf(KEYWORD_RETURN, KEYWORD_BREAK, KEYWORD_CONTINUE))) else if (MATCHES(oneOf(KEYWORD_RETURN, KEYWORD_BREAK, KEYWORD_CONTINUE)))
statement = parseFunctionControlFlowStatement(); statement = parseFunctionControlFlowStatement();
else if (MATCHES(sequence(KEYWORD_IF, SEPARATOR_ROUNDBRACKETOPEN))) { else if (MATCHES(sequence(KEYWORD_IF, SEPARATOR_ROUNDBRACKETOPEN))) {
@ -533,14 +547,20 @@ namespace hex::pl {
return statement; return statement;
} }
ASTNode *Parser::parseFunctionVariableAssignment() { ASTNode *Parser::parseFunctionVariableAssignment(const std::string &lvalue) {
const auto &lvalue = getValue<Token::Identifier>(-2).get();
auto rvalue = this->parseMathematicalExpression(); auto rvalue = this->parseMathematicalExpression();
return create(new ASTNodeAssignment(lvalue, rvalue)); return create(new ASTNodeAssignment(lvalue, rvalue));
} }
ASTNode *Parser::parseFunctionVariableCompoundAssignment(const std::string &lvalue) {
const auto &op = getValue<Token::Operator>(-2);
auto rvalue = this->parseMathematicalExpression();
return create(new ASTNodeAssignment(lvalue, create(new ASTNodeMathematicalExpression(create(new ASTNodeRValue({ lvalue })), rvalue, op))));
}
ASTNode *Parser::parseFunctionControlFlowStatement() { ASTNode *Parser::parseFunctionControlFlowStatement() {
ControlFlowStatement type; ControlFlowStatement type;
if (peek(KEYWORD_RETURN, -1)) if (peek(KEYWORD_RETURN, -1))
@ -640,7 +660,7 @@ namespace hex::pl {
if (!MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT))) if (!MATCHES(sequence(IDENTIFIER, OPERATOR_ASSIGNMENT)))
throwParseError("expected for loop variable assignment"); throwParseError("expected for loop variable assignment");
auto postExpression = parseFunctionVariableAssignment(); auto postExpression = parseFunctionVariableAssignment(getValue<Token::Identifier>(-2).get());
auto postExpressionCleanup = SCOPE_GUARD { delete postExpression; }; auto postExpressionCleanup = SCOPE_GUARD { delete postExpression; };
std::vector<ASTNode *> body; std::vector<ASTNode *> body;
@ -880,7 +900,9 @@ namespace hex::pl {
else if (MATCHES(sequence(KEYWORD_CONTINUE))) else if (MATCHES(sequence(KEYWORD_CONTINUE)))
member = new ASTNodeControlFlowStatement(ControlFlowStatement::Continue, nullptr); member = new ASTNodeControlFlowStatement(ControlFlowStatement::Continue, nullptr);
else if (MATCHES(sequence(OPERATOR_DOLLAR, OPERATOR_ASSIGNMENT))) else if (MATCHES(sequence(OPERATOR_DOLLAR, OPERATOR_ASSIGNMENT)))
member = create(new ASTNodeAssignment("$", parseMathematicalExpression())); member = parseFunctionVariableAssignment("$");
else if (MATCHES(oneOf(OPERATOR_DOLLAR) && oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT, OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT, OPERATOR_BITOR, OPERATOR_BITAND, OPERATOR_BITXOR) && sequence(OPERATOR_ASSIGNMENT)))
member = parseFunctionVariableCompoundAssignment("$");
else else
throwParseError("invalid struct member", 0); throwParseError("invalid struct member", 0);