Commits

David Mugnai committed 9919053

slam/parser: rule to parse an attributes list

  • Participants
  • Parent commits 93f24fb

Comments (0)

Files changed (2)

 #pragma once
 #define BOOST_RESULT_OF_USE_DECLTYPE
 #define BOOST_SPIRIT_USE_PHOENIX_V3
+#include <map>
 #include <string>
 #include <vector>
-#include <utility>
+#include <boost/fusion/include/std_pair.hpp>
 #include <boost/spirit/include/qi.hpp>
 #include <boost/spirit/include/phoenix.hpp>
 #include <boost/spirit/include/phoenix_fusion.hpp>
 #include <boost/spirit/include/phoenix_stl.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
 
-#include <boost/fusion/include/std_pair.hpp>
 #include "slam/ast.h"
 
 namespace slam { namespace parser {
     qi::rule<Iterator, Tag*()> tag;
     qi::rule<Iterator, int(int)> indent;
 
+    qi::rule<Iterator, std::map<string, string>(), qi::locals<char>> attributes_list;
     qi::rule<Iterator, std::pair<string, string>()> attribute;
     qi::rule<Iterator, string()> attribute_name;
     qi::rule<Iterator, string()> attribute_value;
         // matches at least _r1 spaces -> expose the number of matched spaces
         indent = (qi::repeat(_r1, qi::inf)[qi::blank])[_val = phx::size(_1)];
 
+        attributes_list =
+            qi::omit[qi::char_(" ({[")[_a = _1] | qi::eps[_a = 0]]
+            >> *attribute
+            >> qi::lit(_a);
         attribute = qi::skip(qi::space)[attribute_name >> "=" >> attribute_value];
         attribute_name = identifier.alias();
         attribute_value = quoted_string.alias();

tests/test_slam_parser.cpp

     EXPECT_EQ(result4, std::make_pair(string("class"), string("title selected")));
 }
 
+TEST_F(GrammarRuleTest, attributes) {
+    auto result1 = this->parse("class=\"title selected\"", grammar.attributes_list);
+    EXPECT_EQ(result1.size(), 1);
+    EXPECT_EQ(result1["class"], "title selected");
+
+    auto result2 = this->parse("id=\"page\" class=\"title selected\"", grammar.attributes_list);
+    EXPECT_EQ(result2.size(), 2);
+    EXPECT_EQ(result2["id"], "page");
+    EXPECT_EQ(result2["class"], "title selected");
+
+    auto result3 = this->parse("(class=\"title selected\")", grammar.attributes_list);
+    EXPECT_EQ(result3.size(), 1);
+    EXPECT_EQ(result3["class"], "title selected");
+
+    bool success;
+    this->parse("(class=\"title selected\"", grammar.attributes_list, &success);
+    EXPECT_EQ(success, false);
+}
+
 TEST(Parsing, just_one_tag) {
     auto result = static_cast<Tag*>(parse("html"));
     ASSERT_NE(result, nullptr);