summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-07-28 05:37:24 +0430
committerAndreas Kling <kling@serenityos.org>2021-08-02 01:03:59 +0200
commit331911412745eded57f5e5c461d4cd7fbcdedb68 (patch)
treeec656901541a13962cb7eb3e07634f24c3d5809b
parent3c1422d774f2b18d687a276d5ca1a459ed60b8e3 (diff)
downloadserenity-331911412745eded57f5e5c461d4cd7fbcdedb68.zip
LibCpp: Add support for parsing reference types
-rw-r--r--Userland/Libraries/LibCpp/AST.cpp23
-rw-r--r--Userland/Libraries/LibCpp/AST.h27
-rw-r--r--Userland/Libraries/LibCpp/Parser.cpp10
3 files changed, 60 insertions, 0 deletions
diff --git a/Userland/Libraries/LibCpp/AST.cpp b/Userland/Libraries/LibCpp/AST.cpp
index 40f960b785..3187911794 100644
--- a/Userland/Libraries/LibCpp/AST.cpp
+++ b/Userland/Libraries/LibCpp/AST.cpp
@@ -100,6 +100,19 @@ String Pointer::to_string() const
return builder.to_string();
}
+String Reference::to_string() const
+{
+ if (!m_referenced_type)
+ return {};
+ StringBuilder builder;
+ builder.append(m_referenced_type->to_string());
+ if (m_kind == Kind::Lvalue)
+ builder.append("&");
+ else
+ builder.append("&&");
+ return builder.to_string();
+}
+
void Parameter::dump(FILE* output, size_t indent) const
{
ASTNode::dump(output, indent);
@@ -359,6 +372,16 @@ void Pointer::dump(FILE* output, size_t indent) const
}
}
+void Reference::dump(FILE* output, size_t indent) const
+{
+ ASTNode::dump(output, indent);
+ print_indent(output, indent + 1);
+ outln(output, "{}", m_kind == Kind::Lvalue ? "&" : "&&");
+ if (!m_referenced_type.is_null()) {
+ m_referenced_type->dump(output, indent + 1);
+ }
+}
+
void MemberExpression::dump(FILE* output, size_t indent) const
{
ASTNode::dump(output, indent);
diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h
index 912312770a..7bb9b36490 100644
--- a/Userland/Libraries/LibCpp/AST.h
+++ b/Userland/Libraries/LibCpp/AST.h
@@ -281,6 +281,33 @@ private:
RefPtr<Type> m_pointee;
};
+class Reference : public Type {
+public:
+ virtual ~Reference() override = default;
+ virtual const char* class_name() const override { return "Reference"; }
+ virtual void dump(FILE* = stdout, size_t indent = 0) const override;
+ virtual String to_string() const override;
+
+ enum class Kind {
+ Lvalue,
+ Rvalue,
+ };
+
+ Reference(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename, Kind kind)
+ : Type(parent, start, end, filename)
+ , m_kind(kind)
+ {
+ }
+
+ const Type* referenced_type() const { return m_referenced_type.ptr(); }
+ void set_referenced_type(RefPtr<Type>&& pointee) { m_referenced_type = move(pointee); }
+ Kind kind() const { return m_kind; }
+
+private:
+ RefPtr<Type const> m_referenced_type;
+ Kind m_kind;
+};
+
class FunctionDefinition : public ASTNode {
public:
virtual ~FunctionDefinition() override = default;
diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp
index c3a630f0db..64c814d717 100644
--- a/Userland/Libraries/LibCpp/Parser.cpp
+++ b/Userland/Libraries/LibCpp/Parser.cpp
@@ -1237,6 +1237,16 @@ NonnullRefPtr<Type> Parser::parse_type(ASTNode& parent)
type = ptr;
}
+ if (!eof() && (peek().type() == Token::Type::And || peek().type() == Token::Type::AndAnd)) {
+ type->set_end(position());
+ auto ref_token = consume();
+ auto ref = create_ast_node<Reference>(parent, type->start(), ref_token.end(), ref_token.type() == Token::Type::And ? Reference::Kind::Lvalue : Reference::Kind::Rvalue);
+ type->set_parent(*ref);
+ ref->set_referenced_type(type);
+ ref->set_end(position());
+ type = ref;
+ }
+
type->set_end(position());
return type;
}