diff --git a/README b/README deleted file mode 100644 index 0f45b870..00000000 --- a/README +++ /dev/null @@ -1,56 +0,0 @@ -LibCSS -- a CSS parser and selection engine -=========================================== - -Overview --------- - - LibCSS is a CSS parser and selection engine. It aims to parse the forward - compatible CSS grammar. - -Requirements ------------- - - LibCSS requires the following tools: - - + A C99 capable C compiler - + GNU make or compatible - + Pkg-config - + Perl (for the testcases) - + Python3 (minimum 3.6, for generated selection code) - - LibCSS also requires the following libraries to be installed: - - + LibParserUtils - + LibWapcaplet - -Compilation ------------ - - If necessary, modify the toolchain settings in the Makefile. - Invoke make: - - $ make - -Regenerating generated selection source code --------------------------------------------- - - To regenerate the selection sources (computed style data accesses), - note this requires python3: - - $ make select_generator - -Verification ------------- - - To verify that the parser is working, it is necessary to specify a - different makefile target than that used for normal compilation, thus: - - $ make test - -API documentation ------------------ - - Currently, there is none. However, the code is well commented and the - public API may be found in the "include" directory. The testcase sources - may also be of use in working out how to use it. - diff --git a/README.md b/README.md new file mode 100644 index 00000000..8bc11b59 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +LibCSS -- a CSS parser and selection engine +=========================================== + +Overview +-------- + +LibCSS is a CSS parser and selection engine. It aims to parse the forward +compatible CSS grammar. + +Requirements +------------ + +LibCSS requires the following tools: + +* A C99 capable C compiler +* GNU make or compatible +* Pkg-config +* Perl (for the testcases) +* Python3 (minimum 3.6, for generated selection code) + +LibCSS also requires the following libraries to be installed: + +* LibParserUtils +* LibWapcaplet + +Compilation +----------- + +If necessary, modify the toolchain settings in the Makefile. +Invoke make: + + make + +Regenerating generated selection source code +-------------------------------------------- + +To regenerate the selection sources (computed style data accesses), +note this requires python3: + + make select_generator + +Verification +------------ + +To verify that the parser is working, it is necessary to specify a +different makefile target than that used for normal compilation, thus: + + make test + +API documentation +----------------- + +Currently, there is none. However, the code is well commented and the +public API may be found in the "include" directory. The testcase sources +may also be of use in working out how to use it. + diff --git a/docs/API-ABI-Changes b/docs/API-ABI-Changes deleted file mode 100644 index e567d80b..00000000 --- a/docs/API-ABI-Changes +++ /dev/null @@ -1,77 +0,0 @@ -LibCSS API & ABI Changes -======================== - - This document explains how to upgrade clients to use new versions of LibCSS. - - -LibCSS 0.2.0 --> LibCSS 0.3.0 ------------------------------ - - Both the API and ABI are changed. - - LibCSS no longer lets clients provide a memory allocator function. - This change affects the following functions: - - From include/libcss/computed.h -- css_computed_style_create() - - From include/libcss/select.h -- css_select_ctx_create() - - From include/libcss/stylesheet.h -- css_stylesheet_create() - - - There are changes to selection handler callback table: - - node_classes - LibCSS no longer frees the any array of classes passed to the - node_classes callback. It does still unref the individual strings. - This means clients need not allocate a new array each call, but can - keep the array cached on the node. - - set_libcss_node_data - New selection handler function used to store a private cache belonging - to libcss on document element nodes. When the node is deleted or - modified, clients should call css_libcss_node_data_handler(). - - get_libcss_node_data - New selection handler function used to retrieve private cache belonging - to libcss from document element nodes. - - -LibCSS 0.3.0 --> LibCSS 0.4.0 ------------------------------ - - The API is changed. - - Due to the change from CSS2 overflow to CSS3 overflow properties, the - computed style access functions for overflow properties have changed. - The overflow property is removed. Added are overflow-x and overflow-y - properties. (The overflow shorthand property now sets overflow-x and - overflow-y.) - - This change affects the following functions: - - Removed from include/libcss/computed.h -- css_computed_overflow() - - Added to include/libcss/computed.h -- css_computed_overflow_x() - - Added to include/libcss/computed.h -- css_computed_overflow_y() - - -LibCSS 0.5.0 --> LibCSS 0.6.0 ------------------------------ - - The API is changed. - - The way that presentational hints are handled has changed to be more - optimal. Instead of calling the presentational hint callback once - per property per node to get each hint, we now call the callback once - per node to get all the hints that apply to it. - - There are changes to selection handler callback table: - - node_presentational_hint - Rather than asking for any hint for the given node and property, - it now asks for an array of hints that should apply to the node. - - The css_hint structure has been changed to include the property which - the hint applies to. diff --git a/docs/API-ABI-Changes.md b/docs/API-ABI-Changes.md new file mode 100644 index 00000000..28f04ed9 --- /dev/null +++ b/docs/API-ABI-Changes.md @@ -0,0 +1,77 @@ +LibCSS API & ABI Changes +======================== + +This document explains how to upgrade clients to use new versions of LibCSS. + + +LibCSS 0.2.0 --> LibCSS 0.3.0 +----------------------------- + +Both the API and ABI are changed. + +LibCSS no longer lets clients provide a memory allocator function. +This change affects the following functions: + +| Header | Function | +| ----------------------------- | --------------------------- | +| `include/libcss/computed.h` | css_computed_style_create() | +| `include/libcss/select.h` | css_select_ctx_create() | +| `include/libcss/stylesheet.h` | css_stylesheet_create() | + + +There are changes to selection handler callback table: + +* node_classes + * LibCSS no longer frees the any array of classes passed to the + node_classes callback. It does still unref the individual strings. + This means clients need not allocate a new array each call, but can + keep the array cached on the node. + +* set_libcss_node_data + * New selection handler function used to store a private cache belonging + to libcss on document element nodes. When the node is deleted or + modified, clients should call css_libcss_node_data_handler(). + +* get_libcss_node_data + * New selection handler function used to retrieve private cache belonging + to libcss from document element nodes. + + +LibCSS 0.3.0 --> LibCSS 0.4.0 +----------------------------- + +The API is changed. + +Due to the change from CSS2 overflow to CSS3 overflow properties, the +computed style access functions for overflow properties have changed. +The overflow property is removed. Added are overflow-x and overflow-y +properties. (The overflow shorthand property now sets overflow-x and +overflow-y.) + +This change affects the following functions: + +| Change | Header | Function | +| ------- | --------------------------- | --------------------------- | +| Removed | `include/libcss/computed.h` | `css_computed_overflow()` | +| Added | `include/libcss/computed.h` | `css_computed_overflow_x()` | +| Added | `include/libcss/computed.h` | `css_computed_overflow_y()` | + + +LibCSS 0.5.0 --> LibCSS 0.6.0 +----------------------------- + +The API is changed. + +The way that presentational hints are handled has changed to be more +optimal. Instead of calling the presentational hint callback once +per property per node to get each hint, we now call the callback once +per node to get all the hints that apply to it. + +There are changes to selection handler callback table: + +* node_presentational_hint + * Rather than asking for any hint for the given node and property, + it now asks for an array of hints that should apply to the node. + +The css_hint structure has been changed to include the property which +the hint applies to. diff --git a/docs/API b/docs/API.md similarity index 81% rename from docs/API rename to docs/API.md index 6115b5bb..c0ef9329 100644 --- a/docs/API +++ b/docs/API.md @@ -22,16 +22,19 @@ Load one or more CSS files A stylesheet is represented by the opaque type css_stylesheet. To create one, use css_stylesheet_create(), for example: - css_stylesheet *sheet; - css_stylesheet_params params; - /* Set params */ - ... - code = css_stylesheet_create(¶ms, &sheet); - if (code != CSS_OK) - ... +```c +css_stylesheet *sheet; +css_stylesheet_params params; +/* Set params */ +... +code = css_stylesheet_create(¶ms, &sheet); +if (code != CSS_OK) + ... +``` The arguments are as follows: +``` + css_stylesheet_params params | + uint32_t params_version | | Version of the params struct. @@ -87,15 +90,18 @@ The arguments are as follows: | + css_stylesheet **stylesheet Updated with the newly created stylesheet object. +``` Once the stylesheet has been created, CSS source data can be added to it. LibCSS parses the data into internal structures. Only data in memory is supported; you must handle reading from files or the network if required. Data is added using css_stylesheet_append_data(), for example: - code = css_stylesheet_append_data(sheet, data, length); - if (code != CSS_OK && code != CSS_NEEDDATA) - ... +```c +code = css_stylesheet_append_data(sheet, data, length); +if (code != CSS_OK && code != CSS_NEEDDATA) + ... +``` The second argument is a pointer to a buffer containing some CSS to be parsed, with length in bytes given in the 3rd argument. @@ -109,9 +115,11 @@ data may be expected. The two states can be treated identically. When all the data has been supplied, css_stylesheet_data_done() completes the processing: - code = css_stylesheet_data_done(sheet); - if (code != CSS_OK) - ... +```c +code = css_stylesheet_data_done(sheet); +if (code != CSS_OK) + ... +``` The stylesheet is now in memory and ready for further use. @@ -122,7 +130,7 @@ Use the Selection API to determine styles The Selection API is currently the only way to get information about styles from stylesheets that have been loaded. It takes a document node as input and returns the computed style that applies to that node. For example, it can be used to -answer the question "What style should this

