summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-27 01:40:54 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-27 01:40:54 +0100
commitec7f4ee73430906bf53648eba427bfad353a7409 (patch)
treeacd16dba92fa9702fa45c456a321b664de96c0c3 /src
parent84f0004cdf45f6fbad6461676897aa27f03cbb93 (diff)
parenta95cf9c477f7259f04d3759acec40a4070ae2b31 (diff)
Merge branch 'master' of somweyr.de:ousia
Diffstat (limited to 'src')
-rw-r--r--src/cli/Main.cpp110
-rw-r--r--src/core/model/Style.cpp (renamed from src/core/CSS.cpp)4
-rw-r--r--src/core/model/Style.hpp (renamed from src/core/CSS.hpp)8
-rw-r--r--src/plugins/css/CSSParser.cpp87
-rw-r--r--src/plugins/css/CSSParser.hpp24
5 files changed, 177 insertions, 56 deletions
diff --git a/src/cli/Main.cpp b/src/cli/Main.cpp
new file mode 100644
index 0000000..73c46ba
--- /dev/null
+++ b/src/cli/Main.cpp
@@ -0,0 +1,110 @@
+/*
+ Ousía
+ Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file Main.cpp
+ *
+ * This file provides the command line interface for Ousia. More information
+ * on command line options can be found in the test.
+ *
+ * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de)
+ */
+#include <algorithm>
+#include <iostream>
+
+#include <boost/program_options.hpp>
+
+const size_t ERROR_IN_COMMAND_LINE = 1;
+const size_t SUCCESS = 0;
+const size_t ERROR_UNHANDLED_EXCEPTION = 2;
+
+namespace po = boost::program_options;
+
+int main(int argc, char **argv)
+{
+ // Program options
+ po::options_description desc("Options");
+ std::string inputPath;
+ std::string outputPath;
+ std::string format;
+ /*
+ * This is a rather strange access mechanism: add_options() returns an
+ * easy_init object that has overloaded the () operator to accept new
+ * initializations. Again: Rather strange syntax, but it works.
+ */
+ desc.add_options()("help", "Program help")(
+ "input,i", po::value<std::string>(&inputPath)->required(),
+ "The input document file name")(
+ "include,I", po::value<std::vector<std::string>>(),
+ "Include paths, where resources like the input document "
+ "or additional domains, typesystems, etc. might be "
+ "found.")(
+ "output,o", po::value<std::string>(&outputPath),
+ "The output file name. Per default the input file name will be used.")(
+ "format,F", po::value<std::string>(&format)->required(),
+ "The output format that shall be produced.");
+
+ po::variables_map vm;
+ try {
+ // try to read the values for each option to the variable map.
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+
+ // first check the help option.
+ if (vm.count("help")) {
+ std::cout
+ << "Ousia" << std::endl
+ << "Copyright (C) 2014 Benjamin Paassen, Andreas Stoeckel"
+ // write the program options description as generated by boost
+ << std::endl << desc << std::endl << std::endl;
+ return SUCCESS;
+ }
+
+ // only if the user did not want help to we use notify, which checks
+ // if all required options were given.
+ po::notify(vm);
+ }
+ catch (po::error &e) {
+ std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
+ std::cerr << desc << std::endl;
+ return ERROR_IN_COMMAND_LINE;
+ }
+
+ if(!vm.count("output")){
+ // TODO: Handle this better.
+ outputPath = inputPath;
+ if(outputPath.find(".oxd") != std::string::npos){
+ outputPath.erase(outputPath.end()-3, outputPath.end());
+ outputPath += format;
+ }
+ }
+
+ // TODO: Program logic.
+ std::cout << "input : " << vm["input"].as<std::string>() << std::endl;
+ std::cout << "output : " << outputPath << std::endl;
+ std::cout << "format : " << vm["format"].as<std::string>() << std::endl;
+ if(vm.count("include")){
+ std::vector<std::string> includes = vm["include"].as<std::vector<std::string>>();
+ std::cout << "includes : ";
+ for(auto& i : includes){
+ std::cout << i << ", ";
+ }
+ std::cout << std::endl;
+ }
+
+ return SUCCESS;
+}
diff --git a/src/core/CSS.cpp b/src/core/model/Style.cpp
index c42cf6c..b01b0c7 100644
--- a/src/core/CSS.cpp
+++ b/src/core/model/Style.cpp
@@ -16,9 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "CSS.hpp"
+#include "Style.hpp"
namespace ousia {
+namespace model {
void RuleSet::merge(Rooted<RuleSet> other){
for(auto& o : other->rules){
@@ -140,3 +141,4 @@ std::vector<Rooted<SelectorNode>> SelectorNode::append(Handle<SelectorNode> node
return append(new SelectorEdge{this->getManager(), node});
}
}
+}
diff --git a/src/core/CSS.hpp b/src/core/model/Style.hpp
index 75ac73f..673f51e 100644
--- a/src/core/CSS.hpp
+++ b/src/core/model/Style.hpp
@@ -17,12 +17,12 @@
*/
/**
- * @file CSS.hpp
+ * @file Style.hpp
* @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de)
*/
-#ifndef _OUSIA_CSS_HPP_
-#define _OUSIA_CSS_HPP_
+#ifndef _OUSIA_STYLE_HPP_
+#define _OUSIA_STYLE_HPP_
#include <map>
#include <vector>
@@ -33,6 +33,7 @@
#include <core/model/Node.hpp>
namespace ousia {
+namespace model {
/*
* The Specificity or Precedence of a CSS RuleSet, which decides which
@@ -402,4 +403,5 @@ public:
void setAccepting(bool accepting) { this->accepting = accepting; }
};
}
+}
#endif
diff --git a/src/plugins/css/CSSParser.cpp b/src/plugins/css/CSSParser.cpp
index cf92d32..40179bf 100644
--- a/src/plugins/css/CSSParser.cpp
+++ b/src/plugins/css/CSSParser.cpp
@@ -79,12 +79,13 @@ Rooted<Node> CSSParser::doParse(CharReader &reader, ParserContext &ctx)
CodeTokenizer tokenizer{reader, CSS_ROOT, CSS_DESCRIPTORS};
tokenizer.ignoreComments = true;
tokenizer.ignoreLinebreaks = true;
- Rooted<SelectorNode> root = {new SelectorNode{ctx.getManager(), "root"}};
+ Rooted<model::SelectorNode> root = {
+ new model::SelectorNode{ctx.getManager(), "root"}};
parseDocument(root, tokenizer, ctx);
return root;
}
-void CSSParser::parseDocument(Rooted<SelectorNode> root,
+void CSSParser::parseDocument(Rooted<model::SelectorNode> root,
CodeTokenizer &tokenizer, ParserContext &ctx)
{
Token t;
@@ -92,11 +93,11 @@ void CSSParser::parseDocument(Rooted<SelectorNode> root,
return;
}
tokenizer.resetPeek();
- std::vector<Rooted<SelectorNode>> leafList;
+ std::vector<Rooted<model::SelectorNode>> leafList;
// parse the SelectorTree for this ruleSet.
parseSelectors(root, tokenizer, leafList, ctx);
// parse the RuleSet itself.
- Rooted<RuleSet> ruleSet = parseRuleSet(tokenizer, ctx);
+ Rooted<model::RuleSet> ruleSet = parseRuleSet(tokenizer, ctx);
for (auto &leaf : leafList) {
/*
* every leaf is an accepting node, if one considers the SelectorTree
@@ -113,14 +114,14 @@ void CSSParser::parseDocument(Rooted<SelectorNode> root,
parseDocument(root, tokenizer, ctx);
}
-void CSSParser::parseSelectors(Rooted<SelectorNode> root,
- CodeTokenizer &tokenizer,
- std::vector<Rooted<SelectorNode>> &leafList,
- ParserContext &ctx)
+void CSSParser::parseSelectors(
+ Rooted<model::SelectorNode> root, CodeTokenizer &tokenizer,
+ std::vector<Rooted<model::SelectorNode>> &leafList, ParserContext &ctx)
{
auto tuple = parseSelector(tokenizer, ctx);
// append the SelectorPath to the root node.
- std::vector<Rooted<SelectorNode>> unmergedLeafs = root->append(tuple.first);
+ std::vector<Rooted<model::SelectorNode>> unmergedLeafs =
+ root->append(tuple.first);
// append the leaf to the leafList.
switch (unmergedLeafs.size()) {
case 0:
@@ -146,10 +147,10 @@ void CSSParser::parseSelectors(Rooted<SelectorNode> root,
}
}
-std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
- CodeTokenizer &tokenizer, ParserContext &ctx)
+std::pair<Rooted<model::SelectorNode>, Rooted<model::SelectorNode>>
+CSSParser::parseSelector(CodeTokenizer &tokenizer, ParserContext &ctx)
{
- Rooted<SelectorNode> s = parsePrimitiveSelector(tokenizer, ctx);
+ Rooted<model::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
@@ -164,8 +165,8 @@ std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
// so we parse the rest of the subsequent SelectorPath
auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
- s->getEdges().push_back(
- new SelectorNode::SelectorEdge(ctx.getManager(), tuple.first));
+ s->getEdges().push_back(new model::SelectorNode::SelectorEdge(
+ ctx.getManager(), tuple.first));
// and we return this node as well as the leaf.
return std::make_pair(s, tuple.second);
}
@@ -176,9 +177,9 @@ std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
// so we parse the rest of the subsequent SelectorPath
auto tuple = parseSelector(tokenizer, ctx);
// then we establish the DESCENDANT relationship
- s->getEdges().push_back(new SelectorNode::SelectorEdge(
+ s->getEdges().push_back(new model::SelectorNode::SelectorEdge(
ctx.getManager(), tuple.first,
- SelectionOperator::DIRECT_DESCENDANT));
+ model::SelectionOperator::DIRECT_DESCENDANT));
// and we return this node as well as the leaf.
return std::make_pair(s, tuple.second);
}
@@ -189,8 +190,8 @@ std::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> CSSParser::parseSelector(
}
}
-Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
- ParserContext &ctx)
+Rooted<model::SelectorNode> CSSParser::parsePrimitiveSelector(
+ CodeTokenizer &tokenizer, ParserContext &ctx)
{
// first and foremost we expect a class name.
Token t;
@@ -198,7 +199,8 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
const std::string name = t.content;
if (!tokenizer.peek(t)) {
// if we are at the end, we just return this selector with its name.
- Rooted<SelectorNode> n{new SelectorNode(ctx.getManager(), name)};
+ Rooted<model::SelectorNode> n{
+ new model::SelectorNode(ctx.getManager(), name)};
return n;
}
@@ -218,8 +220,9 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
// look for additional arguments.
if (!expect(PAREN_OPEN, tokenizer, t, false, ctx)) {
// if we don't have any, we return here.
- Rooted<SelectorNode> n{new SelectorNode(
- ctx.getManager(), name, {pseudo_select_name, isGenerative})};
+ Rooted<model::SelectorNode> n{
+ new model::SelectorNode(ctx.getManager(), name,
+ {pseudo_select_name, isGenerative})};
return n;
}
// parse the argument list.
@@ -227,18 +230,19 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
// we require at least one argument, if parantheses are used
// XXX
args.push_back(VariantReader::parseGeneric(tokenizer.getInput(),
- ctx.getLogger(),
- {',', ')'}).second);
+ ctx.getLogger(),
+ {',', ')'}).second);
while (expect(COMMA, tokenizer, t, false, ctx)) {
// as long as we find commas we expect new arguments.
- args.push_back(
- VariantReader::parseGeneric(
- tokenizer.getInput(), ctx.getLogger(), {',', ')'}).second);
+ args.push_back(VariantReader::parseGeneric(tokenizer.getInput(),
+ ctx.getLogger(),
+ {',', ')'}).second);
}
expect(PAREN_CLOSE, tokenizer, t, true, ctx);
// and we return with the finished Selector.
- Rooted<SelectorNode> n{new SelectorNode(
- ctx.getManager(), name, {pseudo_select_name, args, isGenerative})};
+ Rooted<model::SelectorNode> n{
+ new model::SelectorNode(ctx.getManager(), name,
+ {pseudo_select_name, args, isGenerative})};
return n;
}
case HASH: {
@@ -249,8 +253,8 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
expect(TOKEN_TEXT, tokenizer, t, true, ctx);
Variant::arrayType args{Variant(t.content.c_str())};
// and we return the finished Selector
- Rooted<SelectorNode> n{
- new SelectorNode(ctx.getManager(), name, {"has_id", args, false})};
+ Rooted<model::SelectorNode> n{new model::SelectorNode(
+ ctx.getManager(), name, {"has_id", args, false})};
return n;
}
case BRACKET_OPEN: {
@@ -269,7 +273,7 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
// we expect a closing bracket.
expect(BRACKET_CLOSE, tokenizer, t, true, ctx);
// and then we can return the result.
- Rooted<SelectorNode> n{new SelectorNode(
+ Rooted<model::SelectorNode> n{new model::SelectorNode(
ctx.getManager(), name, {"has_attribute", args, false})};
return n;
} else {
@@ -280,7 +284,7 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
// then we expect a closing bracket.
expect(BRACKET_CLOSE, tokenizer, t, true, ctx);
// and then we can return the result.
- Rooted<SelectorNode> n{new SelectorNode(
+ Rooted<model::SelectorNode> n{new model::SelectorNode(
ctx.getManager(), name, {"has_value", args, false})};
return n;
}
@@ -288,15 +292,16 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer,
default:
// everything else is not part of the Selector anymore.
tokenizer.resetPeek();
- Rooted<SelectorNode> n{new SelectorNode(ctx.getManager(), name)};
+ Rooted<model::SelectorNode> n{
+ new model::SelectorNode(ctx.getManager(), name)};
return n;
}
}
-Rooted<RuleSet> CSSParser::parseRuleSet(CodeTokenizer &tokenizer,
- ParserContext &ctx)
+Rooted<model::RuleSet> CSSParser::parseRuleSet(CodeTokenizer &tokenizer,
+ ParserContext &ctx)
{
- Rooted<RuleSet> ruleSet{new RuleSet(ctx.getManager())};
+ Rooted<model::RuleSet> ruleSet{new model::RuleSet(ctx.getManager())};
// if we have no ruleset content, we return an empty ruleset.
Token t;
if (!expect(CURLY_OPEN, tokenizer, t, false, ctx)) {
@@ -309,8 +314,8 @@ Rooted<RuleSet> CSSParser::parseRuleSet(CodeTokenizer &tokenizer,
return ruleSet;
}
-void CSSParser::parseRules(CodeTokenizer &tokenizer, Rooted<RuleSet> ruleSet,
- ParserContext &ctx)
+void CSSParser::parseRules(CodeTokenizer &tokenizer,
+ Rooted<model::RuleSet> ruleSet, ParserContext &ctx)
{
std::string key;
Variant value;
@@ -333,7 +338,7 @@ bool CSSParser::parseRule(CodeTokenizer &tokenizer, ParserContext &ctx,
// then the value
// TODO: Resolve key for appropriate parsing function here.
value = VariantReader::parseGeneric(tokenizer.getInput(), ctx.getLogger(),
- {';'}).second;
+ {';'}).second;
// and a ;
expect(SEMICOLON, tokenizer, t, true, ctx);
return true;
@@ -347,10 +352,10 @@ bool CSSParser::expect(int expectedType, CodeTokenizer &tokenizer, Token &t,
if (force) {
if (end) {
throw LoggableException{"Unexpected end of file!",
- tokenizer.getInput()};
+ tokenizer.getInput()};
} else {
throw LoggableException{"Unexpected token!",
- tokenizer.getInput()};
+ tokenizer.getInput()};
}
} else {
tokenizer.resetPeek();
diff --git a/src/plugins/css/CSSParser.hpp b/src/plugins/css/CSSParser.hpp
index c6594f6..2f37e6a 100644
--- a/src/plugins/css/CSSParser.hpp
+++ b/src/plugins/css/CSSParser.hpp
@@ -32,8 +32,8 @@
#include <utility>
#include <core/CodeTokenizer.hpp>
-#include <core/CSS.hpp>
#include <core/common/CharReader.hpp>
+#include <core/model/Style.hpp>
#include <core/parser/Parser.hpp>
namespace ousia {
@@ -71,42 +71,44 @@ private:
/**
* Implements the DOC Nonterminal
*/
- void parseDocument(Rooted<SelectorNode> root, CodeTokenizer &tokenizer,
- ParserContext &ctx);
+ void parseDocument(Rooted<model::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,
+ void parseSelectors(Rooted<model::SelectorNode> root,
+ CodeTokenizer &tokenizer,
+ std::vector<Rooted<model::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::pair<Rooted<SelectorNode>, Rooted<SelectorNode>> parseSelector(
- CodeTokenizer &tokenizer, ParserContext &ctx);
+ std::pair<Rooted<model::SelectorNode>, Rooted<model::SelectorNode>>
+ parseSelector(CodeTokenizer &tokenizer, ParserContext &ctx);
/**
* Implements the SELECT' Nonterminal, which parses a single Selector with
* its PseudoSelector and returns it.
*/
- Rooted<SelectorNode> parsePrimitiveSelector(CodeTokenizer &tokenizer,
- ParserContext &ctx);
+ Rooted<model::SelectorNode> parsePrimitiveSelector(CodeTokenizer &tokenizer,
+ ParserContext &ctx);
/**
* Implements the RULESET Nonterminal, which parses an entire RuleSet. Note
* that we do not require RuleSets to be parsed. It is permitted to just
* insert Selector expressions.
*/
- Rooted<RuleSet> parseRuleSet(CodeTokenizer &tokenizer, ParserContext &ctx);
+ Rooted<model::RuleSet> parseRuleSet(CodeTokenizer &tokenizer,
+ ParserContext &ctx);
/**
* Implements the RULES Nonterminal, which parses CSSRules inside a RuleSet.
*/
- void parseRules(CodeTokenizer &tokenizer, Rooted<RuleSet> ruleSet,
+ void parseRules(CodeTokenizer &tokenizer, Rooted<model::RuleSet> ruleSet,
ParserContext &ctx);
/**