summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-12-05 17:53:51 +0100
committerAndreas Stöckel <andreas@somweyr.de>2014-12-05 17:53:51 +0100
commitc5daa927663cb0eafa56495bded0d80b21d94e4d (patch)
tree9fd75d70b3d07d1e71aa6187ae20d266546f6fcc
parent2069538e089696eead64169895c935ff4bc577ba (diff)
parentb7c2dd440523948bebca54a91a4ba06451b473f0 (diff)
Merge branch 'master' of somweyr.de:ousia
-rw-r--r--src/core/CSS.cpp6
-rw-r--r--src/core/CSS.hpp9
-rw-r--r--src/core/Managed.cpp12
-rw-r--r--src/core/Managed.hpp2
-rw-r--r--src/core/Tokenizer.hpp2
-rw-r--r--src/plugins/css/CSSParser.cpp24
-rw-r--r--src/plugins/css/CSSParser.hpp4
-rw-r--r--test/core/ManagedTest.cpp42
-rw-r--r--test/plugins/css/CSSParserTest.cpp112
9 files changed, 165 insertions, 48 deletions
diff --git a/src/core/CSS.cpp b/src/core/CSS.cpp
index c3900e8..d131fec 100644
--- a/src/core/CSS.cpp
+++ b/src/core/CSS.cpp
@@ -20,6 +20,12 @@
namespace ousia {
+void RuleSet::merge(Rooted<RuleSet> other){
+ for(auto& o : other->rules){
+ rules[o.first] = o.second;
+ }
+}
+
/*
* different versions of "getChildren".
*/
diff --git a/src/core/CSS.hpp b/src/core/CSS.hpp
index 4cf15be..aa701b5 100644
--- a/src/core/CSS.hpp
+++ b/src/core/CSS.hpp
@@ -85,10 +85,11 @@ public:
return rules;
}
- void merge(Rooted<RuleSet> other)
- {
- rules.insert(other->rules.begin(), other->rules.end());
- }
+ /**
+ * This implements an overriding "insert all" of all rules in the other
+ * RuleSet to the rules in this RuleSet.
+ */
+ void merge(Rooted<RuleSet> other);
};
/**
diff --git a/src/core/Managed.cpp b/src/core/Managed.cpp
index 8cbbb17..f3a68a3 100644
--- a/src/core/Managed.cpp
+++ b/src/core/Managed.cpp
@@ -101,7 +101,7 @@ void ObjectDescriptor::incrDegree(RefDir dir, Managed *o)
}
// Fetch a reference to either the input or the output reference map
- auto &m = dir == RefDir::in ? refIn : refOut;
+ auto &m = dir == RefDir::IN ? refIn : refOut;
// Insert a new entry or increment the corresponding reference counter
auto it = m.find(o);
@@ -128,7 +128,7 @@ bool ObjectDescriptor::decrDegree(RefDir dir, Managed *o, bool all)
}
// Fetch a reference to either the input or the output reference map
- auto &m = dir == RefDir::in ? refIn : refOut;
+ auto &m = dir == RefDir::IN ? refIn : refOut;
// Decrement corresponding reference counter, delete the entry if the
// reference counter reaches zero
@@ -187,11 +187,11 @@ void Manager::addRef(Managed *tar, Managed *src)
// Store the tar <- src reference
assert(dTar);
- dTar->incrDegree(RefDir::in, src);
+ dTar->incrDegree(RefDir::IN, src);
if (src) {
// Store the src -> tar reference
assert(dSrc);
- dSrc->incrDegree(RefDir::out, tar);
+ dSrc->incrDegree(RefDir::OUT, tar);
} else {
// We have just added a root reference, remove the element from the
// list of marked objects
@@ -207,11 +207,11 @@ void Manager::deleteRef(Managed *tar, Managed *src, bool all)
// Decrement the output degree of the source Managed first
if (dSrc) {
- dSrc->decrDegree(RefDir::out, tar, all);
+ dSrc->decrDegree(RefDir::OUT, tar, all);
}
// Decrement the input degree of the input Managed
- if (dTar && dTar->decrDegree(RefDir::in, src, all)) {
+ if (dTar && dTar->decrDegree(RefDir::IN, src, all)) {
// If the Managed has a zero in degree, it can be safely deleted, otherwise
// if it has no root reference, add it to the "marked" set which is
// subject to tracing garbage collection
diff --git a/src/core/Managed.hpp b/src/core/Managed.hpp
index 6199e33..25fa14b 100644
--- a/src/core/Managed.hpp
+++ b/src/core/Managed.hpp
@@ -45,7 +45,7 @@ class Owned;
* Enum used to specify the direction of a object reference (inbound or
* outbound).
*/
-enum class RefDir { in, out };
+enum class RefDir { IN, OUT };
/**
* The ObjectDescriptor struct is used by the Manager for reference counting and
diff --git a/src/core/Tokenizer.hpp b/src/core/Tokenizer.hpp
index 4aebf56..8f80150 100644
--- a/src/core/Tokenizer.hpp
+++ b/src/core/Tokenizer.hpp
@@ -225,6 +225,8 @@ public:
void consumePeek();
const BufferedCharReader &getInput() const { return input; }
+
+ BufferedCharReader &getInput() { return input; }
};
}
diff --git a/src/plugins/css/CSSParser.cpp b/src/plugins/css/CSSParser.cpp
index 82ed7e1..51b2fd2 100644
--- a/src/plugins/css/CSSParser.cpp
+++ b/src/plugins/css/CSSParser.cpp
@@ -18,6 +18,8 @@
#include "CSSParser.hpp"
+#include <core/variant/Reader.hpp>
+
namespace ousia {
namespace parser {
namespace css {
@@ -121,13 +123,13 @@ void CSSParser::parseSelectors(Rooted<SelectorNode> root,
auto tuple = parseSelector(tokenizer, ctx);
// append the SelectorPath to the root node.
std::vector<Rooted<SelectorNode>> unmergedLeafs =
- root->append(std::get<0>(tuple));
+ root->append(tuple.first);
// append the leaf to the leafList.
switch (unmergedLeafs.size()) {
case 0:
// if the leaf could be merged we take the leaf reference from the
// parseSelector method.
- leafList.push_back(std::get<1>(tuple));
+ leafList.push_back(tuple.second);
break;
case 1:
// if the leaf could not be merged we take the existing leaf.
@@ -147,7 +149,7 @@ void CSSParser::parseSelectors(Rooted<SelectorNode> root,
}
}
-std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
+std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
CodeTokenizer &tokenizer, ParserContext &ctx)
{
Rooted<SelectorNode> s = parsePrimitiveSelector(tokenizer, ctx);
@@ -155,7 +157,7 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
if (!tokenizer.peek(t)) {
// if we are at the end the found selector is the immediate child as
// well as the leaf.
- return std::make_tuple(s, s);
+ return std::make_pair(s, s);
}
switch (t.tokenId) {
case TOKEN_TEXT: {
@@ -166,9 +168,9 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
s->getEdges().push_back(new SelectorNode::SelectorEdge(
- ctx.manager, std::get<0>(tuple)));
+ ctx.manager, tuple.first));
// and we return this node as well as the leaf.
- return std::make_tuple(s, std::get<1>(tuple));
+ return std::make_pair(s, tuple.second);
}
case ARROW: {
tokenizer.consumePeek();
@@ -178,15 +180,15 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
s->getEdges().push_back(new SelectorNode::SelectorEdge(
- ctx.manager, std::get<0>(tuple),
+ ctx.manager, tuple.first,
SelectionOperator::DIRECT_DESCENDANT));
// and we return this node as well as the leaf.
- return std::make_tuple(s, std::get<1>(tuple));
+ return std::make_pair(s, tuple.second);
}
default:
// everything else is not part of the SelectorPath anymore.
tokenizer.resetPeek();
- return std::make_tuple(s, s);
+ return std::make_pair(s, s);
}
}
@@ -330,8 +332,8 @@ bool CSSParser::parseRule(CodeTokenizer &tokenizer, ParserContext &ctx,
expect(COLON, tokenizer, t, true, ctx);
// then the value
// TODO: Resolve key for appropriate parsing function here.
- expect(STRING, tokenizer, t, true, ctx);
- value = variant::Variant(t.content.c_str());
+ value = variant::Reader::parseGeneric(tokenizer.getInput(), ctx.logger,
+ {';'}).second;
// and a ;
expect(SEMICOLON, tokenizer, t, true, ctx);
return true;
diff --git a/src/plugins/css/CSSParser.hpp b/src/plugins/css/CSSParser.hpp
index 27a483d..a4d8cdc 100644
--- a/src/plugins/css/CSSParser.hpp
+++ b/src/plugins/css/CSSParser.hpp
@@ -20,7 +20,7 @@
#define _OUSIA_CSS_PARSER_HPP_
#include <vector>
-#include <tuple>
+#include <utility>
#include <core/BufferedCharReader.hpp>
#include <core/CodeTokenizer.hpp>
@@ -79,7 +79,7 @@ private:
* of the SelectorTree and returns the beginning node of the path as first
* element as well as the leaf of the path as second tuple element.
*/
- std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> parseSelector(
+ std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> parseSelector(
CodeTokenizer &tokenizer, ParserContext &ctx);
/**
diff --git a/test/core/ManagedTest.cpp b/test/core/ManagedTest.cpp
index a52ba88..a4011f1 100644
--- a/test/core/ManagedTest.cpp
+++ b/test/core/ManagedTest.cpp
@@ -42,49 +42,49 @@ TEST(ObjectDescriptor, Degree)
ASSERT_EQ(0, nd.refIn.size());
ASSERT_EQ(0, nd.refInCount(n1));
- nd.incrDegree(RefDir::in, n1);
+ nd.incrDegree(RefDir::IN, n1);
ASSERT_EQ(1, nd.refInCount());
ASSERT_EQ(1, nd.refInCount(n1));
ASSERT_EQ(0, nd.refInCount(n2));
ASSERT_EQ(1, nd.refIn.size());
- nd.incrDegree(RefDir::in, n1);
+ nd.incrDegree(RefDir::IN, n1);
ASSERT_EQ(2, nd.refInCount());
ASSERT_EQ(2, nd.refInCount(n1));
ASSERT_EQ(0, nd.refInCount(n2));
ASSERT_EQ(1, nd.refIn.size());
- nd.incrDegree(RefDir::in, n2);
+ nd.incrDegree(RefDir::IN, n2);
ASSERT_EQ(3, nd.refInCount());
ASSERT_EQ(2, nd.refInCount(n1));
ASSERT_EQ(1, nd.refInCount(n2));
ASSERT_EQ(2, nd.refIn.size());
- nd.incrDegree(RefDir::in, nullptr);
+ nd.incrDegree(RefDir::IN, nullptr);
ASSERT_EQ(4, nd.refInCount());
ASSERT_EQ(2, nd.refInCount(n1));
ASSERT_EQ(1, nd.refInCount(n2));
ASSERT_EQ(2, nd.refIn.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::in, n1));
+ ASSERT_TRUE(nd.decrDegree(RefDir::IN, n1));
ASSERT_EQ(3, nd.refInCount());
ASSERT_EQ(1, nd.refInCount(n1));
ASSERT_EQ(1, nd.refInCount(n2));
ASSERT_EQ(2, nd.refIn.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::in, n1));
+ ASSERT_TRUE(nd.decrDegree(RefDir::IN, n1));
ASSERT_EQ(2, nd.refInCount());
ASSERT_EQ(0, nd.refInCount(n1));
ASSERT_EQ(1, nd.refInCount(n2));
ASSERT_EQ(1, nd.refIn.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::in, n2));
+ ASSERT_TRUE(nd.decrDegree(RefDir::IN, n2));
ASSERT_EQ(1, nd.refInCount());
ASSERT_EQ(0, nd.refInCount(n1));
ASSERT_EQ(0, nd.refInCount(n2));
ASSERT_EQ(0, nd.refIn.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::in, nullptr));
+ ASSERT_TRUE(nd.decrDegree(RefDir::IN, nullptr));
ASSERT_EQ(0, nd.refInCount());
ASSERT_EQ(0, nd.refInCount(n1));
ASSERT_EQ(0, nd.refInCount(n2));
@@ -94,49 +94,49 @@ TEST(ObjectDescriptor, Degree)
ASSERT_EQ(0, nd.refOut.size());
ASSERT_EQ(0, nd.refOutCount(n1));
- nd.incrDegree(RefDir::out, n1);
+ nd.incrDegree(RefDir::OUT, n1);
ASSERT_EQ(1, nd.refOutCount());
ASSERT_EQ(1, nd.refOutCount(n1));
ASSERT_EQ(0, nd.refOutCount(n2));
ASSERT_EQ(1, nd.refOut.size());
- nd.incrDegree(RefDir::out, n1);
+ nd.incrDegree(RefDir::OUT, n1);
ASSERT_EQ(2, nd.refOutCount());
ASSERT_EQ(2, nd.refOutCount(n1));
ASSERT_EQ(0, nd.refOutCount(n2));
ASSERT_EQ(1, nd.refOut.size());
- nd.incrDegree(RefDir::out, n2);
+ nd.incrDegree(RefDir::OUT, n2);
ASSERT_EQ(3, nd.refOutCount());
ASSERT_EQ(2, nd.refOutCount(n1));
ASSERT_EQ(1, nd.refOutCount(n2));
ASSERT_EQ(2, nd.refOut.size());
- nd.incrDegree(RefDir::out, nullptr);
+ nd.incrDegree(RefDir::OUT, nullptr);
ASSERT_EQ(3, nd.refOutCount());
ASSERT_EQ(2, nd.refOutCount(n1));
ASSERT_EQ(1, nd.refOutCount(n2));
ASSERT_EQ(2, nd.refOut.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::out, n1));
+ ASSERT_TRUE(nd.decrDegree(RefDir::OUT, n1));
ASSERT_EQ(2, nd.refOutCount());
ASSERT_EQ(1, nd.refOutCount(n1));
ASSERT_EQ(1, nd.refOutCount(n2));
ASSERT_EQ(2, nd.refOut.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::out, n1));
+ ASSERT_TRUE(nd.decrDegree(RefDir::OUT, n1));
ASSERT_EQ(1, nd.refOutCount());
ASSERT_EQ(0, nd.refOutCount(n1));
ASSERT_EQ(1, nd.refOutCount(n2));
ASSERT_EQ(1, nd.refOut.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::out, n2));
+ ASSERT_TRUE(nd.decrDegree(RefDir::OUT, n2));
ASSERT_EQ(0, nd.refOutCount());
ASSERT_EQ(0, nd.refOutCount(n1));
ASSERT_EQ(0, nd.refOutCount(n2));
ASSERT_EQ(0, nd.refOut.size());
- ASSERT_TRUE(nd.decrDegree(RefDir::out, nullptr));
+ ASSERT_TRUE(nd.decrDegree(RefDir::OUT, nullptr));
ASSERT_EQ(0, nd.refOutCount());
ASSERT_EQ(0, nd.refOutCount(n1));
ASSERT_EQ(0, nd.refOutCount(n2));
@@ -148,10 +148,10 @@ TEST(ObjectDescriptor, rootRefCount)
ObjectDescriptor nd;
ASSERT_EQ(0, nd.rootRefCount);
- nd.incrDegree(RefDir::in, nullptr);
+ nd.incrDegree(RefDir::IN, nullptr);
ASSERT_EQ(1, nd.rootRefCount);
- nd.incrDegree(RefDir::out, nullptr);
+ nd.incrDegree(RefDir::OUT, nullptr);
ASSERT_EQ(2, nd.rootRefCount);
ASSERT_EQ(2, nd.refInCount(nullptr));
@@ -159,13 +159,13 @@ TEST(ObjectDescriptor, rootRefCount)
ASSERT_EQ(0, nd.refOutCount(nullptr));
ASSERT_EQ(0, nd.refOutCount());
- ASSERT_TRUE(nd.decrDegree(RefDir::out, nullptr));
+ ASSERT_TRUE(nd.decrDegree(RefDir::OUT, nullptr));
ASSERT_EQ(1, nd.rootRefCount);
- ASSERT_TRUE(nd.decrDegree(RefDir::in, nullptr));
+ ASSERT_TRUE(nd.decrDegree(RefDir::IN, nullptr));
ASSERT_EQ(0, nd.rootRefCount);
- ASSERT_FALSE(nd.decrDegree(RefDir::in, nullptr));
+ ASSERT_FALSE(nd.decrDegree(RefDir::IN, nullptr));
ASSERT_EQ(0, nd.rootRefCount);
}
diff --git a/test/plugins/css/CSSParserTest.cpp b/test/plugins/css/CSSParserTest.cpp
index 8880fc5..8873673 100644
--- a/test/plugins/css/CSSParserTest.cpp
+++ b/test/plugins/css/CSSParserTest.cpp
@@ -59,6 +59,7 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(2, A->getEdges().size());
ASSERT_FALSE(A->isAccepting());
+ ASSERT_EQ(0, A->getRuleSet()->getRules().size());
{
// assert A > B
std::vector<Rooted<SelectorNode>> Achildren =
@@ -72,6 +73,7 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(0, B->getEdges().size());
ASSERT_TRUE(B->isAccepting());
+ ASSERT_EQ(0, B->getRuleSet()->getRules().size());
// assert A B:r
Achildren = A->getChildren(SelectionOperator::DESCENDANT, "B");
ASSERT_EQ(1, Achildren.size());
@@ -83,6 +85,7 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(0, Br->getEdges().size());
ASSERT_TRUE(Br->isAccepting());
+ ASSERT_EQ(0, Br->getRuleSet()->getRules().size());
}
// assert C#a
children = root->getChildren("C");
@@ -95,6 +98,7 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(1, C->getEdges().size());
ASSERT_FALSE(C->isAccepting());
+ ASSERT_EQ(0, C->getRuleSet()->getRules().size());
{
// assert C#a A[bla=\"blub\"]
std::vector<Rooted<SelectorNode>> Cchildren =
@@ -108,6 +112,7 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(0, A->getEdges().size());
ASSERT_TRUE(A->isAccepting());
+ ASSERT_EQ(0, A->getRuleSet()->getRules().size());
}
// assert A::g(4,2,3)
children = root->getChildren("A");
@@ -120,10 +125,12 @@ TEST(CSSParser, testParseSelectors)
}
ASSERT_EQ(0, Ag->getEdges().size());
ASSERT_TRUE(Ag->isAccepting());
+ ASSERT_EQ(0, Ag->getRuleSet()->getRules().size());
}
TEST(CSSParser, testParseCSS)
{
+
// create the CSS input
std::stringstream input;
input << "A, B A {\n";
@@ -140,18 +147,117 @@ TEST(CSSParser, testParseCSS)
input << "A {\n";
input << "\t ident1 : \"val4\";\n";
input << "}\n";
-
-
+
// initialize an empty parser context.
StandaloneParserContext ctx;
// parse the input.
CSSParser instance;
Rooted<SelectorNode> root = instance.parse(input, ctx).cast<SelectorNode>();
+
+ // we expect three children of the root node overall.
+ ASSERT_EQ(3, root->getEdges().size());
+ // get all "A" children, which should be two.
+ std::vector<Rooted<SelectorNode>> children = root->getChildren("A");
+ ASSERT_EQ(2, children.size());
+ // assert A
+ /*
+ * A {
+ * ident1 : "val1";
+ * ident2 : "val2";
+ * }
+ *
+ * and
+ *
+ * A {
+ * ident1 : "val4";
+ * }
+ *
+ * should be merged.
+ */
+ Rooted<SelectorNode> A = children[0];
+ ASSERT_EQ("A", A->getName());
+ {
+ PseudoSelector select{"true", false};
+ ASSERT_EQ(select, A->getPseudoSelector());
+ }
+ ASSERT_EQ(0, A->getEdges().size());
+ ASSERT_TRUE(A->isAccepting());
+ {
+ Rooted<RuleSet> ruleSet = A->getRuleSet();
+ ASSERT_EQ(2, ruleSet->getRules().size());
+ variant::Variant v = ruleSet->getRules()["ident1"];
+ ASSERT_EQ(variant::Variant::Type::STRING, v.getType());
+ ASSERT_EQ("val4", v.asString());
+ v = ruleSet->getRules()["ident2"];
+ ASSERT_EQ(variant::Variant::Type::STRING, v.getType());
+ ASSERT_EQ("val2", v.asString());
+ }
+ /*
+ * For this part of the SelectorTree we only have
+ *
+ * A:select(a,b) {
+ * ident3 : val3;
+ * }
+ */
+ Rooted<SelectorNode> Aselect = children[1];
+ ASSERT_EQ("A", Aselect->getName());
+ {
+ PseudoSelector select{"select",{"a","b"}, false};
+ ASSERT_EQ(select, Aselect->getPseudoSelector());
+ }
+ ASSERT_EQ(0, Aselect->getEdges().size());
+ ASSERT_TRUE(Aselect->isAccepting());
+ {
+ Rooted<RuleSet> ruleSet = Aselect->getRuleSet();
+ ASSERT_EQ(1, ruleSet->getRules().size());
+ variant::Variant v = ruleSet->getRules()["ident3"];
+ ASSERT_EQ(variant::Variant::Type::STRING, v.getType());
+ ASSERT_EQ("val3", v.asString());
+ }
+ /*
+ * The remaining part of the SelectorTree is
+ *
+ * B A {
+ * ident1 : val1;
+ * ident2 : val2;
+ * }
+ */
+ children = root->getChildren("B");
+ ASSERT_EQ(1, children.size());
+ Rooted<SelectorNode> B = children[0];
+ ASSERT_EQ("B", B->getName());
+ {
+ PseudoSelector select{"true", false};
+ ASSERT_EQ(select, B->getPseudoSelector());
+ }
+ ASSERT_EQ(1, B->getEdges().size());
+ ASSERT_FALSE(B->isAccepting());
+ ASSERT_EQ(0, B->getRuleSet()->getRules().size());
+
+ children = B->getChildren("A");
+ ASSERT_EQ(1, children.size());
+ Rooted<SelectorNode> BA = children[0];
+ ASSERT_EQ("A", BA->getName());
+ {
+ PseudoSelector select{"true", false};
+ ASSERT_EQ(select, BA->getPseudoSelector());
+ }
+ ASSERT_EQ(0, BA->getEdges().size());
+ ASSERT_TRUE(BA->isAccepting());
+ {
+ Rooted<RuleSet> ruleSet = BA->getRuleSet();
+ ASSERT_EQ(2, ruleSet->getRules().size());
+ variant::Variant v = ruleSet->getRules()["ident1"];
+ ASSERT_EQ(variant::Variant::Type::STRING, v.getType());
+ ASSERT_EQ("val1", v.asString());
+ v = ruleSet->getRules()["ident2"];
+ ASSERT_EQ(variant::Variant::Type::STRING, v.getType());
+ ASSERT_EQ("val2", v.asString());
+ }
}
-
}
}
}