diff --git a/lexer.mll b/lexer.mll
index cb5c12637a42a3d7da333b7b467046a8be5a1907..47f84616dfb6b250ff18334c682bed9aee0c4bdd 100644
--- a/lexer.mll
+++ b/lexer.mll
@@ -80,8 +80,8 @@ rule token = parse
 
   | "<!--"              { CDO }
   | "-->"               { CDC }
-  | ['~''|']?'=' as op  { RELATION op }
-  | ['>''~'] as c       { COMBINATOR (Char.escaped c) }
+  | ['~' '^' '$' '*' '|']? '=' as op  { RELATION op }
+  | ['>' '~'] as c      { COMBINATOR (Char.escaped c) }
 
   | mystring as s       { STRING (strip_quotes s) }
   | badstring           { raise (SyntaxError "bad string") }
diff --git a/parser.mly b/parser.mly
index 4cbafc5c69154cf9634efafd4b117e2f44d52109..0e71aa03e37775c9b2d2b1213d97a124cd1b1133 100644
--- a/parser.mly
+++ b/parser.mly
@@ -228,18 +228,13 @@ simple_selector:
   { elem ^ String.concat "" addons }
   | addons=element_addon+
   { String.concat "" addons }
-%inline element_addon:
-  | a=HASH | a=cls | a=attrib | a=pseudo
-  { a }
-
+%inline element_addon: a=HASH | a=cls | a=attrib | a=pseudo { a }
 element_name:
   | tag=IDENT  { tag }
   | STAR       { "*" }
-
 cls:
   | DOT name=IDENT
   { "." ^ name }
-
 attrib:
   | LBRACK S* left=IDENT S* right=pair(RELATION, rel_value)? RBRACK
   { let right = match right with None -> "" | Some (op, term) -> op ^ term in
@@ -247,13 +242,11 @@ attrib:
 %inline rel_value:
   | S* id=IDENT S*  { id }
   | S* s=STRING S*  { "\"" ^ s ^ "\"" }
-
 pseudo:
   | COLON id=IDENT
   { ":" ^ id }
-  | COLON f=FUNCTION S* arg=terminated(IDENT, S*)? RPAREN
-  { let arg = match arg with None -> "" | Some id -> id in
-    ":" ^ f ^ "(" ^ arg ^ ")" }
+  | COLON f=FUNCTION args=wslist(COMMA, simple_selector) RPAREN
+  { ":" ^ f ^ "(" ^ String.concat "," args ^ ")" }
 
 declaration:
   | name=property S* COLON S* value=expr important=boption(ig2(IMPORTANT_SYM, S*))