element have?" +answer the question "What style should this `

` element have?" CSS selectors can be complex and apply to certain arrangments of elements within a document tree. Therefore LibCSS has to be able to navigate your document tree @@ -130,7 +138,9 @@ and read attributes of it to determine if a style applies. It does this through a series of functions that you supply. In this way LibCSS is independent of the representation of the document. For example, with the style rule: - table h2 { color: red; } +```css +table h2 { color: red; } +``` when requesting the style for an h2 element node, LibCSS will search its ancestors for a table element to determine if this style applies. @@ -139,17 +149,21 @@ The first step in using the Selection API is creating a selection context. This is a list of the stylesheets to be used. A context is created using css_select_ctx_create(): - css_select_ctx *select_ctx; - code = css_select_ctx_create(&select_ctx); - if (code != CSS_OK) - ... +```c +css_select_ctx *select_ctx; +code = css_select_ctx_create(&select_ctx); +if (code != CSS_OK) + ... +``` Stylesheets are added to the context using css_select_ctx_append_sheet(): - code = css_select_ctx_append_sheet(select_ctx, sheet, CSS_ORIGIN_AUTHOR, - CSS_MEDIA_ALL); - if (code != CSS_OK) - ... +```c +code = css_select_ctx_append_sheet(select_ctx, sheet, CSS_ORIGIN_AUTHOR, + CSS_MEDIA_ALL); +if (code != CSS_OK) + ... +``` When adding a stylesheet, the origin and media can be specified. These are used in the computation of styles as defined in the CSS specification. @@ -158,21 +172,26 @@ Alternatively stylesheets may be added using css_select_ctx_insert_sheet(). After the context has been prepared, an empty computed style is created: - css_computed_style *style; - code = css_computed_style_create(&style); - if (code != CSS_OK) - ... +```c +css_computed_style *style; +code = css_computed_style_create(&style); +if (code != CSS_OK) + ... +``` The style is then determined for a document node using css_select_style(): - code = css_select_style(select_ctx, element_node, 0, - CSS_MEDIA_SCREEN, NULL, style, - &select_handler, 0); - if (code != CSS_OK) - ... +```c +code = css_select_style(select_ctx, element_node, 0, + CSS_MEDIA_SCREEN, NULL, style, + &select_handler, 0); +if (code != CSS_OK) + ... +``` The arguments are as follows: +``` + css_select_ctx *ctx | The selection context, as described above. | @@ -201,31 +220,34 @@ The arguments are as follows: + css_computed_style **result Updated to the computed styles for the node. Array indexed by css_pseudo_element. +``` The types of the handler functions that need to be supplied and the definition of css_select_handler are given in libcss/select.h. The functions all have the following in common: - * the first argument is the private data pointer that was the last argument to - css_select_style() +* the first argument is the private data pointer that was the last argument to + css_select_style() - * the second argument is the document node that is being queried is some way +* the second argument is the document node that is being queried is some way - * the last one or two arguments are pointers that must be updated with the +* the last one or two arguments are pointers that must be updated with the required information - * the return value is a css_error and should be CSS_OK if everything worked and - an error code otherwise +* the return value is a css_error and should be CSS_OK if everything worked and + an error code otherwise For example, the node_name function, which determines the element name of a node, could be this: - css_error node_name(void *pw, void *n, lwc_string **name) - { - my_document_node *node = n; - *name = lwc_string_ref(node->name); - return CSS_OK; - } +```c +css_error node_name(void *pw, void *n, lwc_string **name) +{ + my_document_node *node = n; + *name = lwc_string_ref(node->name); + return CSS_OK; +} +``` where my_document_node is your document tree node type (e.g. a struct of some sort). @@ -244,9 +266,11 @@ work to read the properties correctly. For example, the css_computed_color() accessor retrieves the color property: - uint8_t color_type; - css_color color_shade; - color_type = css_computed_color(style, &color_shade); +```c +uint8_t color_type; +css_color color_shade; +color_type = css_computed_color(style, &color_shade); +``` In this case color_type can be CSS_COLOR_INHERIT or CSS_COLOR_COLOR. In the latter case, color_shade contains the actual color in RRGGBBAA format. Together diff --git a/docs/Bytecode b/docs/Bytecode.md similarity index 98% rename from docs/Bytecode rename to docs/Bytecode.md index 272fd07b..699b4e8e 100644 --- a/docs/Bytecode +++ b/docs/Bytecode.md @@ -4,6 +4,7 @@ CSS style declaration bytecode Format ------ +``` [] is 32 bits wide: @@ -20,6 +21,7 @@ The 8 bits of flag data are defined as follows: 011 => revert 100 => unset bit 0 : value is important +``` The 14 bits of value are opcode-specific. @@ -35,9 +37,10 @@ assigned to the fractional part. Strings are stored as a 32bit index into a table of interned string pointers. The table is found in the stylesheet object. -CSS dimensions are stored as two 32bit values: . +CSS dimensions are stored as two 32bit values: ``. Length is a 32bit numeric value (as described above) and unit is as follows: +``` bit 8 set => length unit bits 9-31: MBZ bits 0-7 : @@ -94,6 +97,7 @@ Length is a 32bit numeric value (as described above) and unit is as follows: 00000000 => dpi 00000001 => dpcm 00000010 => dppx +``` CSS colours are stored as one 32bit value. See "Colour" for their format. @@ -106,33 +110,38 @@ component parts, and then creating bytecode for these. For example, "background: red none no-repeat scroll left top !important;" would be decomposed to: - background-color: red !important; - background-image: none !important; - background-repeat: no-repeat !important; - background-attachment: scroll !important; - background-position: left top !important; +```css +background-color: red !important; +background-image: none !important; +background-repeat: no-repeat !important; +background-attachment: scroll !important; +background-position: left top !important; +``` and bytecode generated for each of these properties. The full list of CSS 2.1 shorthand properties is: - background - border-color - border-style - border-{top,right,bottom,left} - border-width - border - cue - font - list-style - margin - outline - padding - pause +``` +background +border-color +border-style +border-{top,right,bottom,left} +border-width +border +cue +font +list-style +margin +outline +padding +pause +``` Opcodes ------- +``` 00 - azimuth (14bits) : bits 8-13: MBZ @@ -1402,3 +1411,4 @@ Opcodes bits 0-6: MBZ 7e-3ff - Reserved for future expansion. +``` diff --git a/docs/Colour b/docs/Colour deleted file mode 100644 index b3e78503..00000000 --- a/docs/Colour +++ /dev/null @@ -1,10 +0,0 @@ -The exported representation of colours is an unsigned 32bit value in host order - -The value is divided into four 8bit channels. These are: - -Bits Name Desciption -0-7 Blue The blue intensity of the colour 0 is off 0xff is fully on -8-15 Green The green intensity of the colour 0 is off 0xff is fully on -16-23 Red The red intensity of the colour 0 is off 0xff is fully on -24-31 Alpha The Alpha component represents the opacity of the colour 0 is fully transparent and 0xff is opaque - diff --git a/docs/Colour.md b/docs/Colour.md new file mode 100644 index 00000000..baa98702 --- /dev/null +++ b/docs/Colour.md @@ -0,0 +1,10 @@ +The exported representation of colours is an unsigned 32bit value in host order + +The value is divided into four 8bit channels. These are: + +| Bits | Name | Desciption | +| ------- | ----- | ---------- | +| ` 0- 7` | Blue | The blue intensity of the colour `0` is off `0xff` is fully on | +| ` 8-15` | Green | The green intensity of the colour `0` is off `0xff` is fully on | +| `16-23` | Red | The red intensity of the colour `0` is off `0xff` is fully on | +| `24-31` | Alpha | The Alpha component represents the opacity of the colour `0` is fully transparent and `0xff` is opaque | diff --git a/docs/Grammar b/docs/Grammar deleted file mode 100644 index c3d24b41..00000000 --- a/docs/Grammar +++ /dev/null @@ -1,210 +0,0 @@ -Expanded grammar rules -====================== - -This file provides a fully-expanded version of (a slightly modified) -forward-compatible CSS grammar. See CSS3 Syntax $4.3.2 for the compact version. - -start -> ws stylesheet EOF - -stylesheet -> CDO ws stylesheet -stylesheet -> CDC ws stylesheet -stylesheet -> statement stylesheet -stylesheet -> - -statement -> ruleset -statement -> at-rule - -ruleset -> selector '{' ws ruleset-end -ruleset -> '{' ws ruleset-end - -ruleset-end -> declaration decl-list '}' ws -ruleset-end -> decl-list '}' ws - -at-rule -> ATKEYWORD ws any0 at-rule-end - -at-rule-end -> block -at-rule-end -> ';' ws - -block -> '{' ws block-content '}' ws - -block-content -> any block-content -block-content -> block block-content -block-content -> ATKEYWORD ws block-content -block-content -> ';' ws block-content -block-content -> - -selector -> any1 - -declaration -> property ':' ws value1 - -decl-list -> ';' ws decl-list-end -decl-list -> - -decl-list-end -> declaration decl-list -decl-list-end -> decl-list - -property -> IDENT ws - -value0 -> value value0 -value0 -> - -value1 -> value value0 - -value -> any -value -> block -value -> ATKEYWORD ws - -any0 -> any any0 -any0 -> - -any1 -> any any0 - -any -> IDENT ws -any -> NUMBER ws -any -> PERCENTAGE ws -any -> DIMENSION ws -any -> STRING ws -any -> CHAR ws -any -> URI ws -any -> HASH ws -any -> UNICODE-RANGE ws -any -> INCLUDES ws -any -> DASHMATCH ws -any -> PREFIXMATCH ws -any -> SUFFIXMATCH ws -any -> SUBSTRINGMATCH ws -any -> FUNCTION ws any0 ')' ws -any -> '(' ws any0 ')' ws -any -> '[' ws any0 ']' ws - -ws -> S ws -ws -> - -Differences from the specification ----------------------------------- - -1) The start non-terminal has been introduced. It eats any leading whitespace - and handles EOF. -2) The "stylesheet -> S stylesheet" production has been removed. -3) The "stylesheet -> CDO stylesheet" production has been changed to - "stylesheet -> CDO ws stylesheet". -4) The "stylesheet -> CDC stylesheet" production has been changed to - "stylesheet -> CDC ws stylesheet". - -Essentially, the above changes remove the expectation of leading whitespace -from the stylesheet non-terminal. This is handled by either the start -non-terminal, or by the changes made to the production rules for the stylesheet -non-terminal. Note that the "stylesheet -> statement stylesheet" production -does not require modification as the statement production rule already consumes -any whitespace following the statement. - -If '{', '}', '[', ']', '(', ')', and ';' are omitted from any, then the above -grammar is LL(1). - -Nullable productions --------------------- - -stylesheet, block-content, decl-list, decl-list-end, value0, any0, ws - -FIRST sets ----------- - -start CDO, CDC, S, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -stylesheet CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD -statement IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD -ruleset IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{' -ruleset-end IDENT, ';' -at-rule ATKEYWORD -at-rule-end '{', ';' -block '{' -block-content IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD, ';' -selector IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[' -declaration IDENT -decl-list ';', '}' -decl-list-end IDENT, ';', '}' -property IDENT -value0 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD -value1 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD -value IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD -any0 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[' -any1 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[' -any IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[' -ws S - -FOLLOW sets ------------ - -start -stylesheet EOF -statement CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -ruleset CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -ruleset-end CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -at-rule CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -at-rule-end CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF -block CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF, ';', '}' -block-content '}' -selector '{' -declaration ';', '}' -decl-list '}' -decl-list-end '}' -property ':' -value0 ';', '}' -value1 ';', '}' -value IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD, ';', '}' -any0 '{', ';', ')', ']' -any1 '{' -any IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, - UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, - SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ';', ATKEYWORD, '}' -ws CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, - CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, - PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', - '[', '{', ATKEYWORD, EOF, ';', '}', ':' - - diff --git a/docs/Grammar.md b/docs/Grammar.md new file mode 100644 index 00000000..75051336 --- /dev/null +++ b/docs/Grammar.md @@ -0,0 +1,214 @@ +Expanded grammar rules +====================== + +This file provides a fully-expanded version of (a slightly modified) +forward-compatible CSS grammar. See CSS3 Syntax $4.3.2 for the compact version. + +``` +start -> ws stylesheet EOF + +stylesheet -> CDO ws stylesheet +stylesheet -> CDC ws stylesheet +stylesheet -> statement stylesheet +stylesheet -> + +statement -> ruleset +statement -> at-rule + +ruleset -> selector '{' ws ruleset-end +ruleset -> '{' ws ruleset-end + +ruleset-end -> declaration decl-list '}' ws +ruleset-end -> decl-list '}' ws + +at-rule -> ATKEYWORD ws any0 at-rule-end + +at-rule-end -> block +at-rule-end -> ';' ws + +block -> '{' ws block-content '}' ws + +block-content -> any block-content +block-content -> block block-content +block-content -> ATKEYWORD ws block-content +block-content -> ';' ws block-content +block-content -> + +selector -> any1 + +declaration -> property ':' ws value1 + +decl-list -> ';' ws decl-list-end +decl-list -> + +decl-list-end -> declaration decl-list +decl-list-end -> decl-list + +property -> IDENT ws + +value0 -> value value0 +value0 -> + +value1 -> value value0 + +value -> any +value -> block +value -> ATKEYWORD ws + +any0 -> any any0 +any0 -> + +any1 -> any any0 + +any -> IDENT ws +any -> NUMBER ws +any -> PERCENTAGE ws +any -> DIMENSION ws +any -> STRING ws +any -> CHAR ws +any -> URI ws +any -> HASH ws +any -> UNICODE-RANGE ws +any -> INCLUDES ws +any -> DASHMATCH ws +any -> PREFIXMATCH ws +any -> SUFFIXMATCH ws +any -> SUBSTRINGMATCH ws +any -> FUNCTION ws any0 ')' ws +any -> '(' ws any0 ')' ws +any -> '[' ws any0 ']' ws + +ws -> S ws +ws -> +``` + +Differences from the specification +---------------------------------- + +1) The start non-terminal has been introduced. It eats any leading whitespace + and handles EOF. +2) The "stylesheet -> S stylesheet" production has been removed. +3) The "stylesheet -> CDO stylesheet" production has been changed to + "stylesheet -> CDO ws stylesheet". +4) The "stylesheet -> CDC stylesheet" production has been changed to + "stylesheet -> CDC ws stylesheet". + +Essentially, the above changes remove the expectation of leading whitespace +from the stylesheet non-terminal. This is handled by either the start +non-terminal, or by the changes made to the production rules for the stylesheet +non-terminal. Note that the "stylesheet -> statement stylesheet" production +does not require modification as the statement production rule already consumes +any whitespace following the statement. + +If '{', '}', '[', ']', '(', ')', and ';' are omitted from any, then the above +grammar is LL(1). + +Nullable productions +-------------------- + +stylesheet, block-content, decl-list, decl-list-end, value0, any0, ws + +FIRST sets +---------- + +``` +start CDO, CDC, S, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +stylesheet CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD +statement IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD +ruleset IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{' +ruleset-end IDENT, ';' +at-rule ATKEYWORD +at-rule-end '{', ';' +block '{' +block-content IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD, ';' +selector IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[' +declaration IDENT +decl-list ';', '}' +decl-list-end IDENT, ';', '}' +property IDENT +value0 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD +value1 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD +value IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD +any0 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[' +any1 IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[' +any IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[' +ws S +``` + +FOLLOW sets +----------- + +``` +start +stylesheet EOF +statement CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +ruleset CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +ruleset-end CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +at-rule CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +at-rule-end CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF +block CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF, ';', '}' +block-content '}' +selector '{' +declaration ';', '}' +decl-list '}' +decl-list-end '}' +property ':' +value0 ';', '}' +value1 ';', '}' +value IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ATKEYWORD, ';', '}' +any0 '{', ';', ')', ']' +any1 '{' +any IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, CHAR, URI, HASH, + UNICODE-RANGE, INCLUDES, DASHMATCH, PREFIXMATCH, SUFFIXMATCH, + SUBSTRINGMATCH, FUNCTION, '(', '[', '{', ';', ATKEYWORD, '}' +ws CDO, CDC, IDENT, NUMBER, PERCENTAGE, DIMENSION, STRING, + CHAR, URI, HASH, UNICODE-RANGE, INCLUDES, DASHMATCH, + PREFIXMATCH, SUFFIXMATCH, SUBSTRINGMATCH, FUNCTION, '(', + '[', '{', ATKEYWORD, EOF, ';', '}', ':' +``` diff --git a/docs/Lexer b/docs/Lexer deleted file mode 100644 index 23626d13..00000000 --- a/docs/Lexer +++ /dev/null @@ -1,31 +0,0 @@ -Lexical analyser -================ - -This document contains various snippets of information about the lexer -implementation. - -First sets ----------- - -IDENT [a-zA-Z] | '-' | '_' | [^#x0-#x7F] | '\' -ATKEYWORD '@' -STRING '"' | "'" -INVALID_STRING '"' | "'" -HASH '#' -NUMBER [0-9] | '.' | '-' | '+' -PERCENTAGE [0-9] | '.' | '-' | '+' -DIMENSION [0-9] | '.' -URI [Uu] -UNICODE-RANGE [Uu] -CDO '<' -CDC '-' -S #x9 | #xA | #xC | #xD | #x20 -COMMENT '/' -FUNCTION [a-zA-Z] | '-' | '_' | [^#x0-#x7F] | '\' -INCLUDES '~' -DASHMATCH '|' -PREFIXMATCH '^' -SUFFIXMATCH '$' -SUBSTRINGMATCH '*' -CHAR anything except " or ' - diff --git a/docs/Lexer.md b/docs/Lexer.md new file mode 100644 index 00000000..064d1ee7 --- /dev/null +++ b/docs/Lexer.md @@ -0,0 +1,32 @@ +Lexical analyser +================ + +This document contains various snippets of information about the lexer +implementation. + +First sets +---------- + +``` +IDENT [a-zA-Z] | '-' | '_' | [^#x0-#x7F] | '\' +ATKEYWORD '@' +STRING '"' | "'" +INVALID_STRING '"' | "'" +HASH '#' +NUMBER [0-9] | '.' | '-' | '+' +PERCENTAGE [0-9] | '.' | '-' | '+' +DIMENSION [0-9] | '.' +URI [Uu] +UNICODE-RANGE [Uu] +CDO '<' +CDC '-' +S #x9 | #xA | #xC | #xD | #x20 +COMMENT '/' +FUNCTION [a-zA-Z] | '-' | '_' | [^#x0-#x7F] | '\' +INCLUDES '~' +DASHMATCH '|' +PREFIXMATCH '^' +SUFFIXMATCH '$' +SUBSTRINGMATCH '*' +CHAR anything except " or ' +``` diff --git a/docs/Representation b/docs/Representation.md similarity index 98% rename from docs/Representation rename to docs/Representation.md index b91419f8..ffebf2c2 100644 --- a/docs/Representation +++ b/docs/Representation.md @@ -3,6 +3,7 @@ LibCSS internal stylesheet representation Selector: +```c struct selector { selector_type type; /**< Type of selector */ @@ -26,9 +27,11 @@ struct selector { struct selector *next; /**< Next selector in list */ struct selector *prev; /**< Previous selector */ }; +``` Rule: +```c struct rule { rule_type type; /**< Type of rule */ @@ -68,9 +71,11 @@ struct rule { struct rule *next; /**< Next rule */ struct rule *prev; /**< Previous rule */ }; +``` Stylesheet: +```c struct stylesheet { #define HASH_SIZE (37) struct selector *selectors[HASH_SIZE]; /**< Hashtable of selectors */ @@ -95,4 +100,4 @@ struct stylesheet { struct stylesheet *next; /**< Next in sibling list */ struct stylesheet *prev; /**< Previous in sibling list */ }; - +``` diff --git a/docs/Tokens b/docs/Tokens.md similarity index 99% rename from docs/Tokens rename to docs/Tokens.md index 9535e813..a6d89eb6 100644 --- a/docs/Tokens +++ b/docs/Tokens.md @@ -7,6 +7,7 @@ by the lexer. In case of ambiguity, the longest match wins. Components ---------- +``` ident ::= '-'? nmstart nmchar* name ::= nmchar+ nmstart ::= [a-zA-Z] | '_' | nonascii | escape @@ -21,10 +22,12 @@ urlchar ::= [#x9#x21#x23-#x26#x28#x2A-#x7E] | nonascii | escape nl ::= #xA | #xD #xA | #xD | #xC w ::= wc* wc ::= #x9 | #xA | #xC | #xD | #x20 +``` Tokens ------ +``` IDENT ::= ident ATKEYWORD ::= '@' ident STRING ::= string @@ -46,6 +49,7 @@ PREFIXMATCH ::= "^=" SUFFIXMATCH ::= "$=" SUBSTRINGMATCH ::= "*=" CHAR ::= any other character, except " or ' +``` Differences from the CSS3 Syntax module specification ----------------------------------------------------- diff --git a/test/README b/test/README.md similarity index 69% rename from test/README rename to test/README.md index 557adf9c..ed1320d3 100644 --- a/test/README +++ b/test/README.md @@ -10,7 +10,7 @@ Testcase command lines Testcase command lines are in a unified format, thus: - [ ] + [ ] The aliases file parameter will always be specified (as it is required for the library to work at all). @@ -34,20 +34,22 @@ added to this index as they are created. The test index file format is as follows: - file = *line +``` +file = *line - line = ( entry / comment / blank ) LF +line = ( entry / comment / blank ) LF - entry = testname 1*HTAB description [ 1*HTAB datadir ] - comment = "#" *non-newline - blank = 0 +entry = testname 1*HTAB description [ 1*HTAB datadir ] +comment = "#" *non-newline +blank = 0 - testname = 1*non-reserved - description = 1*non-reserved - datadir = 1*non-reserved +testname = 1*non-reserved +description = 1*non-reserved +datadir = 1*non-reserved - non-newline = VCHAR / WSP - non-reserved = VCHAR / SP +non-newline = VCHAR / WSP +non-reserved = VCHAR / SP +``` Each entry contains a mandatory binary name and description followed by an optional data directory specifier. The data directory specifier is @@ -57,7 +59,7 @@ directory in the source tree. If a data directory is specified, the test binary will be invoked for each data file listed within the data directory INDEX, passing the -filename as the second parameter (, above). +filename as the second parameter (``, above). Data Index ---------- @@ -67,18 +69,20 @@ index of all available test data files. The data index file format is as follows: - file = *line +``` +file = *line - line = ( entry / comment / blank ) LF +line = ( entry / comment / blank ) LF - entry = dataname 1*HTAB description - comment = "#" *non-newline - blank = 0 +entry = dataname 1*HTAB description +comment = "#" *non-newline +blank = 0 - dataname = 1*non-reserved - description = 1*non-reserved +dataname = 1*non-reserved +description = 1*non-reserved - non-newline = VCHAR / WSP - non-reserved = VCHAR / SP +non-newline = VCHAR / WSP +non-reserved = VCHAR / SP +``` Each entry contains a mandatory data file name and description. diff --git a/test/data/parse/README b/test/data/parse/README.md similarity index 69% rename from test/data/parse/README rename to test/data/parse/README.md index 135dd3be..a9844f6a 100644 --- a/test/data/parse/README +++ b/test/data/parse/README.md @@ -4,6 +4,7 @@ Parser testcases Format ------ +``` #data #errors @@ -11,17 +12,18 @@ Format #expected #reset +``` Format of rule list ------------------- - line ::= rule | bytecode - rule ::= '| ' type ' '+ name - name ::= .+ - type ::= [0-9]+ - bytecode ::= '| ' ' '* hexnum (' '+ (hexnum | ptr))* - hexnum ::= '0x' [0-9a-fA-F]+ - ptr ::= 'PTR(' .* ')' + line ::= rule | bytecode + rule ::= '| ' type ' '+ name + name ::= .+ + type ::= [0-9]+ + bytecode ::= '| ' ' '* hexnum (' '+ (hexnum | ptr))* + hexnum ::= '0x' [0-9a-fA-F]+ + ptr ::= 'PTR(' .* ')' Type corresponds to css_rule_type. Consult the library sources for the values. @@ -32,6 +34,7 @@ documentation for what the hexnums should be representing. Example ------- +``` #data * { color: #ff0000; background-image: url("foo.png"); } #errors @@ -40,9 +43,10 @@ Example | 0x0200000f 0xff000000 | 0x02000003 PTR(foo.png) #reset +``` TODO ---- - + Permit nesting of rules (for nested block support) +* Permit nesting of rules (for nested block support) diff --git a/test/data/parse2/README b/test/data/parse2/README.md similarity index 65% rename from test/data/parse2/README rename to test/data/parse2/README.md index dec15f4a..862aa127 100644 --- a/test/data/parse2/README +++ b/test/data/parse2/README.md @@ -4,6 +4,7 @@ Parser testcases Format ------ +``` #data #errors @@ -11,18 +12,20 @@ Format #expected #reset +``` Format of cssom tree -------------------- - line ::= rule | declaration - rule ::= '| ' name - name ::= .+ - declaration ::= '| ' property-name ': ' property-value + line ::= rule | declaration + rule ::= '| ' name + name ::= .+ + declaration ::= '| ' property-name ': ' property-value Example ------- +``` #data * { color: #ff0000; background-image: url("foo.png"); } #errors @@ -31,9 +34,10 @@ Example | color: #ff000000 | background-image: url("foo.png") #reset +``` TODO ---- - + Permit nesting of rules (for nested block support) +* Permit nesting of rules (for nested block support)