diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-27 01:40:54 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-27 01:40:54 +0100 |
commit | ec7f4ee73430906bf53648eba427bfad353a7409 (patch) | |
tree | acd16dba92fa9702fa45c456a321b664de96c0c3 /src | |
parent | 84f0004cdf45f6fbad6461676897aa27f03cbb93 (diff) | |
parent | a95cf9c477f7259f04d3759acec40a4070ae2b31 (diff) |
Merge branch 'master' of somweyr.de:ousia
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/Main.cpp | 110 | ||||
-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.cpp | 87 | ||||
-rw-r--r-- | src/plugins/css/CSSParser.hpp | 24 |
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); /** |