# Ifc Syntax Express

> Use when reading or reasoning about an IFC EXPRESS schema declaration : an ENTITY, TYPE, ENUMERATION, SELECT, a WHERE or UNIQUE rule, or an attribute, and when deciding what a serialized IFC instance must contain. Prevents serializing DERIVE or INVERSE attributes, miscounting positional attributes, instantiating an ABSTRACT supertype, treating SELECT as inheritance, and confusing the three EXPRESS equality operators. Covers the EXPRESS language (ISO 10303-11) used for IFC2x3, IFC4 and IFC4.3 : defined types, enumerations, selects, entities and inheritance, the explicit / DERIVE / INVERSE attribute kinds, WHERE / UNIQUE / global RULE constraints, the four aggregations, the SELF backslash path syntax, and the built-in functions. Keywords: EXPRESS, ISO 10303-11, IFC schema, ENTITY, SUBTYPE OF, SUPERTYPE OF, ABSTRACT SUPERTYPE, ONEOF, ANDOR, TYPE, ENUMERATION OF, SELECT, DERIVE, INVERSE, OPTIONAL, WHERE rule, UNIQUE rule, global RULE, LIST SET ARRAY BAG, SELF backslash supertype, EXISTS SIZEOF TYPEOF QUERY HIINDE

- Skill: `impertio-studio/ifc-syntax-express` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-syntax-express`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-syntax-express/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/ifc-syntax-express

---


# IFC Syntax : The EXPRESS Schema Language

Every IFC schema (IFC2x3, IFC4, IFC4.3) is written entirely in **EXPRESS**, the data
modeling language standardized as ISO 10303-11:2004. EXPRESS is **declarative** : it
describes what a valid population of data looks like, never behaviour or algorithms.
This skill teaches how to read an EXPRESS declaration and how it maps to a serialized
IFC instance. The EXPRESS schema is the **single source of truth** : the STEP physical
file, ifcXML, and ifcJSON are all derived encodings of the same EXPRESS model.

## Quick Reference

### The three attribute kinds : the most important table

| Kind | Stored? | Serialized in the STEP file? | What it is |
|------|---------|------------------------------|------------|
| **Explicit** | Yes | Yes : a positional value | An independently stored value, supplied in the file |
| **DERIVE** | No | No : slot holds `*` | A value computed by an expression (`:=`) |
| **INVERSE** | No | No : occupies no slot at all | A navigable back-reference, reconstructed by the reader |

ALWAYS count only **explicit** attributes (across the full inheritance chain) when
reading or writing a STEP instance. NEVER give a DERIVE or INVERSE attribute a value.

### EXPRESS construct cheat-sheet

| Construct | Declares | Example |
|-----------|----------|---------|
| `TYPE name = base; END_TYPE;` | A defined type (a named, optionally constrained base type) | `TYPE IfcLengthMeasure = REAL; END_TYPE;` |
| `TYPE name = ENUMERATION OF (...); END_TYPE;` | A fixed list of named values | `IfcWallTypeEnum` |
| `TYPE name = SELECT (...); END_TYPE;` | A type union (one-of alternatives) | `IfcUnit` |
| `ENTITY name ... END_ENTITY;` | An entity type with attributes and inheritance | `IfcWall` |
| `RULE name FOR (...); ... END_RULE;` | A schema-level population constraint | global rules |
| `FUNCTION name(...) : T; ... END_FUNCTION;` | A computation used by DERIVE / WHERE | `IfcBaseAxis` |

### STEP physical file markers (the EXPRESS-to-file mapping)

| Marker in the file | EXPRESS meaning |
|--------------------|-----------------|
| `#42=IFCWALL(...)` | An instance ; keyword upper-case, `#id` file-local |
| `$` | An **unset OPTIONAL** explicit attribute |
| `*` | A **DERIVE** (or re-declared) attribute slot ; computed, not stored |
| (absent) | An **INVERSE** attribute : no slot exists in the parentheses |
| `.STANDARD.` `.T.` `.F.` `.U.` | An enumeration, BOOLEAN, or LOGICAL value (dotted) |
| `IFCLENGTHMEASURE(2.5)` | A SELECT-of-defined-type value (wrapped in the type name) |
| `#84` | A SELECT-of-entity value (a bare reference, no wrapper) |
| `(0.,0.,0.)` | Any aggregate (LIST / SET / ARRAY / BAG : the wire syntax is the same) |

