Browse Source

LibCpp: Parse ellipsis

We can now parse the printf function declaration :^)
Itamar 4 năm trước cách đây
mục cha
commit
1d3b5dabc3

+ 7 - 2
Userland/Libraries/LibCpp/AST.cpp

@@ -83,7 +83,7 @@ void Type::dump(size_t indent) const
     ASTNode::dump(indent);
     print_indent(indent + 1);
     String qualifiers_string;
-    if(!m_qualifiers.is_empty())
+    if (!m_qualifiers.is_empty())
         qualifiers_string = String::formatted("[{}] ", String::join(" ", m_qualifiers));
     outln("{}{}", qualifiers_string, m_name);
 }
@@ -91,11 +91,16 @@ void Type::dump(size_t indent) const
 void Parameter::dump(size_t indent) const
 {
     ASTNode::dump(indent);
+    if (m_is_ellipsis) {
+        print_indent(indent + 1);
+        outln("...");
+    }
     if (!m_name.is_null()) {
         print_indent(indent);
         outln("{}", m_name);
     }
-    m_type->dump(indent + 1);
+    if (m_type)
+        m_type->dump(indent + 1);
 }
 
 void FunctionDefinition::dump(size_t indent) const

+ 3 - 1
Userland/Libraries/LibCpp/AST.h

@@ -202,13 +202,15 @@ public:
     virtual const char* class_name() const override { return "Parameter"; }
     virtual void dump(size_t indent) const override;
 
-    Parameter(ASTNode* parent, Optional<Position> start, Optional<Position> end, StringView name, const String& filename)
+    Parameter(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename, StringView name)
         : VariableOrParameterDeclaration(parent, start, end, filename)
     {
         m_name = name;
     }
 
     virtual bool is_parameter() const override { return true; }
+
+    bool m_is_ellipsis { false };
 };
 
 class Type : public ASTNode {

+ 30 - 18
Userland/Libraries/LibCpp/Parser.cpp

@@ -24,9 +24,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#undef CPP_DEBUG
-#define CPP_DEBUG 1
-
 #ifdef CPP_DEBUG
 #    define DEBUG_SPAM
 #endif
@@ -560,20 +557,30 @@ Optional<NonnullRefPtrVector<Parameter>> Parser::parse_parameter_list(ASTNode& p
     SCOPE_LOGGER();
     NonnullRefPtrVector<Parameter> parameters;
     while (peek().m_type != Token::Type::RightParen && !eof()) {
-        auto type = parse_type(parent);
+        if (match_ellipsis()) {
+            auto last_dot = consume();
+            while (peek().type() == Token::Type::Dot)
+                last_dot = consume();
+            auto param = create_ast_node<Parameter>(parent, position(), last_dot.end(), StringView {});
+            param->m_is_ellipsis = true;
+            parameters.append(move(param));
+        } else {
+            auto type = parse_type(parent);
 
-        auto name_identifier = peek(Token::Type::Identifier);
-        if (name_identifier.has_value())
-            consume(Token::Type::Identifier);
+            auto name_identifier = peek(Token::Type::Identifier);
+            if (name_identifier.has_value())
+                consume(Token::Type::Identifier);
 
-        StringView name;
-        if (name_identifier.has_value())
-            name = text_of_token(name_identifier.value());
+            StringView name;
+            if (name_identifier.has_value())
+                name = text_of_token(name_identifier.value());
 
-        auto param = create_ast_node<Parameter>(parent, type->start(), name_identifier.has_value() ? name_identifier.value().m_end : type->end(), name);
+            auto param = create_ast_node<Parameter>(parent, type->start(), name_identifier.has_value() ? name_identifier.value().m_end : type->end(), name);
+
+            param->m_type = move(type);
+            parameters.append(move(param));
+        }
 
-        param->m_type = move(type);
-        parameters.append(move(param));
         if (peek(Token::Type::Comma).has_value())
             consume(Token::Type::Comma);
     }
@@ -640,12 +647,11 @@ Token Parser::consume()
     return m_tokens[m_state.token_index++];
 }
 
-Token Parser::peek() const
+Token Parser::peek(size_t offset) const
 {
-    if (eof()) {
+    if (m_state.token_index + offset >= m_tokens.size())
         return { Token::Type::EOF_TOKEN, position(), position() };
-    }
-    return m_tokens[m_state.token_index];
+    return m_tokens[m_state.token_index + offset];
 }
 
 Optional<Token> Parser::peek(Token::Type type) const
@@ -1081,10 +1087,16 @@ void Parser::consume_attribute_specification()
         if (token.type() == Token::Type::RightParen) {
             --left_count;
         }
-        if(left_count == 0)
+        if (left_count == 0)
             return;
     }
 }
 
+bool Parser::match_ellipsis()
+{
+    if (m_state.token_index > m_tokens.size() - 3)
+        return false;
+    return peek().type() == Token::Type::Dot && peek().type() == Token::Type::Dot && peek().type() == Token::Type::Dot;
+}
 
 }

+ 2 - 1
Userland/Libraries/LibCpp/Parser.h

@@ -111,7 +111,7 @@ private:
     Token consume(Token::Type);
     Token consume();
     Token consume_keyword(const String&);
-    Token peek() const;
+    Token peek(size_t offset = 0) const;
     Optional<Token> peek(Token::Type) const;
     Position position() const;
     StringView text_of_range(Position start, Position end) const;
@@ -163,6 +163,7 @@ private:
     Vector<StringView> parse_type_qualifiers();
     bool match_attribute_specification();
     void consume_attribute_specification();
+    bool match_ellipsis();
 };
 
 }