DOLA: Difference between revisions

From BITPlan cr Wiki
Jump to navigation Jump to search
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
This is an experiment for the {{Link|target=Syntax Matters}} research topic.
see {{Link|target=Lola-2}} and [[Talk:DOLA]] for how this was created
{{LLMHint}}
{{LLMHint}}
see {{Link|target=Lola-2}}
= DOLA: A Description Ontology Language =
 
''Inspired by N. Wirth's Lola-2''
 
DOLA is a notation for specifying ontologies in the tradition of OWL Description Logic. In many ways it resembles Lola-2: where Lola describes static circuits, DOLA describes conceptual domains. Objects in a description are '''classes''' (sets of individuals), '''properties''' (relations), and '''individuals''' (concrete entities). Class expressions combine classes and property restrictions using operators that mirror the logical gates of Lola.
 
----
 
== 0. Vocabulary ==
 
'''Special characters:'''
<pre>
~ & | = # < <= > >= ( ) [ ] { } <: := . , ; : o
</pre>
 
'''Reserved words:'''
<pre>
<pre>
BEGIN BOT CLASS CONST DATA DIFF DISJOINT END EXACT FUNC
IND IFUNC IMPORT INVERSE MAX MIN ONLY ONTOLOGY PROP RANGE
DOMAIN REFL IRREFL SAME SELF SOME SYM ASYM TOP TRANS VALUE CHAIN
</pre>
----
== 1. Identifiers, IRIs, and Comments ==
Identifiers denote classes, properties, individuals, and constants.
<syntaxhighlight lang="ebnf">
identifier = letter {letter | digit}.
iri        = "<" {character} ">".
integer    = digit {digit}.
string    = '"' {character} '"'.
literal    = integer | string.
</syntaxhighlight>
Capital and lower-case letters are considered distinct. IRIs (Internationalized Resource Identifiers) reference external ontologies.
Comments are enclosed by <code>(*</code> and <code>*)</code> and may occur between any two symbols.
----
== 2. Classes and Datatypes ==
Every individual belongs to one or more classes. The universal class is <code>TOP</code> (owl:Thing); the empty class is <code>BOT</code> (owl:Nothing).


<syntaxhighlight lang="ebnf">
classRef = identifier | "TOP" | "BOT".
datatype = "INT" | "FLOAT" | "STRING" | "BOOL" | identifier.
</syntaxhighlight>


is is possible to translate owl description logic terms to lola-2?
The predeclared datatypes <code>INT</code>, <code>FLOAT</code>, <code>STRING</code>, and <code>BOOL</code> correspond to xsd:integer, xsd:float, xsd:string, and xsd:boolean respectively.
35 seconds ago
Favicon for anthropic
Claude Opus 4.6
Translating OWL Description Logic to LOLA-2


This is an interesting but somewhat unusual question. Let me break it down.
----
Clarifying the Systems


OWL DL is based on Description Logics (primarily SHOIN(D) for OWL 1 and SROIQ(D) for OWL 2), with constructs like:
== 3. Constant Declarations ==
DL Construct Syntax Meaning
Concept Intersection C⊓D AND of concepts
Concept Union C⊔D OR of concepts
Complement ¬C NOT a concept
Existential Restriction ∃R.C some values from
Universal Restriction ∀R.C all values from
Number Restriction ≤nR.C at most n


LOLA-2 — could you clarify which system you mean? The name maps to several possibilities:
<syntaxhighlight lang="ebnf">
ConstDeclaration = identifier "=" integer ";".
</syntaxhighlight>


    LoLa 2 (Low-Level Petri Net Analyzer) — a model checker for place/transition nets
Constants may be used wherever an integer is expected, for example in cardinality restrictions.
    LOLA 2.0 — a stream-based runtime verification specification language
    Something else?


General Feasibility
----


Reasoning
== 4. Class Expressions ==


The user is asking about translating OWL (Web Ontology Language) Description Logic (DL) terms to LOLA-2. Let me think about what LOLA-2 is.
Class expressions define classes by combining atomic classes with operators representing set-theoretic constructions and property restrictions. Whereas Lola expressions define signal values through gates, DOLA expressions define classes through set-theoretic and relational constructors.


LOLA-2 could refer to several things. Let me think...
<syntaxhighlight lang="ebnf">
classExpr  = classTerm {"|" classTerm}.
classTerm  = classFactor {"&" classFactor}.
classFactor = classAtom
            | "~" classFactor
            | restriction
            | "{" identifier {"," identifier} "}"
            | "(" classExpr ")".
classAtom  = identifier | "TOP" | "BOT".


LOLA-2 is likely referring to a Petri net analysis tool, or possibly a logic language. Actually, let me think more carefully.
restriction = ("SOME" | "ONLY") identifier ["." classFactor]
            | ("MIN" | "MAX" | "EXACT") integer identifier ["." classFactor]
            | "VALUE" identifier identifier
            | "SELF" identifier.
</syntaxhighlight>


LOLA-2 might refer to:
When the <code>"." classFactor</code> of a restriction is omitted, it defaults to <code>TOP</code>.


    LoLa (Low Level Analyzer) - a tool for analyzing Petri nets
'''Operators''' (in order of increasing precedence):


    LOLA-2 as a programming language or logic specification language
{| class="wikitable"
! Operator !! Meaning !! DL Notation
|-
| <code>|</code> || class union || <math>C \sqcup D</math>
|-
| <code>&</code> || class intersection || <math>C \sqcap D</math>
|-
| <code>~</code> || class complement || <math>\lnot C</math>
|}


    LOLA 2.0, which is a stream runtime verification specification language for real-time stream processing
'''Restrictions''' construct classes from properties:


I'm trying to figure out which LOLA-2 the user means—it could be the temporal stream-based specification language developed by Ben d'Angelo and others, or possibly something else entirely that could express Description Logic concepts. I'm not entirely certain what LOLA-2 refers to in this context—it could be a second-order logic system or a formal language I'm not immediately placing. Rather than guess further, I should acknowledge the uncertainty and pivot to what I do know: translating OWL DL, which maps to description logics like SHOIN(D) or SROIQ(D), would require understanding the target system's expressiveness and whether it can represent the key constructs involved. Concept names (atomic classes)
{| class="wikitable"
! Restriction !! Meaning !! DL Notation
|-
| <code>SOME R . C</code> || existential — has at least one <math>R</math>-filler in <math>C</math> || <math>\exists R.C</math>
|-
| <code>ONLY R . C</code> || universal — all <math>R</math>-fillers are in <math>C</math> || <math>\forall R.C</math>
|-
| <code>MIN n R . C</code> || minimum qualified cardinality || <math>\geq n\; R.C</math>
|-
| <code>MAX n R . C</code> || maximum qualified cardinality || <math>\leq n\; R.C</math>
|-
| <code>EXACT n R . C</code> || exact qualified cardinality || <math>= n\; R.C</math>
|-
| <code>VALUE R a</code> || has-value — has <math>R</math>-filler <math>a</math> || <math>\exists R.\{a\}</math>
|-
| <code>SELF R</code> || has-self — is <math>R</math>-related to itself || <math>\exists R.\mathsf{Self}</math>
|}


    Role names (properties)
The enumeration <code>{a, b, c}</code> denotes the class containing exactly the named individuals <math>a</math>, <math>b</math>, <math>c</math> (OneOf).
    Concept intersection (C⊓D)
 
    Concept union (C⊔D)
'''Examples:'''
    Negation/complement (¬C)
<pre>
    Existential restriction (∃R.C)
Person & Male                                        (* intersection *)
    Universal restriction (∀R.C)
Doctor | Lawyer                                      (* union *)
    Number restrictions (≤nR.C, ≥nR.C)
~Parent                                              (* complement *)
     Nominals ({a})
SOME hasChild . Person                                (* existential *)
    Role hierarchies
ONLY hasChild . (Doctor | Lawyer)                    (* universal *)
    Transitive roles
MIN 2 hasChild                                        (* unqualified min card. *)
    etc.
Person & SOME hasChild . (SOME hasChild . Person)    (* nesting *)
{mon, tue, wed, thu, fri}                             (* enumeration *)
</pre>


If LOLA-2 is a Petri net analysis tool, the translation would be quite unusual since Petri nets focus on concurrent systems and state reachability rather than ontological reasoning. If it's a stream specification language, it deals with temporal properties of data streams, which is also fundamentally different from description logic. I'm uncertain about what LOLA-2 specifically refers to—it could be a linear logic-based language or something else entirely—so I should be transparent about the ambiguity and discuss the feasibility of translation across the different interpretations I can think of.
----
Collapse reasoning


1
== 5. Class Declarations ==
Lola-2: A Logic Description Language
N. Wirth, 24.4.1994 / 1.9.2015
Lola is a notation (language) for specifying digital circuits (logic). In many ways it resembles a
programming language. However, Lola texts describe static circuits rather than dynamic processes.
Objects occurring in a description can be variables representing signals or registers. Their values
are defined as expressions of other objects and operators representing gates.
0. Vocabulary
The vocabulary of Lola consists of special characters (or pairs), and so-called reserved words which
cannot be chosen as identifiers.
Special characters:
~ & | ^ + - * = # < <= > >=
( ) [ ] { } -> . , ; : := ' !
Reserved words:
BEGIN CONST END IN INOUT MODULE OUT REG TS TYPE VAR


    Identifiers, integers, and comments
<syntaxhighlight lang="ebnf">
    Identifiers are used to denote constants, variables, and types.
ClassDeclaration = identifier ["=" classExpr | "<:" classExpr] ";".
    identifier = letter {letter | digit}.