### The four aggregations

| Aggregation | Ordered | Duplicates | Bounds | Notes |
|-------------|---------|------------|--------|-------|
| `LIST [lo:hi] OF T` | Yes | Allowed (unless `OF UNIQUE`) | Optional, default `[0:?]` | Indexable |
| `SET [lo:hi] OF T` | No | Never | Optional | Set semantics |
| `ARRAY [lo:hi] OF T` | Yes | Allowed (unless `UNIQUE`) | **Mandatory** | Only one that allows `OPTIONAL` holes |
| `BAG [lo:hi] OF T` | No | Allowed | Optional | Unordered multiset |

`?` as the high bound means unbounded. `LIST OF UNIQUE` differs from `SET` only in that
it is ordered.

### The three equality tokens (NEVER confuse these)

- `=` : **value** equality (deep, structural comparison).
- `:=:` : **instance** equality (identity : same `#id`).
- `:=` : **assignment** ; used ONLY to give a DERIVE attribute its expression. It is not
  a comparison operator.

## Decision Trees

### Which attribute kind is this, and does it go in the file?

```
Where is the attribute declared in the ENTITY body?
|
+-- In the main attribute block (before DERIVE/INVERSE/WHERE)
|   --> EXPLICIT attribute. Serialized as a positional value.
|       If marked OPTIONAL and unset --> written as $
|
+-- Under the DERIVE keyword (has := and an expression)
|   --> DERIVE attribute. NEVER serialized as a value ; slot is *
|
+-- Under the INVERSE keyword (has a FOR clause)
    --> INVERSE attribute. NEVER serialized ; no slot exists at all.
```

### Which TYPE construct is this?

```
TYPE name = ... END_TYPE;  what follows the "=" ?
|
+-- A base type / another defined type (REAL, INTEGER, IfcLengthMeasure, ...)
|   --> Defined type. A named alias, optionally narrowed by a WHERE rule.
|
+-- ENUMERATION OF (V1, V2, ..., USERDEFINED, NOTDEFINED)
|   --> Enumeration. A fixed list of dotted values.
|
+-- SELECT (A, B, C)
    --> Select (type union). An attribute typed by it holds ONE of A, B, C.
        This is NOT inheritance : the alternatives need not share a supertype.
```

### ONEOF vs ANDOR (subtype constraint)

```
SUPERTYPE OF (...)  contains which operator?
|
+-- ONEOF (A, B, C)  --> a concrete instance is EXACTLY ONE of A, B, or C.
|                        Mutually exclusive. The overwhelmingly common IFC case.
|
+-- A ANDOR B        --> an instance may be A alone, B alone, OR A and B together.
                         Multiple inheritance. IFC uses ANDOR rarely.
```

### Can I instantiate this entity?

```
Does the ENTITY declaration say ABSTRACT SUPERTYPE?
|
+-- YES --> NEVER instantiate it. IfcRoot, IfcProduct, IfcElement,
|           IfcObjectDefinition exist only as supertypes. No #id=IFCELEMENT(...).
|
+-- NO  --> It is concrete and instantiable (IfcWall, IfcDoor, IfcCartesianPoint).
            A concrete entity may still be a SUPERTYPE OF other entities.
```

## Patterns

### Pattern : Read an ENTITY declaration top to bottom

An `ENTITY ... END_ENTITY;` block has a fixed order of sections :

