summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2008-08-05 18:48:09 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2008-08-05 18:48:09 +0000
commit99a2e8f808a83eb80925b5e88fc1438883be05d7 (patch)
tree7b37a76122bc7f798f0d6daa68887283382d9417
parent1560847dc040a0bfc90da892cb327001b1a39765 (diff)
downloadlibcss-99a2e8f808a83eb80925b5e88fc1438883be05d7.tar.gz
libcss-99a2e8f808a83eb80925b5e88fc1438883be05d7.tar.bz2
Make selector token vector be associated with the ruleset, rather than having its own event type.
Store details about the current construct on the context stack. Document block-content, selector, and declaration stuff. svn path=/trunk/libcss/; revision=4921
-rw-r--r--src/parse/css21.c121
-rw-r--r--src/parse/parse.c58
-rw-r--r--src/parse/parse.h1
-rw-r--r--test/data/css/simple.css2
4 files changed, 98 insertions, 84 deletions
diff --git a/src/parse/css21.c b/src/parse/css21.c
index 2dafe89..40a728b 100644
--- a/src/parse/css21.c
+++ b/src/parse/css21.c
@@ -33,6 +33,11 @@ static struct {
{ "page", SLEN("page") },
};
+typedef struct context_entry {
+ css_parser_event type; /**< Type of entry */
+ const uint8_t *data; /**< Pointer to interned string */
+} context_entry;
+
/**
* Context for a CSS 2.1 parser
*/
@@ -103,13 +108,14 @@ css_css21 *css_css21_create(css_stylesheet *sheet, css_parser *parser,
if (css21 == NULL)
return NULL;
- css21->context = parserutils_stack_create(sizeof(css_parser_event),
+ css21->context = parserutils_stack_create(sizeof(context_entry),
STACK_CHUNK, (parserutils_alloc) alloc, pw);
if (css21->context == NULL) {
alloc(css21, 0, pw);
return NULL;
}
+ /* Intern all known strings */
for (int i = 0; i < LAST_KNOWN; i++) {
css21->strings[i] = css_parser_dict_add(parser,
(const uint8_t *) stringmap[i].ptr,
@@ -187,8 +193,6 @@ css_error css21_handle_event(css_parser_event type,
return handleEndBlock(css21, tokens);
case CSS_PARSER_BLOCK_CONTENT:
return handleBlockContent(css21, tokens);
- case CSS_PARSER_SELECTOR:
- return handleSelector(css21, tokens);
case CSS_PARSER_DECLARATION:
return handleDeclaration(css21, tokens);
}
@@ -203,13 +207,13 @@ css_error css21_handle_event(css_parser_event type,
css_error handleStartStylesheet(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event type = CSS_PARSER_START_STYLESHEET;
+ context_entry entry = { CSS_PARSER_START_STYLESHEET, NULL };
UNUSED(vector);
assert(c != NULL);
- perror = parserutils_stack_push(c->context, (void *) &type);
+ perror = parserutils_stack_push(c->context, (void *) &entry);
if (perror != PARSERUTILS_OK) {
return css_error_from_parserutils_error(perror);
}
@@ -220,14 +224,14 @@ css_error handleStartStylesheet(css_css21 *c, const parserutils_vector *vector)
css_error handleEndStylesheet(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event *type;
+ context_entry *entry;
UNUSED(vector);
assert(c != NULL);
- type = parserutils_stack_get_current(c->context);
- if (type == NULL || *type != CSS_PARSER_START_STYLESHEET)
+ entry = parserutils_stack_get_current(c->context);
+ if (entry == NULL || entry->type != CSS_PARSER_START_STYLESHEET)
return CSS_INVALID;
perror = parserutils_stack_pop(c->context, NULL);
@@ -241,13 +245,16 @@ css_error handleEndStylesheet(css_css21 *c, const parserutils_vector *vector)
css_error handleStartRuleset(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event type = CSS_PARSER_START_RULESET;
-
- UNUSED(vector);
+ css_error error;
+ context_entry entry = { CSS_PARSER_START_RULESET, NULL };
assert(c != NULL);
- perror = parserutils_stack_push(c->context, (void *) &type);
+ error = handleSelector(c, vector);
+ if (error != CSS_OK)
+ return error;
+
+ perror = parserutils_stack_push(c->context, (void *) &entry);
if (perror != PARSERUTILS_OK) {
return css_error_from_parserutils_error(perror);
}
@@ -258,14 +265,14 @@ css_error handleStartRuleset(css_css21 *c, const parserutils_vector *vector)
css_error handleEndRuleset(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event *type;
+ context_entry *entry;
UNUSED(vector);
assert(c != NULL);
- type = parserutils_stack_get_current(c->context);
- if (type == NULL || *type != CSS_PARSER_START_RULESET)
+ entry = parserutils_stack_get_current(c->context);
+ if (entry == NULL || entry->type != CSS_PARSER_START_RULESET)
return CSS_INVALID;
perror = parserutils_stack_pop(c->context, NULL);
@@ -279,17 +286,12 @@ css_error handleEndRuleset(css_css21 *c, const parserutils_vector *vector)
css_error handleStartAtRule(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event type = CSS_PARSER_START_ATRULE;
+ context_entry entry = { CSS_PARSER_START_ATRULE, NULL };
UNUSED(vector);
assert(c != NULL);
- perror = parserutils_stack_push(c->context, (void *) &type);
- if (perror != PARSERUTILS_OK) {
- return css_error_from_parserutils_error(perror);
- }
-
/* vector contains: ATKEYWORD ws any0 */
const css_token *token = NULL;
const css_token *atkeyword = NULL;
@@ -331,7 +333,7 @@ css_error handleStartAtRule(css_css21 *c, const parserutils_vector *vector)
} else {
return CSS_INVALID;
}
- } else if (atkeyword->data.ptr == c->strings[IMPORT]) {
+ } else if (atkeyword->lower.ptr == c->strings[IMPORT]) {
if (c->state != HAD_RULE) {
/* any0 = (STRING | URI) ws
* (IDENT ws (',' ws IDENT ws)* )? */
@@ -359,28 +361,35 @@ css_error handleStartAtRule(css_css21 *c, const parserutils_vector *vector)
} else {
return CSS_INVALID;
}
- } else if (atkeyword->data.ptr == c->strings[MEDIA]) {
+ } else if (atkeyword->lower.ptr == c->strings[MEDIA]) {
/** \todo any0 = IDENT ws (',' ws IDENT ws)* */
- } else if (atkeyword->data.ptr == c->strings[PAGE]) {
+ } else if (atkeyword->lower.ptr == c->strings[PAGE]) {
/** \todo any0 = (':' IDENT)? ws */
} else {
return CSS_INVALID;
}
+ entry.data = atkeyword->lower.ptr;
+
+ perror = parserutils_stack_push(c->context, (void *) &entry);
+ if (perror != PARSERUTILS_OK) {
+ return css_error_from_parserutils_error(perror);
+ }
+
return CSS_OK;
}
css_error handleEndAtRule(css_css21 *c, const parserutils_vector *vector)
{
parserutils_error perror;
- css_parser_event *type;
+ context_entry *entry;
UNUSED(vector);
assert(c != NULL);
- type = parserutils_stack_get_current(c->context);
- if (type == NULL || *type != CSS_PARSER_START_ATRULE)
+ entry = parserutils_stack_get_current(c->context);
+ if (entry == NULL || entry->type != CSS_PARSER_START_ATRULE)
return CSS_INVALID;
perror = parserutils_stack_pop(c->context, NULL);
@@ -393,38 +402,22 @@ css_error handleEndAtRule(css_css21 *c, const parserutils_vector *vector)
css_error handleStartBlock(css_css21 *c, const parserutils_vector *vector)
{
- parserutils_error perror;
- css_parser_event type = CSS_PARSER_START_BLOCK;
-
+ UNUSED(c);
UNUSED(vector);
- assert(c != NULL);
-
- perror = parserutils_stack_push(c->context, (void *) &type);
- if (perror != PARSERUTILS_OK) {
- return css_error_from_parserutils_error(perror);
- }
+ /* We don't care about blocks. In CSS2.1 they're always attached to
+ * rulesets or at-rules. */
return CSS_OK;
}
css_error handleEndBlock(css_css21 *c, const parserutils_vector *vector)
{
- parserutils_error perror;
- css_parser_event *type;
-
+ UNUSED(c);
UNUSED(vector);
- assert(c != NULL);
-
- type = parserutils_stack_get_current(c->context);
- if (type == NULL || *type != CSS_PARSER_START_BLOCK)
- return CSS_INVALID;
-
- perror = parserutils_stack_pop(c->context, NULL);
- if (perror != PARSERUTILS_OK) {
- return css_error_from_parserutils_error(perror);
- }
+ /* We don't care about blocks. In CSS 2.1 they're always attached to
+ * rulesets or at-rules. */
return CSS_OK;
}
@@ -434,6 +427,10 @@ css_error handleBlockContent(css_css21 *c, const parserutils_vector *vector)
UNUSED(c);
UNUSED(vector);
+ /* In CSS 2.1, block content comprises either declarations (if the
+ * current block is associated with @page or a selector), or rulesets
+ * (if the current block is associated with @media). */
+
return CSS_OK;
}
@@ -442,6 +439,21 @@ css_error handleSelector(css_css21 *c, const parserutils_vector *vector)
UNUSED(c);
UNUSED(vector);
+ /* CSS 2.1 selector syntax:
+ *
+ * selector_list -> selector [ ',' ws selector ]*
+ * selector -> simple_selector [ combinator simple_selector ]*
+ * simple_selector -> element_name [ HASH | class | attrib | pseudo ]*
+ * -> [ HASH | class | attrib | pseudo ]+
+ * combinator -> '+' ws | '>' ws | ws1
+ * element_name -> IDENT | '*'
+ * class -> '.' IDENT
+ * attrib -> '[' ws IDENT ws [
+ * [ '=' | INCLUDES | DASHMATCH ] ws
+ * [ IDENT | STRING ] ws ]? ']'
+ * pseudo -> ':' [ IDENT | FUNCTION ws IDENT? ws ')' ]
+ */
+
return CSS_OK;
}
@@ -450,6 +462,17 @@ css_error handleDeclaration(css_css21 *c, const parserutils_vector *vector)
UNUSED(c);
UNUSED(vector);
+ /* Locations where declarations are permitted:
+ *
+ * + In @page
+ * + In ruleset
+ */
+
+ /* IDENT ws ':' ws value
+ *
+ * In CSS 2.1, value is any1, so '{' or ATKEYWORD => parse error
+ */
+
return CSS_OK;
}
diff --git a/src/parse/parse.c b/src/parse/parse.c
index 1095c26..aa9fd1f 100644
--- a/src/parse/parse.c
+++ b/src/parse/parse.c
@@ -833,14 +833,6 @@ css_error parseRuleset(css_parser *parser)
switch (state->substate) {
case Initial:
-#if !defined(NDEBUG) && defined(DEBUG_EVENTS)
- printf("Begin ruleset\n");
-#endif
- if (parser->event != NULL) {
- parser->event(CSS_PARSER_START_RULESET, NULL,
- parser->event_pw);
- }
-
parserutils_vector_clear(parser->tokens);
error = getToken(parser, &token);
@@ -852,6 +844,20 @@ css_error parseRuleset(css_parser *parser)
* however. */
if (token->type == CSS_TOKEN_CHAR && token->lower.len == 1 &&
token->lower.ptr[0] == '{') {
+#if !defined(NDEBUG) && defined(DEBUG_EVENTS)
+ printf("Begin ruleset\n");
+#endif
+ if (parser->event != NULL) {
+ if (parser->event(CSS_PARSER_START_RULESET,
+ NULL, parser->event_pw) ==
+ CSS_INVALID) {
+ parser_state to =
+ { sMalformedSelector, Initial };
+
+ return transitionNoRet(parser, to);
+ }
+ }
+
state->substate = WS;
goto ws;
} else {
@@ -866,17 +872,19 @@ css_error parseRuleset(css_parser *parser)
}
break;
case Brace:
- if (parser->parseError) {
- parser_state to = { sMalformedSelector, Initial };
-
- /* Still need to announce end of ruleset */
#if !defined(NDEBUG) && defined(DEBUG_EVENTS)
- printf("End ruleset\n");
+ printf("Begin ruleset\n");
+ parserutils_vector_dump(parser->tokens, __func__, tprinter);
#endif
- if (parser->event != NULL) {
- parser->event(CSS_PARSER_END_RULESET,
- NULL, parser->event_pw);
- }
+ if (parser->parseError == false && parser->event != NULL) {
+ if (parser->event(CSS_PARSER_START_RULESET,
+ parser->tokens, parser->event_pw) ==
+ CSS_INVALID)
+ parser->parseError = true;
+ }
+
+ if (parser->parseError == true) {
+ parser_state to = { sMalformedSelector, Initial };
return transitionNoRet(parser, to);
}
@@ -1331,22 +1339,6 @@ css_error parseSelector(css_parser *parser)
return transition(parser, to, subsequent);
}
case AfterAny1:
- if (!parser->parseError) {
-#if !defined(NDEBUG) && defined(DEBUG_EVENTS)
- parserutils_vector_dump(parser->tokens,
- __func__, tprinter);
-#endif
- if (parser->event != NULL) {
- if (parser->event(CSS_PARSER_SELECTOR,
- parser->tokens,
- parser->event_pw) ==
- CSS_INVALID) {
- /* parse error */
- parser->parseError = true;
- }
- }
- }
-
break;
}
diff --git a/src/parse/parse.h b/src/parse/parse.h
index 7d7f56d..29f5a0b 100644
--- a/src/parse/parse.h
+++ b/src/parse/parse.h
@@ -29,7 +29,6 @@ typedef enum css_parser_event {
CSS_PARSER_START_BLOCK,
CSS_PARSER_END_BLOCK,
CSS_PARSER_BLOCK_CONTENT,
- CSS_PARSER_SELECTOR,
CSS_PARSER_DECLARATION,
} css_parser_event;
diff --git a/test/data/css/simple.css b/test/data/css/simple.css
index aeba2f5..741a714 100644
--- a/test/data/css/simple.css
+++ b/test/data/css/simple.css
@@ -48,4 +48,4 @@ foo }
blah { baz: bat; foo: bar !important; }
-foo { bar: ""; }
+foo { bar: ""; }{ color: green; }