</syntaxhighlight>
    integer = digit {digit} ["H"].
    Examples: Lola begin 100 100H 0FFH
    Capital and lower case letters are considered as distinct. If an integer is followed by the capital letter
    H it is in hexadecimal form with digits 0, 1, ..., 9, and A ... F.
    Comments are sequences of characters enclosed by the brackets (* and *), and they may occur
    between any two symbols within a Lola text.
    Simple types and array types
    Every variable in Lola has a type. The elementary type is BIT (BInary digiT), and its variables
    assume the values 0 or 1.
    type = {"[" expression "]"} SimpleType.
    SimpleType = identifier |."MODULE" unit ";" identifier.
    TypeDeclaration = identifier "=" type .
    An array type is specified by the form [n]T, where T is the type of the elements, and the integer n
    specifies the number of elements. In expressions, individual elements are designated by an index.
    Indices range from 0 to the array's length minus 1.
    Examples: [10] BIT [8][16] BIT
    The identifiers BIT, BYTE and WORD are predeclared. The latter denote arrays of 8 and 32 bits
    respectively.
    Constant declarations
    Constant declarations serve to introduce identifiers denoting a constant, numeric value.
    ConstDeclaration = identifier "=" integer ";".
    2
    Variable and register declarations
    Variable declarations introduce registers and variables and associate a type with them. All variables
    declared in an identifier list have the same type. Variables of type [n] BIT are called bitstrings.
    varlist = identifier {"," identifier} ":" type.
    Examples: x, y: BIT a: [32] BIT R: BIT Q (clk50): [4] BIT
    If a register declaration contains an expression, this denotes the register's clock. The default is a
    variable clk, which must be declared (see also Section 7).
    Expressions
    Expressions serve to combine variables with operators to define new values. The operators are
    logical negation, conjunction, disjunction, and difference, or arithmetic sum and difference. Elements
    of an array are selected by an index. (e.g. a.5, a[10]).
    | logical disjunction (or)
    ^ logical difference (exclusive or)
    & logical conjunction (and)
    ~ logical negation (not)


    arithmetic sum
A bare identifier (e.g. <code>Person;</code>) introduces a named class with no axioms. The symbol <code>=</code> specifies an '''equivalent class''' (necessary and sufficient conditions). The symbol <code><:</code> specifies a '''superclass''' (necessary conditions only).


    arithmetic difference
The distinction is fundamental: <math>A = C</math> means an individual is an <math>A</math> if and only if it satisfies <math>C</math>; <math>A <: C</math> means every <math>A</math> satisfies <math>C</math>, but satisfying <math>C</math> does not entail being an <math>A</math>.
    Operands are registers, variables, and constants. Whereas variables denote the value given by the
    assigned expression, registers denote the value of the expression in the preceding clock cycle.
    Registers are instrumental in sequential circuits. The operands of diadic operators must be of the
    same type.
    expression = uncondExpr ["->" expression ":" expression].
    uncondExpr = simpleExpr [ ("=" | "#" | "<" | "<=" | ">" | ">=") simpleExpr].
    simpleExpr = ["+" | "-"] term {("|" | "^" | "+" | "-") term}.
    term = factor {"&" factor}.
    factor = variable | integer | "~" factor | constructor | "(" expression ")".
    variable = identifier {selector}.
    selector = "." factor | "[" expression [":" expression] "]".
    constructor = "{" element {"," element} "}".
    element = expression ["!" integer].
    The form a[m : n] denotes the range of indexed elements a[m], ... , a[n].
    Constructors denote bitstrings and are sequences of elements. The length (number of bits) of every
    element must be known. This length is specified in a declaration, and in this case of constants by an
    explicit integer. For example 10'8 denotes the number 10 represented by 8 bits. The length of the
    bitstring is the sum of the lengths of its elements. Also, an element can be followed by a replication
    factor of the form !n.
    A conditional expression of the form z := cond -> x : y expresses represents a multiplexer. Cond
    must be of type BIT. If cond yields 1, z is equal to x, otherwise to y.
    Examples: x count 1 100 a.4 a[20] operands
    a[15 : 8] range
    {u, a.4, a[25:20], 0'8, 15'4} constructor (20 bit)
    (x & y) | (z & w) (m + n) + 10 simple expressions
    a.5 -> b : c expression


    Assignments and statements
'''Examples:'''
    Assignments serve to define a register's or a variable's value, which is specified by an expression.
<pre>
    An assignment must be understood as a variable's definition (in contrast to an identifier's
Person;                                                (* declaration only *)
    3
Male <: Person;                                        (* subclass *)
    declaration). In an assignment v := x, v and x do not have the same roles, and this asymmetry is
Parent = Person & SOME hasChild . Person;              (* equivalence *)
    emphasized by the use of the symbol := instead of the symmetric equal sign. v and x must be of the
Mother = Female & Parent;                              (* equivalence *)
    same type.
ChildlessPerson = Person & ~Parent;                    (* complement *)
    assignment = variable ":=" expression..
PersonWith3Children = EXACT 3 hasChild . Person;       (* cardinality *)
    Examples: x := y & z a := {x, y, z} R := rst -> 0 : enb -> x : R
DayOfWeek = {mon, tue, wed, thu, fri, sat, sun};      (* enumeration *)
    Every variable and register can be assigned in only one single assignment statement, and the
</pre>
    assignment must be to the entire variable (not to elements). The only exception is the indexed
 
    assignment to an array of registers (e.g. R[n] := x).
----
    For example, instead of
 
    a.0 := x; a.1 := x+y; a.2 := x-y; a.3 := xy
== 6. Property Declarations ==
    the single assignment
 
    a := {x, x+y, x-y, xy)
Properties relate individuals to other individuals ('''object properties''', declared in a <code>PROP</code> section) or to data values ('''data properties''', declared in a <code>DATA</code> section).
    must be used.
 
    Statements are either assignments, or instantiations of modules (see next section), or TSgates.
<syntaxhighlight lang="ebnf">
    statement = [assignment | instantiation | TSgate].
PropDeclaration = identifier {"," identifier}
    StatementSequence = statement {";" statement}.
     ["[" propAttr {";" propAttr} "]"] ";".
    A TSgate (TS stads for tri-state) is used for INOUT interface parameters.
 
    TSgate = "TS" "(" iogate "," input "," output "," control ")".
propAttr = "DOMAIN" classExpr
    iogate = variable.
        | "RANGE" classExpr
    input = variable. from interface
        | "INVERSE" identifier
    output = expression. to interface
        | "=" identifier
    control = expression. 1 for output, 0 for input from interface
        | "<:" identifier
    Examples
        | "CHAIN" identifier {"o" identifier}
    TS(io, in, out, ~wr) TS(io[k], in[k], out[k], ctrl[k])
        | characteristic.
    The parameters may be simple variables or arrays. They must be of the same type, except that the
    control parameter may be of type BIT, even if the other parameters are arrays. In this case it
    controls all elements of the arrays
    Modules
    A module specifies constants, types, variables, registers, and assignments to variables and
    registers. Modules are specified as types, and variables can be declared of this type. This implies
    that modules can be replicated.
    ModuleType = "MODULE" ["*"] unit ";".
    paramlist = ("IN" | "OUT" | "INOUT") varlist.
    unit = "(" paramlist {";" paramlist} ")" ("^" | ";"
     ["CONST" {ConstDeclaration}]
    ["TYPE" {TypeDeclaration}]
    {("VAR" | "REG" "(" expression ")") {varlist ";"}}
    ["BEGIN" StatementSequence] "END").
    The expression after the symbol REG specifies the register's clock.
    Example of a module type:
    TYPE Counter = MODULE (IN clk, rst, enb: BIT; OUT data: WORD);
    REG (clk) R: Word;
    BEGIN data := R;
    R := ~rst -> 0 : enb -> R + 1 : R
    4
    END Counter
    Given a variable of this type (cnt: Counter), its instantiation could be
    cnt (clock, reset, enable, val)
    where clock, reset, enable and data are variables called actual parameters. They must be expressions
    of the corresponding types.
    instantiation = identifier selector "(" expression {"," expression} ")".
    A "main program" has the form
    module = "MODULE" identifier unit identifier ".".
    Evidently, a "main program" is the combined declaration of an (anonymous) module type and of a
    single instance. The identifier at the end of the module's declaration must be the same as the one
    following the symbol MODULE.


21 seconds ago
characteristic = "FUNC" | "IFUNC" | "TRANS" | "SYM" | "ASYM" | "REFL" | "IRREFL".
Favicon for anthropic
Claude Opus 4.6
Lola-2: Logic Description Language — Summary


You've shared the complete specification of Lola-2, a hardware description language (HDL) designed by Niklaus Wirth for specifying digital circuits. Here's a structured overview:
DataDeclaration = identifier {"," identifier}
Key Concepts
    ["[" dataAttr {";" dataAttr} "]"] ";".


Lola-2 describes static circuits, not dynamic processes. It resembles a programming language syntactically but has fundamentally different semantics:
dataAttr = "DOMAIN" classExpr
Concept Meaning in Lola-2
        | "RANGE" datatype
Variable A signal (combinational logic — value defined by its assigned expression)
        | "<:" identifier
Register A clocked storage element (value is from the previous clock cycle)
        | "FUNC".
Expression A combination of operators (gates) applied to operands
</syntaxhighlight>
Module A reusable circuit block (like a component/entity in VHDL)
Assignment := Defines (not updates) a variable's or register's value
Important Constraints


    Every variable/register may be assigned exactly once (single static assignment).