```
ENTITY IfcRoot
 ABSTRACT SUPERTYPE OF (ONEOF
    (IfcObjectDefinition, IfcPropertyDefinition, IfcRelationship));
    GlobalId : IfcGloballyUniqueId;
    OwnerHistory : OPTIONAL IfcOwnerHistory;
    Name : OPTIONAL IfcLabel;
    Description : OPTIONAL IfcText;
 UNIQUE
    UR1 : GlobalId;
END_ENTITY;
```

ALWAYS read in this order :

1. `ABSTRACT` (if present) : the entity cannot be instantiated.
2. `SUPERTYPE OF (...)` : its direct subtypes, with `ONEOF` or `ANDOR`.
3. `SUBTYPE OF (...)` : its direct supertype(s). Absent on a root entity.
4. The explicit attribute block : independently stored values, in declared order.
5. `DERIVE` (if present) : computed attributes.
6. `INVERSE` (if present) : back-references.
7. `WHERE` (if present) : per-instance rules.
8. `UNIQUE` (if present) : per-population uniqueness rules.

A subtype **inherits every attribute of every supertype**. A serialized `IfcWall` (chain
`IfcRoot` to `IfcObjectDefinition` to `IfcObject` to `IfcProduct` to `IfcElement` to
`IfcBuiltElement` to `IfcWall`) carries every explicit attribute of all seven levels, in
supertype-first order.

`IfcBuiltElement` is the IFC4.3 name. In IFC2x3 and IFC4 the equivalent supertype is
`IfcBuildingElement` ; IFC4.3 renamed `IfcBuildingElement` to `IfcBuiltElement`. See
`ifc-core-entity-hierarchy`.

### Pattern : Treat the three attribute kinds correctly

ALWAYS check which keyword block an attribute sits under before reasoning about a file.

- **Explicit** attributes are the only ones that appear as positional values. The number
  of values inside the parentheses MUST equal the count of explicit attributes across
  the full inheritance chain.
- **DERIVE** attributes (introduced with `:=` and an expression, for example
  `IfcDirection.Dim := HIINDEX(DirectionRatios);`) are recomputed by every reader. Their
  positional slot holds `*`, never a value.
- **INVERSE** attributes (which always have a `FOR` clause, for example
  `IfcProduct.ReferencedBy : SET [0:?] OF IfcRelAssignsToProduct FOR RelatingProduct`)
  occupy **no slot at all**. The reader rebuilds them by indexing forward `#id`
  references. This is the foundation of the IFC objectified-relationship pattern.

### Pattern : Read the INVERSE FOR clause

`ReferencedBy : SET [0:?] OF IfcRelAssignsToProduct FOR RelatingProduct` reads :
"the set of every `IfcRelAssignsToProduct` instance whose `RelatingProduct` explicit
attribute points at this instance." The `FOR` names the explicit attribute on the other
entity that this INVERSE mirrors. The cardinality (`SET [0:?]`, `SET [0:1]`, ...)
constrains how many back-links may exist. See `ifc-core-relationships`.

### Pattern : Apply the WHERE / UNIQUE / RULE scope correctly

The three constraint mechanisms differ in **scope** :

- A **WHERE rule** constrains **one instance**. A named boolean expression that MUST
  evaluate TRUE for every instance. On a defined type, `SELF` is the value
  (`IfcPositiveLengthMeasure.WR1 : SELF > 0.;`) ; on an entity, `SELF` is the instance.
- A **UNIQUE rule** constrains **across the whole population of one entity type**.
  `IfcRoot.UR1 : GlobalId;` forbids two `IfcRoot` instances from sharing a `GlobalId`. A
  UNIQUE rule may list several attributes for a compound key.
- A **global RULE** constrains **populations across entity types**. It is declared at
  schema level, not on any entity, and can range over an entire population. An entity
  WHERE rule cannot see other instances ; a global RULE can.

NEVER read a WHERE rule, RULE, or function as application behaviour. They are
constraints and computations, never algorithms with side effects.

