From adacc5283eb660501b8c43ca8363bf9e0dfce051 Mon Sep 17 00:00:00 2001 From: Bastian Blokland Date: Wed, 8 Jan 2020 23:36:17 +0200 Subject: [PATCH] Add '??' overloadable operator --- include/lex/token_kind.hpp | 1 + include/prog/operator.hpp | 1 + src/frontend/internal/utilities.cpp | 4 ++++ src/lex/lexer.cpp | 4 ++++ src/lex/token_cat.cpp | 1 + src/lex/token_kind.cpp | 3 +++ src/parse/op_precedence.cpp | 1 + src/prog/operator.cpp | 2 ++ tests/lex/operators_test.cpp | 1 + 9 files changed, 18 insertions(+) diff --git a/include/lex/token_kind.hpp b/include/lex/token_kind.hpp index 697028c8..5509d4a7 100644 --- a/include/lex/token_kind.hpp +++ b/include/lex/token_kind.hpp @@ -27,6 +27,7 @@ enum class TokenKind { OpGtEq, OpSemi, OpQMark, + OpQMarkQMark, OpDot, OpColonColon, OpSquareSquare, diff --git a/include/prog/operator.hpp b/include/prog/operator.hpp index 3e7118fd..15f0965c 100644 --- a/include/prog/operator.hpp +++ b/include/prog/operator.hpp @@ -24,6 +24,7 @@ enum class Operator { ColonColon, SquareSquare, ParenParen, + QMarkQMark, }; auto getFuncName(Operator op) -> std::string; diff --git a/src/frontend/internal/utilities.cpp b/src/frontend/internal/utilities.cpp index 76a33303..b9e7385c 100644 --- a/src/frontend/internal/utilities.cpp +++ b/src/frontend/internal/utilities.cpp @@ -91,6 +91,8 @@ auto getOperator(const lex::Token& token) -> std::optional { return prog::Operator::SquareSquare; case lex::TokenKind::OpParenParen: return prog::Operator::ParenParen; + case lex::TokenKind::OpQMarkQMark: + return prog::Operator::QMarkQMark; default: return std::nullopt; } @@ -138,6 +140,8 @@ auto getText(const prog::Operator& op) -> std::string { return "[]"; case prog::Operator::ParenParen: return "()"; + case prog::Operator::QMarkQMark: + return "??"; } return "__unknown"; } diff --git a/src/lex/lexer.cpp b/src/lex/lexer.cpp index 3f27af3f..d6faabb1 100644 --- a/src/lex/lexer.cpp +++ b/src/lex/lexer.cpp @@ -139,6 +139,10 @@ auto LexerImpl::next() -> Token { case ';': return basicToken(TokenKind::OpSemi, input::Span{m_inputPos}); case '?': + if (peekChar(0) == '?') { + consumeChar(); + return basicToken(TokenKind::OpQMarkQMark, input::Span{m_inputPos - 1, m_inputPos}); + } return basicToken(TokenKind::OpQMark, input::Span{m_inputPos}); case '.': if (isDigit(peekChar(0))) { diff --git a/src/lex/token_cat.cpp b/src/lex/token_cat.cpp index 7b012821..7b6bcab8 100644 --- a/src/lex/token_cat.cpp +++ b/src/lex/token_cat.cpp @@ -56,6 +56,7 @@ auto lookupCat(const TokenKind kind) -> TokenCat { case TokenKind::OpGtEq: case TokenKind::OpSemi: case TokenKind::OpQMark: + case TokenKind::OpQMarkQMark: case TokenKind::OpDot: case TokenKind::OpColonColon: case TokenKind::OpSquareSquare: diff --git a/src/lex/token_kind.cpp b/src/lex/token_kind.cpp index ee73719a..dae638e4 100644 --- a/src/lex/token_kind.cpp +++ b/src/lex/token_kind.cpp @@ -70,6 +70,9 @@ auto operator<<(std::ostream& out, const TokenKind& rhs) -> std::ostream& { case TokenKind::OpQMark: out << "qmark"; break; + case TokenKind::OpQMarkQMark: + out << "qmarkqmark"; + break; case TokenKind::OpDot: out << "dot"; break; diff --git a/src/parse/op_precedence.cpp b/src/parse/op_precedence.cpp index 84f7b906..a70d934a 100644 --- a/src/parse/op_precedence.cpp +++ b/src/parse/op_precedence.cpp @@ -19,6 +19,7 @@ auto getRhsOpPrecedence(const lex::Token& token) -> int { case lex::TokenKind::OpParenParen: case lex::TokenKind::SepOpenParen: case lex::TokenKind::SepOpenSquare: + case lex::TokenKind::OpQMarkQMark: case lex::TokenKind::OpDot: return callPrecedence; case lex::TokenKind::OpStar: diff --git a/src/prog/operator.cpp b/src/prog/operator.cpp index d33f75c9..b0b7b998 100644 --- a/src/prog/operator.cpp +++ b/src/prog/operator.cpp @@ -45,6 +45,8 @@ auto getFuncName(Operator op) -> std::string { return "__op_squaresquare"; case Operator::ParenParen: return "__op_parenparen"; + case Operator::QMarkQMark: + return "__op_qmarkqmark"; } throw std::invalid_argument("Unknown operator"); } diff --git a/tests/lex/operators_test.cpp b/tests/lex/operators_test.cpp index 75aa6904..5231f59d 100644 --- a/tests/lex/operators_test.cpp +++ b/tests/lex/operators_test.cpp @@ -26,6 +26,7 @@ TEST_CASE("Lexing operators", "[lex]") { CHECK_TOKENS(">=", basicToken(TokenKind::OpGtEq)); CHECK_TOKENS(";", basicToken(TokenKind::OpSemi)); CHECK_TOKENS("?", basicToken(TokenKind::OpQMark)); + CHECK_TOKENS("??", basicToken(TokenKind::OpQMarkQMark)); CHECK_TOKENS(".", basicToken(TokenKind::OpDot)); CHECK_TOKENS("::", basicToken(TokenKind::OpColonColon)); CHECK_TOKENS("[]", basicToken(TokenKind::OpSquareSquare));