diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/selector_syntax.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/selector_syntax.rst
index f4f7c76a3f..cb4628d416 100644
--- a/src/ifcopenshell-python/docs/ifcopenshell-python/selector_syntax.rst
+++ b/src/ifcopenshell-python/docs/ifcopenshell-python/selector_syntax.rst
@@ -56,11 +56,13 @@ Filtering is typically used to select any IFC element or type.
"``IfcWall, Pset_WallCommon.FireRating=2HR``", "Any 2 hour fire rated wall"
+ "``IfcWall, Pset_WallCommon.ThermalTransmittance=""1.5""``", "Any wall with a U-value of 1.5. Note the quotes: ``1.5`` contains a ``.``, so unquoted it is a syntax error. See `Quoting values in filters`_."
+
"``IfcWall, IfcColumn, IfcBeam, IfcFooting, /Pset_.*Common/.LoadBearing=TRUE``", "Any load bearing structure"
"``IfcElement, /Pset_.*Common/.FireRating != NULL``", "Any element with a fire rating property"
- "``IfcWall, type=WT01, location=""Level 3""``", "Any walls of wall type WT01 on level 3 (we quote Level 3 since it has a space)"
+ "``IfcWall, type=WT01, location=""Level 3""``", "Any walls of wall type WT01 on level 3. We quote ``Level 3`` because it contains a space, but a space is only one of several characters that force quoting - see `Quoting values in filters`_."
"``IfcElement, classification=/Pr_.*/``", "Any maintainable product according to Uniclass tables"
@@ -116,7 +118,7 @@ will search through all IfcTypeProducts and IfcProducts in the IFC project.
"Classification", "Filter", "``classification{{=}}{{value}}``", "``classification=Foo`` specifies the criteria that elements must have an IfcClassificationReference with an ``Identification`` attribute with a value of ``Foo``."
"Location", "Filter", "``location{{=}}{{value}}``", "``location=Foo`` specifies the criteria that elements must be contained directly or indirectly in a spatial element with a ``Name`` attribute with a value of ``Foo``."
"Parent", "Filter", "``parent{{=}}{{value}}``", "``parent=Foo`` specifies the criteria that elements must be a direct or indirect child in the spatial hierarchy to an element with a ``Name`` attribute with a value of ``Foo``."
- "Query", "Filter", "``query:{{keys}}{{=}}{{value}}``", "``query:types.count=0`` specifies the criteria that elements must have zero type occurrences. The query keys corresponds to the syntax used in the `Getting element values`_ section"
+ "Query", "Filter", "``query:{{keys}}{{=}}{{value}}``", "``query:""types.count""=0`` specifies the criteria that elements must have zero type occurrences. The query keys corresponds to the syntax used in the `Getting element values`_ section. Note that the keys are quoted: they usually contain a ``.``, which an unquoted string may not. See `Quoting values in filters`_."
.. note::
@@ -149,9 +151,49 @@ three ways you can do so:
:header: "Value Type", "Example", "Description"
"Quoted string", "``""foo \""bar\"" baz""``", "The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value."
- "Unquoted string", "``foobarbaz``", "For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string."
+ "Unquoted string", "``foobarbaz``", "For convenience, if your value contains none of the characters listed under `Quoting values in filters`_ below, you are free to specify it as an unquoted string."
"Regex string", "``/foo.*baz/``", "You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from `Beginners Regex tutorial `_ and `Online Regex testing website `_."
+Quoting values in filters
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+An unquoted ``{{pset}}``, ``{{prop}}``, ``{{keys}}``, or ``{{value}}`` may not
+contain any of the following characters:
+
+.. code-block::
+
+ , . = > < * ! and whitespace
+
+If yours contains one of them, quote it. Every one of them except ``,`` is a
+syntax error when left unquoted. The ``,`` is the more dangerous case, because
+it does not error: it is read as the separator between two filters. So
+``Name=Foo,IfcWall`` does not look for the literal name ``Foo,IfcWall``, it
+quietly means "named ``Foo`` **and** an ``IfcWall``". Write
+``Name="Foo,IfcWall"`` to match the literal value.
+
+The ``.`` is the one most likely to catch you out. It separates a property set
+from a property, so it cannot also appear in an unquoted value, and that makes
+every decimal number a syntax error unless it is quoted:
+
+.. code-block::
+
+ Pset_WallCommon.ThermalTransmittance=1.5 # syntax error
+ Pset_WallCommon.ThermalTransmittance="1.5" # correct
+
+Whole numbers are unaffected, which is why ``FireRating=2HR`` and
+``ThermalTransmittance>1`` are fine unquoted while ``ThermalTransmittance>1.5``
+is not. Quoting a number does not turn the check into a text comparison -
+``>``, ``>=``, ``<``, and ``<=`` still compare numerically, so
+``ThermalTransmittance>"0.9"`` does match a value of ``1.5``.
+
+.. note::
+
+ Query keys obey this same rule, and they nearly always contain a ``.``, so
+ in practice they always need quoting. Write ``query:"types.count"=0``.
+ Written as ``query:types.count=0`` it does not error, it is silently read
+ as a *property* filter looking for a ``count`` property inside a property
+ set named ``query:types``, which is not what you asked for.
+
Getting element values
----------------------
@@ -235,9 +277,31 @@ do so:
:header: "Value Type", "Example", "Description"
"Quoted string", "``""foo \""bar\"" baz""``", "The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value."
- "Unquoted string", "``foobarbaz``", "For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string."
+ "Unquoted string", "``foobarbaz``", "For convenience, if your key contains none of the characters listed under `Quoting keys in value queries`_ below, you are free to specify it as an unquoted string."
"Regex string", "``/foo.*baz/``", "You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from `Beginners Regex tutorial `_ and `Online Regex testing website `_."
+Quoting keys in value queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The characters that need quoting here are not the same set as in
+`Quoting values in filters`_. An unquoted key may not contain any of:
+
+.. code-block::
+
+ . = / and whitespace
+
+All four are a syntax error when left unquoted, so there is no silent
+misreading to worry about in this position. The ``.`` is the key separator and
+the ``/`` delimits a regex, so a property set or property whose own name
+contains either - or a space - has to be quoted:
+
+.. code-block::
+
+ "Fire Rating Data".FireRating
+
+The remaining characters that force quoting in a filter - ``,``, ``>``, ``<``,
+``*``, and ``!`` - are accepted unquoted here.
+
Formatting
----------