summaryrefslogtreecommitdiff
path: root/css/parser.y
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2003-03-25 21:03:14 +0000
committerJames Bursa <james@netsurf-browser.org>2003-03-25 21:03:14 +0000
commit6e0fdd2078c11ceec667de9b115408bb7688caa4 (patch)
tree39359e4e130c3dbdb2b93ae53d7232e697d81e77 /css/parser.y
parent91f8a679db6211b883ce2a7499728ee2b6a5f2af (diff)
downloadnetsurf-6e0fdd2078c11ceec667de9b115408bb7688caa4.tar.gz
netsurf-6e0fdd2078c11ceec667de9b115408bb7688caa4.tar.bz2
[project @ 2003-03-25 21:03:14 by bursa]
New CSS parser. svn path=/import/netsurf/; revision=108
Diffstat (limited to 'css/parser.y')
-rw-r--r--css/parser.y162
1 files changed, 162 insertions, 0 deletions
diff --git a/css/parser.y b/css/parser.y
new file mode 100644
index 000000000..5dfe1bd01
--- /dev/null
+++ b/css/parser.y
@@ -0,0 +1,162 @@
+/**
+ * $Id: parser.y,v 1.1 2003/03/25 21:03:14 bursa Exp $
+ */
+
+/*
+
+CSS parser using the lemon parser generator
+
+see CSS2 Specification, chapter 4
+http://www.w3.org/TR/REC-CSS2/syndata.html,
+and errata
+http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata
+
+stylesheet : [ CDO | CDC | S | statement ]*;
+statement : ruleset | at-rule;
+at-rule : ATKEYWORD S* any* [ block | ';' S* ];
+block : '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
+ruleset : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
+selector : any+;
+declaration : property ':' S* value;
+property : IDENT S*;
+value : [ any | block | ATKEYWORD S* ]+;
+any : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
+ | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
+ | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
+
+Note: S, CDO, CDC will be stripped out by the scanner
+*/
+
+stylesheet ::= statement_list(A).
+ { *stylesheet = A; }
+
+statement_list(A) ::= .
+ { A = 0; }
+statement_list(A) ::= statement(B) statement_list(C).
+ { if (B == 0) { A = C; } else { B->next = C; A = B; } }
+
+statement(A) ::= ruleset(B).
+ { A = B; }
+statement(A) ::= at_rule(B).
+ { A = B; }
+
+at_rule(A) ::= ATKEYWORD any_list block.
+ { A = css_new_node(CSS_NODE_AT_RULE, 0, 0, 0); }
+at_rule(A) ::= ATKEYWORD any_list SEMI.
+ { A = css_new_node(CSS_NODE_AT_RULE, 0, 0, 0); }
+
+block ::= LBRACE block_body RBRACE.
+block_body ::= .
+block_body ::= block_body any.
+block_body ::= block_body block.
+block_body ::= block_body ATKEYWORD.
+block_body ::= block_body SEMI.
+
+ruleset(A) ::= selector(B) LBRACE declaration_list(C) RBRACE.
+ { A = css_new_node(CSS_NODE_RULESET, 0, B, C); }
+ruleset(A) ::= LBRACE declaration_list RBRACE.
+ { A = 0; } /* this form of ruleset not used in CSS2 */
+
+selector(A) ::= any_list_1(B).
+ { A = B; }
+
+declaration_list(A) ::= .
+ { A = 0; }
+declaration_list(A) ::= declaration(B).
+ { A = B; }
+declaration_list(A) ::= declaration_list(B) SEMI.
+ { A = B; }
+declaration_list(A) ::= declaration(B) SEMI declaration_list(C).
+ { B->next = C; A = B; }
+
+declaration(A) ::= property(B) COLON value(C).
+ { A = css_new_node(CSS_NODE_DECLARATION, B, C, 0); }
+
+property(A) ::= IDENT(B).
+ { A = B; }
+
+value(A) ::= any(B).
+ { A = B; }
+value(A) ::= any(B) value(C).
+ { B->next = C; A = B; }
+value(A) ::= value(B) block.
+ { A = B; }
+value(A) ::= value(B) ATKEYWORD.
+ { A = B; }
+
+any_list(A) ::= .
+ { A = 0; }
+any_list(A) ::= any(B) any_list(C).
+ { B->next = C; A = B; }
+any_list_1(A) ::= any(B) any_list(C).
+ { B->next = C; A = B; }
+any(A) ::= IDENT(B).
+ { A = css_new_node(CSS_NODE_IDENT, B, 0, 0); }
+any(A) ::= NUMBER(B).
+ { A = css_new_node(CSS_NODE_NUMBER, B, 0, 0); }
+any(A) ::= PERCENTAGE(B).
+ { A = css_new_node(CSS_NODE_PERCENTAGE, B, 0, 0); }
+any(A) ::= DIMENSION(B).
+ { A = css_new_node(CSS_NODE_DIMENSION, B, 0, 0); }
+any(A) ::= STRING(B).
+ { A = css_new_node(CSS_NODE_STRING, B, 0, 0); }
+any(A) ::= DELIM(B).
+ { A = css_new_node(CSS_NODE_DELIM, B, 0, 0); }
+any(A) ::= URI(B).
+ { A = css_new_node(CSS_NODE_URI, B, 0, 0); }
+any(A) ::= HASH(B).
+ { A = css_new_node(CSS_NODE_HASH, B, 0, 0); }
+any(A) ::= UNICODE_RANGE(B).
+ { A = css_new_node(CSS_NODE_UNICODE_RANGE, B, 0, 0); }
+any(A) ::= INCLUDES(B).
+ { A = css_new_node(CSS_NODE_INCLUDES, B, 0, 0); }
+any(A) ::= FUNCTION(B).
+ { A = css_new_node(CSS_NODE_FUNCTION, B, 0, 0); }
+any(A) ::= DASHMATCH(B).
+ { A = css_new_node(CSS_NODE_DASHMATCH, B, 0, 0); }
+any(A) ::= COLON(B).
+ { A = css_new_node(CSS_NODE_COLON, B, 0, 0); }
+any(A) ::= LPAREN any_list(B) RPAREN.
+ { A = css_new_node(CSS_NODE_PAREN, 0, B, 0); }
+any(A) ::= LBRAC any_list(B) RBRAC.
+ { A = css_new_node(CSS_NODE_BRAC, 0, B, 0); }
+
+
+/* lemon directives */
+
+%extra_argument { struct css_node **stylesheet }
+%include { #include "netsurf/css/css.h"
+#include "netsurf/utils/utils.h" }
+%name css_parser_
+
+%token_type { char* }
+%token_destructor { xfree($$); }
+
+%type stylesheet { struct css_node * }
+%type statement_list { struct css_node * }
+%type statement { struct css_node * }
+%type at_rule { struct css_node * }
+%type ruleset { struct css_node * }
+%type selector { struct css_node * }
+%type declaration_list { struct css_node * }
+%type declaration { struct css_node * }
+%type value { struct css_node * }
+%type any_list { struct css_node * }
+%type any_list_1 { struct css_node * }
+%type any { struct css_node * }
+
+%destructor stylesheet { css_free_node($$); }
+%destructor statement_list { css_free_node($$); }
+%destructor statement { css_free_node($$); }
+%destructor at_rule { css_free_node($$); }
+%destructor ruleset { css_free_node($$); }
+%destructor selector { css_free_node($$); }
+%destructor declaration_list { css_free_node($$); }
+%destructor declaration { css_free_node($$); }
+%destructor value { css_free_node($$); }
+%destructor any_list { css_free_node($$); }
+%destructor any_list_1 { css_free_node($$); }
+%destructor any { css_free_node($$); }
+
+%parse_failure { *stylesheet = 0; }
+