'''Characteristics:'''
    Assignments must target the entire variable — not individual elements — with the sole exception of indexed register arrays like R[n] := x.
    The conditional expression cond -> x : y models a multiplexer.


Example — A Counter Module
{| class="wikitable"
! Keyword !! Meaning !! OWL Axiom
|-
| <code>FUNC</code> || at most one value per individual || FunctionalObjectProperty
|-
| <code>IFUNC</code> || at most one individual per value || InverseFunctionalObjectProperty
|-
| <code>TRANS</code> || transitive || TransitiveObjectProperty
|-
| <code>SYM</code> || symmetric || SymmetricObjectProperty
|-
| <code>ASYM</code> || asymmetric || AsymmetricObjectProperty
|-
| <code>REFL</code> || reflexive || ReflexiveObjectProperty
|-
| <code>IRREFL</code> || irreflexive || IrreflexiveObjectProperty
|}


TYPE Counter = MODULE (IN clk, rst, enb: BIT; OUT data: WORD);
<code>CHAIN p o q</code> defines a property as the composition of properties <math>p</math> and <math>q</math> (a property chain). <code>INVERSE p</code> declares the property as the inverse of <math>p</math>. Within brackets, <code><:</code> gives a super-property, and <code>=</code> gives an equivalent property.
  REG (clk) R: WORD;
BEGIN
  data := R;
  R := ~rst -> 0 : enb -> R + 1 : R
END Counter


This defines:
'''Examples:'''
<pre>
hasChild [DOMAIN Person; RANGE Person];
hasParent [INVERSE hasChild];
hasAncestor [TRANS; <: hasRelative];
hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person];
hasUncle [CHAIN hasParent o hasBrother];
hasBrother [<: hasSibling; RANGE Male];
</pre>


    A register R clocked by clk
----
    Output data wired directly to R
    R's next-state logic: if rst is low (~ is negation), reset to 0; else if enb is high, increment; else hold


Do you have a specific question about the language, or would you like help writing a Lola-2 module, translating between Lola-2 and another HDL (e.g., Verilog/VHDL), or analyzing a particular construct?
== 7. Individual Declarations ==
Reasoning


could we have a lola like language for description logics?
Individuals are concrete members of classes.
21 seconds ago
Favicon for anthropic
Claude Opus 4.6
Reasoning


The user is asking about whether we could have a "LOLA-like" language for description logics. Let me think about what LOLA is and what description logics are, and how they might be combined.
<syntaxhighlight lang="ebnf">
IndDeclaration = identifier {"," identifier} ":" classExpr ";".
</syntaxhighlight>


LOLA (Logic of Logical Agents, or possibly referring to LOLA - a tool for analyzing Petri nets, or possibly another formalism) - actually, I think the user might be referring to LOLA as in a specific formal language or logic programming paradigm. Let me think more carefully.
The class expression after <code>:</code> specifies class membership (a class assertion).


Actually, "LOLA" could refer to several things:
'''Examples:'''
<pre>
john : Father;
mary : Female & Parent;
mon, tue, wed, thu, fri, sat, sun : DayOfWeek;
</pre>


    LOLA - a monitoring specification language for stream-based runtime verification
----


    LOLA - Logic of Logical Agents
== 8. Axioms and Statements ==


    Some other formalism
The <code>BEGIN ... END</code> section contains axioms not captured by declarations. A statement is separated by <code>;</code> (as a separator, not a terminator, following Wirth's convention).


Given the context of "description logics," I think the user might be referring to LOLA as a stream-based specification language, or possibly to a particular kind of declarative/logical specification language. The most likely reference is probably the stream runtime verification language that allows specifying properties over streams of data in a declarative way, though it could also be a lightweight or linear logic variant.
<syntaxhighlight lang="ebnf">
statement = classExpr "<:" classExpr
          | "DISJOINT" classRef {"," classRef}
          | identifier "." identifier ":=" (identifier | literal)
          | "SAME" identifier {"," identifier}
          | "DIFF" identifier {"," identifier}.


Actually, I'm realizing there are several possibilities here. The user could mean Lola as a synchronous stream processing language for runtime verification and monitoring, where you specify output streams as functions of input streams. Or they might be referring to Lola as a hardware description language designed by Niklaus Wirth for describing digital circuits in a clean, simple way. Given the mention of "description logics," maybe they're asking about an analogous clean language but applied to description logics instead.
StatementSequence = statement {";" statement}.
</syntaxhighlight>


Description logics are formal knowledge representation languages that underpin OWL, dealing with concepts, roles, and individuals while reasoning about subsumption and satisfiability. The standard syntax uses mathematical notation with symbols like intersection, union, quantifiers, and negation. There are various ways to express them—OWL in XML, Manchester Syntax for readability, mathematical DL notation, Turtle/RDF for serialization, KRSS syntax, and fragments like DL-Lite and EL. So the user might be asking whether we could design a minimalist, elegant language for description logics similar to how Wirth designed Lola for hardware.
{| class="wikitable"
Collapse reasoning
! Form !! Meaning !! OWL Axiom
|-
| <math>C</math> <code><:</code> <math>D</math> || every member of <math>C</math> is a member of <math>D</math> || SubClassOf (GCI)
|-
| <code>DISJOINT</code> <math>A, B, \ldots</math> || no individual belongs to more than one class || DisjointClasses
|-
| <code>a.R := b</code> || individual <math>a</math> is <math>R</math>-related to <math>b</math> || PropertyAssertion
|-
| <code>SAME</code> <math>a, b</math> || <math>a</math> and <math>b</math> denote the same individual || SameIndividual
|-
| <code>DIFF</code> <math>a, b, \ldots</math> || pairwise distinct individuals || DifferentIndividuals
|}


given 1
The property assertion <code>a.R := b</code> resembles assignment in Lola but denotes a '''stated fact''' rather than a computed value. Unlike Lola, where each variable is assigned exactly once, an individual may participate in multiple property assertions for the same property (unless that property is declared <code>FUNC</code>).
Lola-2: A Logic Description Language
N. Wirth, 24.4.1994 / 1.9.2015
Lola is a notation (language) for specifying digital circuits (logic). In many ways it resembles a
programming language. However, Lola texts describe static circuits rather than dynamic processes.
Objects occurring in a description can be variables representing signals or registers. Their values
are defined as expressions of other objects and operators representing gates.
0. Vocabulary
The vocabulary of Lola consists of special characters (or pairs), and so-called reserved words which
cannot be chosen as identifiers.
Special characters:
~ & | ^ + - * = # < <= > >=
( ) [ ] { } -> . , ; : := ' !
Reserved words:
BEGIN CONST END IN INOUT MODULE OUT REG TS TYPE VAR


    Identifiers, integers, and comments
General Concept Inclusions (GCIs) allow complex class expressions on both sides of <code><:</code>, e.g., <code>SOME hasChild . Doctor <: HappyParent</code> — anything that has a child who is a Doctor is a HappyParent.
    Identifiers are used to denote constants, variables, and types.
    identifier = letter {letter | digit}.
    integer = digit {digit} ["H"].
    Examples: Lola begin 100 100H 0FFH
    Capital and lower case letters are considered as distinct. If an integer is followed by the capital letter
    H it is in hexadecimal form with digits 0, 1, ..., 9, and A ... F.
    Comments are sequences of characters enclosed by the brackets (* and *), and they may occur
    between any two symbols within a Lola text.
    Simple types and array types
    Every variable in Lola has a type. The elementary type is BIT (BInary digiT), and its variables
    assume the values 0 or 1.
    type = {"[" expression "]"} SimpleType.
    SimpleType = identifier |."MODULE" unit ";" identifier.
    TypeDeclaration = identifier "=" type .
    An array type is specified by the form [n]T, where T is the type of the elements, and the integer n
    specifies the number of elements. In expressions, individual elements are designated by an index.
    Indices range from 0 to the array's length minus 1.
    Examples: [10] BIT [8][16] BIT
    The identifiers BIT, BYTE and WORD are predeclared. The latter denote arrays of 8 and 32 bits
    respectively.
    Constant declarations
    Constant declarations serve to introduce identifiers denoting a constant, numeric value.
    ConstDeclaration = identifier "=" integer ";".
    2
    Variable and register declarations
    Variable declarations introduce registers and variables and associate a type with them. All variables
    declared in an identifier list have the same type. Variables of type [n] BIT are called bitstrings.
    varlist = identifier {"," identifier} ":" type.
    Examples: x, y: BIT a: [32] BIT R: BIT Q (clk50): [4] BIT
    If a register declaration contains an expression, this denotes the register's clock. The default is a
    variable clk, which must be declared (see also Section 7).
    Expressions
    Expressions serve to combine variables with operators to define new values. The operators are
    logical negation, conjunction, disjunction, and difference, or arithmetic sum and difference. Elements
    of an array are selected by an index. (e.g. a.5, a[10]).
    | logical disjunction (or)
    ^ logical difference (exclusive or)
    & logical conjunction (and)
    ~ logical negation (not)


    arithmetic sum
'''Examples:'''
<pre>
DISJOINT Male, Female;
SOME hasChild . TOP <: Parent;
john.hasChild := mary;
john.hasAge := 42;
john.hasName := "John Smith";
DIFF john, mary, bob
</pre>


    arithmetic difference
----
    Operands are registers, variables, and constants. Whereas variables denote the value given by the
    assigned expression, registers denote the value of the expression in the preceding clock cycle.
    Registers are instrumental in sequential circuits. The operands of diadic operators must be of the
    same type.
    expression = uncondExpr ["->" expression ":" expression].
    uncondExpr = simpleExpr [ ("=" | "#" | "<" | "<=" | ">" | ">=") simpleExpr].
    simpleExpr = ["+" | "-"] term {("|" | "^" | "+" | "-") term}.
    term = factor {"&" factor}.
    factor = variable | integer | "~" factor | constructor | "(" expression ")".
    variable = identifier {selector}.
    selector = "." factor | "[" expression [":" expression] "]".
    constructor = "{" element {"," element} "}".
    element = expression ["!" integer].
    The form a[m : n] denotes the range of indexed elements a[m], ... , a[n].
    Constructors denote bitstrings and are sequences of elements. The length (number of bits) of every
    element must be known. This length is specified in a declaration, and in this case of constants by an
    explicit integer. For example 10'8 denotes the number 10 represented by 8 bits. The length of the
    bitstring is the sum of the lengths of its elements. Also, an element can be followed by a replication
    factor of the form !n.
    A conditional expression of the form z := cond -> x : y expresses represents a multiplexer. Cond
    must be of type BIT. If cond yields 1, z is equal to x, otherwise to y.
    Examples: x count 1 100 a.4 a[20] operands
    a[15 : 8] range
    {u, a.4, a[25:20], 0'8, 15'4} constructor (20 bit)
    (x & y) | (z & w) (m + n) + 10 simple expressions
    a.5 -> b : c expression


    Assignments and statements
== 9. Ontologies ==
    Assignments serve to define a register's or a variable's value, which is specified by an expression.
 
    An assignment must be understood as a variable's definition (in contrast to an identifier's
An ontology is the top-level unit of description, combining declarations and axioms into a self-contained specification. The identifier at the end must match the one following <code>ONTOLOGY</code>.
    3
 
    declaration). In an assignment v := x, v and x do not have the same roles, and this asymmetry is
