porky11 / minlang
README.mdinitial commiton October 25, 2017
minlang.asdinitial commiton October 25, 2017
minlang.lispinitial commiton October 25, 2017
story.txtstory exampleon October 26, 2017

Minimal Language

For some example story see story.txt. It's just a translation of an existing story.

For examples, see file examples.md

Goals of the language

This language aims to have a minimalistic but yet flexible grammar. It is based on set theory and tries to use as few as needed grammatically different kinds of words.

Even the used letters should be minimal. In order to keep it simple, all brackets should be implicit.

It also should be possible to define new words of all kinds in a simple way.

The language is aimed to be a speakable language, but it would be preferable if the language can also be used as programming language.

It would be possible to replace the used letters and sounds by letters and sounds of other languages, to use tones, prefixes, postfixes for some grammatical elements, and more.

But in order to keep it simple and general, none of such things exists. A single word has a single function everytime, there are almost no unspeakable symbols to structure the sentences, except for seperating words, sentences and optinally also syllables.


In order to be able to discriminate between vowels independent of the own language, there are only five of them:

a, e, i, o, u

There are also just a few consonants.

The following consonants can be used for the words. How they can be spoken is declared after them:

p: b p

t: d t

c: k g

s: s z

v: w

x: (spanish "j", german "ch")

z: sh (german "sch")

f: f v

n: m n

r: r l

j: i y

Letters can be grouped like this:

A = a, e, i, o, u

T = p, t, k

S = f, s, z, x

N = n

R = r, j, v

L = n, r, j, v

Words can be written as multiple syllables. They are seperated by a -.

This is how a syllable S can be built:


For each group of letters one letter can be inserted. All gropus are optional. So a syllable does not require to have a vowel in it. There cannot be double vowels, because for some it is not clear, how they are pronounced. The letters v and j are used to simulate double and triple voewls.

v is used to simulate o or u , and j to simulate i or e.

Without seperating syllables, they are interpreted so, that there are as few syllables as possible.

If something could be attached to two syllables, it will be interpreted as the beginning of the first syllable.




Sentences of the described language are described by making it this way.

Translations are written after such a sentence with a => before them.


Everything in this language is represented by sets.

The only kinds of grammatical elements are simple sets, binary operators, relative sets and modifiers.

Preferably simple sets and binary operators should be used for talking about objects. relative sets and modifiers should only be used for things, that cannot be expressed in different ways, or are too complicated to be expressed that way.

Sets will be expressed by ' followed by an uppercase letter.

'A => The set of 'As.

Simple sets

The simplest sets are just represented by single words. In most cases, where simple sets can be used, also other sets can be used.

Binary operators

Sets can be constructed with simple operations of the set theory.

Connection operators are the only binary operations. They are inserted between multiple sets.

They will be denoted by - followed by a lowercase letter.

'A -a 'B => The set generated by the operation -a applied to the sets 'A and 'B

The default relation, when nothing is written between the two sets, is the intersection of them.

'A 'B => 'As, that also are 'Bs.

Relative sets

Relative sets are like functions of sets.

They can just select elements from a set, create a special set of objects, which relate to the elements of a set, or everything you can think of.

Relative sets will be denoted by ' followed by a lowercase letter.

'a 'A => The set 'a relative to 'A.


These modify the meaning of the following word. Together with the following word they can be treated as a single word. They may be used to talk about the words itself, without interpreting them as sets, or to change the meaning of relative sets.

You can also think of them as macros, that don't know about the semantics, which replace words with meanings, that may have no names.

They can be seen as prefixes.

In order to apply multiple modifiers to a word, the modifier has to accept being applied to other modifiers, which has to generate a new modifier.

Modifiers even can take any numbers of arguments using currying.


The language tries to be simple and expressive. In order to achieve this, brackets should be possible, but implicite.

The way this language handles this is without using special symbols.

Every relative set increases the hierarchy level. Every simple set decreases the hierarchy level.

Binary operations don't change the hierachy level.

The simplest way to know these relationships for a large sentence is just putting a opening bracket after a relative set, and a closing bracket after a simple set. In the end you optionally have to add some additional brackets at the beginning and the end of the sentence until every bracket has a matching partner.

If there are some pairs of brackets at the same hierarchy level, they are right associative.

