The Amorfs Format Specification
Status: DRAFT 0.1 — first public draft. Implementations should expect breaking changes.
Version: 0.1 · Date: June 2026
Copyright: © 2025–2026 First Cognition · License: MIT
Abstract
Amorfs describes how to represent knowledge. It includes a formal model and an intuitive text format for data exchange. It separates the ideas behind the data (concepts) from the words and values used to express them (expressions), and it records every relationship as a first-class thing in its own right — so a relationship between concepts can itself become the subject of another relationship.
Turning data and relationships into abstract concepts creates a structural foundation for context, which is represented as either metadata on concepts/expressions, or relationships with other concepts. Two kinds of relationship are defined: which-is and has-a. Everything in this document is built using these structural elements.
This specification is in two parts. Part I is a guided tour: it builds the model up one idea at a time, using a single running example, and by the end you will be able to read and write Amorfs fluently. Part II is the normative reference: the data model, the formal grammar, semantic rules, conformance classes, and interoperability mappings that implementers need. Read Part I once; consult Part II when you need detailed rules.
How to read this document
| If you are… | Start at | And you can skip |
|---|---|---|
| New to Amorfs | Part I, §A ("The problem") | Part II until you need it |
| Writing Amorfs by hand | Part I in full, then §15 (Syntax cheatsheet) | The grammar appendices |
| Building a parser or renderer | Part I §C–§E, then Part II §10–§14 | — |
| Mapping to RDF / Schema.org | Part I §D, then Appendix E | — |
A note on the two parts. Part I is deliberately informal and example-led; where it simplifies, Part II gives the exact rule. When the two appear to disagree, Part II is authoritative.
Contents
Part I — A Guided Tour (read once, front to back) A. The problem Amorfs solves · B. Two predicates, and nothing else · C. Where Amorfs gets interesting · D. Speaking other systems' languages · E. The whole picture
Part II — Normative Reference (reach for as needed) 6. Terminology · 7. The Data Model · 8. Syntax Specification · 9. Semantic Rules · 10. Expression Types · 11. Metadata Reference · 12. Interoperability and Interchange · 13. Parsing Requirements · 14. Rendering Requirements · 15. Syntax Cheatsheet · 16. Security Considerations · 17. Conformance
Appendices A. Grammar Reference (EBNF) · B. Worked Examples · C. Implementation Checklist · D. Ohm Grammar (Normative) · E. Standard Vocabulary Mappings · F. Change Log · G. References · H. Document Information
Part I — A Guided Tour
A. The problem Amorfs solves
Most data formats are good at storing values and bad at knowing how to interpret them. A spreadsheet cell says 1188.3. A JSON field says "radius": 1188.3. Neither tells you the units, who measured it, when, how confident they were, or whether that figure has since been superseded. The number arrives at its destination as an orphan — separated from the context that makes it meaningful.
We have workarounds to fill in the missing details: a radius_km column name, a sibling radius_source field, a _confidence suffix, a comment, a footnote, a wiki page. Every workaround is a customised agreement between two systems, and every new integration re-formalises it. The meaning lives outside the data, in coding conventions and integration logic.
Amorfs has the representational power to include contextual details with raw data values. The context travels with the data, inside the same structure, using the same machinery as the data itself. A measurement, the unit it is in, the instrument that produced it, the date it was taken, and your confidence in it are all the same kind of thing — concepts in a graph — so they can all be written down together and read back without a separate schema or legend.
We can see how Amorfs works by walking through a worked example: the history of Pluto.
B. Two predicates, and nothing else
B.1 Your first Amorfs
Here is a complete, valid Amorfs document:
planet [Pluto]
It reads aloud as "planet, which is, Pluto." The square brackets denote the which-is relationship. They say that the concept on the left (planet) is instantiated by the concept inside (Pluto).
There are two important things to call out, because they apply everywhere:
planetandPlutoare both concepts. Neither is "more real" than the other.planetis not a column header or a type tag with special status; it is a concept that happens to play a classifying role here. Roles emerge from position in the graph, and a concept can be used in more than one role.- The text
planetand the textPlutoare expressions — the visible surface of those concepts, not the concepts themselves. This distinction (borrowed, in spirit, from Frege's sense and reference) is what lets one concept have several expressions, as seen in subsequent examples.
B.2 The other predicate: has-a
The second and final predicate attaches a property or type of thing. It's written with a leading + or -:
planet [Pluto
+ discovered date [1930]
]
Read this as "planet which is Pluto, has-a discovered date, which is 1930." The + discovered date [...] line opens a has-a slot on Pluto and then fills it. Notice the slot itself uses which-is again (discovered date [1930]): the two relationships interlock. Has-a opens a slot; which-is fills it.
That is the entire grammar. There are no other relationships. "Was discovered in," "has a mass of," "is classified as," "was named by" — all of them are has-a slots whose names are ordinary concepts (discovered date, mass, classification, named by). The relationship stays fixed; the meaning lives in the concept that names the slot. A closed set of relationship types is what makes Amorfs uniformly parseable and uniformly queryable: a tool never has to know your vocabulary to know your structure.
Why
+and-? Both mean has-a. They differ only in what the slot hangs off of — a subtlety that's explained in §C.3. Until then, read both as "has a," and when in doubt use-.
B.3 One concept, many expressions
Pluto has been called many things. It is Pluto in English, 冥王星 in Japanese, and 134340 Pluto in the Minor Planet Center's catalogue. These are not three different concepts — they are three expressions of the same concept. The pipe | lists them as alternatives:
planet [Pluto | 冥王星 | 134340 Pluto]
All three expressions attach to the same concept node in the graph. Search for any one of them and you find the others; merge two records that share an expression and the concept unifies. That is why the sense/reference split matters: meaning lives in the concept, not in the string. Synonyms, translations, and catalogue designations become standard capabilities.
We can tag each surface form with the language it's in, using expression metadata — tight braces with no space before them:
planet [Pluto{en} | 冥王星{ja} | 134340 Pluto]
{en} and {ja} annotate those specific strings, not the underlying concept. (The catalogue designation gets no language tag — it isn't English or Japanese, it's just an identifier.)
B.4 Building out the entity
Let's give Pluto some properties. Each is a has-a slot filled by a which-is:
planet [Pluto | 冥王星{ja}
+ discovered [1930-02-18]
+ radius [1188.3]
+ moons [Charon, Nix, Hydra, Kerberos, Styx]
]
Indentation and newlines are for humans; the parser ignores them. What it sees is: a concept planet instantiated by Pluto (with two expressions), which has a discovery date, a radius, and a set of moons.
The moons have , as the divider. Those aren't alternative names for one moon. They're five different moons. For that we need a different separator, which raises an important distinction in the syntax.
B.5 | versus , — alternatives versus a list
This is the one piece of punctuation that can be confusing:
| Separator | Means | Graph effect |
|---|---|---|
| |
Alternative expressions of one concept (synonyms, translations) | |
, (comma-then-space) |
Several distinct concepts | Several concepts, each bound separately |
So Pluto's five moons — five different bodies — use comma-space:
planet [Pluto
+ moons [Charon, Nix, Hydra, Kerberos, Styx]
]
…whereas Pluto's several names — one body — use the pipe:
planet [Pluto | 冥王星 | 134340 Pluto]
The space after the comma is significant. It allows in-value commas like 1,188 km or $12,345 to stay as individual expressions, because there's no space after. Common punctuation doesn't accidentally change the meaning.
That covers how to describe an entity. What else can the Amorfs format do?
C. Where Amorfs gets powerful
C.1 Relationships are concepts too
From §B, planet [Pluto] created an association — a which-is linking planet and Pluto. Here is a central pillar that supports the whole model:
Every association is itself a concept. It has an identity. It can be named, annotated, and it can be the subject or object of further associations.
This means you can make statements about statements. Relational tables and plain JSON cannot do that without a side-table or a parallel structure. Amorfs carries context using the same structure as the data.
As an example, take Pluto's most famous moment in 2006, when it was reclassified. That fact is not really a property of Pluto — it's a property of the statement "Pluto is a planet." The statement was true, until one day an organisation decided otherwise. Amorfs lets you attach that history to the statement itself rather than spreading it across separate fields on Pluto.
C.2 Contextual claims and intrinsic facts
Pluto's reclassification is the moment to separate facts about Pluto from facts about the claims we make about Pluto.
+(intrinsic) hangs a slot off the entity — Pluto itself. Its radius, its moons, its discovery date are facts about the rock itself. They use+.- Contextual metadata
{…}attaches to the which-is relationship. The bracketplanet [Pluto {1930-02-18/2006-08-24}]is the statement "Pluto is a planet," valid from discovery until 24 August 2006. You do not need to restate the type inside a nested slot — the label already carries it. - Supersession is a new parameter binding, not an overwrite. When the IAU reclassified Pluto in 2006, the superseding claim is simply another line:
planet [Pluto {{~1.0}} {1930-02-18/2006-08-24} # the claim "Pluto is a planet"
+ radius [1188.3 - unit [km]] # about the body
- discovered by [Clyde Tombaugh]
]
dwarf planet [Pluto {2006-08-24/} # the superseding claim
- reclassified by [IAU | International Astronomical Union]
]
The interval {1930-02-18/2006-08-24} attaches to the "planet which is Pluto" relationship itself — the claim whose validity ended in 2006. The open-ended {2006-08-24/} on the dwarf-planet binding means "from then, still current." Both claims can exist at the same time because each carries its own validity period on its own is-bind — no overwrite, no lost history. The intrinsic + facts attach to Pluto itself, regardless of which type bracket it appears under; a query keyed on Pluto gathers radius and discovery without duplicating them under the dwarf-planet line.
- (contextual) hangs a slot off the association currently in scope — the statement we're inside. The - reclassified by line attaches to the "dwarf planet which is Pluto" binding: who made that claim, not a fact about Pluto the body. Use - for attributes of a relationship (§C.5 shows another with - name [...]), not the object or thing itself. When there's no surrounding context (no parent association), - simply behaves like +.
Remember:
+for the thing,-for the thing in context.
C.3 Following the chain: nesting and inherited context
Slots can be filled by whole sub-structures, nesting to any depth. Each level inherits the context of its parents:
observatory [Lowell Observatory
- location [
+ city [Flagstaff]
+ state [Arizona]
+ country [USA]
]
- discovery [
+ of [Pluto]
+ by [Clyde Tombaugh]
+ date [1930-02-18]
]
]
The discovery here is an implied concept — a bracket with no instance expression of its own. It has no name, yet it's a perfectly good concept defined entirely by its associations: a discovery of Pluto, by Tombaugh, on a date. A concept need not have a label expression; its associations can be enough.
C.4 Reuse: naming a concept with @
We've now mentioned Pluto in two documents — once as a planet, once as the object of a discovery. We'd like those to be the same Pluto. Concept references let you name a concept once and point at it anywhere:
planet [{{@pluto}} Pluto | 冥王星{ja}
+ radius [1188.3 - unit [km]]
]
observatory [Lowell Observatory
- discovery [
+ of [@pluto]
+ by [Clyde Tombaugh]
]
]
The {{@pluto}} registers the name on first use (inside the concept's metadata block); every later @pluto is a lookup. Now both documents agree on a single Pluto node, and a query that asks "what do we know about @pluto?" gathers the radius and the discovery.
C.5 Provenance, the natural way
This is the point from §A. Because relationships are concepts, and metadata attaches to them, recording where a fact came from needs no special facility — it's just more concepts and more metadata. The naming of Pluto is a good example: the name was suggested by Venetia Burney, an eleven-year-old schoolgirl in Oxford, passed to the observatory through her grandfather, and formally adopted in 1930. That is a chain of provenance, and Amorfs records it as one:
source [Lowell Observatory records {@lowell}]
proposer [Venetia Burney {@venetia}
- age at proposal [11]
+ city [Oxford]
]
planet [@pluto
- name [Pluto {proposed_by=@venetia, adopted=1930-05-01, source=@lowell, ~1.0}]
]
The {proposed_by=@venetia, adopted=1930-05-01, source=@lowell, ~1.0} block hangs off the naming is-association — the bind (name, is, Pluto). (Order matters: {@venetia} and {@lowell} register those anchors on earlier is-binds first, because a @name used inside metadata must already exist — §11.4.) The - age at proposal line attaches to the proposer binding; + city attaches to Venetia herself. It says: this name was proposed by Venetia, adopted on this date, sourced from these records, with full confidence — and @venetia and @lowell are not strings but links to actual concepts you can follow and ask further questions of. The fact and its provenance stay together, and both are queryable.
C.6 Confidence, importance, and time, in one place
Three kinds of annotation recur often enough to have dedicated sigils:
| Sigil | Meaning | Example |
|---|---|---|
~n |
Confidence, 0.0–1.0 | ~0.95 |
+n / -n |
Importance (relative weight) | +2, -1 |
| ISO‑8601 | Time — an instant or an interval with / |
2006-08-24, 1930-02-18/2006-08-24 |
They live in metadata blocks alongside everything else. A measurement whose precision improved when New Horizons flew past in 2015 might read:
planet [@pluto
- radius [1188.3 {2015-07-14, ~0.99} - unit [km]]
]
A confidence of ~0.99, valid from the flyby date. Earlier, less certain figures could sit beside it under their own dates and confidences, and nothing would be lost.
D. Speaking other systems' languages
A representation that can't talk to RDF, Schema.org, or your existing database doesn't interoperate without extra work. Amorfs interoperates through the same alternative-expressions mechanism you already met in §B.3 — by giving a slot both a human name and a standard predicate:
planet [@pluto
+ same as | owl:sameAs [<http://dbpedia.org/resource/Pluto>]
- name | schema:name | rdfs:label [Pluto]
- discoverer | dbo:discoverer [Clyde Tombaugh]
]
name, schema:name, and rdfs:label are three expressions of one slot-naming concept. A human reads name; an RDF tool recognises schema:name; a triple store ingests rdfs:label. No translation layer, no loss — the standards live in the data as additional surface forms. Angle brackets <...> mark IRIs, which give machine-resolvable identity to anything that has a URL. (Appendix E catalogues the common vocabularies: Dublin Core, FOAF, Schema.org, OWL, SKOS, QUDT, PROV.)
The same pipe syntax exports cleanly to JSON and XML (§12.2), round-trips back to Amorfs text without loss, and can flatten to CSV when someone just wants a flat table (losing recursion and abstract concepts, as any flattening must).
E. The whole picture
Notice what we didn't need. No schema declared up front. No distinction between a class and an instance, a field and a value, data and metadata, content and presentation. Pluto's radius, the unit that radius is in, the date it was measured, the confidence in it, the schoolgirl who named the planet, and the very claim that it is a planet — all of these are concepts, related by the same two predicates, annotated by the same metadata. The same pattern runs throughout.
That uniformity is the point of the design. A format with one kind of node and two kinds of edge is small enough to specify completely, parse unambiguously, and query generically — yet, because edges are themselves nodes, it is expressive enough to carry the context that other formats leave orphaned. Here is the running example assembled, every feature from this tour visible at once:
source [Lowell Observatory records {@lowell}]
proposer [Venetia Burney {@venetia}
- age at proposal [11]
+ city [Oxford]
]
planet [{{@pluto, ~1.0}} Pluto | 冥王星{ja} | 134340 Pluto {1930-02-18/2006-08-24}
# intrinsic facts about the body
+ radius [1188.3 {2015-07-14, ~0.99} - unit [km | kilometres{en}]]
+ moons [Charon, Nix, Hydra, Kerberos, Styx]
+ discovered [1930-02-18 - by [Clyde Tombaugh] - at [@lowell]]
# facts about the *claim* we make about Pluto
- name [Pluto {proposed_by=@venetia, adopted=1930-05-01, source=@lowell}]
# interoperability
+ same as | owl:sameAs [<http://dbpedia.org/resource/Pluto>]
]
dwarf planet [@pluto {2006-08-24/}
- reclassified by [IAU | International Astronomical Union]
]
If you can read that — the names, the moons, the measurement with its unit and confidence and date, the two time-bounded type bindings, the provenance of the name and reclassification, the link out to the wider web — you can read Amorfs. The rest of this document makes every rule above precise.
Part II — Normative Reference
The sections that follow are the authoritative specification. Part I introduced the model through one example; here we define it for implementers. The keywords MUST, MUST NOT, REQUIRED, SHALL, SHOULD, RECOMMENDED, MAY, and OPTIONAL are to be interpreted in their conventional specification sense: MUST/SHALL/REQUIRED are absolute, SHOULD/RECOMMENDED are strong defaults, MAY/OPTIONAL are permitted.
This specification defines: the abstract data model, the concrete text syntax and its grammar, semantic interpretation rules, requirements for conformant parsers and renderers, interoperability with standard formats, and presentation handling. It does not define: application programming interfaces, user-interface implementations, storage backends, or networking protocols.
6. Terminology
These are the working definitions referenced throughout Part II. Part I §B–§C is the informal introduction; this is the precise one.
Amorfs knowledge base. The complete formal object denoted by an Amorfs document: — concept identifiers , expressions , expression mapping , association structure (reified quads over ), and metadata . See §7.1. A formal treatment of the model is forthcoming from First Cognition.
Concept. An opaque identifier in — the sole node universe. A concept carries no semantic content in itself; it derives meaning from its expressions (via ), from association structure (when it names a quad in ), and from its associations to other concepts. (In Part I: planet, Pluto, and discovery are all concepts.)
Expression. A member of — a concrete, physical representation that makes a concept readable to a human or a machine (text, a number, a date, an IRI, or multimedia). Expressions appear before [ (naming the concept being described) or inside [ (providing a value or further description). Alternative expressions of one concept are separated by |. Expressions are the sense/reference surface; the concept is the referent. All semantic content for base concepts lives in expressions, linked through .
Expression mapping (). The many-to-many relation linking concepts to expressions. One expression may represent several concepts; one concept may have several expressions. This is the presentation layer of the model alongside .
Association structure (). The set of reified quads over : subject , predicate , object , and name . The name is a concept that may appear as subject or object of further quads. This is the structure layer of the model alongside . The formal home of relational structure is , not a separate ontology.
Association. A directed relationship between concepts, recorded as a named quad in and structured as a subject–predicate–object triple carried by the name concept . Associations are themselves concepts and may participate in further associations (the recursion of Part I §C.1).
Base concept. A concept whose content is carried chiefly by its expressions in — typically an entity, attribute, or value (e.g. Pluto, radius, 1188.3). Distinguished for exposition only from an association-name concept; both are the same kind of node.
Association concept (association-name concept). A concept that names a quad in and carries the triple recorded there. It is a first-class member of the single concept set with the same capabilities as any other concept.
Intrinsic association (+). A has-a association whose subject is the intrinsic subject of the enclosing bracket — the instance referent (e.g. Pluto in planet [Pluto + radius […]]), or the implied instance when the bracket has no instance expression. The + is surface syntax that selects a subject; it is not stored in the graph.
Contextual association (-). A has-a association whose subject is the parent association-name in scope (e.g. the "planet which is Pluto" association for - name [...]). When no parent association exists in scope, - is equivalent to +. Like +, it is a surface-syntax subject selector, not persisted.
Implied concept. The instance side of ⟨label, is, implied⟩ produced when a bracket has no instance expression: a concept with no expression of its own, defined wholly through its associations (e.g. the unnamed discovery in Part I §C.3). The bracket's label remains a separate concept.
Concept reference (@name). A named anchor that lets a concept be referenced elsewhere in the document or across documents (Part I §C.4).
Basic predicate phrases. The two — and only two — relationship types: has-a (written - or +) and which-is (written []). Has-a opens a class-side attribute or relation slot; which-is optionally binds the instance side — when present, the class-side subject instantiates as the instance-side object (both concepts).
7. The Data Model
7.1 Abstract model
An Amorfs document denotes an Amorfs knowledge base :
| Component | Role |
|---|---|
| Concept identifiers — the sole node universe (ordinary concepts and association-name concepts alike). Concepts carry no semantic content in themselves. | |
| Expressions — text, numbers, IRIs, multimedia, ciphertext, and other surface forms. | |
| Expression mapping — many-to-many links between concepts and expressions. All semantic content for base concepts lives here. | |
| Association structure — reified quads over , with predicate and name . Association-name concepts carry via membership in . | |
| Metadata on concepts, expression links in , and association-name concepts — including temporal bounds, confidence, importance, and provenance (§11). |
Two layers compose the model:
- Structure layer — opaque identifiers and reflexively reified quads. Each quad is named by a concept that may itself participate in further quads. (This naming-of-quads is the formal core of "relationships are concepts.") The relational skeleton is role-ordered, fixed-arity reified quads — not a hypergraph: subject, predicate, object, and name are distinct roles.
- Presentation layer — expressions and their links to concepts. Readable meaning for base concepts is entirely in this layer; structure and surface meaning are independently manipulable (separated semantics).
Metadata cross-cuts both layers at three attachment points (§11): base concepts, expression links, and association names. Temporal validity periods live in , not as a separate model component.
Implementations SHOULD represent as in packages/core — concepts, expressions, expression links, associations (quads), and metadata maps aligned with this definition.
7.2 Concepts
7.2.1 Identity. Each concept MUST have a unique identifier that persists in the model, zero or more linked expressions, zero or more associations to other concepts, and OPTIONAL metadata (confidence, importance, temporal bounds, provenance). Concepts MUST NOT contain their own data directly — data lives only in expressions — and MUST NOT be duplicated when semantically equivalent (merging is required; see §9.1).
7.2.2 Concept roles. The model recognises two roles in , for organisational purposes only:
- Base concepts (ordinary): content is chiefly in the expression mapping — entities, attributes, values.
- Association concepts (association-name): content is the triple recorded in ; the concept id is the quad name .
This distinction is organisational, not a separate node type. Association-name concepts are first-class members of with identical capabilities to ordinary concepts.
7.3 Expressions
7.3.1 Properties. Expressions MUST reference at least one concept; MAY reference several (a shared expression); MAY be any digital format (text, number, multimedia, IRI); MAY carry language tags for linguistic content; SHOULD carry type indicators where interpretation depends on them; and MAY carry metadata.
7.3.2 Concept linkage. The expression↔concept mapping is many-to-many (one expression may represent several concepts; one concept may have several expressions). It MUST preserve all linkages when concepts are merged, SHOULD support prioritisation when several expressions exist, and MAY carry metadata.
7.4 Associations
7.4.1 Structure. Every association concept MUST have a subject (the concept possessing a characteristic or performing an action), a predicate (the relationship type — for basic associations, has-a or which-is), and an object (the characteristic or the receiver of the action).
7.4.2 First-class status. Association-name concepts MUST receive unique identifiers in like any other concept; carry their via membership in ; MAY have linked expressions describing the relationship; MAY serve as subject or object of further quads (enabling recursion); and MAY carry metadata.
7.4.3 Intrinsic vs. contextual (+ / -). The + and - operators are surface-syntax subject selectors for new has-a associations and are not stored in the graph.
- Intrinsic (
+): subject = the intrinsic subject of the enclosing bracket — the instance referent, or the implied instance when there is no instance expression. - Contextual (
-): subject = the parent association-name in scope. Fallback: when no parent association exists,-is equivalent to+on the intrinsic subject (soPluto - moon [Charon]≡Pluto + moon [Charon]).
Concept matching (§9.1.1) may weight referent-level versus association-scoped has-edges by inferring subject position from the graph, not from any stored operator marker.
7.4.4 Association names. Every quad in has a name concept (the reified fourth coordinate). The name uniquely determines the triple; distinct quads MUST have distinct names; and the name MAY appear as subject or object of further quads, enabling recursive provenance and statement-level metadata. Implementations MUST assign a persistent unique identifier to each association name when building a graph from text.
7.5 Recursive reification properties
The recursion of §7.4.4 — quad names in participating as subjects or objects of further quads in — means associations can nest to any depth, carry inherited context, support different views of the same concepts, and record provenance at the level of individual statements (Part I §C.5).
8. Syntax Specification
8.1 Overview
The text syntax is a human-readable, machine-parseable surface for the model of §7. It uses ASCII-compatible structural delimiters, supports nesting to arbitrary depth, and maps directly onto the abstract model. Implementations MUST support UTF-8.
8.2 Character set
| Character | Name | Purpose |
|---|---|---|
[ ] |
Brackets | Begin / end an item list (the which-is predicate) |
+ |
Plus | Intrinsic has-a operator (with trailing space) |
- |
Minus | Contextual has-a operator (with trailing space) |
| |
Pipe | Expression alternative separator |
, |
Comma | Item / multi-value separator (multi-bind requires a following space) |
{ } |
Braces | Metadata block |
< > |
Angles | IRI delimiters |
~ |
Tilde | Confidence indicator |
@ |
At sign | Concept reference |
# |
Hash | Comment |
8.3 Lexical structure
8.3.1 Whitespace. Whitespace is generally insignificant, except: inside quoted strings; where it separates adjacent alphanumeric tokens; that a SPACE is REQUIRED before and after an association operator (+ / - ); that a SPACE is REQUIRED before an inline comment (#); and that a NEWLINE is equivalent to a comma (item separator) within a concept list. Implementations SHOULD preserve whitespace inside expressions but MUST NOT require specific whitespace for correct parsing beyond these cases.
8.3.2 Comments. A comment begins with # and runs to end of line. Comments are stripped during parsing, create no concepts or associations, and are not preserved in the graph — they exist only in the source text.
dwarf planet [@pluto {2006-08-24/}
- reclassified by [IAU] # contextual slot on the claim, not the body
]
8.3.3 Expressions. At parse time every expression slot holds an opaque string — quoted or unquoted text, or a @name reference at a slot boundary. Type interpretation (number, date, URL, email) is a semantic concern, not a grammar branch.
- Unquoted expressions: text without the delimiters
[]|,{}". May contain Unicode letters, digits, spaces, underscores, hyphens, mid-string@(emails),.(e.g. IPv4), and#(e.g. a colour like#0064f3— not a comment inside an expression). Case-sensitive. Examples:radius,1930-02-18,1188.3,134340 Pluto,clyde@lowell.edu,#0064f3,12 Nov 2024 7 am / 1 hour. - Quoted expressions: REQUIRED when text contains Amorfs delimiters. Enclosed in double quotes; internal quotes escaped. Examples:
"value, with comma","He said \"hello\"","@handle"(a literal beginning with@). - Angle-bracket expressions: IRIs and paths in
<…>, e.g.<http://dbpedia.org/resource/Pluto>,<./transforms/normalise.py>.
Importance and confidence literals (+1, ~0.9) appear only inside metadata blocks, not as separate expression alternatives. Datetime / temporal forms (§10.3) MAY appear either as metadata items or as a whole expression string. A whole expression that matches TemporalSpec SHOULD auto-mint temporal metadata when none is already present (expression-first authoring), except bare four-digit yearLiterals (2026), which are too ambiguous with numeric ids. Duration-only strings such as 20 min are ordinary text and MUST NOT auto-mint temporal metadata.
8.3.4 Operator disambiguation. The +, -, and @ characters are overloaded; implementations MUST disambiguate:
- Inside
{…}metadata,+/-immediately followed by a digit is an importance marker (§11.6.4), not an association operator. - A
+/-(operator then space) at an inner-item position introduces a nested intrinsic/contextual association. - Inside expression slots,
+and-are ordinary characters (-1,2010-09-19,C++); a lone+/-before a space is not a valid expression, so it cannot be confused with an operator. @nameat an expression boundary (after[,,, or|) is a concept reference; a mid-string@is literal (emails). A trailing@nameafter]uses the same reference token as an association anchor (§11.4).
8.4 Grammar productions
The grammar below uses simplified EBNF: ::= is "is defined as"; | separates alternatives; * is zero-or-more; + is one-or-more; ? is zero-or-one; () groups; "" is literal. The normative artifact is the Ohm grammar in Appendix D; §8.4 here is its readable companion, and the two are kept aligned.
amorfs_document ::= concept_list
concept_list ::= concept ("," concept)*
concept ::= label_part? "[" inner_content "]" anchor?
| referent_first_concept
| unbound_concept
| concept_reference
unbound_concept ::= expression_list concept_meta? anchor?
referent_first_concept ::= expression_list concept_meta? referent_first_inner_item+ anchor?
referent_first_inner_item ::= association_operator assoc_meta? nested_concept
label_part ::= expression_with_metadata ("|" expression_with_metadata)* label_trailing_meta?
label_trailing_meta ::= concept_meta
concept_meta ::= "{{" metadata_list "}}"
inner_content ::= concept_meta? expression_list? inner_item*
inner_item ::= association_operator assoc_meta? nested_concept
assoc_meta ::= "{" metadata_list "}"
anchor ::= "@" reference_name
expression_list ::= expression_slot ("|" expression_slot | ", " expression_slot)* concept_meta?
expression_slot ::= expression_with_metadata referent_assoc_meta?
referent_assoc_meta ::= "{" metadata_list "}"
expression_with_metadata ::= expression expr_meta?
expr_meta ::= "{" metadata_list "}"
expression ::= unquoted_text | quoted_text | concept_reference
association_operator ::= "+ " | "- "
metadata_list ::= metadata_item ("," metadata_item)* ","?
metadata_item ::= concept_ref_item | language_code | temporal_spec
| confidence_spec | importance_spec | custom_attribute | flag_item
concept_ref_item ::= "@" reference_name /* registration directive; §11.4 */
language_code ::= letter letter /* ISO 639-1 */
temporal_spec ::= slash_interval | instant_spec
slash_interval ::= instant_spec "/" (instant_spec | duration_spec)?
instant_spec ::= friendly_instant | datetime_literal | year_literal
duration_spec ::= iso_duration | human_duration
confidence_spec ::= "~" numeric_literal /* 0.0 to 1.0 */
importance_spec ::= ("+" | "-") numeric_literal
custom_attribute ::= reference_name "=" (expression | concept_reference)
flag_item ::= reference_name /* bare flag, e.g. formal, informal */
concept_reference ::= "@" reference_name
reference_name ::= (letter | "_") (letter | digit | "_" | "-")*
unquoted_text ::= /* text without delimiters []{},|+- or boundary whitespace */
quoted_text ::= '"' (escaped_char | [^"])* '"'
escaped_char ::= "\\" ('"' | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
iri_literal ::= "<" iri_content ">"
numeric_literal ::= ["-"] digit+ ("." digit+)? (("e" | "E") ["+"|"-"] digit+)?
datetime_literal ::= /* ISO 8601: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS±HH:MM */
friendly_instant ::= /* D Mon YYYY [h[:mm] am|pm] [±HH:MM] — see §10.3 */
8.5 Grammar notes
These notes resolve the cases implementers most often get wrong.
- Which-is at concept level.
planet [Pluto]is a concept with leading expressionplanetand inner expressionPluto; semantically a which-is (instantiation)⟨planet, is, Pluto⟩. Text before[is not a special "label" type — it uses the same expression algebra as values inside brackets. - Implied instance.
discovery [ + of [Pluto] ](no instance expression) creates⟨discovery, is, implied⟩then(implied, has, of), the same association spine asdiscovery [event + of [Pluto]], differing only in implied-versus-named instance. - Bracket interior.
inner_contentisconcept_meta? expression_list? inner_item*. Leading expressions inexpression_listare the instance referent for the bracket label — they are not inner-items and do not take+/-. Every inner-item requires+or-before a nested concept. A bare nestedchild [value…]sibling (without+/-) is a syntax error: it would skip the has-a spine and incorrectly chain direct which-is edges. Referent expressions belong inexpression_listinstead. - Anchor declaration. An optional
@nameafter]registers a reusable reference, e.g.planet [Pluto] @pluto. This is distinct from{{@name, …}}row-anchor creation inside the bracket (§11.4). - Metadata attachment points.
expr_metaon expressions;concept_meta({{…}}) on base concepts;assoc_meta({…}) on association steps and inside value brackets. Metadata MUST NOT follow a closing](§11.3). - Referent-first concepts. At document level,
referent inner_item+(no type label, no wrapping brackets) is valid — the leading expression is the direct subject of the associations, e.g.Tombaugh - discovered [Pluto]. Label-first associations, by contrast, require brackets:discovery [ - of [Pluto] ], not barediscovery - of [Pluto].
8.6 Syntax examples
The examples below each isolate one feature. Where natural they continue the astronomy thread; together they cover the surface syntax exhaustively.
8.6.1 Basic concept (which-is).
planet [Pluto]
Concept planet with an instance concept Pluto. The brackets denote ⟨planet, is, Pluto⟩.
8.6.2 Multiple expressions (synonyms / catalogues / languages).
planet [Pluto | 134340 Pluto | 冥王星]
star [Sirius | α Canis Majoris | Dog Star]
Alternatives separated by | are surface forms of one concept.
8.6.3 Expression language metadata.
planet [Pluto{en} | 冥王星{ja}]
greeting [Hello{en} | Bonjour{fr} | Hola{es} | こんにちは{ja}]
Tight expr{meta} (no space before {); language codes are ISO 639-1. See §11.1.1.
8.6.4 Quoted expressions.
note ["This [text] has special characters"]
formula ["x = [a + b] / 2"]
Quotes are required when an expression contains Amorfs delimiters.
8.6.5 Intrinsic associations (+).
planet [Pluto
+ radius [1188.3]
+ discovered [1930-02-18]
]
+ selects Pluto (the instance referent) as subject: (Pluto, has, radius), (Pluto, has, discovered) — not the parameter concept planet.
8.6.6 Timed parameter bindings (reclassification).
planet [Pluto {1930-02-18/2006-08-24}
+ radius [1188.3]
+ discovered [1930-02-18]
]
dwarf planet [Pluto {2006-08-24/}
- reclassified by [IAU | International Astronomical Union]
]
Each {…} interval attaches to the is association for that type binding — the claim itself, not a nested slot. Supersession is a new parameter binding with its own validity period. Contextual - on the dwarf-planet binding (- reclassified by) and in §8.6.7 (- employer, - discovered) attach slots to the binding rather than the referent.
8.6.7 Entity-wide vs. per-association metadata.
person [Clyde Tombaugh {{1906-02-04, ~1.0}}
- employer [Lowell Observatory {1929-01-01/}]
- discovered [Pluto {1930-02-18}]
]
Entity-wide attributes (birth, confidence) on the referent via {{…}}; per-association dates inside each value bracket. Metadata never follows a closing ] (§11.3).
8.6.8 Nested structures and inherited context.
country [USA
- state [Arizona
- city [Flagstaff
- observatory [Lowell Observatory]
]
]
]
Arbitrary nesting; each level inherits the context of its parents (§9.5).
8.6.9 Implied concepts.
discovery [
+ of [Pluto]
+ by [Clyde Tombaugh]
+ date [1930-02-18]
+ at [Lowell Observatory]
]
The bracket creates a parameter concept discovery and an implied instance with no expression; each + child uses that implied instance as subject. A contextual child (- …) would instead use the binding association as subject.
8.6.10 Concept references.
planet [{{@pluto}} Pluto | 冥王星{ja}
+ radius [1188.3]
]
mission [New Horizons
- flew past [@pluto {2015-07-14}]
]
First registration uses {{@name}} (base concept) or {@name} (association); afterward bare @name is lookup only. See §11.4.
8.6.11 IRI expressions.
planet [Pluto
+ same as | owl:sameAs [<http://dbpedia.org/resource/Pluto>]
- data [<https://api.le-systeme-solaire.net/rest/bodies/pluto>]
]
IRIs give machine-readable identity for disambiguation and linking.
8.6.12 Metadata flags.
person [Venetia Burney{en, ~0.99, formal} | Venetia{informal, ~0.85}]
Bare identifiers in a metadata list are flags. Language codes and formality flags (formal, informal) are expression metadata only — they tag a surface form, and MUST NOT appear in base-concept {{…}} blocks (§11.6.6).
8.6.13 | vs. , — alternatives vs. multi-bind.
| Separator | Semantics | Graph effect |
|---|---|---|
| |
Alternative expressions of one concept | One is association; multiple expressions in |
, |
Multi-value bind | Several is associations from one subject |
- name [Venetia Burney | V. Burney] # alternatives — one person
+ moons [Charon, Nix, Hydra] # multi-bind — three moons
- price [$12,345] # no space after comma → literal
For moons [Charon, Nix, Hydra], each value binds through a separate is association from the same has occurrence.
8.6.14 Referent-first concepts.
Tombaugh - discovered [Pluto]
The leading expression Tombaugh is the direct subject: (Tombaugh, has, discovered) then (discovered, is, Pluto). With no parent association in scope, - behaves as +. Contrast the typed form person [Tombaugh - discovered [Pluto]], where - discovered attaches to the person-is-Tombaugh binding rather than to Tombaugh directly.
9. Semantic Rules
9.1 Concept equality and merging
9.1.1 Equality. Two concepts are equivalent if they share identical referent-level has-associations (same property concepts as objects, with referent or implied-instance subjects) at high confidence; or they share sufficient expressions with matching context; or equivalence is explicitly asserted by merging.
9.1.2 Automatic merging. When the parser encounters expressions indicating equivalence —
planet [Pluto]
planet [134340 Pluto]
later made explicit as planet [Pluto | 134340 Pluto] — the system MUST identify the previously separate concepts, merge them, preserve all expressions and associations from both, and update all references to the unified identifier.
9.1.3 Conflict resolution. When merging concepts with conflicting associations: conflicting referent-level has-associations MUST be reconciled (treated as a potential error); association-scoped has-associations MAY coexist with temporal or source differentiation (this is exactly how Pluto's two timed type bindings — planet and dwarf planet — live side by side); and expression priorities MAY be adjusted by confidence.
9.2 Association semantics
9.2.1 The two predicates.
Has-a (- or +) opens a class-side attribute or relation slot — Pluto has-a radius, discovery has-a date, observatory has-a location.
Which-is ([]) is instantiation, and is optional — radius which-is 1188.3, classification which-is "dwarf planet". All which-is associations share one instantiation semantics: the class-side subject instantiates as the instance-side object (both concepts). Whether a which-is is a slot binding (after a has-a, the occurrence instantiates as the object) or a parameter binding (e.g. planet [Pluto]) is determined by graph structure, not by a separate predicate or object kind. A has-a is well-formed without a matching which-is; unfilled slots are valid until filled.
Worked breakdown:
planet [Pluto
+ radius [1188.3]
]
reads as: planet which is Pluto; Pluto has a radius (referent-level subject, from +); the occurrence which is 1188.3.
9.2.2 Directionality. Associations are directed; order matters.
observatory [Lowell Observatory - discoverer [Clyde Tombaugh]]
means Lowell Observatory has a discoverer who is Tombaugh, not Tombaugh has a Lowell Observatory.
9.3 Temporal semantics
9.3.1 Implicit context. Every concept and association exists in temporal context. With no explicit bounds, assume current/permanent validity; context MAY be inherited from a parent association; precision MAY vary (year, month, day, minute).
9.3.2 Explicit bounds. In association metadata ({…}):
person [Clyde Tombaugh
- title [Astronomer {1929-01-01/}]
- title [Research Assistant {1929-01-01/1945-12-31}]
]
Multiple temporal instances of one relationship coexist with distinct validity periods. Intervals use / as a single list item (§11.2).
9.4 Expression selection
When a concept has several expressions, implementations SHOULD select based on: language preference (user locale), formality (formal vs. casual), length constraints (abbreviated vs. full), media type (text/audio/visual), and confidence (prefer higher). With no criteria specified, use the first listed expression, or the highest-confidence one, or the most recently added.
9.5 Nesting and context
9.5.1 Inheritance. Nested associations inherit the context of their parents:
country [USA
- state [Arizona
- city [Flagstaff]
]
]
Flagstaff implicitly carries the context (in Arizona) (in USA).
9.5.2 Override. Explicit associations MAY override inherited context:
country [USA
- state [Arizona
- observatory [Lowell Observatory
+ country [USA] # explicit, reaffirming inherited context
]
]
]
10. Expression Types
Expressions are opaque strings at parse time (§8.3.3); the types below describe how implementations SHOULD interpret and validate them.
10.1 Text. MUST be UTF-8. MAY be machine-readable (explain via metadata). SHOULD escape delimiter characters when they appear in content. Example: observation ["Tombaugh compared plates taken weeks apart"].
10.2 Numeric. JSON number syntax — integer (42, -17), decimal (3.14159, 1188.3), scientific (1.303e22, 6.022e23). Infinity/NaN handling is implementation-defined; large magnitudes SHOULD be supported to reasonable precision.
10.3 Temporal. Temporal values appear in {…} / {{…}} metadata and MAY appear as a whole expression value (§8.3.3). Two profiles are accepted:
ISO 8601 — date 2006-08-24; datetime 2015-07-14T11:49:00Z; time T11:49:00; duration P1Y2M3DT4H5M6S / PT1H.
English month-name (Amorfs-friendly) — D Mon YYYY or D Month YYYY, optional 12-hour time (7 am, 7:00 am, 6:30 pm), optional weekday, optional zone Z or ±HH:MM. Prefer omitting the offset when it matches the author’s/viewer’s local zone; renderers SHOULD elide a matching local offset in superficial display.
Intervals use / as a single item (optional spaces around /). Prefer start / duration when the end is “start + length”; use start / end when both bounds are independently meaningful:
| Form | Example |
|---|---|
| Start / duration (friendly) | {{12 Nov 2024 7:00 am +11:00/1 hour}} |
| Start / duration (expression-first) | when [12 Nov 2024 7 am / 1 hour] |
| Start / duration (ISO) | {2024-11-12T07:00:00+11:00/PT1H} |
| Start / end | {1930-02-18/2006-08-24}, when [7 Dec 2024 6 pm / 7 Dec 2024 10 pm] |
| Start / same-day end time | when [7 Dec 2024 6pm / 10pm] (end time inherits the start date) |
| Open-ended | {2006-08-24/} |
| Start / ISO duration (years) | {1930-02-18/P76Y} |
Human duration tokens after /: N minute(s)|min(s), N hour(s)|hr(s), N day(s) (e.g. 1 hour, 60 mins). Unknown-start {/2006-08-24} is reserved (MAY be accepted later). Duration-only text (60 mins) outside an interval is not a temporal spec.
10.4 IRI. Machine-readable identifiers in <…>, MUST be valid per RFC 3987, SHOULD be dereferenceable, MAY reference external ontologies:
planet [Pluto
+ same as | owl:sameAs [<http://dbpedia.org/resource/Pluto>]
]
10.5 Multimedia. By external reference or embedded base64:
planet [Pluto
- image [<https://photojournal.jpl.nasa.gov/jpeg/PIA19873.jpg>] # New Horizons portrait
]
11. Metadata Reference
Metadata annotates concepts, expressions, and associations. There are three scopes, plus expression tags on surface text. This section is the precise version of Part I §C.5–§C.6.
| Form | Scope | Attaches to |
|---|---|---|
expression{meta} |
Expression | The expression-mapping link for that surface form only — no space, a single {…} |
{item, …} |
Association | The most recently minted association in the current chain — only when an association exists |
{{item, …}} |
Base concept | The base concept for the current syntactic context — the only form for concept-scoped metadata |
Rationale. Associations carry temporal metadata; base concepts carry permanent attributes. {{…}} is the only form for concept metadata; {…} is association-only — parsers MUST NOT fall back to concept scope when no association exists.
| Form | Example |
|---|---|
expr{meta} — expression (surface text only) |
Pluto{en}, man{en} | homme{fr} |
{{…}} — base concept (one block per position) |
Pluto {{~1.0}}, {{@pluto, 1930-02-18}} |
{…} — association (only when one exists) |
planet [Pluto {1930-02-18/2006-08-24}] |
{{@name, …}} — create @name on base concept |
planet [{{@pluto, 1930-02-18}} Pluto] |
{@name, …} — create @name on latest association |
{@naming_event, 1930-05-01} |
Never use {…} for concept metadata — always {{…}}. Never split concept metadata across consecutive {{…}} {{…}}. Never use a bare @name at first occurrence.
11.1 The three scopes
11.1.1 Expression metadata. Tight single braces immediately after surface text, no space before {:
planet [Pluto{en} | 冥王星{ja}]
observatory{en} [Lowell Observatory]
{en}/{ja} apply to those expression links only. There is no Pluto{{en}} or Pluto {en} for expression scope. Double braces denote base concept metadata only. Expression metadata is not valid on a bare @name.
11.1.2 Base concept metadata. Double braces {{…}}:
planet [Pluto {{1930-02-18, ~1.0}} + radius [1188.3]]
greeting [hello{en} | bonjour{fr} {{+1.0}}]
One {{…}} block per concept position. All concept-scoped attributes at one attachment point — @ref creation, dates, confidence, importance — MUST go in a single block. Consecutive double-brace blocks are a parse error. A {{…}} MAY appear after a complete expression (or | alt list), or before the first expression in a bracket (equivalent attachment to the referent).
11.1.3 Association metadata. Spaced single braces {…}, attaching to the latest minted association in the chain:
dwarf planet [Pluto {2006-08-24/}]
planet [ @pluto - studied_by [@new_horizons {2015-07-14}] ]
Strict separation: {…} never attaches to a base concept except as the final comma segment in a referent list with no association minted at that position (e.g. when [Saturday, 6 pm, {2024-12-07T18:00:00+11:00/…}]). Otherwise, if no association has been minted yet at that position, spaced single braces are a parse error — use {{…}} instead.
11.2 Metadata lists
Items inside {…} and {{…}} are comma-separated lists for document metadata.
| Rule | Detail |
|---|---|
| Separator | Comma between items; optional space after |
| Single item | Commas optional ({{+1.0}}, {2006-08-24}) |
| Trailing comma | Allowed ({{@pluto, 1930-02-18,}}) |
| Sigil items | Bare forms: en, 2006-08-24, 2026, ~0.95, +1, formal |
key=value |
Named attributes: source=@lowell, order=date DESC, limit=10 |
@ref creation |
Leading item in block: @pluto inside {{…}} or {…} (§11.4) |
| Temporal intervals | Single item using /: 1930-02-18/2006-08-24 — not a space-separated pair |
| Not in lists | Expression tags stay expr{en} (no comma, no space before {) |
Quoted expressions follow the same rules: "Pluto"{en} → expression; "Pluto" {{~1.0}} → base concept; "Pluto" {date} → association (error if none minted). Whitespace-separated items inside a block MUST be rejected — use commas.
11.3 Placement rules
Metadata MUST appear inside brackets, adjacent to the expression or association step it describes, and MUST NOT follow a closing ].
| Position | Rule |
|---|---|
expression{meta} |
Immediately after surface text, no space, single {…} — language / X-link tags only. Not valid on @name. |
expression {{meta}} |
One block after a complete expression or | alt list — base concept only |
Consecutive {{…}} {{…}} |
Error — merge into one block |
{meta} |
Association only — latest minted; error if none |
Between | alternatives |
Error for {{…}} or {…} — metadata must not split an alt list |
| Before the first expression in a bracket | {{…}} → base concept; {…} → error (no association yet) |
{…} on is bind inside value bracket (radius [1188.3 {meta}]) |
Association on is |
{…} after value bracket close (radius [1188.3] {meta}) |
Error — use radius [1188.3 {meta}] |
{…} before child [ on a -/+ item (- radius {meta} [1188.3]) |
Association on the has-a step |
{…} after a label-only child inside a bracket (body [ - moon {meta}]) |
Association on has-a moon |
{…}/{{…}} immediately after a closing ] |
Parse error (e.g. planet [ … ] {2006}) |
11.3.1 Which association {…} targets. It attaches to the latest association in the minted chain:
| Pattern | {…} attaches to |
|---|---|
label [value {…}] |
is |
body [ - moon {…}] |
has-a (label-only child) |
- field {…} [value] |
has-a (opening child) |
- studied_by {…} [@target] |
has-a (step) |
- studied_by [@target {…}] |
is (bind to target) |
Tombaugh - discovered {…} |
has-a (referent-first) |
When metadata previously meant "everything in the bracket," decompose into a base-concept {{…}} on the referent (entity-wide permanent) plus per-association {…} on each -/+ item that needs temporal metadata.
11.4 Concept references (@name)
A @name is not an expression — no expr{meta} on a bare @ref. Creating a name (first registration) MUST place @name inside {…} or {{…}}; the brace form determines what it names:
| Creation form | Registers @name on |
|---|---|
{{@name, …}} |
Base concept — @name plus concept metadata in the same block |
{@name, …} |
Association — @name on the latest minted association |
A @name in a metadata list is a registration directive, not a metadata attribute. After creation, @name is used bare — lookup only:
planet [ {{@pluto, 1930-02-18}} Pluto ]
mission [New Horizons - flew past [@pluto {2015-07-14}]]
Invalid: bare @pluto at first occurrence; {{@pluto}} {{1930-02-18}} (split blocks); @pluto{date}; @pluto {date}.
Metadata reference rule. A @name in a key=value item (e.g. {source=@lowell}) MUST reference a concept already registered; parsers MUST report a semantic error if it does not exist — metadata values MUST NOT create concepts on first sight.
Trailing anchor. An optional @name after ] registers a reusable reference to the bracket's primary ⟨label, is, referent⟩ binding — planet [Pluto] @pluto. Distinct from {{@name, …}} row-anchor creation inside the bracket.
11.5 Base concept positions
The base concept that {{…}} attaches to depends on syntactic position:
| Position | Base concept for {{…}} |
|---|---|
| Referent-first subject | After alt list: `man{en} |
Referent slot inside [ … ] |
After alt list, single referent, or row anchor: planet [Pluto {{…}} …], planet [{{@pluto, …}} …] |
Label before [ |
After label expression: observatory{en} {{…}} [Lowell] — not observatory{{en}} |
| Label-only child | After alt list: `- moon{en} |
11.6 Standard attributes
11.6.1 Language — ISO 639-1 (lowercase recommended); expression scope only: Pluto{en}, never Pluto {{en}}.
11.6.2 Temporal — association or base-concept lists; {2006-08-24}, {{1930-02-18}}, intervals as single items {1930-02-18/2006-08-24}, friendly forms {{12 Nov 2024 7:00 am +11:00/1 hour}}. ISO 8601 and the English month-name profile (§10.3). A whole expression that matches TemporalSpec SHOULD auto-mint the same temporal metadata (§8.3.3) unless an explicit temporal item is already present (bare four-digit years are excluded from auto-mint).
11.6.3 Confidence — ~ then a numeric literal 0.0–1.0: {~0.99}, {{@pluto, 1930-02-18, ~1.0}}.
11.6.4 Importance — +/- then a numeric literal: {{+1.0}}, {+2}.
11.6.5 Combined — several items in one comma-separated block: {{@pluto, 1930-02-18, ~1.0, +1.0, formal}}, radius [1188.3 {2015-07-14, ~0.99}].
11.6.6 Flags — bare identifiers (e.g. formal, informal). Language codes and formality flags are expression metadata only; they tag a surface form, not the concept, and MUST NOT appear in {{…}}. Flags are distinct from importance markers (+2).
11.7 Worked examples
11.7.1 Multilingual referent-first subject. astronomer{en} | astronome{fr} - discovered [Pluto] — language per surface form on astronomer.
11.7.2 Permanent metadata on a referent-first subject. planet{en} | planète{fr} {{+1.0}} - moon [Charon] — {{+1.0}} after the alt list is base-concept (no association yet).
11.7.3 Concept date vs. edge date.
<h1 id="concept-date-on-the-body">concept date on the body:</h1>
planet [Pluto {{1930-02-18}} - studied_by [@new_horizons]]
<h1 id="edge-date-on-the-has-a-step">edge date on the has-a step:</h1>
planet [Pluto - studied_by [@new_horizons {2015-07-14}]]
11.7.4 Entity-wide vs. per-association metadata.
person [Clyde Tombaugh {{1906-02-04, ~1.0}}
- employer [Lowell Observatory {1929-01-01/}]
- discovered [Pluto {1930-02-18}]
]
Entity-wide permanence/confidence on the referent via {{…}}; per-edge temporal on each value bracket.
11.7.5 Row-anchor entity creation.
planet [ {{@pluto, 1930-02-18}} Pluto | 冥王星{ja} ]
Creates the row referent and a creation date in one block. Later statements use @pluto bare.
11.8 Invalid forms
| Form | Error |
|---|---|
{2006} planet [Pluto] |
Leading {…} with no association — use {{2006}} on the concept |
Pluto{en} {date} (no - item yet) |
No association — use Pluto{en} {{date}} |
Pluto{en} {{draft}} | 冥王星{ja} |
{{…}} between alts forbidden |
Pluto{{en}} for language |
Language uses Pluto{en} |
bare @pluto at creation, or @pluto{date} |
Use {{@pluto, 1930-02-18}} |
{{@pluto}} {{1930-02-18}} |
Consecutive concept blocks — merge into one |
planet [ … ] {2006} |
Metadata after ] — move inside the bracket |
Pluto {{~1.0}} {{1930-02-18}} |
Use one block: Pluto {{~1.0, 1930-02-18}} |
{{@p 1930-02-18}} (whitespace between items) |
Use commas |
Pluto {en} (spaced before {) |
Expression language uses Pluto{en} |
12. Interoperability and Interchange
12.1 The interchange model
Amorfs interchange formats represent the Amorfs knowledge base — the separated-semantics structure — not the text syntax. Serialisation exposes concepts (), expressions () with their links (), associations (quads in , each named by a concept in ), and metadata (). Amorfs text is the primary, most compact format; JSON and XML are equivalent machine-readable serialisations; CSV is a lossy export.
12.2 JSON and XML serialisation
Take a fragment with an implied concept — the discovery from Part I §C.3, which has no expression of its own:
discovery [
- of [Pluto]
- by [Clyde Tombaugh]
]
This yields parameter concepts (discovery, of, by), value concepts (Pluto, Clyde Tombaugh), the predicate concepts (has a, which is), an implied concept for the discovery itself (no expression), and one association concept per relationship. In JSON:
{
"concepts": [
{"id": "c_discovery"},
{"id": "c_discovery_impl"},
{"id": "a1", "associations": [
{"subject": "c_discovery", "predicate": "c_which_is", "object": "c_discovery_impl"}]},
{"id": "c_of"}, {"id": "c_pluto"},
{"id": "a2", "associations": [
{"subject": "c_of", "predicate": "c_which_is", "object": "c_pluto"}]},
{"id": "a3", "associations": [
{"subject": "c_discovery_impl", "predicate": "c_has_a", "object": "a2"}]},
{"id": "c_by"}, {"id": "c_tombaugh"},
{"id": "a4", "associations": [
{"subject": "c_by", "predicate": "c_which_is", "object": "c_tombaugh"}]},
{"id": "a5", "associations": [
{"subject": "c_discovery_impl", "predicate": "c_has_a", "object": "a4"}]},
{"id": "c_has_a"}, {"id": "c_which_is"}
],
"expressions": [
{"id": "e_discovery", "value": "discovery", "concepts": ["c_discovery"]},
{"id": "e_of", "value": "of", "concepts": ["c_of"]},
{"id": "e_pluto", "value": "Pluto", "concepts": ["c_pluto"]},
{"id": "e_by", "value": "by", "concepts": ["c_by"]},
{"id": "e_tombaugh", "value": "Clyde Tombaugh", "concepts": ["c_tombaugh"]},
{"id": "e_has_a", "value": "has a", "concepts": ["c_has_a"]},
{"id": "e_which_is", "value": "which is", "concepts": ["c_which_is"]}
]
}
Note c_discovery_impl has no expression — it is the implied concept, knowable only through its associations. Metadata attaches per node or per expression:
{"id": "a3",
"associations": [{"subject": "c_discovery_impl", "predicate": "c_has_a", "object": "a2"}],
"metadata": {"temporal": {"start": "1930-02-18"}, "confidence": 1.0}}
{"id": "e_tombaugh", "value": "Clyde Tombaugh",
"concepts": ["c_tombaugh"], "metadata": {"lang": "en"}}
The XML serialisation mirrors this one-to-one: a <concept id="…"> element per concept (with a nested <associations> for association concepts and <metadata> where present), and an <expression id="…" value="…"> element per expression listing its <concepts>. Both serialisations show the same properties: parameters, values, and predicates are all concepts-with-expressions; associations are concepts that can bear metadata and participate further; abstract concepts have no expression; there is no class/instance distinction — role emerges from graph position; the structure is uniform throughout.
12.3 CSV is lossy by nature
CSV can represent only a flat, tabular projection. discovery [ - of [Pluto] - by [Clyde Tombaugh] ] flattens to:
discovery_of,discovery_by
Pluto,Clyde Tombaugh
This loses the implied discovery concept, the association structure, the fact that the column headers are themselves concepts, all metadata, and any alternative expressions. CSV is suitable for spreadsheet viewing, predefined-structure legacy integration, and human-readable summaries — not for round-trip. Recommended formats by use case: Amorfs text for all exchange (most compact and readable); JSON/XML where a standard parser is required; CSV for lossy export only.
12.4 Importing from legacy formats
CSV — column headers become parameter concepts, row values become expressions, and each row is an implied concept with associations to the column concepts:
name,discovered,by
Pluto,1930,Tombaugh
Eris,2005,Brown
→
body [ - name [Pluto] - discovered [1930] - by [Tombaugh] ]
body [ - name [Eris] - discovered [2005] - by [Brown] ]
JSON — object properties become has-associations (typically - when nested), nested objects become nested concepts, arrays become multiple associations or expressions.
XML — element names become concept identifiers, attributes become + associations (referent-level subjects), child elements become - associations (association-scoped), text content becomes expressions.
Relational databases — table names suggest concept types, columns become associations, foreign keys become explicit concept references, and join tables become association concepts.
12.5 Exporting and information loss
When flattening to tabular formats: choose a row concept type, flatten nested associations to columns, handle multi-valued fields, and preserve identifiers for re-import. JSON export MAY use a nested structure (preserving hierarchy), a flat structure (one object per concept with references), or an explicit graph format (nodes and edges). Exporters SHOULD warn when the target cannot preserve all information, offer handling options (omit, flatten, external files), and enable round-trip where possible (e.g. by embedding Amorfs in metadata or comments).
12.6 Standard vocabularies
Interoperability with the semantic web uses the alternative-expressions mechanism (Part I §D): a slot is given both a human term and one or more standard predicates, separated by |. Appendix E catalogues mappings for Dublin Core, FOAF, Schema.org, OWL, SKOS, QUDT, and PROV.
13. Parsing Requirements
13.1 Conformance levels
Levels here correspond to the conformance classes of §17.1 (Level 1 = Minimal, 2 = Standard, 3 = Full).
Level 1 (Basic). Recognise all syntax elements; build a complete knowledge base ; support text and numeric expressions; handle basic metadata (temporal, confidence); SHOULD deduplicate concepts by (role, expression) via find-or-create when building the graph.
Level 2 (Standard). All of Level 1, plus all expression types (IRI, multimedia references); concept merging (§9.1); concept references (@); and metadata-consistency validation.
Level 3 (Full). All of Level 2, plus automatic type inference; advanced conflict resolution; and optimisation (duplicate detection, graph simplification).
13.2 The parsing process
Lexical analysis MUST tokenise into identifiers, operators, literals, and delimiters; handle UTF-8 correctly; track line and column for error reporting; and distinguish significant from insignificant whitespace.
Syntactic analysis MUST build a parse tree per the grammar, validate nesting and bracketing, detect syntax errors with meaningful messages, and support incremental parsing of large documents.
Semantic analysis MUST identify concepts and assign unique identifiers, link expressions to concepts (many-to-many), create association concepts for all relationships, store metadata with the appropriate concepts/associations, and resolve concept references.
13.3 Error handling
Syntax errors MUST report line and column with a descriptive message, MAY attempt recovery, and SHOULD suggest corrections when obvious:
Error at line 4, column 31: Expected ']' but found ','
planet [Pluto + radius [1188.3,
^
Semantic errors (e.g. a merge conflict, or an unresolved @name in {…} metadata) SHOULD report the conflict with location, indicate conflicting sources when known, SHOULD NOT silently discard data, and MAY flag for manual review:
Error at line 6, column 38: Unknown concept reference @lowell in metadata
- name [Pluto {source=@lowell}]
^
Register @lowell (e.g. `source [Lowell records {@lowell}]`) before using it in {…} metadata.
13.4 Incremental parsing
Parsers SHOULD support parsing fragments independently, merging parsed fragments into an existing graph, and updating the graph without a full re-parse.
14. Rendering Requirements
14.1 Conformance
A conformant renderer MUST accept Amorfs text, parse and validate it, build the corresponding knowledge base , and support one or more output formats.
14.2 Output formats
14.2.1 Text (round-trip). MUST convert the knowledge base back to Amorfs text, preserving all concepts, expressions, expression links, associations, and metadata, with readable formatting.
14.2.2 Visual. SHOULD support structured forms, grid tables, and network graphs. A rendered form for one of Pluto's records might read:
┌──────────────────────────────────────┐
│ Pluto · 冥王星 · 134340 Pluto │
├──────────────────────────────────────┤
│ Radius: 1188.3 km (~0.99) │
│ Moons: Charon, Nix, Hydra, │
│ Kerberos, Styx │
│ Discovered: 1930-02-18 │
│ Type binding: planet 1930–2006│
│ dwarf planet 2006– │
└──────────────────────────────────────┘
14.2.3 Data exchange. JSON and XML per §12.2.
14.3 Expression selection and metadata rendering
Renderers MUST implement the selection criteria of §9.4 and accept parameters for language preference, formality, and length. They SHOULD display temporal bounds when relevant, indicate confidence visually, signal importance through formatting, and provide access to provenance.
15. Syntax Cheatsheet
Everything in one place for hand-authors.
| You want to… | Write | Notes |
|---|---|---|
| Say A which-is B | A [B] |
The brackets are the which-is predicate |
| Give B a property | A [B + prop [val]] |
+ opens a has-a slot on the entity |
| Annotate the claim, not the entity | A [B - prop [val]] |
- hangs off the association in scope |
| List synonyms / translations | [Pluto | 冥王星] |
| separates expression alternatives |
| List several things | [Charon, Nix, Hydra] |
, (comma-space) = several concepts |
| Tag a surface form's language | Pluto{en} |
Tight braces, no space — expression scope |
| Add permanent concept metadata | Pluto {{~1.0, 1930-02-18}} |
{{…}} — one block per position |
| Add association/temporal metadata | [planet {1930/2006}] |
{…} — only when an association exists |
| State a validity interval | {1930-02-18/2006-08-24} |
/ joins start/end as one item; {2006-08-24/} = ongoing |
| Confidence / importance | ~0.99 / +2 |
Inside a metadata block |
| Name a concept for reuse | [{{@pluto}} Pluto] then @pluto |
Register in {{…}}/{…}; later bare = lookup |
| Link to the web | [<http://…>] |
Angle brackets = IRI |
| Map to a standard predicate | name | schema:name [Pluto] |
Human + standard as alternatives |
| Comment | # … (space before inline #) |
Stripped at parse; not in the graph |
The two rules to remember: (1) there are only two predicates — which-is [] and has-a +/-; (2) metadata never follows a closing ] — put it inside, adjacent to what it describes.
16. Security Considerations
16.1 Input validation
Parsers MUST validate input against the grammar, limit nesting depth to prevent stack overflow (RECOMMENDED: 1000 levels), limit document size to prevent resource exhaustion, and sanitise expressions before rendering in web contexts (XSS prevention).
16.2 Access control
Implementations MAY support concept-level permissions and association filtering based on viewer permissions.
17. Conformance
17.1 Conformance classes
Minimal (Level 1) MUST support all syntax elements (§8), text and numeric expressions, basic metadata (temporal, confidence), knowledge-base construction (), and basic error reporting.
Standard (Level 2) MUST support all Minimal requirements plus all expression types (§10), concept merging (§9.1), concept references, and advanced error handling.
Full (Level 3) MUST support all Standard requirements plus incremental parsing, optimisation and validation, and the performance benchmarks of §17.3.
Conformant renderer MUST support round-trip to text, at least one visual format (form, table, or graph), at least one data-exchange format (JSON or XML), and the expression-selection criteria.
17.2 Test suite
A conformance test suite SHALL include valid-syntax (positive) and invalid-syntax (negative) examples, edge cases (empty concepts, deep nesting, special characters), semantic tests (merging, conflict resolution), and round-trip tests (parse → render → parse preserves meaning).
17.3 Performance benchmarks
Non-normative reference targets: parse 10,000 concepts in < 1 s; merge 1,000 concepts in < 100 ms; render 10,000 concepts to JSON in < 1 s; memory usage O(n) in concept count.
Appendix A: Grammar Reference (EBNF)
This appendix restates the grammar of §8.4 in formal EBNF, aligned with the normative Ohm artifact in Appendix D. Where this appendix and §8.4 appear to diverge, §8.4 — and ultimately the Ohm grammar — is authoritative.
document ::= concept-list ;
concept-list ::= concept { "," concept } ;
concept ::= label-part? "[" inner-content "]" anchor?
| referent-first-concept | unbound-concept
| concept-reference ;
unbound-concept ::= expression-list concept-meta? anchor? ;
referent-first-concept ::= expression-list concept-meta? referent-first-inner-item+ anchor? ;
referent-first-inner-item ::= association-operator assoc-meta? nested-concept ;
label-part ::= expression-with-metadata { "|" expression-with-metadata } label-trailing-meta? ;
label-trailing-meta ::= concept-meta ;
concept-meta ::= "{{" metadata-list "}}" ;
inner-content ::= concept-meta? expression-list? inner-item* ;
inner-item ::= association-operator assoc-meta? nested-concept ;
assoc-meta ::= "{" metadata-list "}" ;
anchor ::= "@" reference-name ;
expression-list ::= expression-slot { ("|" | ", ") expression-slot } concept-meta? ;
expression-slot ::= expression-with-metadata referent-assoc-meta? ;
referent-assoc-meta ::= "{" metadata-list "}" ;
expression-with-metadata ::= expression expr-meta? ;
expr-meta ::= "{" metadata-list "}" ;
expression ::= unquoted-text | quoted-text | concept-reference ;
association-operator ::= "+ " | "- " ;
metadata-list ::= metadata-item { "," metadata-item } [ "," ] ;
metadata-item ::= concept-ref-item | language-code | temporal-spec
| confidence-spec | importance-spec | custom-attribute | flag-item ;
concept-ref-item ::= "@" reference-name ;
language-code ::= letter letter ;
temporal-spec ::= slash-interval | datetime-literal datetime-literal? | datetime-literal ;
slash-interval ::= datetime-literal "/" datetime-literal? | datetime-literal "/" ;
confidence-spec ::= "~" numeric-literal ;
importance-spec ::= ( "+" | "-" ) numeric-literal ;
custom-attribute ::= reference-name "=" expression ;
flag-item ::= reference-name ;
concept-reference ::= "@" reference-name ;
reference-name ::= ( letter | "_" ) { letter | digit | "_" | "-" } ;
Appendix B: Worked Examples
These examples are independent of the Part I tour and of one another; each shows a different use of the formalism.
B.1 A contested attribution — statements about statements
Art history is full of paintings whose authorship has been argued over for centuries. Amorfs records each attribution as its own thing, with who said it, when, and how confidently — so the disagreement is data, not a lost edit.
painting [{{@salvator}} Salvator Mundi
+ medium [oil on walnut panel]
+ subject [Christ as Saviour of the World]
- attribution {asserted_by=@christies, date=2017-11-15, ~0.6} [Leonardo da Vinci]
- attribution {asserted_by=@dispute, date=2021-01-01, ~0.4} [Leonardo workshop]
- last_sale {venue=@christies, ~1.0} [
+ price [450300000 - currency [USD]]
+ date [2017-11-15]
]
]
source [Christie's auction house {{@christies}}]
source [scholarly dispute, post-sale {{@dispute}}]
The two - attribution claims attach to the painting-as-claim, each with its own asserter, date, and confidence — and they coexist. The sale price, by contrast, is an intrinsic fact, given as an implied concept (price + date) with no overwriting of either attribution.
B.2 A scientific measurement with full provenance
A single number, with everything traceable: the value, its unit, the instrument, the operator, the date, and a confidence — each piece a concept you can follow.
instrument [Mass Spectrometer MS-7 {{@ms7}}]
person [Dr. Sarah Chen {{@chen}} + role [Analytical Chemist]]
measurement [{{@m_iso}} isotope ratio
- value {measured_by=@ms7, operator=@chen, date=2024-03-15, ~0.98} [
+ ratio [0.0072]
+ of [13C/12C]
+ unit [dimensionless]
]
- method | schema:measurementTechnique [IRMS]
]
B.3 Multilingual catalogue entry
One product concept, localised without duplicating its structure — each surface form carrying its own language tag.
product [{{@watch}} Smart Watch{en} | Montre Intelligente{fr} | スマートウォッチ{ja}
- description [
A versatile wearable device{en} |
Un appareil portable polyvalent{fr} |
多機能なウェアラブルデバイス{ja}
]
- price [
+ amount [299]
+ currency [USD | ${en}]
]
- released [2024-11-01]
]
B.4 Recursive lineage — a supply chain that remembers
Because an association can be the subject of another, a shipment can carry its own predecessor, to any depth — provenance that chains backward through the supply line.
Each leg is self-contained: shipper (carrier), consignment number (tracking ID, transit window, and route), and previous shipment (lineage). Transit time uses slash-interval association metadata on the consignment is-bind ({departure/arrival}), not an ambiguous top-level timestamp slot — and not on the opening shipment [ (that would be {…} before the first - with no referent, a parse error per §7.8.12).
shipment [
- shipper [Harbor Hub Couriers]
- consignment number [HHC-SYD-3301 {2024-03-25T10:30:00Z/2024-03-25T16:00:00Z}
- origin [Café Imports Melbourne]
- destination [Single O - address [Surry Hills Sydney]]
]
- previous shipment [
- shipper [Melbourne Freight Collective]
- consignment number [MFC-88421-AU {2024-03-22T08:00:00Z/2024-03-22T14:00:00Z}
- origin [Port of Melbourne]
- destination [Café Imports Melbourne]
]
- previous shipment [
- shipper [Café Imports Export Desk]
- consignment number [CI-2024-0312-CO {2024-03-05T14:00:00Z/2024-03-20T06:00:00Z}
- origin [Finca El Paraiso - address [Huila Colombia]]
- destination [Port of Melbourne]
]
]
]
]
Forward chain: Finca El Paraiso → Port of Melbourne → Café Imports Melbourne → Single O, Surry Hills.
B.5 Linked-data person (bridge to Appendix E)
Human-readable slots paired with standard predicates, so the same record serves a person, a search engine, and a triple store at once.
person [Tim Berners-Lee {{@timbl}}
- name | foaf:name | schema:name [Tim Berners-Lee]
- homepage | foaf:homepage [<https://www.w3.org/People/Berners-Lee/>]
- same as | owl:sameAs [
<https://orcid.org/0000-0001-2345-6789> |
<https://www.wikidata.org/wiki/Q80>
]
- knows | foaf:knows [@vint_cerf, @bob_kahn]
]
Appendix C: Implementation Checklist
Parser: lexical analyser (tokenisation) · syntax parser (grammar validation) · knowledge-base builder () · unique-identifier assignment · expression linking (many-to-many, ) · association (quad) creation · metadata extraction and storage · error handling and reporting · concept-merging logic · reference resolution (@name).
Renderer: knowledge-base input · text round-trip · form rendering · table rendering · JSON export · XML export · expression-selection logic · metadata rendering · multi-language support.
Testing: positive syntax tests · negative syntax tests · edge cases (empty, deep nesting, special characters) · semantic tests (merging, conflicts) · round-trip tests · performance benchmarks · memory-leak tests · concurrency tests (if applicable).
Appendix D: Ohm Grammar (Normative)
Normative Ohm implementation of the grammar in §8.4 and Appendix A:
Amorfs {
Document = ConceptList
Fragment = ConceptFragment ("," ConceptFragment)*
ConceptList = Concept ("," Concept)*
Concept = ReferentFirstConcept
| BracketedConcept
| UnboundConcept
| conceptRef
ConceptFragment = ReferentFirstConcept
| BracketedConcept
| UnboundConcept
| conceptRef
UnboundConcept = ExprListWithConceptMeta
ReferentFirstConcept = ExprListWithConceptMeta ReferentFirstInnerItem+
ReferentFirstInnerItem = AssocOp BracketedConceptChild
BracketedConceptChild = BracketedConcept | LabelOnlyChild
LabelOnlyChild = AnnotatedAltList
BracketedConcept = LabelPrefix? "[" InnerContent "]"
LabelPrefix = AnnotatedAltList
InnerContent = ConceptLeading? ReferentSlot? InnerItems
ConceptLeading = MetaPrefix
ReferentSlot = CommaReferentRows | ExprListWithConceptMeta
CommaReferentRowLeading = ReferentRowExpr ReferentFirstInnerItem+
CommaReferentRowTrailing = ReferentRowExpr ReferentFirstInnerItem*
CommaReferentRows = CommaReferentRowLeading (commaSpace CommaReferentRowTrailing)+
ReferentRowExpr = AnnotatedAltList
ReferentSegment = AnnotatedAltList | MetaBlock
ExprListWithConceptMeta = ReferentSegment (ExprSep ReferentSegment)* TrailingListMeta?
TrailingListMeta = MetaPrefix
ExprSep = "|" | commaSpace
commaSpace = "," space+
InnerItems = InnerItem*
InnerItem = AssocOp BracketedConceptChild
MetaBlock = ConceptMeta | AssocMeta
ConceptMeta = "{{" MetadataList "}}"
AssocMeta = "{" MetadataList "}"
MetaPrefix = MetaBlock (space+ MetaBlock)*
SpacedSuffix = (space+ MetaBlock)+
TightMeta = &( "{" ~"{" ) "{" MetadataList "}"
ExpressionWithMetadata = Expression TightMeta?
AnnotatedAltList = MetaPrefix?
ExpressionWithMetadata ("|" ExpressionWithMetadata)*
SpacedSuffix?
conceptRef = "@" referenceName
AssocOp = assocOp
assocOp = "+ " | "- "
MetadataList = MetadataItem (comma MetadataItem)* comma?
comma = "," space?
MetadataItem = TemporalSpec
| ConfidenceSpec
| ImportanceSpec
| CustomAttribute
| FlagItem
| ConceptRefItem
ConceptRefItem = conceptRef
TemporalSpec = SlashInterval | InstantSpec | DatetimeRange
InstantSpec = friendlyInstant | datetimeLiteral | yearLiteral
yearLiteral = digit digit digit digit
DatetimeRange = datetimeLiteral datetimeLiteral
SlashInterval = InstantSpec "/" IntervalEnd?
IntervalEnd = InstantSpec | DurationSpec | SameDayEndTime
SameDayEndTime = friendlyTime zonePartFriendly?
DurationSpec = isoDuration | humanDuration
ConfidenceSpec = "~" numericLiteral
ImportanceSpec = ("+" | "-") numericLiteral
CustomAttribute = referenceName "=" Expression
FlagItem = referenceName
Expression = quotedText
| leadingRefUnquoted
| conceptRef
| angleBracketText
| unquotedText
leadingRefUnquoted = conceptRef singleSpace unquotedText
singleSpace = " "
identifier = referenceName
referenceName = (letter | "_") (alnum | "_" | "-")*
quotedText = "\"" quotedTextChar* "\""
quotedTextChar = escapeSequence
| ~("\"" | "\\") any
escapeSequence = "\\" ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
angleBracketText = "<" (~">" any)* ">"
unquotedText = signedUnquoted | otherUnquoted
signedUnquoted = ("+" | "-") signedBody
signedBody = spacedSigned | tightSigned
tightSigned = (~space unquotedTextChar)+
spacedSigned = signedSegment (space signedSegment)+
signedSegment = (~space unquotedTextChar)+
otherUnquoted = otherUnquotedChunk+
otherUnquotedChunk = (~("+" | "-" | "<") unquotedTextChar) (~("+" | "-") unquotedTextChar)*
| ("+" | "-") (~space unquotedTextChar)+
unquotedTextChar = ~(exprDelimiter | ", ") any
numericLiteral = "-"? digit+ ("." digit+)? (("e" | "E") ("+" | "-")? digit+)?
datetimeLiteral = datePart timePart? timezone?
datePart = digit digit digit digit "-" digit digit "-" digit digit
timePart = "T" digit digit (":" digit digit (":" digit digit)?)?
timezone = "Z" | offset
offset = ("+" | "-") digit digit ":" digit digit
exprDelimiter = "[" | "]" | "|" | "{" | "}" | "\""
space += "\t" | "\n" | "\r" | " "
}
Reference implementation in packages/core/grammar/amorfs.ohm.
Grammar notes:
- Ohm-js compatibility: PascalCase syntactic rules; lowercase lexical tokens;
letter/digit/alnumfrom OhmBuiltInRules - Document grammar: This artifact defines document interchange only
- Metadata cluster (§11): One
AnnotatedAltListat each attachment site; lowering assigns Expression / Concept / Association scope. No metadata after closing] - Nested children: Every
InnerItemrequires lexicalassocOp(+/-), then aBracketedConceptChild(bracketed value or label-only open binding). Pre-operator{…}before+/-is invalid (§7.8.12) conceptRefat expr boundaries:@mid-string allowed in unquoted text (emails); row-anchor creation via{{@name, …}}ExprSep:|= expression alternatives;,(comma-space) = multi-value bind- Temporal intervals: Datetime literals and slash intervals in metadata lists
Appendix E: Standard Vocabulary Mappings
E.1 Overview
Amorfs can list a human-readable term and a standard vocabulary term as alternative expressions of the same slot (Part I §D). A human reads name; an RDF tool reads schema:name; both refer to the same concept.
Pattern:
- human_readable | standard:term [value]
Humans get readable text. RDF and OWL tools get recognisable predicates. Schema.org consumers get structured fields. Nothing is lost in translation because the standards sit alongside the human terms in the same record.
E.2 Dublin Core Metadata Terms
Dublin Core is the usual metadata vocabulary for libraries, archives, and digital repositories.
Namespace: dc: http://purl.org/dc/elements/1.1/
Namespace: dcterms: http://purl.org/dc/terms/
document [Titanium Alloy Properties
- title | dc:title [Fatigue Behavior of Ti-6Al-4V Under Cyclic Loading]
- creator | dc:creator [@jane_smith]
- subject | dc:subject [Materials Science | Titanium Alloys | Fatigue Testing]
- description | dc:description [Analysis of fatigue properties of aerospace-grade titanium alloy]
- publisher | dc:publisher [Nature Publishing]
- contributor | dc:contributor [@bob_johnson | @alice_wong]
- date | dc:date | dcterms:created [2024-03-15]
- type | dc:type [Research Article | Text]
- format | dc:format [application/pdf]
- identifier | dc:identifier [doi:10.1234/nature.2024.12345]
- source | dc:source [@universal_testing_machine]
- language | dc:language [en | eng]
- relation | dc:relation [<https://doi.org/10.1234/related.paper>]
- coverage | dcterms:spatial [Laboratory Testing]
- rights | dc:rights [© 2024 Nature Publishing. CC BY 4.0]
]
Common Dublin Core Terms:
| Human Term | DC Term | Meaning |
|---|---|---|
| title | dc:title | Document title |
| creator | dc:creator | Primary author/creator |
| subject | dc:subject | Topic keywords |
| description | dc:description | Abstract or summary |
| publisher | dc:publisher | Publishing entity |
| contributor | dc:contributor | Additional contributors |
| date | dc:date | Date of publication |
| type | dc:type | Resource type |
| format | dc:format | MIME type or format |
| identifier | dc:identifier | Unique identifier (DOI, ISBN, etc.) |
| source | dc:source | Related source resource |
| language | dc:language | Language of content |
| rights | dc:rights | Copyright and licensing |
E.3 FOAF (Friend of a Friend)
FOAF describes people, their relationships, and their online presence.
Namespace: foaf: http://xmlns.com/foaf/0.1/
person [Tim Berners-Lee
- name | foaf:name [Tim Berners-Lee]
- first name | foaf:givenName [Tim | Timothy]
- family name | foaf:familyName [Berners-Lee]
- nickname | foaf:nick [TimBL]
- email | foaf:mbox [<mailto:timbl@w3.org>]
- homepage | foaf:homepage [<https://www.w3.org/People/Berners-Lee/>]
- phone | foaf:phone [<tel:+1-555-0123>]
- image | foaf:depiction | foaf:img [<https://www.w3.org/People/Berners-Lee/timbl.jpg>]
- works for | foaf:workplaceHomepage [<https://www.w3.org/>]
- knows | foaf:knows [@vint_cerf | @bob_kahn]
- account | foaf:account [
- account name | foaf:accountName [timbl]
- service | foaf:accountServiceHomepage [<https://twitter.com/>]
]
- based near | foaf:based_near [Cambridge, MA]
- publications | foaf:publications [<https://www.w3.org/People/Berners-Lee/Publications>]
]
Common FOAF Terms:
| Human Term | FOAF Term | Meaning |
|---|---|---|
| name | foaf:name | Full name |
| first name | foaf:givenName | Given name |
| family name | foaf:familyName | Surname |
| nickname | foaf:nick | Informal name |
| foaf:mbox | Email address (as mailto: URI) | |
| homepage | foaf:homepage | Personal website |
| image | foaf:depiction | Photo or image |
| knows | foaf:knows | Social connection |
| works for | foaf:workplaceHomepage | Employer website |
| account | foaf:account | Online account |
E.4 Schema.org
Schema.org is the structured-data vocabulary that search engines use for rich snippets and knowledge graphs.
Namespace: schema: http://schema.org/
person [Jane Smith
- name | schema:name [Jane Smith]
- given name | schema:givenName [Jane]
- family name | schema:familyName [Smith]
- email | schema:email [jane@example.com]
- telephone | schema:telephone [+1-555-0199]
- job title | schema:jobTitle [Chief Data Scientist]
- works for | schema:worksFor [
- name | schema:name [Tech Corp]
- url | schema:url [<https://techcorp.com>]
]
- address | schema:address [
- street | schema:streetAddress [123 Main St]
- city | schema:addressLocality [San Francisco]
- state | schema:addressRegion [CA]
- postal code | schema:postalCode [94102]
- country | schema:addressCountry [US | USA | United States]
]
- same as | schema:sameAs [
<https://www.linkedin.com/in/janesmith> |
<https://twitter.com/janesmith>
]
- image | schema:image [<https://example.com/jane.jpg>]
- birth date | schema:birthDate [1985-03-22]
- nationality | schema:nationality [American | US]
]
product [Smart Watch Ultra
- name | schema:name [Smart Watch Ultra]
- description | schema:description [Advanced fitness and health tracking device]
- brand | schema:brand [TechBrand]
- price | schema:price [299]
- currency | schema:priceCurrency [USD]
- availability | schema:availability [In Stock | schema:InStock]
- rating | schema:aggregateRating [
- value | schema:ratingValue [4.5]
- count | schema:ratingCount [1247]
]
- image | schema:image [<https://example.com/watch.jpg>]
- sku | schema:sku [SWU-2024-BLK]
]
Common Schema.org Terms:
| Human Term | Schema.org Term | Meaning |
|---|---|---|
| name | schema:name | Name of thing |
| description | schema:description | Description |
| image | schema:image | Image URL |
| url | schema:url | Webpage URL |
| schema:email | Email address | |
| telephone | schema:telephone | Phone number |
| address | schema:address | Physical address |
| same as | schema:sameAs | Equivalent entity URI |
| birth date | schema:birthDate | Date of birth |
| job title | schema:jobTitle | Job position |
| works for | schema:worksFor | Employer |
| price | schema:price | Monetary price |
| brand | schema:brand | Brand name |
E.5 OWL (Web Ontology Language)
OWL has terms for ontologies and semantic relationships.
Namespace: owl: http://www.w3.org/2002/07/owl#
person [Tim Berners-Lee
- same as | owl:sameAs [
<http://dbpedia.org/resource/Tim_Berners-Lee> |
<https://www.wikidata.org/wiki/Q80> |
<https://viaf.org/viaf/85312226> |
<http://id.loc.gov/authorities/names/n91109222>
]
]
concept [Computer Science
- equivalent to | owl:equivalentClass [
<http://dbpedia.org/resource/Computer_science> |
<https://www.wikidata.org/wiki/Q21198>
]
]
property [email address
- equivalent property | owl:equivalentProperty [
foaf:mbox |
schema:email
]
]
Common OWL Terms:
| Human Term | OWL Term | Meaning |
|---|---|---|
| same as | owl:sameAs | Two URIs refer to same entity |
| equivalent to | owl:equivalentClass | Classes have same members |
| equivalent property | owl:equivalentProperty | Properties have same meaning |
| different from | owl:differentFrom | Explicitly different entities |
E.6 SKOS (Simple Knowledge Organization System)
SKOS is for thesauri, taxonomies, and classification schemes.
Namespace: skos: http://www.w3.org/2004/02/skos/core#
concept [Organic Chemistry
- preferred label | skos:prefLabel [Organic Chemistry{en} | Chimie Organique{fr}]
- alternate label | skos:altLabel [Carbon Chemistry{en} | Study of Carbon Compounds{en}]
- definition | skos:definition [Branch of chemistry studying carbon-containing compounds]
- broader | skos:broader [@chemistry]
- narrower | skos:narrower [@biochemistry | @polymer_chemistry | @medicinal_chemistry]
- related | skos:related [@molecular_biology | @pharmacology]
- example | skos:example [Synthesis of aspirin from salicylic acid]
- note | skos:note [Carbon forms the basis of all known life on Earth]
]
Common SKOS Terms:
| Human Term | SKOS Term | Meaning |
|---|---|---|
| preferred label | skos:prefLabel | Primary name for concept |
| alternate label | skos:altLabel | Synonym or alternative name |
| hidden label | skos:hiddenLabel | Searchable but not displayed |
| definition | skos:definition | Formal definition |
| broader | skos:broader | More general concept |
| narrower | skos:narrower | More specific concept |
| related | skos:related | Associated concept |
| example | skos:example | Example usage |
E.7 QUDT (Quantities, Units, Dimensions and Types)
QUDT is an ontology for units of measurement and quantities.
Namespace: qudt: http://qudt.org/schema/qudt/
Units: unit: http://qudt.org/vocab/unit/
measurement [Room Temperature
- value | qudt:numericValue [22.5]
- unit | qudt:unit [Celsius{uri=<http://qudt.org/vocab/unit/DEG_C>} | °C{uri=<http://qudt.org/vocab/unit/DEG_C>}]
]
measurement [Blood Pressure
- systolic [
- value | qudt:numericValue [120]
- unit | qudt:unit [mmHg | unit:MilliM-HG]
]
- diastolic [
- value | qudt:numericValue [80]
- unit | qudt:unit [mmHg | unit:MilliM-HG]
]
]
measurement [Distance
- value | qudt:numericValue [5.2]
- unit | qudt:unit [
kilometers{uri=<http://qudt.org/vocab/unit/KiloM>} |
miles{en, uri=<http://qudt.org/vocab/unit/MI>}
]
]
Common QUDT Terms:
| Human Term | QUDT Term | Meaning |
|---|---|---|
| value | qudt:numericValue | Numeric measurement value |
| unit | qudt:unit | Unit of measurement |
| quantity | qudt:Quantity | Type of quantity (length, mass, etc.) |
E.8 Provenance Ontology (PROV)
PROV is for provenance and data lineage.
Namespace: prov: http://www.w3.org/ns/prov#
dataset [Stellar Parallax Measurements 2024
- generated by | prov:wasGeneratedBy [@telescope_observation_process]
- derived from | prov:wasDerivedFrom [@raw_telescope_data]
- attributed to | prov:wasAttributedTo [@astronomy_team]
- started at | prov:startedAtTime [2024-01-01T00:00:00Z]
- ended at | prov:endedAtTime [2024-12-31T23:59:59Z]
- used | prov:used [@calibrated_telescope]
]
activity [Data Cleaning Process
- used | prov:used [@raw_data_2024]
- generated | prov:generated [@cleaned_data_2024]
- started by | prov:wasStartedBy [@data_engineer]
- at location | prov:atLocation [@data_center_east]
]
agent [Research Team
- acted on behalf of | prov:actedOnBehalfOf [@university_department]
]
Common PROV Terms:
| Human Term | PROV Term | Meaning |
|---|---|---|
| generated by | prov:wasGeneratedBy | Entity was created by activity |
| derived from | prov:wasDerivedFrom | Entity created from other entity |
| attributed to | prov:wasAttributedTo | Entity credited to agent |
| used | prov:used | Activity used entity |
| started by | prov:wasStartedBy | Activity initiated by agent |
| at location | prov:atLocation | Where activity occurred |
E.9 Combined Example: Linked Data Across Vocabularies
<h1 id="person-with-standard-predicates-alongside-human-readable-slots">Person with standard predicates alongside human-readable slots</h1>
person [Dr. Sarah Chen
- name | foaf:name | schema:name [Sarah Chen]
- title | schema:honorificPrefix [Dr.]
- job title | schema:jobTitle [Materials Scientist]
- email | foaf:mbox | schema:email [<mailto:sarah.chen@university.edu>]
- homepage | foaf:homepage | schema:url [<https://materials.edu/chen>]
- same as | owl:sameAs | schema:sameAs [
<https://orcid.org/0000-0001-2345-6789> |
<https://www.wikidata.org/wiki/Q12345678>
]
- works for | foaf:workplaceHomepage | schema:worksFor [
- name | schema:name [University Materials Research Center]
- url | schema:url [<https://materials.edu>]
]
] @sarah_chen
<h1 id="research-paper-with-full-metadata">Research paper with full metadata</h1>
document [Titanium Alloy Stress Analysis 2024 {{generated_by=@analysis_process, derived_from=@raw_test_data, prov:wasGeneratedBy=@analysis_process}}
- title | dc:title | schema:headline [Titanium Alloy Fatigue: 2020-2024 Testing Results]
- creator | dc:creator | schema:author [@sarah_chen]
- date | dc:date | schema:datePublished [2024-03-15]
- description | dc:description | schema:abstract [
Analysis of Ti-6Al-4V alloy fatigue behavior under cyclic loading
]
- subject | dc:subject | schema:keywords [
Materials Science |
Titanium Alloys |
Fatigue Testing
]
- identifier | dc:identifier | schema:identifier [doi:10.1234/nature.2024.12345]
- language | dc:language [en]
- format | dc:format | schema:encodingFormat [application/pdf]
- same as | owl:sameAs [<https://doi.org/10.1234/nature.2024.12345>]
]
<h1 id="measurement-with-units">Measurement with units</h1>
measurement [Tensile Strength {{measured_by=@universal_testing_machine, confidence=~0.98}}
- value | qudt:numericValue [950]
- unit | qudt:unit [MPa | Megapascals{uri=<http://qudt.org/vocab/unit/MegaPA>}]
- specimen | schema:object [Ti-6Al-4V Sample 47]
- date | dc:date [2024]
]
E.10 Best Practices
- Include human-readable first:
- name | schema:nameputs human term first - Add language tags where helpful:
Celsius{en} | °C{en} - Use URIs for external links:
<http://dbpedia.org/resource/...> - Combine multiple standards: Can use both
foaf:andschema:terms together - Reference established ontologies: Link to QUDT, DBpedia, Wikidata for disambiguation
- Document custom terms: If creating domain-specific terms, document their meaning
E.11 Why use standard terms
Standard vocabulary mappings let the same Amorfs record serve humans and machines: RDF and OWL tools can read the predicates, search engines can pick up Schema.org fields, and you can link out to DBpedia or Wikidata — without giving up readable human terms or maintaining a separate translation layer.
Appendix F: Change Log
Draft 0.1 (June 2026)
First public draft of the Amorfs Format Specification.
- Two-part structure: Part I guided tour; Part II normative reference (data model, grammar, semantics, conformance, interoperability).
- Data model: Amorfs knowledge base — concepts, expressions, expression mapping, association structure, and metadata.
- Document syntax with normative Ohm grammar (Appendix D), metadata scopes (§11), and a Syntax Cheatsheet (§15).
- Conformance classes (Minimal, Standard, Full), interoperability mappings (Appendix E), and worked examples (Appendix B).
Appendix G: References
Standards and specifications. RDF 1.1 Turtle (W3C Recommendation, https://www.w3.org/TR/turtle/); ISO 8601 (date and time); RFC 3987 (Internationalized Resource Identifiers); JSON (ECMA-404, https://www.json.org/); Ohm parser generator (https://ohmjs.org/); ISO 639-1 (two-letter language codes).
Ontologies and vocabularies. Dublin Core Metadata Terms (https://www.dublincore.org/specifications/dublin-core/dcmi-terms/); FOAF (http://xmlns.com/foaf/spec/); Schema.org (https://schema.org/); OWL (https://www.w3.org/OWL/); SKOS (https://www.w3.org/2004/02/skos/); QUDT (http://www.qudt.org/); PROV-O (https://www.w3.org/TR/prov-o/).
External resources. DBpedia (https://www.dbpedia.org/); Wikidata (https://www.wikidata.org/); VIAF (https://viaf.org/); ORCID (https://orcid.org/).
Related work. First Cognition patent application FTC.1001, Computer-Implemented Knowledge Representation Systems.
Appendix H: Document Information
Authors: Pete Chapman, First Cognition team · Contact: tech@firstcognition.com · Copyright: © 2025–2026 First Cognition · License: MIT (LICENSE) · Patent: Implementation may relate to pending application FTC.1001, Computer-Implemented Knowledge Representation Systems (see Appendix G); the MIT license does not grant patent rights except as expressly stated therein · Status: Draft for Review · Version: 0.1 · Date: June 2026.