Attempto Controlled English

· 9 min · 2,177 words

topic/sciencecomputer science/programming languagescomputer science/natural language processing

Everyone hates natural language and its ambiguity (maybe except your manager), because ambiguity is where responsibilities go to die. “The customer entered the card with the code” sounds harmless until you ask whether the code is on the card, used as the instrument of entry, typed after the card, or sitting in some compliance spreadsheet waiting to ruin your afternoon.

Natural language can afford vagueness; people patch it with context. The deeper sin is quieter: syntax can pretend the semantics are already settled. A sentence can look completely normal while hiding multiple parse trees, multiple quantifier scopes, multiple pronoun antecedents, and multiple temporal readings. Human conversation survives this by leaning on context, charity, and social repair. Machines need the thing to compile.

Controlled Natural Language (CNL) is the compromise: keep the surface close enough to English that humans can read it, but restrict grammar, vocabulary, or interpretation enough that a parser can assign one intended meaning. Attempto Controlled English (ACE) is one of the most explicit versions of this idea: a controlled subset of English that behaves like a formal language while still looking, mostly, like English.

The Problem: English Is a Bad API

Natural English fails as a formal interface in predictable ways.

Prepositional phrase attachment

I saw the man with the telescope.

Who has the telescope? Me, the man, or the seeing event?

Quantifier scope

Every engineer reviewed a design.

This can mean each engineer reviewed some design, possibly different ones:

x(Engineer(x)y(Design(y)Reviewed(x,y)))\forall x(Engineer(x) \rightarrow \exists y(Design(y) \land Reviewed(x,y)))

Or it can mean there is one blessed design reviewed by everybody:

y(Design(y)x(Engineer(x)Reviewed(x,y)))\exists y(Design(y) \land \forall x(Engineer(x) \rightarrow Reviewed(x,y)))

Anaphora

Alice gave Bob the file because he needed it.

Who needed it? Bob probably, but the grammar leaves that as a guess.

Coordination

Old men and women entered the room.

Are the women old too? English shrugs.

This is fine for casual speech. It is a disaster if the sentence is supposed to become a database query, an ontology axiom, a regulatory rule, a requirements document, or a theorem premise. Formal languages solve the ambiguity problem by becoming unreadable to most people. CNLs try to land between English and logic.

CNL: The Family

A controlled natural language is a constructed language based on a natural language, usually more restrictive in lexicon, syntax, or semantics, while preserving enough naturalness that speakers of the base language can still understand it.1

Historically, CNLs split into three broad tribes.

1. Human-comprehension CNLs

These are for technical documentation. They reduce vocabulary, sentence length, grammar variation, and idioms so non-native speakers and technicians can read manuals reliably. The historical line runs through Basic English in the 1930s, Caterpillar Fundamental English in the 1970s, and Simplified Technical English in aerospace. Here the target is practical comprehension: write maintenance instructions that stay unambiguous when someone is holding a wrench near a turbine.

2. Translation-oriented CNLs

These languages make source text easier for machine translation. The discipline is similar: fewer idioms, restricted grammar, explicit terminology. The target is multilingual consistency rather than theorem proving.

3. Formal-meaning CNLs

These are the languages ACE belongs to. Here readability becomes a front-end for computability. A sentence should map into a formal representation such as First-order logic, Discourse Representation Theory, OWL, RuleML, or a query language. This is the zone where English becomes a front-end syntax for logic.

Tobias Kuhn’s survey classifies CNLs by PENS: Precision, Expressiveness, Naturalness, and Simplicity.1 That is the useful mental model. You can make a language very natural, very expressive, very precise, or very simple, but you rarely get all four for free. ACE deliberately spends some naturalness to buy precision.

ACE in One Sentence

ACE is a rich controlled subset of English, developed in the Attempto project at the University of Zurich, designed to serve as a knowledge representation language.2 ACE texts can be parsed unambiguously by the Attempto Parsing Engine (APE) into discourse representation structures (DRSs), which can then be translated into formal targets such as FOL, OWL, SWRL, RuleML, and TPTP.2 The official nutshell guide is the right short entry point; the construction and interpretation rules are where the real machinery lives.3

The sales pitch is simple:

Write English-looking sentences. Get logic.

The catch is equally simple:

You must write the kind of English ACE accepts.