This method of relation may seem not intuitive, but in example sentences you'll see it works well for many situations.

A simpler way to think about this is, that a relative set can take an arbitrary amount of other relative sets as arguments, but just a single simple set.

This is useful in many situations.


Important sets


o => everything, true

l 'A => same set as 'A (mainly important for structure)

a 'A => a set containing a single element of 'A

no 'A => complement set of 'A

Binary set operations

'A is 'B => elements of 'A are elements of 'B (the resulting set contains everything except 'A without 'B) (implication)

'A en 'B => elements of 'A or 'B (union)

'A or 'B => elements are either in 'A or 'B (exclusive or, unequal)

'A se 'B => elements of 'A without elements of B (equal to *no l 'A is 'B)

'A ic 'B => sets 'A and 'B are equal (equal)

Relative sets

i => I, me, we, us, the talker(s)

u => you, the one(s) being talked to

ju => me (or us) and you

jo => me (or us) and others

vo => you and others

juo => me (or us), you and others

Referencing specific objects

Sets may depend on context:

te 'A => the last recent talked single element of 'A referenced by a 'A

it => set containing the last element refernecec by a; equal to *te o

tis => the object(s) I point at

You can also call something by names explicitely:

… n => modifier turns the following word into a name. it can be referenced also by using … n

Tuple sets

All sets of objects can be seen as sets of tuples of objects. To get an element of a tuples, there are accessor functions, which can be described as relative sets.


The simplest way to describe a relation between multiple objects is by using a relative set describing the relation.

But it may be useful to be able to express both directions of a relation, so there is the need of two relation, so that following is true:

'A is 'a 'B o ic l 'B is 'b 'A

It would also be possible to just define one of 'a or 'b, and generate the other one of them using a modifier, but then it would not be clear, which of them is the default.

They could also be generated by using different modifiers on a single word expressing the relation. but then the word itself wouldn't have a meaning.

So the best way to express a relation is as a set of objects containing information to both kinds of related objects.

These have to be accessed by relative sets. Since most relations are binary, but the roles have no special meaning these are the accessors for the relative sets:

ni 'A => minor/first/smaller elements of tuples in 'A

na 'A => major/last/larger elements of tuples in 'A

This way, it's also possible to talk about the relation as objects themselves, and to describe even other objects participating in the relation.

par => a parent-child relationship

ni par => children

na par => parents

Actions and actors

The simplest way to describe an action is as the set of actors of it.

For simple actions this is useful, but most actions have multiple actors in different roles.

'A is 'B => 'A is doing action 'B

If there are only two roles, it may be possible to describe this as a relative set.

'A is 'a 'B => 'A is actor of 'a relative to 'B

There are problems with this approach:

  • only useful for binary actions

  • difficult, to talk about the action itself

  • the additional argument to may often be not required

  • even for actions with just two roles, you may find new roles applying to it

Instead, actions should be defined as a simple set of objects themself.

There are relative sets, when used relative to actions, they extract the different roles of these actions.

These are the most important words for extracting them:

ca 'A => set of actors of 'A

ci 'A => set of objects affected by 'A

co 'A => set of object aimed at by 'A

So when you want to describe an action 'A more detailled, you can say this:

a n is 'A. 'B is ca a n. 'C is ci a n. 'D is co a n.

=> what we call a is 'A done by 'B affecting 'C aimed at 'D

Instead of writing 'B is 'b 'A for every set 'A and every role 'b where 'B is of, it would be nicer to write something like 'a 'B, where 'a 'X => 'X is 'b o

Such a action can be created by following modifier for every relative set:

t 'a 'A => modifier of a relative set. set of objects, where 'A is in relation 'a to it

The sentences from before can now be written in a simpler way:

'A is t ca 'B t ci 'C t co 'D

Selection based on attributes

Selecting objects from a set based on attributes can often be done by unification.

But when an attribute has to have a value:

saj 'A is ni x l t na saj 'B

'X is element of 'A and it's size is smaller than 'B.

'X is l 'A ni x saj t na 'B


Numbers are just like other objects, but they can be defined by different modifier prefixes:

ov … => octal number

pin … => binary number

tetzi … => decimal number

In order to get a set of a specific size, you can use cardinal numbers, which are relative sets.

'n 'A => a set containing 'n elements of 'A

Numbers are generated using modifiers and a representation for numbers.