### Pattern : Read the SELF backslash supertype path

Inside a WHERE rule or DERIVE expression, `SELF\Supertype.Attribute` names an attribute
**inherited from a supertype**. The backslash `\` is the supertype-cast operator : it
narrows the view of `SELF` to a named supertype.

`DimIs3D : SELF\IfcCartesianTransformationOperator.Dim = 3;` reads "this instance,
viewed as its supertype `IfcCartesianTransformationOperator`, its `Dim` attribute." The
qualifier is required because EXPRESS allows an attribute name to be re-declared in a
subtype. ALWAYS expect `SELF\...` whenever a rule reaches up the inheritance chain.

### Pattern : Read the built-in functions in WHERE rules

The functions that actually appear in IFC WHERE rules :

- `EXISTS(v)` : TRUE if `v` is set. The standard guard for OPTIONAL attributes.
- `SIZEOF(agg)` : element count of an aggregate.
- `TYPEOF(v)` : the set of type-name strings of `v` ; used with `IN`, for example
  `'IFC4X3.IFCWALL' IN TYPEOF(x)`. The type-name string is schema-qualified, upper-case.
- `HIINDEX(agg)` / `LOINDEX(agg)` : the actual high / low index of a populated aggregate.
  Distinct from `HIBOUND` / `LOBOUND`, which return the **declared** bounds.
- `QUERY(x <* agg | condition)` : iterate-and-filter. `<*` binds `x` to each element ;
  returns the elements where the filter is TRUE. Almost always wrapped in `SIZEOF(...)`.
- `NVL(v, default)` : returns `v` if set, otherwise `default`.
- `USEDIN(v, 'Schema.Entity.Attribute')` : the instances referencing `v` through that
  role. The functional counterpart of an INVERSE attribute.

See `references/methods.md` for the full ISO 10303-11 function library.

### Pattern : Honour the USERDEFINED / NOTDEFINED enumeration convention

Every IFC predefined-type enumeration ends with `USERDEFINED` and `NOTDEFINED`. When an
instance's `PredefinedType` is `.USERDEFINED.`, the paired free-text attribute (usually
`ObjectType`, inherited from `IfcObject`) MUST carry the actual type name. This pairing
is **enforced by a WHERE rule** on the entity. ALWAYS set the paired attribute when
using `USERDEFINED`. See `ifc-syntax-data-types`.

## Reference Links

- `references/methods.md` : the full EXPRESS construct reference : TYPE / ENUMERATION /
  SELECT / ENTITY grammar, the three attribute kinds, WHERE / UNIQUE / RULE, the four
  aggregations with BNF, the built-in function library, operators, and the complete
  EXPRESS-to-STEP mapping rules.
- `references/examples.md` : verbatim, source-verified EXPRESS snippets from IFC4.3 and
  IFC4 entity pages, each explained, plus the matching STEP serialization.
- `references/anti-patterns.md` : the twelve common EXPRESS misreadings, each with the
  reason it corrupts a file or a reading.

### Official sources

- ISO 10303-11:2004 (EXPRESS Language Reference Manual) : https://www.iso.org/standard/38047.html
- IFC4.3 schema documentation : https://ifc43-docs.standards.buildingsmart.org/
- IFC4 ADD2 TC1 schema : https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/
- IFC2x3 TC1 schema : https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/

### Related skills

- `ifc-syntax-data-types` : the IFC resource-layer value-type system built on EXPRESS
  defined types, selects, and enumerations.
- `ifc-core-data-model` : the four-layer schema architecture written in EXPRESS.
- `ifc-syntax-step-physical-file` : the STEP physical file (ISO 10303-21) encoding.
- `ifc-core-entity-hierarchy` : the IFC inheritance lattice and the
  `IfcBuildingElement` to `IfcBuiltElement` rename.
- `ifc-core-relationships` : the objectified-relationship pattern built on INVERSE.

