summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt22
-rw-r--r--src/core/BufferedCharReader.cpp2
-rw-r--r--src/core/BufferedCharReader.hpp6
-rw-r--r--src/core/parser/Parser.hpp14
-rw-r--r--src/core/parser/Scope.hpp7
-rw-r--r--src/core/variant/Reader.cpp14
-rw-r--r--src/core/variant/Reader.hpp54
-rw-r--r--src/plugins/css/CSSParser.cpp (renamed from src/core/CSSParser.cpp)122
-rw-r--r--src/plugins/css/CSSParser.hpp (renamed from src/core/CSSParser.hpp)44
-rw-r--r--test/core/LoggerTest.cpp16
-rw-r--r--test/plugins/css/CSSParserTest.cpp (renamed from test/core/CSSParserTest.cpp)20
11 files changed, 190 insertions, 131 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 922acfc..e9cc0da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -100,7 +100,6 @@ ADD_LIBRARY(ousia_core
src/core/BufferedCharReader
src/core/CodeTokenizer
src/core/CSS
- src/core/CSSParser
src/core/Exceptions
src/core/Logger
src/core/Managed
@@ -119,6 +118,14 @@ ADD_LIBRARY(ousia_core
src/core/variant/Variant
)
+ADD_LIBRARY(ousia_css
+ src/plugins/css/CSSParser
+)
+
+TARGET_LINK_LIBRARIES(ousia_css
+ ousia_core
+)
+
ADD_LIBRARY(ousia_xml
src/plugins/xml/XmlParser
)
@@ -147,8 +154,7 @@ IF(TEST)
ADD_EXECUTABLE(ousia_test_core
test/core/BufferedCharReaderTest
test/core/CodeTokenizerTest
-# test/core/CSSTest
-# test/core/CSSParserTest
+ test/core/CSSTest
test/core/LoggerTest
test/core/ManagedTest
test/core/ManagedContainersTest
@@ -169,6 +175,16 @@ IF(TEST)
ousia_core
)
+ ADD_EXECUTABLE(ousia_test_css
+ test/plugins/css/CSSParserTest
+ )
+
+ TARGET_LINK_LIBRARIES(ousia_test_css
+ ${GTEST_LIBRARIES}
+ ousia_core
+ ousia_css
+ )
+
ADD_EXECUTABLE(ousia_test_xml
test/plugins/xml/XmlParserTest
)
diff --git a/src/core/BufferedCharReader.cpp b/src/core/BufferedCharReader.cpp
index cf481df..23c219a 100644
--- a/src/core/BufferedCharReader.cpp
+++ b/src/core/BufferedCharReader.cpp
@@ -224,7 +224,7 @@ void BufferedCharReader::resetPeek()
peekCursor.assign(readCursor);
}
-bool BufferedCharReader::atEnd()
+bool BufferedCharReader::atEnd() const
{
if (depleted || !inputStream) {
if (buffer.size() <= 0) {
diff --git a/src/core/BufferedCharReader.hpp b/src/core/BufferedCharReader.hpp
index ec76b03..bd19d4a 100644
--- a/src/core/BufferedCharReader.hpp
+++ b/src/core/BufferedCharReader.hpp
@@ -252,21 +252,21 @@ public:
*
* @return true if there is no more data.
*/
- bool atEnd();
+ bool atEnd() const;
/**
* Returns the current line (starting with one).
*
* @return the current line number.
*/
- inline int getLine() { return readCursor.line; }
+ int getLine() const { return readCursor.line; }
/**
* Returns the current column (starting with one).
*
* @return the current column number.
*/
- inline int getColumn() { return readCursor.column; }
+ int getColumn() const { return readCursor.column; }
};
}
diff --git a/src/core/parser/Parser.hpp b/src/core/parser/Parser.hpp
index fa5dd49..5dac956 100644
--- a/src/core/parser/Parser.hpp
+++ b/src/core/parser/Parser.hpp
@@ -70,6 +70,10 @@ struct ParserContext {
* Reference to the Logger the parser should log any messages to.
*/
Logger &logger;
+ /**
+ * Reference to the Manager the parser should append nodes to.
+ */
+ Manager &manager;
/**
* Constructor of the ParserContext class.
@@ -81,9 +85,12 @@ struct ParserContext {
* implementations.
* @param logger is a reference to the Logger instance that should be used
* to log error messages and warnings that occur while parsing the document.
+ * @param manager is a Reference to the Manager the parser should append
+ *nodes to.
*/
- ParserContext(Scope &scope, Registry &registry, Logger &logger)
- : scope(scope), registry(registry), logger(logger){};
+ ParserContext(Scope &scope, Registry &registry, Logger &logger,
+ Manager &manager)
+ : scope(scope), registry(registry), logger(logger), manager(manager){};
};
struct StandaloneParserContext : public ParserContext {
@@ -91,10 +98,11 @@ private:
Logger logger;
Scope scope;
Registry registry;
+ Manager manager;
public:
StandaloneParserContext()
- : ParserContext(scope, registry, logger),
+ : ParserContext(scope, registry, logger, manager),
scope(nullptr),
registry(logger){};
};
diff --git a/src/core/parser/Scope.hpp b/src/core/parser/Scope.hpp
index 9c5504f..5b19b3d 100644
--- a/src/core/parser/Scope.hpp
+++ b/src/core/parser/Scope.hpp
@@ -55,7 +55,7 @@ public:
* Creates a new ScopedScope instance.
*
* @param scope is the backing Scope instance.
- * @param node is the Node instance that should be poped onto the stack of
+ * @param node is the Node instance that should be pushed onto the stack of
* the Scope instance.
*/
ScopedScope(Scope *scope, Handle<Node> node);
@@ -108,11 +108,6 @@ public:
Scope(Handle<Node> rootNode) { nodes.push_back(rootNode); }
/**
- * Returns a reference at the Manager instance all nodes belong to.
- */
- Manager &getManager() { return getRoot()->getManager(); }
-
- /**
* Pushes a new node onto the scope.
*
* @param node is the node that should be used for local lookup.
diff --git a/src/core/variant/Reader.cpp b/src/core/variant/Reader.cpp
index 6142ecf..e9a58a1 100644
--- a/src/core/variant/Reader.cpp
+++ b/src/core/variant/Reader.cpp
@@ -26,12 +26,17 @@
namespace ousia {
namespace variant {
+static const char *ERR_UNEXPECTED_CHARACTER = "Unexpected character";
+static const char *ERR_UNEXPECTED_END = "Unexpected end";
+static const char *ERR_UNTERMINATED = "Unterminated literal";
+
static const int STATE_INIT = 0;
static const int STATE_IN_STRING = 1;
static const int STATE_ESCAPE = 2;
static std::pair<Err, std::string> parseString(
- BufferedCharReader &reader, const unordered_set<char> *delims = nullptr)
+ BufferedCharReader &reader, const unordered_set<char> *delims = nullptr,
+ Logger *logger = nullptr)
{
// Initialize the internal state
Err errCode = Err::OK;
@@ -51,9 +56,13 @@ static std::pair<Err, std::string> parseString(
quote = c;
state = STATE_IN_STRING;
} else if (delims && delims.count(c)) {
+ Logger.log(ERR_UNTERMINATED, reader);
return std::make_pair(Err::UNEXPECTED_END, res.str());
+ } else if (Utils::isWhitespace(c)) {
+ reader.consumePeek();
+ continue;
}
- reader.consumePeek();
+ return std::make_pair(Err::UNEXPECTED_CHARACTER, res.str());
break;
case STATE_IN_STRING:
if (c == q) {
@@ -171,7 +180,6 @@ static std::pair<Err, Variant> parseGeneric(BufferedCharReader &reader,
}
return std::make_pair(Err::UNEXPECTED_END, res.str());
}
-
}
}
diff --git a/src/core/variant/Reader.hpp b/src/core/variant/Reader.hpp
index 3f945f0..339127f 100644
--- a/src/core/variant/Reader.hpp
+++ b/src/core/variant/Reader.hpp
@@ -32,6 +32,7 @@
#include <utility>
#include <core/BufferedCharReader.hpp>
+#include <core/Logger.hpp>
#include "Variant.hpp"
@@ -40,44 +41,6 @@ namespace variant {
class Reader {
public:
- // TODO: Pass logger instance instead of using error codes?
-
- /**
- * The Err enum describes possible error codes that may be encountered when
- * parsing the microtypes.
- */
- enum class Err : int {
- /**
- * Reached the end of the stream, but expected more data.
- */
- ERR_UNEXPECTED_END = -1,
-
- /**
- * The stream is malformed.
- */
- ERR_MALFORMED = -2,
-
- /**
- * Unexpected character.
- */
- ERR_UNEXPECTED_CHARACTER = -3,
-
- /**
- * Unterminated literal.
- */
- ERR_UNTERMINATED = -4,
-
- /**
- * Invalid escape character.
- */
- ERR_INVALID_ESCAPE = -5,
-
- /**
- * A value of the requested type was extracted successfully.
- */
- OK = 0
- };
-
/**
* Parses a string which may either be enclosed by " or ', unescapes
* entities in the string as specified for JavaScript.
@@ -91,9 +54,10 @@ public:
* outside). If nullptr is given, no delimiter is used and a complete string
* is read.
*/
- static std::pair<Err, std::string> parseString(
+ static std::pair<bool, std::string> parseString(
BufferedCharReader &reader,
- const unordered_set<char> *delims = nullptr);
+ const unordered_set<char> *delims = nullptr,
+ Logger *logger = nullptr);
/**
* Extracts an unescaped string from the given buffered char reader
@@ -106,8 +70,9 @@ public:
* @param delims is a set of characters which will terminate the string.
* These characters are not included in the result. May not be nullptr.
*/
- static std::pair<Err, std::string> parseUnescapedString(
- BufferedCharReader &reader, const unordered_set<char> *delims);
+ static std::pair<bool, std::string> parseUnescapedString(
+ BufferedCharReader &reader, const unordered_set<char> *delims,
+ Logger *logger = nullptr);
/**
* Tries to parse the most specific item from the given stream until one of
@@ -120,8 +85,9 @@ public:
* @param delims is a set of characters which will terminate the string.
* These characters are not included in the result. May not be nullptr.
*/
- static std::pair<Err, Variant> parseGeneric(
- BufferedCharReader &reader, const unordered_set<char> *delims);
+ static std::pair<bool, Variant> parseGeneric(
+ BufferedCharReader &reader, const unordered_set<char> *delims,
+ Logger *logger = nullptr);
};
}
}
diff --git a/src/core/CSSParser.cpp b/src/plugins/css/CSSParser.cpp
index b762844..22752dd 100644
--- a/src/core/CSSParser.cpp
+++ b/src/plugins/css/CSSParser.cpp
@@ -19,6 +19,8 @@
#include "CSSParser.hpp"
namespace ousia {
+namespace parser {
+namespace css {
// CSS code tokens
static const int CURLY_OPEN = 1;
@@ -76,19 +78,18 @@ static const std::map<int, CodeTokenDescriptor> CSS_DESCRIPTORS = {
{ESCAPE, {CodeTokenMode::ESCAPE, ESCAPE}},
{LINEBREAK, {CodeTokenMode::LINEBREAK, LINEBREAK}}};
-Rooted<SelectorNode> CSSParser::parse(BufferedCharReader &input)
+Rooted<Node> CSSParser::parse(std::istream &is, ParserContext &ctx)
{
+ BufferedCharReader input{is};
CodeTokenizer tokenizer{input, CSS_ROOT, CSS_DESCRIPTORS};
tokenizer.ignoreComments = true;
- // TODO: Is this the correct way to retrieve the Manager?
- Manager mgr;
- Rooted<SelectorNode> root = {new SelectorNode{mgr, "root"}};
- parseDocument(root, tokenizer);
+ Rooted<SelectorNode> root = {new SelectorNode{ctx.manager, "root"}};
+ parseDocument(root, tokenizer, ctx);
return root;
}
void CSSParser::parseDocument(Rooted<SelectorNode> root,
- CodeTokenizer &tokenizer)
+ CodeTokenizer &tokenizer, ParserContext &ctx)
{
Token t;
if (!tokenizer.peek(t)) {
@@ -96,16 +97,17 @@ void CSSParser::parseDocument(Rooted<SelectorNode> root,
}
tokenizer.resetPeek();
std::vector<Rooted<SelectorNode>> leafList;
- parseSelectors(root, tokenizer, leafList);
+ parseSelectors(root, tokenizer, leafList, ctx);
// TODO: Parse Ruleset
- parseDocument(root, tokenizer);
+ parseDocument(root, tokenizer, ctx);
}
void CSSParser::parseSelectors(Rooted<SelectorNode> root,
CodeTokenizer &tokenizer,
- std::vector<Rooted<SelectorNode>> &leafList)
+ std::vector<Rooted<SelectorNode>> &leafList,
+ ParserContext &ctx)
{
- auto tuple = parseSelector(tokenizer);
+ auto tuple = parseSelector(tokenizer, ctx);
// append the SelectorPath to the root node.
std::vector<Rooted<SelectorNode>> unmergedLeafs =
root->append(std::get<0>(tuple));
@@ -123,21 +125,30 @@ void CSSParser::parseSelectors(Rooted<SelectorNode> root,
case 2:
// as the parseSelector is supposed to parse only a SelectorPath
// there should not be more than one leaf.
+<<<<<<< HEAD:application/src/core/CSSParser.cpp
throw LoggableException{
"Internal Error: More than one leaf in SelectorPath!", true,
tokenizer.getInput()};
+=======
+ throw ParserException{
+ "Internal Error: More than one leaf in SelectorPath!", "",
+ // TODO: Line handling?
+ // tokenizer.getInput().getLine(),
+ // tokenizer.getInput().getColumn()
+ };
+>>>>>>> 8a4203636865b6edc380b731c68d3483ca110a27:application/src/plugins/css/CSSParser.cpp
}
// if we find a comma, we can proceed parsing selectors.
Token t;
- if (expect(COMMA, tokenizer, t, false)) {
- parseSelectors(root, tokenizer, leafList);
+ if (expect(COMMA, tokenizer, t, false, ctx)) {
+ parseSelectors(root, tokenizer, leafList, ctx);
}
}
std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
- CodeTokenizer &tokenizer)
+ CodeTokenizer &tokenizer, ParserContext &ctx)
{
- Rooted<SelectorNode> s = parsePrimitiveSelector(tokenizer);
+ Rooted<SelectorNode> s = parsePrimitiveSelector(tokenizer, ctx);
Token t;
if (!tokenizer.peek(t)) {
// if we are at the end the found selector is the immediate child as
@@ -150,12 +161,10 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
// relationship (A B)
tokenizer.resetPeek();
// so we parse the rest of the subsequent SelectorPath
- auto tuple = parseSelector(tokenizer);
+ auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
- // TODO: Is this the correct way to retrieve the Manager?
- Manager mgr;
- s->getEdges().push_back(
- new SelectorNode::SelectorEdge(mgr, std::get<0>(tuple)));
+ s->getEdges().push_back(new SelectorNode::SelectorEdge(
+ ctx.manager, std::get<0>(tuple)));
// and we return this node as well as the leaf.
return std::make_tuple(s, std::get<1>(tuple));
}
@@ -164,12 +173,11 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
// if we find an arrow there is a next token in a CHILD
// relationship (A > B)
// so we parse the rest of the subsequent SelectorPath
- auto tuple = parseSelector(tokenizer);
+ auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
- // TODO: Is this the correct way to retrieve the Manager?
- Manager mgr;
s->getEdges().push_back(new SelectorNode::SelectorEdge(
- mgr, std::get<0>(tuple), SelectionOperator::DIRECT_DESCENDANT));
+ ctx.manager, std::get<0>(tuple),
+ SelectionOperator::DIRECT_DESCENDANT));
// and we return this node as well as the leaf.
return std::make_tuple(s, std::get<1>(tuple));
}
@@ -180,17 +188,16 @@ std::tuple<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
}
}
-Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer)
+Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
+ ParserContext &ctx)
{
// first and foremost we expect a class name.
Token t;
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
const std::string name = t.content;
- // TODO: Is this the correct way to retrieve the Manager?
- Manager mgr;
if (!tokenizer.peek(t)) {
// if we are at the end, we just return this selector with its name.
- Rooted<SelectorNode> n{new SelectorNode(mgr, name)};
+ Rooted<SelectorNode> n{new SelectorNode(ctx.manager, name)};
return n;
}
@@ -200,33 +207,34 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer)
case DOUBLE_COLON:
// if we find a double colon we have a generative PseudoSelector.
isGenerative = true;
+ // this is supposed to fall through; no missing break.
case COLON: {
// if we find a colon we have a restrictive PseudoSelector.
tokenizer.consumePeek();
// get the PseudoSelector name.
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
const std::string pseudo_select_name = t.content;
// look for additional arguments.
- if (!expect(PAREN_OPEN, tokenizer, t, false)) {
+ if (!expect(PAREN_OPEN, tokenizer, t, false, ctx)) {
// if we don't have any, we return here.
Rooted<SelectorNode> n{new SelectorNode(
- mgr, name, {pseudo_select_name, isGenerative})};
+ ctx.manager, name, {pseudo_select_name, isGenerative})};
return n;
}
// parse the argument list.
std::vector<std::string> args;
// we require at least one argument, if parantheses are used
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
args.push_back(t.content);
- while (expect(COMMA, tokenizer, t, false)) {
+ while (expect(COMMA, tokenizer, t, false, ctx)) {
// as long as we find commas we expect new arguments.
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
args.push_back(t.content);
}
- expect(PAREN_CLOSE, tokenizer, t, true);
+ expect(PAREN_CLOSE, tokenizer, t, true, ctx);
// and we return with the finished Selector.
Rooted<SelectorNode> n{new SelectorNode(
- mgr, name, {pseudo_select_name, args, isGenerative})};
+ ctx.manager, name, {pseudo_select_name, args, isGenerative})};
return n;
}
case HASH: {
@@ -234,11 +242,11 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer)
// :has_id(id)
// so we expect an ID now.
Token t;
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
std::vector<std::string> args{t.content};
// and we return the finished Selector
Rooted<SelectorNode> n{
- new SelectorNode(mgr, name, {"has_id", args, false})};
+ new SelectorNode(ctx.manager, name, {"has_id", args, false})};
return n;
}
case BRACKET_OPEN: {
@@ -249,34 +257,34 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer)
// has_value [attribute_name="value"]
// in both cases the attribute name comes first.
Token t;
- expect(TOKEN_TEXT, tokenizer, t, true);
+ expect(TOKEN_TEXT, tokenizer, t, true, ctx);
std::vector<std::string> args{t.content};
- if (!expect(EQUALS, tokenizer, t, false)) {
+ if (!expect(EQUALS, tokenizer, t, false, ctx)) {
// if no equals sign follows we have a has_attribute
// PseudoSelector
// we expect a closing bracket.
- expect(BRACKET_CLOSE, tokenizer, t, true);
+ expect(BRACKET_CLOSE, tokenizer, t, true, ctx);
// and then we can return the result.
Rooted<SelectorNode> n{new SelectorNode(
- mgr, name, {"has_attribute", args, false})};
+ ctx.manager, name, {"has_attribute", args, false})};
return n;
} else {
// with an equals sign we have a has_value PseudoSelector and
// expect the value next.
- expect(STRING, tokenizer, t, true);
+ expect(STRING, tokenizer, t, true, ctx);
args.push_back(t.content);
// then we expect a closing bracket.
- expect(BRACKET_CLOSE, tokenizer, t, true);
+ expect(BRACKET_CLOSE, tokenizer, t, true, ctx);
// and then we can return the result.
- Rooted<SelectorNode> n{
- new SelectorNode(mgr, name, {"has_value", args, false})};
+ Rooted<SelectorNode> n{new SelectorNode(
+ ctx.manager, name, {"has_value", args, false})};
return n;
}
}
default:
// everything else is not part of the Selector anymore.
tokenizer.resetPeek();
- Rooted<SelectorNode> n{new SelectorNode(mgr, name)};
+ Rooted<SelectorNode> n{new SelectorNode(ctx.manager, name)};
return n;
}
}
@@ -284,17 +292,33 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer)
// TODO: Add RuleSet parsing methods.
bool CSSParser::expect(int expectedType, CodeTokenizer &tokenizer, Token &t,
- bool force)
+ bool force, ParserContext &ctx)
{
bool end = !tokenizer.peek(t);
if (end || t.tokenId != expectedType) {
if (force) {
if (end) {
+<<<<<<< HEAD:application/src/core/CSSParser.cpp
throw LoggableException{"Unexpected end of file!", true,
tokenizer.getInput()};
} else {
throw LoggableException{"Unexpected token!", true,
tokenizer.getInput()};
+=======
+ throw ParserException{
+ "Unexpected end of file!", "",
+ // TODO: Line handling?
+ // tokenizer.getInput().getLine(),
+ // tokenizer.getInput().getColumn()
+ };
+ } else {
+ throw ParserException{
+ "Unexpected token!", "",
+ // TODO: Line handling?
+ // tokenizer.getInput().getLine(),
+ // tokenizer.getInput().getColumn()
+ };
+>>>>>>> 8a4203636865b6edc380b731c68d3483ca110a27:application/src/plugins/css/CSSParser.cpp
}
} else {
tokenizer.resetPeek();
@@ -305,3 +329,5 @@ bool CSSParser::expect(int expectedType, CodeTokenizer &tokenizer, Token &t,
return true;
}
}
+}
+}
diff --git a/src/core/CSSParser.hpp b/src/plugins/css/CSSParser.hpp
index 7dfc872..eb51dfa 100644
--- a/src/core/CSSParser.hpp
+++ b/src/plugins/css/CSSParser.hpp
@@ -22,12 +22,14 @@
#include <vector>
#include <tuple>
-#include "BufferedCharReader.hpp"
-#include "CodeTokenizer.hpp"
-#include "CSS.hpp"
-#include "Exceptions.hpp"
+#include <core/BufferedCharReader.hpp>
+#include <core/CodeTokenizer.hpp>
+#include <core/CSS.hpp>
+#include <core/parser/Parser.hpp>
namespace ousia {
+namespace parser {
+namespace css {
/**
* This is a context free, recursive parser for a subset of the CSS3 language
@@ -57,32 +59,35 @@ namespace ousia {
*
* @author Benjamin Paassen - bpaassen@techfak.uni-bielefeld.de
*/
-class CSSParser {
+class CSSParser : public Parser {
private:
/**
* Implements the DOC Nonterminal
*/
- void parseDocument(Rooted<SelectorNode> root, CodeTokenizer &tokenizer);
+ void parseDocument(Rooted<SelectorNode> root, CodeTokenizer &tokenizer,
+ ParserContext &ctx);
/**
* Implements the SELECTORS Nonterminal and adds all leaf nodes of the
* resulting SelectorTree to the input leafList so that a parsed RuleSet can
* be inserted there.
*/
void parseSelectors(Rooted<SelectorNode> root, CodeTokenizer &tokenizer,
- std::vector<Rooted<SelectorNode>> &leafList);
+ std::vector<Rooted<SelectorNode>> &leafList,
+ ParserContext &ctx);
/**
* Implements the SELECT Nonterminal, which in effect parses a SelectorPath
* 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(
- CodeTokenizer &tokenizer);
+ CodeTokenizer &tokenizer, ParserContext &ctx);
/**
* Implements the SELECT' Nonterminal, which parses a single Selector with
* its PseudoSelector and returns it.
*/
- Rooted<SelectorNode> parsePrimitiveSelector(CodeTokenizer &tokenizer);
+ Rooted<SelectorNode> parsePrimitiveSelector(CodeTokenizer &tokenizer,
+ ParserContext &ctx);
// TODO: Add RuleSet parsing methods.
@@ -101,7 +106,7 @@ private:
* @return true iff a token of the expected type was found.
*/
bool expect(int expectedType, CodeTokenizer &tokenizer, Token &t,
- bool force);
+ bool force, ParserContext &ctx);
public:
/**
@@ -110,9 +115,26 @@ public:
* SelectorTree.
* TODO: The RuleSet at the respective node at the tree lists all CSS Style
* rules that apply.
+ *
+ * @param is is a reference to the input stream that should be parsed.
+ * @param ctx is a reference to the context that should be used while
+ * parsing the document.
+ * @return returns the root node of the resulting SelectorTree. For more
+ * information on the return conventions consult the Parser.hpp.
+ */
+ Rooted<Node> parse(std::istream &is, ParserContext &ctx) override;
+
+ /**
+ * As befits a class called CSSParser, this Parser parses CSS.
*/
- Rooted<SelectorNode> parse(BufferedCharReader &input);
+ std::set<std::string> mimetypes()
+ {
+ std::set<std::string> out{"text/css"};
+ return out;
+ }
};
}
+}
+}
#endif
diff --git a/test/core/LoggerTest.cpp b/test/core/LoggerTest.cpp
index b4549ed..0c333ce 100644
--- a/test/core/LoggerTest.cpp
+++ b/test/core/LoggerTest.cpp
@@ -26,7 +26,7 @@ namespace ousia {
struct Pos {
int line, column;
- Pos(int line, int column) : line(line), column(column) {};
+ Pos(int line, int column) : line(line), column(column){};
int getLine() const { return line; }
int getColumn() const { return column; }
};
@@ -52,13 +52,23 @@ TEST(TerminalLogger, log)
logger.fatalError("This is a test fatal error!", 10, 20);
try {
- throw LoggableException{"A fatal exception"};
+ throw LoggableException{"A fatal exception", true};
}
catch (const LoggableException &ex) {
logger.log(ex);
}
- logger.logAt(Severity::ERROR, "This is a positioned error", Pos(10, 20));
+ try {
+ throw LoggableException{"A fatal exception at position", true, Pos(10, 20)};
+ }
+ catch (const LoggableException &ex) {
+ logger.log(ex);
+ }
+
+ logger.logAt(Severity::ERROR, "This is a positioned log message",
+ Pos(10, 20));
+ logger.debugAt("This is a positioned debug message", Pos(10, 20));
+ logger.noteAt("This is a positioned log error", Pos(10, 20));
}
}
diff --git a/test/core/CSSParserTest.cpp b/test/plugins/css/CSSParserTest.cpp
index a717093..84d4893 100644
--- a/test/core/CSSParserTest.cpp
+++ b/test/plugins/css/CSSParserTest.cpp
@@ -18,14 +18,18 @@
#include <gtest/gtest.h>
-#include <core/CSSParser.hpp>
+#include <sstream>
+
+#include <plugins/css/CSSParser.hpp>
namespace ousia {
+namespace parser {
+namespace css {
TEST(CSSParser, testParseSelectors)
{
- // create a selector Tree as input.
- BufferedCharReader reader;
- reader.feed("A>B,A B:r, C#a A[bla=\"blub\"], A::g(4,2,3)");
+ // create a string describing a SelectorTree as input.
+ std::stringstream input;
+ input << "A>B,A B:r, C#a A[bla=\"blub\"], A::g(4,2,3)";
/* This should describe the tree:
* root_____
* | \ \
@@ -34,9 +38,12 @@ TEST(CSSParser, testParseSelectors)
* B B::r A[bla="blub"]
*/
+ // initialize an empty parser context.
+ StandaloneParserContext ctx;
+
// parse the input.
CSSParser instance;
- Rooted<SelectorNode> root = instance.parse(reader);
+ Rooted<SelectorNode> root = instance.parse(input, ctx).cast<SelectorNode>();
// we expect three children of the root node overall.
ASSERT_EQ(3, root->getEdges().size());
@@ -109,4 +116,5 @@ TEST(CSSParser, testParseSelectors)
ASSERT_EQ(0, Ag->getEdges().size());
}
}
-
+}
+}