nan … => Extracts … elements from number.

(How should … be evaluated? Should something like this be possible:

nan sun l ov 1 en ov 2 o o

((nan sun(l(ov 1) en ov 2) o) o)

=> one plus two objects

This seems complicated, and is a pretty complicated extra grammar using modifiers. This modifiers uses the whole grammar of the language. Another solution may be preferable)

So numbers could just be interpreted as sets of size of this number:

nan … o => Set of … arbitrary elements

z … => reverse meaning of assymetric binary relations (the only of such relations is is


The rank of an object is the position of an object in the referenced set.

ran 'A => rank of an object in set 'A, starting at zero

A rank can be specified by looking at multiple elements of the set in an unspecified order, and giving it some numbers.

Getting some elements of a set.

'X is l 'A ni x ran t na ov 7

=> 'X contains the first 7 elements of 'A

Following means the same thing:

'X is l 'A. ran 'X is ni x l t na ov 7

So the way to interpret this is, when all elements have a rank smaller than the specified value, the set contains just these elements.

(When this really works, why does the relative set a have to be relative? Because it additionally sets a reference marker)

Mathematical functions on sets

nun 'A => Count of the elements in 'A, zero, a natural Number, or unknown (which is also used for infinite sets)

sun 'A => Set containing the sum of all elements in 'A

nur 'A => Product (mul)

nec 'A => Negate all values inside 'A

inf 'A => inverse of the elements of 'A (one devided by the element)

n avg ic nur sun 'A inf nun 'A *n avg ic nur


One way to talk about attributes of an object is by having a relative set, which describes all parts of an object.

pa 'A => parts of 'A, parts 'A consists of

But in most cases, it's more useful to have different kinds of attributes, which can be accessed using different relative sets. These are sets of objects, that are not necessarily useful by themselves.

*saj 'A => (spatial/volumetric) size of 'A *taj 'A => age of 'A

Comparing attributes

In order to compare attributes, it would be possible to have a relation 'A, whose both related objects have the role of something that has a higher value and something that has a lower value. Then, in order to compare attribute 'a of 'B and 'C, you could say:

'a 'B is ni t na 'a 'C o 'A => the value 'a of 'B is lower than the value 'a of 'C

The way this really is done is by using modifiers. Now it is required to repeat the name of the attribute. There is a modifier, which generates a new relation, which compares the specific value.

x 'a => the relation (as set) looking at value 'a

This is the way to express such a relationship:

'B is ni t na 'C x 'a => 'B is lower than 'C when looking at value 'a for both

It's still possible to create the previously mentioned relation 'A and apply it to the attributes itself. Therefore the watched attribute 'a has to be l.

Absolute attributes

When you want to say some of the attributes has a high value, it is difficult this way. What would it logically mean?


van 'A => someone who wants 'A to be true

i is van l u is ca go

=> I want you to go/move by yourself

zav 'A => someone who should/has to be (do) 'A

u is zav ca go

=> you should go (be a goer)

tu 'A => do (be) 'A

tu ca go

=> (please) go!


Quoting is useful to talk about things, not neccessarily having a meaning, mostly for using multiple words as single words.

"Quoted text"

(Problem: Recursive quotes? Solution: Quotes have to touch non-whitespace letters. Problem: Quoting Whitespace? Solution: Recursive quotes not possible. Problem: Talking about quoted whitespace? Not possible)


*an 'A => objects at the same place as 'A

Talking about talking

sej => The action of talking/saying something.

u is ca t co i t ci l i is ca t ci l o is ci sej o o sej o sej

u is ca l sej t co i t ci l i is ca l sej t ci l o is ci sej

=> You say to me, that I say, that something is said.

Here you also can see the problems of the implicit brackets, where the words l and o sometimes act like brackets. By restructuring it's possible to make it simpler.

Sets with Subsets

These are used to get subsets of a set.

These are only useful with using with some default set, since they don't select objects of a set, that have a specific attribute, but describe the attribute.

The modifiers together with the words have the meaning themselves. There may not be other words for these sets.

This is done, when there are multiple subsets of a set. This way it's easier to learn all of these words. Instead of three words (the super set, both subsets) you have to learn the both subset modifiers once and the meaning of the set, and probably one of the meanings of the sets, but this should be clear anyway.

The other meaning will be known after that.

ir 'A => modifier, the one kind of 'A

ar 'A => modifier, the other kind of 'A

Here the probably most simple example, you would think of. In this case you may know both meanings without reading the specialized meanings.

noj => having a sex/gender

noj ir => female

noj ar => male

It is not required, that all objects of the superset are in one of both subsets, and that they are in just one of the subsets, when creating such words.

But normally that's the case.

Even in this case, there may be cases, where some object, having a gender, is as well male as female, or non of both (especially for non human races)

Time and Space

Time and space are interpretet as the set of objects, that exist at a specific time or space.

*nav => the current time.

ri 'A => horizontal position of 'A (left is smaller)

ro 'A => vertical position of 'A (down is smaller)

ra 'A => positoin in look direction of 'A (behind is smaller)

faj = time relationship (before, after)

et 'A => At the time of 'A, all objects, that exist at the specified time, at the same time as 'A is true. While/During 'A.

in 'A => Everything in the same position as 'A.

Relative clauses


if 'A => true if 'A is true (o), else it's false (no o)


pov 'A => because of 'A

(is this really required or is it simple enough to express this with set theory directly?)

Modal not required(?)


TODO** =>

Temporal (while, before, after) done by combination of et and faj


vat => Set of objects one wants to know about, used to ask questions.

u is ca vat => What do you do? vat ic l u is ca 'A => You do 'A, right?/Do you do 'A?


tat => the thing someone asked about.

tat ic 'A => I do 'A tat ic o => That's correct/I do 'A tat ic no o => That's not correct/I don't do 'A/that you do a is equal to nothing

vat nav is ca 'A => Who is doing 'A? i is tat => I (for example) am doing a 'A i ic tat => I am doing 'A

if vat u is ca 'A => in which case do you do 'A? pov vat u is ca 'A => Why do you do 'A? et vat u is ca 'A => When do you do 'A? tat ic nav => Now I do 'A u is ca 'B o is tat => While you do 'B (maybe even longer, since it's just a subset using is)