<syntaxhighlight lang="ebnf">
    emphasized by the use of the symbol := instead of the symmetric equal sign. v and x must be of the
ontology = "ONTOLOGY" identifier
    same type.
     ["(" ["IMPORT" iri {"," iri}] ")"] ";"
    assignment = variable ":=" expression..
    Examples: x := y & z a := {x, y, z} R := rst -> 0 : enb -> x : R
    Every variable and register can be assigned in only one single assignment statement, and the
    assignment must be to the entire variable (not to elements). The only exception is the indexed
    assignment to an array of registers (e.g. R[n] := x).
    For example, instead of
    a.0 := x; a.1 := x+y; a.2 := x-y; a.3 := xy
    the single assignment
    a := {x, x+y, x-y, xy)
    must be used.
    Statements are either assignments, or instantiations of modules (see next section), or TSgates.
    statement = [assignment | instantiation | TSgate].
    StatementSequence = statement {";" statement}.
    A TSgate (TS stads for tri-state) is used for INOUT interface parameters.
    TSgate = "TS" "(" iogate "," input "," output "," control ")".
    iogate = variable.
    input = variable. from interface
    output = expression. to interface
    control = expression. 1 for output, 0 for input from interface
    Examples
    TS(io, in, out, ~wr) TS(io[k], in[k], out[k], ctrl[k])
    The parameters may be simple variables or arrays. They must be of the same type, except that the
    control parameter may be of type BIT, even if the other parameters are arrays. In this case it
     controls all elements of the arrays
    Modules
    A module specifies constants, types, variables, registers, and assignments to variables and
    registers. Modules are specified as types, and variables can be declared of this type. This implies
    that modules can be replicated.
    ModuleType = "MODULE" ["*"] unit ";".
    paramlist = ("IN" | "OUT" | "INOUT") varlist.
    unit = "(" paramlist {";" paramlist} ")" ("^" | ";"
     ["CONST" {ConstDeclaration}]
     ["CONST" {ConstDeclaration}]
     ["TYPE" {TypeDeclaration}]
     ["CLASS" {ClassDeclaration}]
     {("VAR" | "REG" "(" expression ")") {varlist ";"}}
     ["PROP" {PropDeclaration}]
     ["BEGIN" StatementSequence] "END").
     ["DATA" {DataDeclaration}]
     The expression after the symbol REG specifies the register's clock.
     ["IND"   {IndDeclaration}]
    Example of a module type:
     ["BEGIN" StatementSequence]
    TYPE Counter = MODULE (IN clk, rst, enb: BIT; OUT data: WORD);
     "END" identifier ".".
    REG (clk) R: Word;
</syntaxhighlight>
    BEGIN data := R;
 
    R := ~rst -> 0 : enb -> R + 1 : R
----
    4
    END Counter
    Given a variable of this type (cnt: Counter), its instantiation could be
    cnt (clock, reset, enable, val)
    where clock, reset, enable and data are variables called actual parameters. They must be expressions
    of the corresponding types.
    instantiation = identifier selector "(" expression {"," expression} ")".
     A "main program" has the form
     module = "MODULE" identifier unit identifier ".".
    Evidently, a "main program" is the combined declaration of an (anonymous) module type and of a
    single instance. The identifier at the end of the module's declaration must be the same as the one
    following the symbol MODULE.


could we have a similar language as an alternative to the owl description logic syntax?
== Complete Example ==
just now
Favicon for anthropic
Claude Opus 4.6
Processing
Reasoning


The user is asking me to design a language similar to Lola-2 (a hardware description language) but for OWL (Web Ontology Language) description logic. This is an interesting idea — taking the clean, concise syntax of Lola and applying it to ontology description.
<pre>
ONTOLOGY Family ();


Let me think about what OWL Description Logic needs:
  CONST
    MaxChildren = 20;


     Classes (concepts) — analogous to types in Lola
  CLASS
     Person;
    Male <: Person;
    Female <: Person;
    Parent = Person & SOME hasChild . Person;
    Mother = Female & Parent;
    Father = Male & Parent;
    Grandparent = Person & SOME hasChild . Parent;
    ChildlessPerson = Person & ~Parent;
    PersonWithManyChildren = Person & MIN 5 hasChild . Person;
    DayOfWeek = {mon, tue, wed, thu, fri, sat, sun};


     Properties (roles) — object properties and data properties
  PROP
     hasChild [DOMAIN Person; RANGE Person];
    hasParent [INVERSE hasChild];
    hasSibling [SYM; DOMAIN Person; RANGE Person];
    hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person];
    hasAncestor [TRANS];
    hasRelative;
    hasUncle [CHAIN hasParent o hasBrother];
    hasBrother [<: hasSibling; RANGE Male];


     Individuals — instances/members of classes
  DATA
     hasAge [DOMAIN Person; RANGE INT; FUNC];
    hasName [DOMAIN Person; RANGE STRING];


     Class expressions — intersection, union, complement, restrictions
  IND
     john : Father;
    mary : Mother;
    bob : Male;
    mon, tue, wed, thu, fri, sat, sun : DayOfWeek;


     Axioms — subclass, equivalence, disjointness
  BEGIN
     DISJOINT Male, Female;
    john.hasChild := mary;
    john.hasChild := bob;
    john.hasAge := 42;
    john.hasName := "John Smith";
    mary.hasAge := 15;
    SOME hasChild . TOP <: Parent;
    DIFF john, mary, bob
  END Family.
</pre>


    Property characteristics — transitive, symmetric, functional, etc.
----


    Restrictions — existential (some), universal (only), cardinality
== Correspondence to OWL 2 and Lola-2 ==


Now I'm mapping the core Lola constructs to their OWL equivalents modules become ontologies or classes, types map to class definitions, variables become individuals or properties, and the logical operators translate directly to OWL's intersection, union, and complement operations.
{| class="wikitable"
! Concept !! Lola-2 !! DOLA !! OWL 2 Functional Syntax
|-
| Encapsulation || <code>MODULE</code> || <code>ONTOLOGY</code> || <code>Ontology(...)</code>
|-
| Type/Category || <code>TYPE</code> || <code>CLASS</code> || <code>Declaration(Class(...))</code>
|-
| Instance || <code>VAR</code> || <code>IND</code> || <code>Declaration(NamedIndividual(...))</code>
|-
| Definition || <code>:=</code> || <code>:=</code> / <code>=</code> || <code>EquivalentClasses</code> / <code>PropertyAssertion</code>
|-
| Subsumption || || <code><:</code> || <code>SubClassOf</code>
|-
| And-gate / Intersection || <code>&</code> || <code>&</code> || <code>ObjectIntersectionOf</code>
|-
| Or-gate / Union || <code>|</code> || <code>|</code> || <code>ObjectUnionOf</code>
|-
| Not-gate / Complement || <code>~</code> || <code>~</code> || <code>ObjectComplementOf</code>
|-
| Conditional / Restriction || <code>-> :</code> || <code>SOME</code>/<code>ONLY</code> || <code>ObjectSomeValuesFrom</code> / <code>ObjectAllValuesFrom</code>
|-
| Array / Cardinality || <code>[n] BIT</code> || <code>MIN</code>/<code>MAX</code>/<code>EXACT</code> || <code>ObjectMinCardinality</code> etc.
|-
| Constructor / Enumeration || <code>{...}</code> || <code>{...}</code> || <code>ObjectOneOf</code>
|}
=== OWL version of Family example ===
<source lang='owl'>
Prefix(:=<http://example.org/family#>)
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)