Rather than “LLM, please infer what I meant,” ACE feels closer to IMP Language or Lambda Calculus: the syntax is constrained because the semantics are supposed to be mechanical.

Formal Shape

A compact definition:

Let GACEG_{ACE} be the ACE grammar, VfV_f the fixed function-word vocabulary, and VcV_c a domain lexicon of content words: nouns, verbs, adjectives, adverbs, and proper names. Then:

LACE={ss is accepted by GACE over VfVc}L_{ACE} = \{s \mid s \text{ is accepted by } G_{ACE} \text{ over } V_f \cup V_c\}

An ACE processor gives a deterministic interpretation function:

IACE:LACEDRSI_{ACE}: L_{ACE} \rightarrow DRS

For the non-modal, non-query, non-command core, the DRS can be translated into ordinary first-order logic:

TFOL:DRScoreFOLT_{FOL}: DRS_{core} \rightarrow FOL

So the useful pipeline is:

ACE text -> APE parse -> DRS -> FOL / OWL / RuleML / TPTP / other target

English-looking words are the surface feature. Deterministic mapping is the engineering feature. If the parser accepts a sentence, ACE assigns one interpretation. If that interpretation misses your meaning, rewrite the sentence.

Syntax: The English-Looking Shell

An ACE text is a sequence of declarative sentences, interrogative sentences, and imperative sentences. Declaratives end with ., questions with ?, commands with !.4

At the coarse level:

ACEText          ::= CompleteSentence*
CompleteSentence ::= Specification "." | Query "?" | Command "!"

Simple declarative sentences look like this:

subject + verb + complements + adjuncts

Examples:

A customer waits.
A customer owns a card.
A customer gives a card to a clerk.
The temperature is -2.

ACE also supports existential introductions:

There is a customer.
There are at least 3 apples.

Composite sentences are built with coordination, quantification, negation, modality, and subordination:

If a card is valid then a customer inserts it.
Every customer inserts a card.
It is false that a customer inserts a card.
It is not provable that a customer inserts a card.
A clerk believes that a customer inserts a card.

ACE function words are fixed: determiners, quantifiers, coordinators, negation words, pronouns, query words, modal auxiliaries, forms of be, and fixed phrases such as there is or it is false that.5

Content words are domain-specific. Multiword terms are usually hyphenated:

credit-card
Supreme-Court
TPS-decision
legal-status

Phrasal and prepositional verbs also use hyphenation when the particle/preposition is part of the verb:

John looks-up an entry.
A steward waits-on a table.

That hyphen carries semantic weight. It prevents looks up from being parsed as a verb plus a directional prepositional phrase.

Semantics: Where ACE Buys Precision

ACE removes ambiguity in two ways.

First, ACE excludes some English constructions outright. You trade a little fluency for sentences that survive parsing.

Second, accepted sentences are interpreted by fixed rules.6 Some rules are intuitive; some are the price of making English compile.

Determiners

a means existential rather than generic:

A cat is an animal.

means:

x(Cat(x)Animal(x))\exists x(Cat(x) \land Animal(x))

To say all cats are animals:

Every cat is an animal.

which means:

x(Cat(x)Animal(x))\forall x(Cat(x) \rightarrow Animal(x))

Quantifier Scope

Surface order matters.

Every customer inserts a card.

means each customer inserts at least one card, possibly different cards:

x(Customer(x)y(Card(y)Inserts(x,y)))\forall x(Customer(x) \rightarrow \exists y(Card(y) \land Inserts(x,y)))

To force one shared card:

There is a card that every customer inserts.

which maps to:

y(Card(y)x(Customer(x)Inserts(x,y)))\exists y(Card(y) \land \forall x(Customer(x) \rightarrow Inserts(x,y)))

This is exactly the kind of ambiguity English hides and ACE makes you pay for explicitly.

Plurals

Plural noun phrases are collective by default. Distributive readings use each of:

Two girls lift a table.
Each of two girls lifts a table.

The first describes one group-lifting event. The second describes individual lifting events.

Coordination

and binds stronger than or. ACE also has comma coordinators ,and and ,or to override the default binding order.4

The customer enters a red card or enters a blue card and enters a personal-code.

has a different logical shape from:

The customer enters a red card or enters a blue card, and enters a personal-code.

The punctuation is ugly; the payoff is explicit scope.

Prepositional Phrases