Use foreign words

This is done by modifiers. There is a modifier for foreign simple sets and a modifier for foreign relative sets. The language, from which the words come from, can be every langauage, and is also allowed to contain different letters, just no whitespaces. The exact meaning of foreign words may not be clear, especially when used as relative sets.

lo … => Foreign simple set pi … => foreign relative set

i is ca l lo run lo fast => I run fast. *i is ca pi from 'A pi to 'B go => I go/move by myself from 'A to 'B

Referencing single letters

xe … => the name of the letter …

Normally the letter is a single letter of this languages. It is also possible to use foreign symbols or using multiple signs to describe it. If a symbol is not part of this language, it's not clear, how it sounds.

xe cvu => empty sign

Time modifiers?

'a c 'A => for temporal actions, the opposite of it

(assuming 'a 'A ic ni faj is 'b 'A na fai is 'c 'A, then c 'a 'A ic na faj is 'b 'A ni fai is 'c 'A)

(('A) is t('a('B) o) o) ic l('B) is 'a('A)

'A is t 'a 'B o o ic l 'B is 'a 'A

ejt => eat

go => moving by oneself to a place

zu 'A => Action of moving towards something


How a computerprogram could handle sets with undefined elements:

Sets with undefined number of elements are just names for the sets or expressions.

Sets with known elements can be represented as lists of their elements. Complements of sets of known elements can just be defined as complements.


  • More kinds of Questions.
  • Numbers.
  • Talking about the language.
  • Quoting expressions containing whitespace.
  • Implement foreign words. These will allow to connect with lisp directly inside the language.
  • Declaring new word of the language.
  • Program should generate some normalform for set expressions (DNF, CNF, ?)
  • Language should handle sets
  • Write computer programs.
  • Are modifiers too mighty and complicated? Should they be dropped? They just come handy, when no other tool of this language works, or would be too complicated. They were not intended for this design of the language. But without modifiers, there would be a need of many more words, which not even are useful in most cases, and would in some cases almost do, what modifiers do, and could just be called the same. Maybe it would even be useful to restrict the length of a word to one syllable and require other syllables to be handled as modifiers. But this would change the fundamental rules of the language, and be less minimalistic. Modifiers are like cheating and allowing every new grammar you want. And sometimes this even simplifies everything very much.