For the language design, I'm considering names like OWLA or ODL, and I need to think through how to represent OWL's fundamental class expressions — intersections, unions, complements, and the various restriction types like existential and universal quantification along with cardinality constraints.
Ontology(<http://example.org/family>


Now I'm mapping out the core components: classes with their expressions, object and data properties with their characteristics like transitivity and functionality, the main axiom types for defining relationships and assertions, and how to represent individuals with their class and property memberships.
  ##
  ## Class Declarations
  ##


Designing the syntax... I'm laying out the operators for axioms — subclass relationships, equivalence, and disjointness — and now I need to settle on a good name for this language. I'm considering options like DOLA or ODL, but I want something that captures the spirit of being a description logic alternative to OWL, so let me think through what would actually work well here. Defining the formal grammar... I'm looking at the property and individual declaration syntax, then reconsidering how to map this more cleanly to Lola's structure. I'm comparing the key concepts across Lola-2, OWL DL, and DOL to find better alignment—like how MODULE corresponds to ONTOLOGY, TYPE to CLASS, and so on. I'm exploring different syntaxes for property restrictions, comparing a member-access style like hasChild.SOME(Person) against a more operator-heavy approach with SOME hasChild : Person, trying to find what feels most natural and composable for the language.
  Declaration(Class(:Person))
  Declaration(Class(:Male))
  Declaration(Class(:Female))
  Declaration(Class(:Parent))
  Declaration(Class(:Mother))
  Declaration(Class(:Father))
  Declaration(Class(:Grandparent))
  Declaration(Class(:ChildlessPerson))
  Declaration(Class(:PersonWithManyChildren))
  Declaration(Class(:DayOfWeek))


The dot notation SOME hasChild . Person seems cleanest—it mirrors standard description logic notation while staying readable and concise. Now I'm settling on a final design for DOL that balances clarity with formal specification, starting with the vocabulary and special characters.
  ## Male <: Person
  SubClassOf(:Male :Person)


Defining the reserved words and basic syntax rules...
  ## Female <: Person
  SubClassOf(:Female :Person)


Now I'm laying out the grammar for class expressions, which can be unions and intersections of class factors like atomic classes, negations, restrictions on properties, and enumerated individuals. The restrictions handle existential and universal quantification over properties, cardinality constraints, value restrictions, and self-restrictions, with operators for union, intersection, and complement. Now I'm defining the structure for property declarations, which can specify inverse relationships, characteristics like functionality or transitivity, domain and range constraints, subproperty hierarchies, and property chains. Data properties follow a similar pattern but with datatype ranges instead of class expressions, while individual declarations associate instances with classes and assertions about their relationships. Continuing with the ontology structure, I need to finalize how declarations and axioms fit together. The BEGIN...END section should contain the actual statements that define relationships and constraints, separate from where classes and properties are declared. Let me work through what a concrete example would look like to make sure the grammar captures the right semantics. I'm realizing there's some structural confusion between Lola and DOL syntax. In Lola, TYPE defines types with =, VAR declares variables, and BEGIN assigns values with :=. For DOL, I should use CLASS for declarations and definitions, PROP for properties, IND for individuals, and BEGIN for additional axioms like subsumptions and disjointness constraints. The key distinction is that = in CLASS gives equivalence while <: in BEGIN gives subsumption, so I need to reorganize which definitions go where.
  ## Parent = Person & SOME hasChild . Person
  EquivalentClasses(:Parent
    ObjectIntersectionOf(:Person
      ObjectSomeValuesFrom(:hasChild :Person)))


Now I'm thinking through the data types and built-in support—I should include predeclared datatypes like INT, FLOAT, STRING, BOOL, and DATE that map to their XSD equivalents, and I'll keep annotation properties out of the core specification for simplicity.
  ## Mother = Female & Parent
  EquivalentClasses(:Mother
    ObjectIntersectionOf(:Female :Parent))


For the language name, I'm considering a few options: ODL is clear and descriptive, but I'm also drawn to something like Loca or Dola that feels more cohesive with the Lola-2 style. Let me settle on a name and write out the full specification document to match that style. I'm settling on DOLA — Description Ontology Language — as a clean parallel to LOLA. Now I need to write out the full specification with examples, and I'm working through the syntax for restrictions to keep things concise and consistent. I'm comparing a few approaches: a DL-style option with keywords like SOME and ONLY, versus an operator-style approach using arrows and comparison symbols.
  ## Father = Male & Parent
  EquivalentClasses(:Father
    ObjectIntersectionOf(:Male :Parent))


Defining restriction syntax... I'm mapping out the class expression constructors in OWL, showing how each formal construct translates to a more readable notation—complement, existential and universal quantifiers, cardinality constraints, and enumeration of individuals.
  ## Grandparent = Person & SOME hasChild . Parent
  EquivalentClasses(:Grandparent
    ObjectIntersectionOf(:Person
      ObjectSomeValuesFrom(:hasChild :Parent)))


Now I'm organizing the full specification into a logical structure, starting with vocabulary and identifiers, then moving through classes, properties, expressions, and axioms before covering individuals and ontologies.
  ## ChildlessPerson = Person & ~Parent
  EquivalentClasses(:ChildlessPerson
    ObjectIntersectionOf(:Person
      ObjectComplementOf(:Parent)))


Defining the grammar for identifiers, IRIs, and comments... Continuing with the property and data property declarations, specifying domains, ranges, and various characteristics like functionality, transitivity, and symmetry. I'm realizing this formal grammar is getting unwieldy and I should probably streamline the syntax to make it more practical.
  ## PersonWithManyChildren = Person & MIN 5 hasChild . Person
  EquivalentClasses(:PersonWithManyChildren
    ObjectIntersectionOf(:Person
      ObjectMinCardinality(5 :hasChild :Person)))


Looking at how Lola handles variable declarations with their concise syntax, I think properties should follow the same pattern—keep the declarations minimal with just the identifier and key characteristics, then move the detailed axioms like domain and range specifications into the BEGIN section where they belong. This would let me write something like declaring properties with their characteristics inline, then defining their domains and ranges separately as axioms. Refining the property declaration syntax...
  ## DayOfWeek = {mon, tue, wed, thu, fri, sat, sun}
  EquivalentClasses(:DayOfWeek
    ObjectOneOf(:mon :tue :wed :thu :fri :sat :sun))


Defining the grammar for property attributes with domain, range, inverse, and characteristic modifiers, then extending it to handle data properties as well.
  ##
  ## Object Property Declarations
  ##


Now I'm thinking through how modules work in this language—whether to support instantiation like VHDL components or keep it simpler with just imports. I'm also reconsidering the dot notation for class expressions, since it conflicts with the selector syntax I've already used elsewhere, so I need to be careful about how restrictions are written. I think SOME R . C is cleanest since the dot's meaning is unambiguous in context—it always separates a property from its filler class after a restriction keyword. Now I'm writing out the complete grammar specification for the ontology language, starting with the core structure and declaration types.
  Declaration(ObjectProperty(:hasChild))
  Declaration(ObjectProperty(:hasParent))
  Declaration(ObjectProperty(:hasSibling))
  Declaration(ObjectProperty(:hasSpouse))
  Declaration(ObjectProperty(:hasAncestor))
  Declaration(ObjectProperty(:hasRelative))
  Declaration(ObjectProperty(:hasUncle))
  Declaration(ObjectProperty(:hasBrother))


Defining the grammar rules... I'm noticing some redundancy in how I've structured the class equivalence rules—the = operator for equivalence is overlapping with other parts of the grammar, so I should consolidate those definitions.
  ## hasChild [DOMAIN Person; RANGE Person]
  ObjectPropertyDomain(:hasChild :Person)
  ObjectPropertyRange(:hasChild :Person)


More importantly, I'm realizing the individual declarations need better separation: class assertions (declaring what class an individual belongs to) should be distinct from property assertions (assigning property values). I'm restructuring this so individual declarations use a cleaner syntax with the colon notation, while property assignments stay in the BEGIN section with the walrus operator, which feels more aligned with the Lola language style.
  ## hasParent [INVERSE hasChild]
  InverseObjectProperties(:hasParent :hasChild)


Refining the grammar...
  ## hasSibling [SYM; DOMAIN Person; RANGE Person]
  SymmetricObjectProperty(:hasSibling)
  ObjectPropertyDomain(:hasSibling :Person)
  ObjectPropertyRange(:hasSibling :Person)


Now I'm hitting a design decision about cardinality restrictions—specifically how to denote qualified number restrictions without using the dot notation, since that could get confused with the individual.property selector syntax. I'm exploring different syntactic options to keep things unambiguous.
  ## hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person]
  SymmetricObjectProperty(:hasSpouse)
  FunctionalObjectProperty(:hasSpouse)
  ObjectPropertyDomain(:hasSpouse :Person)
  ObjectPropertyRange(:hasSpouse :Person)


I think the dot notation is actually fine here since the context makes it clear whether we're talking about a class or an individual. For value restrictions on individuals and reflexive properties, I can drop the dot entirely since the filler type is obvious from context.
  ## hasAncestor [TRANS]
  TransitiveObjectProperty(:hasAncestor)


Now I want to step back and make sure the overall language design feels coherent—thinking through how types, variables, and assignments work in Lola and how that maps to the ontology layer with classes, instances, and properties.
  ## hasUncle [CHAIN hasParent o hasBrother]
  SubObjectPropertyOf(
    ObjectPropertyChain(:hasParent :hasBrother)
    :hasUncle)


Writing out a complete example to validate the design... I'm noticing a potential ambiguity with the subclass operator—it works fine in the CLASS section where the left side is just a name, but I want to support it in BEGIN for more complex expressions too, which should be grammatically consistent. I'm also considering whether to allow property assertions directly in the IND section for more compact declarations, supporting both simple inline assertions and more complex ones in BEGIN.
  ## hasBrother [<: hasSibling; RANGE Male]
  SubObjectPropertyOf(:hasBrother :hasSibling)
  ObjectPropertyRange(:hasBrother :Male)


For negative assertions, I'm leaning toward using # syntax in the BEGIN section to keep things cleaner and avoid confusion with other operators.
  ##
  ## Data Property Declarations
  ##


I'm going to skip negative property assertions in v1 to keep the language simple—I can always add that as an extension later. Now I'm ready to write out the final design, modeling it after Lola-2's document structure.
  Declaration(DataProperty(:hasAge))
  Declaration(DataProperty(:hasName))


For operators, I'm settling on = for class equivalence in the CLASS section and <: for subsumption, while leaving out arithmetic comparisons since they're not core to description logic.
  ## hasAge [DOMAIN Person; RANGE INT; FUNC]
  DataPropertyDomain(:hasAge :Person)
  DataPropertyRange(:hasAge xsd:integer)
  FunctionalDataProperty(:hasAge)


I'm also clarifying the syntax: = declares equivalence like Mother = Female & Parent, while bare class names like Person; just declare the class without defining it, and I'll use a DISJOINT keyword instead of trying to overload #.
  ## hasName [DOMAIN Person; RANGE STRING]
  DataPropertyDomain(:hasName :Person)
  DataPropertyRange(:hasName xsd:string)


For modularity, I'll keep it simple with just IMPORT statements to bring in other ontologies, skipping parameterized modules for now since OWL doesn't really have that concept anyway.
  ##
  ## Individual Declarations
  ##


I'm also thinking through how to handle data ranges and typed literals—I'll stick with simple named datatypes for data properties rather than complex range constraints, which should cover the practical cases without overcomplicating things.
  Declaration(NamedIndividual(:john))
  Declaration(NamedIndividual(:mary))
  Declaration(NamedIndividual(:bob))
  Declaration(NamedIndividual(:mon))
  Declaration(NamedIndividual(:tue))
  Declaration(NamedIndividual(:wed))
  Declaration(NamedIndividual(:thu))
  Declaration(NamedIndividual(:fri))
  Declaration(NamedIndividual(:sat))
  Declaration(NamedIndividual(:sun))


Now I'm mapping out the structure for the full document: vocabulary, identifiers and IRIs, classes and datatypes, constants, class expressions, properties, individuals, axioms, and ontologies, with a worked example at the end. I'm ready to write this up in markdown.
  ## john : Father
  ClassAssertion(:Father :john)


I'm also working through a design decision for class declarations—whether to support both equality and subclass relationships in the same syntax, or handle them separately. I think allowing Male <: Person; directly in the class declaration is cleaner for simple cases, while reserving the BEGIN section for complex general concept inclusions like (A & B) <: C or existential restrictions. I'll go with that approach and make sure the BEGIN section supports full class expressions on the left side of the subclass operator.
  ## mary : Mother
  ClassAssertion(:Mother :mary)


Now I'm working through the syntax for property assertions on individuals. Using the assignment operator pattern from Lola, I can write john.hasChild := mary for object properties and john.hasAge := 42 for data properties, which reads naturally. I'm skipping negative assertions since they're rarely used in practice.
  ## bob : Male
  ClassAssertion(:Male :bob)


Defining the grammar for statements in the BEGIN section... I've been going in circles on the syntax details—time to just write this up and get a complete document done. Now I'm thinking through the final piece: how the ONTOLOGY structure should work, particularly around imports. I'm considering whether to put imports in parentheses like parameters, or handle them separately in the body, and whether parentheses are even necessary when there are no imports.
  ## mon, tue, wed, thu, fri, sat, sun : DayOfWeek
  ClassAssertion(:DayOfWeek :mon)
  ClassAssertion(:DayOfWeek :tue)
  ClassAssertion(:DayOfWeek :wed)
  ClassAssertion(:DayOfWeek :thu)
  ClassAssertion(:DayOfWeek :fri)
  ClassAssertion(:DayOfWeek :sat)
  ClassAssertion(:DayOfWeek :sun)


Generating comparison table... Generating markdown table...
  ##
  ## Axioms (BEGIN ... END)
  ##


I'm noting that this covers the main OWL 2 DL features, though SWRL rules, annotations, and some advanced features aren't included in this basic version. Now I'll start writing the actual document, aiming for something comparable in length to the Lola-2 spec.
  ## DISJOINT Male, Female
  DisjointClasses(:Male :Female)


I want to include a comprehensive example at the end, similar to how Lola-2 demonstrates modules. For the example ontology, I'm considering the classics—pizza ontology, family relationships, or university structures—but I'll go with a hybrid approach using a simple family and person ontology that showcases all the key features.
  ## john.hasChild := mary
  ObjectPropertyAssertion(:hasChild :john :mary)


Starting the document now...
  ## john.hasChild := bob
  ObjectPropertyAssertion(:hasChild :john :bob)


Defining the vocabulary with special characters and reserved words...
  ## john.hasAge := 42
  DataPropertyAssertion(:hasAge :john "42"^^xsd:integer)


Continuing with identifiers, IRIs, and comments...
  ## john.hasName := "John Smith"
  DataPropertyAssertion(:hasName :john "John Smith"^^xsd:string)


Describing classes and datatypes...
  ## mary.hasAge := 15
  DataPropertyAssertion(:hasAge :mary "15"^^xsd:integer)


Moving into constant declarations and class expressions...
  ## SOME hasChild . TOP <: Parent
  SubClassOf(
    ObjectSomeValuesFrom(:hasChild owl:Thing)
    :Parent)


I'm defining the grammar for class expressions, which combine atomic classes using set-theoretic operators. Class factors can be atomic identifiers, complements, property restrictions, enumerations, or parenthesized expressions. Restrictions let me specify cardinality constraints on properties (like "some," "only," "min," "max," "exact") or value constraints. The operators follow a precedence hierarchy where union has lowest precedence, then intersection, then complement at the highest. I'm looking at how enumeration works in DOLA—sets like {a, b, c} represent classes containing exactly those individuals, which maps to ObjectOneOf in description logics. Then I'm seeing practical examples of how these constructors combine: intersection, union, complement, and various restriction types, including nested ones like existential restrictions within existential restrictions. The key distinction is that DOLA uses set-theoretic and relational operations to define classes, whereas Lola uses gates to define signal values. Now moving into class declarations, which have a syntax where an identifier can optionally be defined as equal to or a subclass of some class expression. Now I'm defining the syntax for property declarations, which can have multiple identifiers and optional attributes like domain, range, inverse relations, subproperty constraints, and characteristic properties like functionality or transitivity. Data properties follow a similar structure but with datatype ranges instead of class expressions, and I'm also laying out a reference table for what each characteristic keyword means. I'm seeing how individuals are declared as concrete members of classes, with syntax like john, bob : Male to assert class membership. Then axioms and statements define relationships beyond declarations—including concept inclusions, disjointness constraints, property assertions, and identity statements. that individuals are pairwise distinct. Now I'm looking at some concrete examples showing how these assertions work in practice—disjoint classes, general concept inclusions with quantifiers, property assignments with both object and literal values, and identity statements. An ontology serves as the top-level container that brings together all the vocabulary and constraints, with sections for imports, constants, classes, properties, and data declarations.
  ## DIFF john, mary, bob
  DifferentIndividuals(:john :mary :bob)


Defining the complete structure... I'm reviewing the schema definition and noticing that NuclearFamily as a class constraint doesn't quite work—it's trying to define a group property on individuals, which doesn't align with how the ontology should structure family units. I should reconsider whether this should be a separate class or relationship instead.
</source>
Collapse reasoning
 
...
**Note:** The DOLA `CONST MaxChildren = 20` has no OWL counterpart — it is a purely syntactic convenience for use inside DOLA cardinality expressions and produces no axiom. The <nowiki>##</nowiki> comments above each axiom show the corresponding DOLA source line.<
</pre>
 
=== Design notes and possible extensions ===
 
The following features are intentionally omitted from the core language for simplicity but could be added:
 
* '''Annotations''' (rdfs:label, rdfs:comment) — could use an <code>@label "..."</code> syntax after declarations.
* '''Data ranges''' — constraining datatypes, e.g., <code>INT[>= 0, <= 150]</code>.
* '''Negative property assertions''' — e.g., <code>john.hasChild ~:= jane</code>.
* '''Prefix/namespace management''' — e.g., <code>IMPORT <...> AS prefix</code>, then <code>prefix.ClassName</code>.
* '''SWRL rules''' — inference rules beyond DL expressivity.
* '''Parameterized ontology modules''' — analogous to Lola's parameterized <code>MODULE</code> types, allowing ontology design patterns to be declared and instantiated with actual parameters.
* '''Disjoint union''' — <code>DISJOINT UNION</code> combining disjointness with a covering axiom.
 
The grammar is designed to be LL(2): a statement beginning with an identifier followed by <code>.</code> is a property assertion; followed by <code>&</code>, <code>|</code>, or <code><:</code> it begins a class axiom. All other statement forms begin with distinct keywords.

Latest revision as of 08:55, 14 February 2026

This is an experiment for the Syntax Matters research topic.

see Lola-2 and Talk:DOLA for how this was created

⚠️ LLM-generated content notice: Parts of this page may have been created or edited with the assistance of a large language model (LLM). The prompts that have been used might be on the page itself, the discussion page or in straight forward cases the prompt was just "Write a mediawiki page on X" with X being the page name. While the content has been reviewed it might still not be accurate or error-free.

DOLA: A Description Ontology Language

Inspired by N. Wirth's Lola-2

DOLA is a notation for specifying ontologies in the tradition of OWL Description Logic. In many ways it resembles Lola-2: where Lola describes static circuits, DOLA describes conceptual domains. Objects in a description are classes (sets of individuals), properties (relations), and individuals (concrete entities). Class expressions combine classes and property restrictions using operators that mirror the logical gates of Lola.


0. Vocabulary

Special characters:

~ & | = # < <= > >= ( ) [ ] { } <: := . , ; : o

Reserved words:

BEGIN BOT CLASS CONST DATA DIFF DISJOINT END EXACT FUNC
IND IFUNC IMPORT INVERSE MAX MIN ONLY ONTOLOGY PROP RANGE
DOMAIN REFL IRREFL SAME SELF SOME SYM ASYM TOP TRANS VALUE CHAIN

1. Identifiers, IRIs, and Comments

Identifiers denote classes, properties, individuals, and constants.

identifier = letter {letter | digit}.
 iri        = "<" {character} ">".
integer    = digit {digit}.
string     = '"' {character} '"'.
literal    = integer | string.

Capital and lower-case letters are considered distinct. IRIs (Internationalized Resource Identifiers) reference external ontologies.

Comments are enclosed by (* and *) and may occur between any two symbols.


2. Classes and Datatypes

Every individual belongs to one or more classes. The universal class is TOP (owl:Thing); the empty class is BOT (owl:Nothing).

classRef = identifier | "TOP" | "BOT".
datatype = "INT" | "FLOAT" | "STRING" | "BOOL" | identifier.

The predeclared datatypes INT, FLOAT, STRING, and BOOL correspond to xsd:integer, xsd:float, xsd:string, and xsd:boolean respectively.


3. Constant Declarations

ConstDeclaration = identifier "=" integer ";".

Constants may be used wherever an integer is expected, for example in cardinality restrictions.


4. Class Expressions

Class expressions define classes by combining atomic classes with operators representing set-theoretic constructions and property restrictions. Whereas Lola expressions define signal values through gates, DOLA expressions define classes through set-theoretic and relational constructors.

classExpr   = classTerm {"|" classTerm}.
classTerm   = classFactor {"&" classFactor}.
classFactor = classAtom
            | "~" classFactor
            | restriction
            | "{" identifier {"," identifier} "}"
            | "(" classExpr ")".
classAtom   = identifier | "TOP" | "BOT".

restriction = ("SOME" | "ONLY") identifier ["." classFactor]
            | ("MIN" | "MAX" | "EXACT") integer identifier ["." classFactor]
            | "VALUE" identifier identifier
            | "SELF" identifier.

When the "." classFactor of a restriction is omitted, it defaults to TOP.

Operators (in order of increasing precedence):

Operator Meaning DL Notation
class union <math>C \sqcup D</math>
& class intersection <math>C \sqcap D</math>
~ class complement <math>\lnot C</math>

Restrictions construct classes from properties:

Restriction Meaning DL Notation
SOME R . C existential — has at least one <math>R</math>-filler in <math>C</math> <math>\exists R.C</math>
ONLY R . C universal — all <math>R</math>-fillers are in <math>C</math> <math>\forall R.C</math>
MIN n R . C minimum qualified cardinality <math>\geq n\; R.C</math>
MAX n R . C maximum qualified cardinality <math>\leq n\; R.C</math>
EXACT n R . C exact qualified cardinality <math>= n\; R.C</math>
VALUE R a has-value — has <math>R</math>-filler <math>a</math> <math>\exists R.\{a\}</math>
SELF R has-self — is <math>R</math>-related to itself <math>\exists R.\mathsf{Self}</math>

The enumeration {a, b, c} denotes the class containing exactly the named individuals <math>a</math>, <math>b</math>, <math>c</math> (OneOf).

Examples:

Person & Male                                         (* intersection *)
Doctor | Lawyer                                       (* union *)
~Parent                                               (* complement *)
SOME hasChild . Person                                (* existential *)
ONLY hasChild . (Doctor | Lawyer)                     (* universal *)
MIN 2 hasChild                                        (* unqualified min card. *)
Person & SOME hasChild . (SOME hasChild . Person)     (* nesting *)
{mon, tue, wed, thu, fri}                             (* enumeration *)

5. Class Declarations

ClassDeclaration = identifier ["=" classExpr | "<:" classExpr] ";".

A bare identifier (e.g. Person;) introduces a named class with no axioms. The symbol = specifies an equivalent class (necessary and sufficient conditions). The symbol <: specifies a superclass (necessary conditions only).

The distinction is fundamental: <math>A = C</math> means an individual is an <math>A</math> if and only if it satisfies <math>C</math>; <math>A <: C</math> means every <math>A</math> satisfies <math>C</math>, but satisfying <math>C</math> does not entail being an <math>A</math>.

Examples:

Person;                                                (* declaration only *)
Male <: Person;                                        (* subclass *)
Parent = Person & SOME hasChild . Person;              (* equivalence *)
Mother = Female & Parent;                              (* equivalence *)
ChildlessPerson = Person & ~Parent;                    (* complement *)
PersonWith3Children = EXACT 3 hasChild . Person;       (* cardinality *)
DayOfWeek = {mon, tue, wed, thu, fri, sat, sun};       (* enumeration *)

6. Property Declarations

Properties relate individuals to other individuals (object properties, declared in a PROP section) or to data values (data properties, declared in a DATA section).

PropDeclaration = identifier {"," identifier}
    ["[" propAttr {";" propAttr} "]"] ";".

propAttr = "DOMAIN" classExpr
         | "RANGE" classExpr
         | "INVERSE" identifier
         | "=" identifier
         | "<:" identifier
         | "CHAIN" identifier {"o" identifier}
         | characteristic.

characteristic = "FUNC" | "IFUNC" | "TRANS" | "SYM" | "ASYM" | "REFL" | "IRREFL".

DataDeclaration = identifier {"," identifier}
    ["[" dataAttr {";" dataAttr} "]"] ";".

dataAttr = "DOMAIN" classExpr
         | "RANGE" datatype
         | "<:" identifier
         | "FUNC".

Characteristics:

Keyword Meaning OWL Axiom
FUNC at most one value per individual FunctionalObjectProperty
IFUNC at most one individual per value InverseFunctionalObjectProperty
TRANS transitive TransitiveObjectProperty
SYM symmetric SymmetricObjectProperty
ASYM asymmetric AsymmetricObjectProperty
REFL reflexive ReflexiveObjectProperty
IRREFL irreflexive IrreflexiveObjectProperty

CHAIN p o q defines a property as the composition of properties <math>p</math> and <math>q</math> (a property chain). INVERSE p declares the property as the inverse of <math>p</math>. Within brackets, <: gives a super-property, and = gives an equivalent property.

Examples:

hasChild [DOMAIN Person; RANGE Person];
hasParent [INVERSE hasChild];
hasAncestor [TRANS; <: hasRelative];
hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person];
hasUncle [CHAIN hasParent o hasBrother];
hasBrother [<: hasSibling; RANGE Male];