In ACE, prepositional phrases attach to the verb. This sentence:

A customer inserts a card with a code.

is read as an inserting event done with a code. For “a card that has a code,” use a relative clause.

To attach the code to the card:

A customer inserts a card that carries a code.

This is probably the most ACE-flavored rule: if you want noun modification, use a relative clause.

Anaphora

ACE resolves pronouns and definite noun phrases by accessibility, recency, specificity, and reflexivity.6

A customer enters a card and a code.
If the code is valid then the ATM accepts the card.

Variables can make the binding explicit:

A customer enters a card X and a code Y.
If Y is valid then the ATM accepts X.

The variable trick is the closest ACE gets to letting English wear a programmer’s badge.

Negation

ACE distinguishes logical negation from negation as failure:

A customer does not insert a card.
It is false that a customer inserts a card.
It is not provable that a customer inserts a card.

The first two are classical negation in different scopes. The third says the available knowledge base lacks a proof for the proposition. If ZFC is a carefully patched foundation for sets, ACE is a carefully patched surface language for saying what goes into the knowledge base in the first place.

The DRS Layer

APE first translates ACE into a DRS before any friendly FOL notation appears on the whiteboard.7

A DRS has:

drs(Domain, Conditions)

The Domain is a list of discourse referents. The Conditions are logical atoms or complex nested DRSs. The report uses a flat, reified notation. Instead of turning “a card” directly into:

card(A)

APE represents it with a predefined predicate:

object(A, card, countable, na, eq, 1)

Verbs become predicate(...) atoms, adjectives become property(...), genitive/of-relations become relation(...), and so on. This looks uglier than normal FOL, but it makes the target language regular. The user’s vocabulary becomes data inside a small number of predefined predicates.

For conceptual examples below, I use readable FOL predicates like Customer(x) and Inserts(x,y). This is the cleaned-up logical reading rather than APE’s exact flat output.

Worked Examples

Basic Knowledge

ACE:

Every customer owns a card.
If a customer owns a card then the customer enters the card.
No expired card is valid.

Readable FOL:

x(Customer(x)y(Card(y)Owns(x,y)))\forall x(Customer(x) \rightarrow \exists y(Card(y) \land Owns(x,y))) xy((Customer(x)Card(y)Owns(x,y))Enters(x,y))\forall x \forall y((Customer(x) \land Card(y) \land Owns(x,y)) \rightarrow Enters(x,y)) x((Card(x)Expired(x))¬Valid(x))\forall x((Card(x) \land Expired(x)) \rightarrow \neg Valid(x))

Anaphora With Variables

ACE:

A customer C owns a card X.
If X is valid then C enters X.

Readable FOL:

cx(Customer(c)Card(x)Owns(c,x)(Valid(x)Enters(c,x)))\exists c \exists x(Customer(c) \land Card(x) \land Owns(c,x) \land (Valid(x) \rightarrow Enters(c,x)))

The second sentence can refer to C and X because variables establish explicit anaphoric links.

Scope Difference

ACE:

Every reviewer reads a paper.

Readable FOL:

r(Reviewer(r)p(Paper(p)Reads(r,p)))\forall r(Reviewer(r) \rightarrow \exists p(Paper(p) \land Reads(r,p)))

ACE:

There is a paper that every reviewer reads.

Readable FOL:

p(Paper(p)r(Reviewer(r)Reads(r,p)))\exists p(Paper(p) \land \forall r(Reviewer(r) \rightarrow Reads(r,p)))

Same English words, different scope. ACE makes the difference visible.

Today News Example

Random source article for June 26, 2026: The Guardian’s report on a U.S. Supreme Court immigration decision.8

Short source excerpt:

“And the court’s TPS decision allows the administration to again strip people of their legal status.”

Modern English paragraph, paraphrased from the same source paragraph:

After the Supreme Court’s TPS ruling, the Trump administration can again remove legal status from affected people. The affected people include many Haitian and Syrian TPS holders who have lived and worked legally in the United States for years.

Even this cleaned-up paragraph contains the normal English mess:

  • the court's TPS decision: which court, which decision?
  • the administration: which administration?
  • people: all people, affected people, people under TPS?
  • their legal status: whose status?
  • again: repeated permission, repeated stripping event, or repeated legal posture?

An ACE-ish rewrite must choose a model. Here is one possible version:

The Supreme-Court makes a TPS-decision D.
The Trump-administration is an administration.
Every Haitian-TPS-holder is a TPS-holder.
Every Syrian-TPS-holder is a TPS-holder.
Every TPS-holder is an affected-person.
If an affected-person P has a legal-status S then D allows that the Trump-administration again removes S from P.

This rewrite chooses the following semantics:

  • The relevant court is Supreme-Court.
  • The relevant administration is Trump-administration.
  • Haitian and Syrian TPS holders are included in the affected class.
  • The legal status belongs to each affected person.
  • again modifies the removal event.

Readable FOL with event reification:

TPSDecision(d)Makes(SupremeCourt,d)Administration(TrumpAdministration)TPSDecision(d) \land Makes(SupremeCourt,d) \land Administration(TrumpAdministration) p(HaitianTPSHolder(p)TPSHolder(p))\forall p(HaitianTPSHolder(p) \rightarrow TPSHolder(p)) p(SyrianTPSHolder(p)TPSHolder(p))\forall p(SyrianTPSHolder(p) \rightarrow TPSHolder(p)) p(TPSHolder(p)AffectedPerson(p))\forall p(TPSHolder(p) \rightarrow AffectedPerson(p)) ps((AffectedPerson(p)LegalStatus(s)Has(p,s))e(Removal(e)Agent(e,TrumpAdministration)Theme(e,s)Source(e,p)Repeated(e)Allows(d,e)))\forall p \forall s((AffectedPerson(p) \land LegalStatus(s) \land Has(p,s)) \rightarrow \exists e(Removal(e) \land Agent(e,TrumpAdministration) \land Theme(e,s) \land Source(e,p) \land Repeated(e) \land Allows(d,e)))

Why reify the event? Because allows relates a legal decision to a possible action. If we write Allows(d, Remove(...)), we smuggle a proposition/action term into FOL. Reifying the removal as an event e keeps the formula first-order.

This is the main lesson: ACE forces the ontology into the open.

Practical Rules for Writing ACE

The troubleshooting guide’s spirit is basically: write like a lawyer who learned compiler construction.9

Use complete, short sentences:

A customer enters a card.
The card is valid.

Use determiners:

A card is valid.
Every card is valid.
The card is valid.

Use simple present tense for ACE declarative verbs:

A customer enters a card.

Use active voice or include the passive agent:

A customer enters a code.
A code is entered by a customer.

Avoid the agentless passive:

A code is entered.

Use relative clauses for noun modification:

A card that is in a slot is invalid.

instead of:

There is a card in a slot.

Check the paraphrase. If the paraphrase diverges from your intended meaning, rewrite the sentence even if the original felt natural.

Why ACE Matters

ACE belongs to a narrow, useful slice of writing. Slack messages can remain gloriously uncontrolled. The interesting case is English as a user interface for logic.

That makes it useful in places where three things must coexist:

  1. domain experts need to read and write the rules;
  2. machines need to reason over the rules;
  3. ambiguity is expensive.

Examples include ontologies, compliance rules, business policies, medical guidelines, semantic wikis, requirements engineering, and formal documentation.

In programming language terms, ordinary English is dynamically scoped global state with invisible coercions. ACE is less elegant than pure formal logic, but much harder to bend into five accidental meanings at once. It gives you a controlled surface, a parser, a discourse model, and a path to FOL. That is a good trade whenever “what did you mean by that?” becomes too expensive after deployment.

Sources

Footnotes

  1. Tobias Kuhn, A Survey and Classification of Controlled Natural Languages, Computational Linguistics, 2014/2015 arXiv version. 2

  2. Attempto Project description, University of Zurich. 2

  3. ACE 6.7 in a Nutshell, Attempto documentation.

  4. ACE 6.7 Syntax Report, Attempto documentation. 2

  5. ACE 6.7 Construction Rules, Attempto documentation.

  6. ACE 6.7 Interpretation Rules, Attempto documentation. 2

  7. Norbert E. Fuchs, Kaarel Kaljurand, Tobias Kuhn, Discourse Representation Structures for ACE 6.6, 2010.

  8. The Guardian, June 26, 2026. The verbatim quote is kept to a short excerpt; the longer modern-English paragraph is paraphrased from the same source paragraph.

  9. ACE 6.7 Troubleshooting Guide, Attempto documentation.