diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2014-12-05 16:09:53 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2014-12-05 16:09:53 +0100 |
commit | 30711f43a6cad9889ee1af8539658c4ca1f59854 (patch) | |
tree | d37c88faf794ad2632fc787ec1724c9ec08bdbd1 /src/plugins | |
parent | 30765a8bbf30aafad89a632afc39966c5b4029b8 (diff) |
Further work on implementing CSSRuleSets. This needs further testing, though.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/css/CSSParser.cpp | 66 | ||||
-rw-r--r-- | src/plugins/css/CSSParser.hpp | 32 |
2 files changed, 85 insertions, 13 deletions
diff --git a/src/plugins/css/CSSParser.cpp b/src/plugins/css/CSSParser.cpp index 85d8858..82ed7e1 100644 --- a/src/plugins/css/CSSParser.cpp +++ b/src/plugins/css/CSSParser.cpp @@ -64,12 +64,7 @@ static const TokenTreeNode CSS_ROOT{{{"{", CURLY_OPEN}, {"*/", COMMENT_CLOSE}, {"\"", DOUBLE_QUOTE}, {"\\", ESCAPE}, - // linux linebreak - {"\n", LINEBREAK}, - // windows linebreak - {"\r\n", LINEBREAK}, - // Mac OS linebreak - {"\r", LINEBREAK}}}; + {"\n", LINEBREAK}}}; static const std::map<int, CodeTokenDescriptor> CSS_DESCRIPTORS = { {COMMENT_OPEN, {CodeTokenMode::BLOCK_COMMENT_START, COMMENT}}, @@ -83,6 +78,7 @@ Rooted<Node> CSSParser::parse(std::istream &is, ParserContext &ctx) BufferedCharReader input{is}; CodeTokenizer tokenizer{input, CSS_ROOT, CSS_DESCRIPTORS}; tokenizer.ignoreComments = true; + tokenizer.ignoreLinebreaks = true; Rooted<SelectorNode> root = {new SelectorNode{ctx.manager, "root"}}; parseDocument(root, tokenizer, ctx); return root; @@ -97,16 +93,22 @@ void CSSParser::parseDocument(Rooted<SelectorNode> root, } tokenizer.resetPeek(); std::vector<Rooted<SelectorNode>> leafList; + // parse the SelectorTree for this ruleSet. parseSelectors(root, tokenizer, leafList, ctx); - // TODO: Parse Ruleset + // parse the RuleSet itself. + Rooted<RuleSet> ruleSet = parseRuleSet(tokenizer, ctx); for (auto &leaf : leafList) { - /* every leaf is an accepting node, if one considers the SelectorTree + /* + * every leaf is an accepting node, if one considers the SelectorTree * to be a finite state machine. This is relevant, if users do not use * the CSS Parser to parse actual Ruleset content but to construct a * SelectorTree just to identify a part of the DocumentTree. */ leaf->setAccepting(true); - //TODO: append RuleSets + /* + * similarly we append the found rules to all leafs. + */ + leaf->getRuleSet()->merge(ruleSet); } parseDocument(root, tokenizer, ctx); } @@ -289,7 +291,51 @@ Rooted<SelectorNode> CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, } } -// TODO: Add RuleSet parsing methods. +Rooted<RuleSet> CSSParser::parseRuleSet(CodeTokenizer &tokenizer, + ParserContext &ctx) +{ + Rooted<RuleSet> ruleSet{new RuleSet(ctx.manager)}; + // if we have no ruleset content, we return an empty ruleset. + Token t; + if (!expect(CURLY_OPEN, tokenizer, t, false, ctx)) { + return ruleSet; + } + // otherwise we parse the rules. + parseRules(tokenizer, ruleSet, ctx); + // and we expect closing curly braces. + expect(CURLY_CLOSE, tokenizer, t, true, ctx); + return ruleSet; +} + +void CSSParser::parseRules(CodeTokenizer &tokenizer, Rooted<RuleSet> ruleSet, + ParserContext &ctx) +{ + std::string key; + variant::Variant value; + while (parseRule(tokenizer, ctx, key, value)) { + ruleSet->getRules().insert({key, value}); + } +} + +bool CSSParser::parseRule(CodeTokenizer &tokenizer, ParserContext &ctx, + std::string &key, variant::Variant &value) +{ + Token t; + if (!expect(TOKEN_TEXT, tokenizer, t, false, ctx)) { + return false; + } + // if we find text that is the key first. + key = t.content; + // then we expect a : + 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()); + // and a ; + expect(SEMICOLON, tokenizer, t, true, ctx); + return true; +} bool CSSParser::expect(int expectedType, CodeTokenizer &tokenizer, Token &t, bool force, ParserContext &ctx) diff --git a/src/plugins/css/CSSParser.hpp b/src/plugins/css/CSSParser.hpp index eb51dfa..27a483d 100644 --- a/src/plugins/css/CSSParser.hpp +++ b/src/plugins/css/CSSParser.hpp @@ -89,7 +89,30 @@ private: Rooted<SelectorNode> parsePrimitiveSelector(CodeTokenizer &tokenizer, ParserContext &ctx); - // TODO: Add RuleSet parsing methods. + /** + * 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); + + /** + * Implements the RULES Nonterminal, which parses CSSRules inside a RuleSet. + */ + void parseRules(CodeTokenizer &tokenizer, Rooted<RuleSet> ruleSet, + ParserContext &ctx); + + /** + * Implements the RULE Nonterminal, which parses one single CSSRule. Key + * and value are stored in the input references. + * + * @param key is a (possibly empty) string reference for the key found. + * @param value is a (possibly empty) Variant reference for the value found. + * + * @return true if a rule was found. + */ + bool parseRule(CodeTokenizer &tokenizer, ParserContext &ctx, + std::string &key, variant::Variant &value); /** * A convenience function to wrap around the tokenizer peek() function that @@ -112,9 +135,12 @@ public: /** * This parses the given input as CSS content as specified by the grammar * seen above. The return value is a Rooted reference to the root of the - * SelectorTree. - * TODO: The RuleSet at the respective node at the tree lists all CSS Style + * SelectorTree. SelectorTrees are documented in detail in the CSS.hpp + * The RuleSet at the respective node at the tree lists all CSS Style * rules that apply. + * Note that you are not required to insert CSS code containing actual + * rules. You are permitted to just insert a CSS Selector expression + * specifying some part of a DocumentTree you want to refer to. * * @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 |