7. Individual Declarations

Individuals are concrete members of classes.

IndDeclaration = identifier {"," identifier} ":" classExpr ";".

The class expression after : specifies class membership (a class assertion).

Examples:

john : Father;
mary : Female & Parent;
mon, tue, wed, thu, fri, sat, sun : DayOfWeek;

8. Axioms and Statements

The BEGIN ... END section contains axioms not captured by declarations. A statement is separated by ; (as a separator, not a terminator, following Wirth's convention).

statement = classExpr "<:" classExpr
          | "DISJOINT" classRef {"," classRef}
          | identifier "." identifier ":=" (identifier | literal)
          | "SAME" identifier {"," identifier}
          | "DIFF" identifier {"," identifier}.

StatementSequence = statement {";" statement}.
Form Meaning OWL Axiom
<math>C</math> <: <math>D</math> every member of <math>C</math> is a member of <math>D</math> SubClassOf (GCI)
DISJOINT <math>A, B, \ldots</math> no individual belongs to more than one class DisjointClasses
a.R := b individual <math>a</math> is <math>R</math>-related to <math>b</math> PropertyAssertion
SAME <math>a, b</math> <math>a</math> and <math>b</math> denote the same individual SameIndividual
DIFF <math>a, b, \ldots</math> pairwise distinct individuals DifferentIndividuals

The property assertion a.R := b resembles assignment in Lola but denotes a stated fact rather than a computed value. Unlike Lola, where each variable is assigned exactly once, an individual may participate in multiple property assertions for the same property (unless that property is declared FUNC).

General Concept Inclusions (GCIs) allow complex class expressions on both sides of <:, e.g., SOME hasChild . Doctor <: HappyParent — anything that has a child who is a Doctor is a HappyParent.

Examples:

DISJOINT Male, Female;
SOME hasChild . TOP <: Parent;
john.hasChild := mary;
john.hasAge := 42;
john.hasName := "John Smith";
DIFF john, mary, bob

9. Ontologies

An ontology is the top-level unit of description, combining declarations and axioms into a self-contained specification. The identifier at the end must match the one following ONTOLOGY.

ontology = "ONTOLOGY" identifier
    ["(" ["IMPORT" iri {"," iri}] ")"] ";"
    ["CONST" {ConstDeclaration}]
    ["CLASS" {ClassDeclaration}]
    ["PROP"  {PropDeclaration}]
    ["DATA"  {DataDeclaration}]
    ["IND"   {IndDeclaration}]
    ["BEGIN" StatementSequence]
    "END" identifier ".".

Complete Example

ONTOLOGY Family ();

  CONST
    MaxChildren = 20;

  CLASS
    Person;
    Male <: Person;
    Female <: Person;
    Parent = Person & SOME hasChild . Person;
    Mother = Female & Parent;
    Father = Male & Parent;
    Grandparent = Person & SOME hasChild . Parent;
    ChildlessPerson = Person & ~Parent;
    PersonWithManyChildren = Person & MIN 5 hasChild . Person;
    DayOfWeek = {mon, tue, wed, thu, fri, sat, sun};

  PROP
    hasChild [DOMAIN Person; RANGE Person];
    hasParent [INVERSE hasChild];
    hasSibling [SYM; DOMAIN Person; RANGE Person];
    hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person];
    hasAncestor [TRANS];
    hasRelative;
    hasUncle [CHAIN hasParent o hasBrother];
    hasBrother [<: hasSibling; RANGE Male];

  DATA
    hasAge [DOMAIN Person; RANGE INT; FUNC];
    hasName [DOMAIN Person; RANGE STRING];

  IND
    john : Father;
    mary : Mother;
    bob : Male;
    mon, tue, wed, thu, fri, sat, sun : DayOfWeek;

  BEGIN
    DISJOINT Male, Female;
    john.hasChild := mary;
    john.hasChild := bob;
    john.hasAge := 42;
    john.hasName := "John Smith";
    mary.hasAge := 15;
    SOME hasChild . TOP <: Parent;
    DIFF john, mary, bob
  END Family.

Correspondence to OWL 2 and Lola-2

Concept Lola-2 DOLA OWL 2 Functional Syntax
Encapsulation MODULE ONTOLOGY Ontology(...)
Type/Category TYPE CLASS Declaration(Class(...))
Instance VAR IND Declaration(NamedIndividual(...))
Definition := := / = EquivalentClasses / PropertyAssertion
Subsumption <: SubClassOf
And-gate / Intersection & & ObjectIntersectionOf
Or-gate / Union ObjectUnionOf
Not-gate / Complement ~ ~ ObjectComplementOf
Conditional / Restriction -> : SOME/ONLY ObjectSomeValuesFrom / ObjectAllValuesFrom
Array / Cardinality [n] BIT MIN/MAX/EXACT ObjectMinCardinality etc.
Constructor / Enumeration {...} {...} ObjectOneOf

OWL version of Family example

Prefix(:=<http://example.org/family#>)
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)

Ontology(<http://example.org/family>

  ##
  ## Class Declarations
  ##

  Declaration(Class(:Person))
  Declaration(Class(:Male))
  Declaration(Class(:Female))
  Declaration(Class(:Parent))
  Declaration(Class(:Mother))
  Declaration(Class(:Father))
  Declaration(Class(:Grandparent))
  Declaration(Class(:ChildlessPerson))
  Declaration(Class(:PersonWithManyChildren))
  Declaration(Class(:DayOfWeek))

  ## Male <: Person
  SubClassOf(:Male :Person)

  ## Female <: Person
  SubClassOf(:Female :Person)

  ## Parent = Person & SOME hasChild . Person
  EquivalentClasses(:Parent
    ObjectIntersectionOf(:Person
      ObjectSomeValuesFrom(:hasChild :Person)))

  ## Mother = Female & Parent
  EquivalentClasses(:Mother
    ObjectIntersectionOf(:Female :Parent))

  ## Father = Male & Parent
  EquivalentClasses(:Father
    ObjectIntersectionOf(:Male :Parent))

  ## Grandparent = Person & SOME hasChild . Parent
  EquivalentClasses(:Grandparent
    ObjectIntersectionOf(:Person
      ObjectSomeValuesFrom(:hasChild :Parent)))

  ## ChildlessPerson = Person & ~Parent
  EquivalentClasses(:ChildlessPerson
    ObjectIntersectionOf(:Person
      ObjectComplementOf(:Parent)))

  ## PersonWithManyChildren = Person & MIN 5 hasChild . Person
  EquivalentClasses(:PersonWithManyChildren
    ObjectIntersectionOf(:Person
      ObjectMinCardinality(5 :hasChild :Person)))

  ## DayOfWeek = {mon, tue, wed, thu, fri, sat, sun}
  EquivalentClasses(:DayOfWeek
    ObjectOneOf(:mon :tue :wed :thu :fri :sat :sun))

  ##
  ## Object Property Declarations
  ##

  Declaration(ObjectProperty(:hasChild))
  Declaration(ObjectProperty(:hasParent))
  Declaration(ObjectProperty(:hasSibling))
  Declaration(ObjectProperty(:hasSpouse))
  Declaration(ObjectProperty(:hasAncestor))
  Declaration(ObjectProperty(:hasRelative))
  Declaration(ObjectProperty(:hasUncle))
  Declaration(ObjectProperty(:hasBrother))

  ## hasChild [DOMAIN Person; RANGE Person]
  ObjectPropertyDomain(:hasChild :Person)
  ObjectPropertyRange(:hasChild :Person)

  ## hasParent [INVERSE hasChild]
  InverseObjectProperties(:hasParent :hasChild)

  ## hasSibling [SYM; DOMAIN Person; RANGE Person]
  SymmetricObjectProperty(:hasSibling)
  ObjectPropertyDomain(:hasSibling :Person)
  ObjectPropertyRange(:hasSibling :Person)

  ## hasSpouse [SYM; FUNC; DOMAIN Person; RANGE Person]
  SymmetricObjectProperty(:hasSpouse)
  FunctionalObjectProperty(:hasSpouse)
  ObjectPropertyDomain(:hasSpouse :Person)
  ObjectPropertyRange(:hasSpouse :Person)

  ## hasAncestor [TRANS]
  TransitiveObjectProperty(:hasAncestor)

  ## hasUncle [CHAIN hasParent o hasBrother]
  SubObjectPropertyOf(
    ObjectPropertyChain(:hasParent :hasBrother)
    :hasUncle)

  ## hasBrother [<: hasSibling; RANGE Male]
  SubObjectPropertyOf(:hasBrother :hasSibling)
  ObjectPropertyRange(:hasBrother :Male)

  ##
  ## Data Property Declarations
  ##

  Declaration(DataProperty(:hasAge))
  Declaration(DataProperty(:hasName))

  ## hasAge [DOMAIN Person; RANGE INT; FUNC]
  DataPropertyDomain(:hasAge :Person)
  DataPropertyRange(:hasAge xsd:integer)
  FunctionalDataProperty(:hasAge)

  ## hasName [DOMAIN Person; RANGE STRING]
  DataPropertyDomain(:hasName :Person)
  DataPropertyRange(:hasName xsd:string)

  ##
  ## Individual Declarations
  ##

  Declaration(NamedIndividual(:john))
  Declaration(NamedIndividual(:mary))
  Declaration(NamedIndividual(:bob))
  Declaration(NamedIndividual(:mon))
  Declaration(NamedIndividual(:tue))
  Declaration(NamedIndividual(:wed))
  Declaration(NamedIndividual(:thu))
  Declaration(NamedIndividual(:fri))
  Declaration(NamedIndividual(:sat))
  Declaration(NamedIndividual(:sun))

  ## john : Father
  ClassAssertion(:Father :john)

  ## mary : Mother
  ClassAssertion(:Mother :mary)

  ## bob : Male
  ClassAssertion(:Male :bob)

  ## mon, tue, wed, thu, fri, sat, sun : DayOfWeek
  ClassAssertion(:DayOfWeek :mon)
  ClassAssertion(:DayOfWeek :tue)
  ClassAssertion(:DayOfWeek :wed)
  ClassAssertion(:DayOfWeek :thu)
  ClassAssertion(:DayOfWeek :fri)
  ClassAssertion(:DayOfWeek :sat)
  ClassAssertion(:DayOfWeek :sun)

  ##
  ## Axioms (BEGIN ... END)
  ##

  ## DISJOINT Male, Female
  DisjointClasses(:Male :Female)

  ## john.hasChild := mary
  ObjectPropertyAssertion(:hasChild :john :mary)

  ## john.hasChild := bob
  ObjectPropertyAssertion(:hasChild :john :bob)

  ## john.hasAge := 42
  DataPropertyAssertion(:hasAge :john "42"^^xsd:integer)

  ## john.hasName := "John Smith"
  DataPropertyAssertion(:hasName :john "John Smith"^^xsd:string)

  ## mary.hasAge := 15
  DataPropertyAssertion(:hasAge :mary "15"^^xsd:integer)

  ## SOME hasChild . TOP <: Parent
  SubClassOf(
    ObjectSomeValuesFrom(:hasChild owl:Thing)
    :Parent)

  ## DIFF john, mary, bob
  DifferentIndividuals(:john :mary :bob)
    • Note:** The DOLA `CONST MaxChildren = 20` has no OWL counterpart — it is a purely syntactic convenience for use inside DOLA cardinality expressions and produces no axiom. The ## comments above each axiom show the corresponding DOLA source line.<

Design notes and possible extensions

The following features are intentionally omitted from the core language for simplicity but could be added:

  • Annotations (rdfs:label, rdfs:comment) — could use an @label "..." syntax after declarations.
  • Data ranges — constraining datatypes, e.g., INT[>= 0, <= 150].
  • Negative property assertions — e.g., john.hasChild ~:= jane.
  • Prefix/namespace management — e.g., IMPORT <...> AS prefix, then prefix.ClassName.
  • SWRL rules — inference rules beyond DL expressivity.
  • Parameterized ontology modules — analogous to Lola's parameterized MODULE types, allowing ontology design patterns to be declared and instantiated with actual parameters.
  • Disjoint unionDISJOINT UNION combining disjointness with a covering axiom.

The grammar is designed to be LL(2): a statement beginning with an identifier followed by . is a property assertion; followed by &, |, or <: it begins a class axiom. All other statement forms begin with distinct keywords.