Commit 90db3f19 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Fixed parsing conflicts and stringification issues with @supports

parent 5d9a7709
...@@ -97,10 +97,13 @@ rule token = parse ...@@ -97,10 +97,13 @@ rule token = parse
| '@' K E Y F R A M E S { KEYFRAMES_SYM } | '@' K E Y F R A M E S { KEYFRAMES_SYM }
| '@' S U P P O R T S { SUPPORTS_SYM } | '@' S U P P O R T S { SUPPORTS_SYM }
| (w | comment)* w A N D w (w | comment)* { SUPPORTS_AND }
| (w | comment)* w O R w (w | comment)* { SUPPORTS_OR }
| O N L Y { ONLY } | O N L Y { ONLY }
| N O T { NOT } | N O T { NOT }
| A N D { AND } | A N D { AND }
| O R { OR } (*| O R { OR } removed in favor of SUPPORTS_OR *)
| F R O M { FROM } | F R O M { FROM }
| T O { TO } | T O { TO }
......
...@@ -53,7 +53,8 @@ ...@@ -53,7 +53,8 @@
%token <float * string> UNIT_VALUE %token <float * string> UNIT_VALUE
%token <string> COMBINATOR RELATION STRING IDENT HASH URI FUNCTION %token <string> COMBINATOR RELATION STRING IDENT HASH URI FUNCTION
%token LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK SEMICOL COLON COMMA DOT PLUS %token LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK SEMICOL COLON COMMA DOT PLUS
%token MINUS SLASH STAR ONLY AND OR NOT FROM TO EOF %token MINUS SLASH STAR ONLY AND (*OR*) NOT FROM TO EOF
%token SUPPORTS_AND SUPPORTS_OR
(* Start symbol *) (* Start symbol *)
%type <Types.stylesheet> stylesheet %type <Types.stylesheet> stylesheet
...@@ -62,8 +63,12 @@ ...@@ -62,8 +63,12 @@
%% %%
(* list with arbitrary whitespace between elements and separators *) (* list with arbitrary whitespace between elements and separators *)
%inline ig2(a, b): a b {}
%inline ig3(a, b, c): a b c {}
%inline wslist(sep, x): S* l=separated_list(sep, terminated(x, S*)) { l } %inline wslist(sep, x): S* l=separated_list(sep, terminated(x, S*)) { l }
%inline wspreceded(prefix, x): p=preceded(pair(prefix, S*), x) { p } %inline wspreceded(prefix, x): p=preceded(ig2(prefix, S*), x) { p }
%inline all_and: AND | SUPPORTS_AND {}
cd: CDO S* | CDC S* {} cd: CDO S* | CDC S* {}
...@@ -112,9 +117,9 @@ media_query_list: ...@@ -112,9 +117,9 @@ media_query_list:
| S* hd=media_query tl=wspreceded(COMMA, media_query)* | S* hd=media_query tl=wspreceded(COMMA, media_query)*
{ hd :: tl } { hd :: tl }
media_query: media_query:
| prefix=only_or_not? typ=media_type S* feat=wspreceded(AND, media_expr)* | prefix=only_or_not? typ=media_type S* feat=wspreceded(all_and, media_expr)*
{ (prefix, Some typ, feat) } { (prefix, Some typ, feat) }
| hd=media_expr tl=wspreceded(AND, media_expr)* | hd=media_expr tl=wspreceded(all_and, media_expr)*
{ (None, None, (hd :: tl)) } { (None, None, (hd :: tl)) }
%inline only_or_not: %inline only_or_not:
| ONLY S* { "only" } | ONLY S* { "only" }
...@@ -171,18 +176,21 @@ supports_negation: ...@@ -171,18 +176,21 @@ supports_negation:
| NOT S+ c=supports_condition_in_parens | NOT S+ c=supports_condition_in_parens
{ Not c } { Not c }
supports_conjunction: supports_conjunction:
| hd=supports_condition_in_parens tl=preceded(delimited(S+, AND, S+), supports_condition_in_parens)+ | hd=supports_condition_in_parens tl=preceded(SUPPORTS_AND, supports_condition_in_parens)+
{ And (hd :: tl) } { And (hd :: tl) }
supports_disjunction: supports_disjunction:
| hd=supports_condition_in_parens tl=preceded(delimited(S+, OR, S+), supports_condition_in_parens)+ | hd=supports_condition_in_parens tl=preceded(SUPPORTS_OR, supports_condition_in_parens)+
{ Or (hd :: tl) } { Or (hd :: tl) }
supports_declaration_condition: supports_declaration_condition:
| LPAREN S* decl=declaration RPAREN | LPAREN S* decl=supports_declaration RPAREN
{ Decl decl } { Decl decl }
supports_declaration:
| name=property S* COLON S* value=expr
{ (name, value) }
(*XXX: (*XXX:
general_enclosed: general_enclosed:
| ( FUNCTION | LPAREN ) ( any | unused )* RPAREN | ( FUNCTION | LPAREN ) ( any | unused )* RPAREN
{ } { Enclosed expr }
any: any:
[ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
...@@ -248,7 +256,7 @@ pseudo: ...@@ -248,7 +256,7 @@ pseudo:
":" ^ f ^ "(" ^ arg ^ ")" } ":" ^ f ^ "(" ^ arg ^ ")" }
declaration: declaration:
| name=property S* COLON S* value=expr important=boption(pair(IMPORTANT_SYM, S*)) | name=property S* COLON S* value=expr important=boption(ig2(IMPORTANT_SYM, S*))
{ (String.lowercase name, value, important) } { (String.lowercase name, value, important) }
%inline property: name=IDENT { name } %inline property: name=IDENT { name }
......
...@@ -27,8 +27,7 @@ let rec filter_none = function ...@@ -27,8 +27,7 @@ let rec filter_none = function
let add_parens s = let add_parens s =
let l = String.length s in let l = String.length s in
if l > 0 & s.[0] = '(' & s.[l - 1] = ')' if l > 0 & s.[0] = '(' & s.[l - 1] = ')'
then String.sub s 1 (l - 2) then s else "(" ^ s ^ ")"
else s
(* (*
* Pretty-printing * Pretty-printing
...@@ -76,12 +75,24 @@ let string_of_media_query query = ...@@ -76,12 +75,24 @@ let string_of_media_query query =
| (Some pre, None, _) -> | (Some pre, None, _) ->
failwith "unexpected media query prefix \"" ^ pre ^ "\"" failwith "unexpected media query prefix \"" ^ pre ^ "\""
let rec string_of_condition = function let stringify_condition w c =
| Not c -> "not " ^ add_parens (string_of_condition c) let rec transform =
| And c -> cat " and " (add_parens @@ string_of_condition) c let p c = `Parens (transform c) in
| Or c -> cat " or " (add_parens @@ string_of_condition) c function
| Decl (name, value, false) -> "(" ^ name ^ ": " ^ string_of_expr value ^ ")" | Not c -> `Not (p c)
| Decl (_, _, true) -> failwith "unexpected \"!important\"" | And c -> `And (List.map p c)
| Or c -> `Or (List.map p c)
| Decl (name, value) -> `Decl (name, value)
in
let rec str = function
| `Not c -> "not " ^ str c
| `And c -> cat " and " str c
| `Or c -> cat " or " str c
| `Decl (name, value) -> "(" ^ name ^ ":" ^ w ^ string_of_expr value ^ ")"
| `Parens (`Decl _ as d) -> str d
| `Parens c -> "(" ^ str c ^ ")"
in
str (transform c)
let block = function "" -> " {}" | body -> " {\n" ^ indent body ^ "\n}" let block = function "" -> " {}" | body -> " {\n" ^ indent body ^ "\n}"
...@@ -117,7 +128,7 @@ let rec string_of_statement = function ...@@ -117,7 +128,7 @@ let rec string_of_statement = function
in in
"@keyframes " ^ id ^ block (cat "\n\n" string_of_keyframe_ruleset rules) "@keyframes " ^ id ^ block (cat "\n\n" string_of_keyframe_ruleset rules)
| Supports (condition, statements) -> | Supports (condition, statements) ->
"@supports " ^ string_of_condition condition ^ "@supports " ^ stringify_condition " " condition ^
block (cat "\n\n" string_of_statement statements) block (cat "\n\n" string_of_statement statements)
let string_of_stylesheet = cat "\n\n" string_of_statement let string_of_stylesheet = cat "\n\n" string_of_statement
...@@ -158,10 +169,9 @@ let minify_media_query query = ...@@ -158,10 +169,9 @@ let minify_media_query query =
let rec minify_condition = function let rec minify_condition = function
| Not c -> "not " ^ add_parens (minify_condition c) | Not c -> "not " ^ add_parens (minify_condition c)
| And c -> cat "and " (add_parens @@ minify_condition) c | And c -> cat " and " (add_parens @@ minify_condition) c
| Or c -> cat "or " (add_parens @@ minify_condition) c | Or c -> cat " or " (add_parens @@ minify_condition) c
| Decl (name, value, false) -> "(" ^ name ^ ":" ^ minify_expr value ^ ")" | Decl (name, value) -> "(" ^ name ^ ":" ^ minify_expr value ^ ")"
| Decl (_, _, true) -> failwith "unexpected \"!important\""
let rec minify_statement = function let rec minify_statement = function
| Ruleset (selectors, decls) -> | Ruleset (selectors, decls) ->
...@@ -189,7 +199,7 @@ let rec minify_statement = function ...@@ -189,7 +199,7 @@ let rec minify_statement = function
in in
"@keyframes " ^ id ^ "{" ^ cat "" minify_keyframe_ruleset rules ^ "}" "@keyframes " ^ id ^ "{" ^ cat "" minify_keyframe_ruleset rules ^ "}"
| Supports (condition, statements) -> | Supports (condition, statements) ->
"@supports " ^ minify_condition condition ^ "@supports " ^ stringify_condition "" condition ^
"{" ^ cat "" minify_statement statements ^ "}" "{" ^ cat "" minify_statement statements ^ "}"
| statement -> string_of_statement statement | statement -> string_of_statement statement
......
...@@ -22,11 +22,13 @@ type descriptor_declaration = string * expr ...@@ -22,11 +22,13 @@ type descriptor_declaration = string * expr
type keyframe_ruleset = expr * declaration list type keyframe_ruleset = expr * declaration list
type supports_declaration = string * expr
type condition = type condition =
| Not of condition | Not of condition
| And of condition list | And of condition list
| Or of condition list | Or of condition list
| Decl of declaration | Decl of supports_declaration
(*XXX: | Enclosed of expr*) (*XXX: | Enclosed of expr*)
type statement = type statement =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment