This data from Wikipedia:
Could be represented in Jevko as follows:
Name [Horse]
Conservation status [Domesticated]
Scientific classification [
Kingdom [Animalia]
Phylum [Chordata]
Class [Mammalia]
Order [Perissodactyla]
Family [Equidae]
Genus [Equus]
Species [E. ferus]
Subspecies [E. f. caballus]
]
Trinomial name [
[Equus ferus caballus]
[Linnaeus, 1758]
]
Synonyms [at least 48 published]
If we parse that using the high-level grammar, we will get a parse tree like:
{
"subjevkos": [
{
"prefix": "Name ",
"jevko": {
"subjevkos": [],
"suffix": "Horse"
}
},
{
"prefix": "\n\nConservation status ",
"jevko": {
"subjevkos": [],
"suffix": "Domesticated"
}
},
{
"prefix": "\nScientific classification ",
"jevko": {
"subjevkos": [
{
"prefix": "\n Kingdom ",
"jevko": {
"subjevkos": [],
"suffix": "Animalia"
}
},
{
"prefix": "\n Phylum ",
"jevko": {
"subjevkos": [],
"suffix": "Chordata"
}
},
{
"prefix": "\n Class ",
"jevko": {
"subjevkos": [],
"suffix": "Mammalia"
}
},
{
"prefix": "\n Order ",
"jevko": {
"subjevkos": [],
"suffix": "Perissodactyla"
}
},
{
"prefix": "\n Family ",
"jevko": {
"subjevkos": [],
"suffix": "Equidae"
}
},
{
"prefix": "\n Genus ",
"jevko": {
"subjevkos": [],
"suffix": "Equus"
}
},
{
"prefix": "\n Species ",
"jevko": {
"subjevkos": [],
"suffix": "E. ferus"
}
},
{
"prefix": "\n Subspecies ",
"jevko": {
"subjevkos": [],
"suffix": "E. f. caballus"
}
}
],
"suffix": "\n"
}
},
{
"prefix": "\nTrinomial name ",
"jevko": {
"subjevkos": [
{
"prefix": "\n ",
"jevko": {
"subjevkos": [],
"suffix": "Equus ferus caballus"
}
},
{
"prefix": "\n ",
"jevko": {
"subjevkos": [],
"suffix": "Linnaeus, 1758"
}
}
],
"suffix": "\n"
}
},
{
"prefix": " \nSynonyms ",
"jevko": {
"subjevkos": [],
"suffix": "at least 48 published"
}
}
],
"suffix": ""
}
There are only 4 distinct keys in this parse tree: jevko
, subjevkos
, prefix
, and suffix
.
These identify all the elements of the parse tree.
jevko
is the basic element. Each jevko
is made of two other elements: a list of subjevkos
and a suffix
.
The top-level object (the root) of the parse tree is therefore a jevko
.
Each element of the subjevkos
list is called a subjevko
.
Like a jevko
, a subjevko
is also made up of two elements: a prefix
and a nested jevko
. Since it carries a nested jevko
, a subjevko
is responsible for the recursive nature of the tree. jevko
is the tree and subjevko
is the subtree.
Finally, both prefix
and suffix
are simple strings. They are the leaves of our parse tree.
Let’s take the top subjevko
:
{
"prefix": "Name ",
"jevko": {
"subjevkos": [],
"suffix": "Horse"
}
}
which corresponds to the fragment:
Name [Horse]
The jevko
of this subjevko
is:
{
"subjevkos": [],
"suffix": "Horse"
}
this simply corresponds to:
Horse
we will call a jevko
like that simple: its list of subjevkos
is empty, so it only carries a suffix
. In other words it is a tree with no subtrees and a single leaf.
Syntactically, a simple jevko
contains no brackets.
Conversely, a complex jevko
is one with a nonempty list of subjevkos
.
For example the following fragment:
Fragment #1: complex Jevko
[Equus ferus caballus]
[Linnaeus, 1758]
and its corresponding parse tree:
Parse tree #1: complex Jevko
{
"subjevkos": [
{
"prefix": "\n ",
"jevko": {
"subjevkos": [],
"suffix": "Equus ferus caballus"
}
},
{
"prefix": "\n ",
"jevko": {
"subjevkos": [],
"suffix": "Linnaeus, 1758"
}
}
],
"suffix": "\n"
}
is a complex jevko
. It has 2 subjevkos
. Each of these contain a simple jevko
.
Syntactically a complex jevko
contains brackets.
A simple jevko
can be interpreted as a string.
This could be done with the following JavaScript function:
const jevkoToString = (jevko) => {
return jevko.suffix
}
For example it would turn this:
{
"subjevkos": [],
"suffix": "Horse"
}
into this:
"Horse"
A complex jevko
can be interpreted as a list.
For example parse tree #1 can be converted to a list of strings with the following JavaScript function:
const jevkoToListOfStrings = (jevko) => {
return jevko.subjevkos.map(({jevko}) => jevkoToString(jevko))
}
It will produce:
[
"Equus ferus caballus",
"Linnaeus, 1758"
]
Name [Horse]
has the following parse tree:
{
"subjevkos": [
{
"prefix": "Name ",
"jevko": {
"subjevkos": [],
"suffix": "Horse"
}
},
],
"suffix": ""
}
Each subjevko
contains a prefix
associated with a nested jevko
. Syntactically, the prefix
is all the text which comes before the opening bracket [
, and jevko
is everything after the bracket up to the matching closing bracket ]
.
Each subjevko
looks and feels very similar to a key-value pair: the prefix
can be interpreted as the key of the pair, and the nested jevko
can be interpreted as the value of the pair.
A complex jevko
can also be interpreted as a collection of key-value pairs.
For example:
Kingdom [Animalia]
Phylum [Chordata]
Class [Mammalia]
Order [Perissodactyla]
Family [Equidae]
Genus [Equus]
Species [E. ferus]
Subspecies [E. f. caballus]
const jevkoToMapOfStrings = (jevko) => {
return Object.fromEntries(
jevko.subjevkos.map(
({prefix, jevko}) => [prefix.trim(), jevkoToString(jevko)]
)
)
}
{
"Kingdom": "Animalia",
"Phylum": "Chordata",
"Class": "Mammalia",
"Order": "Perissodactyla",
"Family": "Equidae",
"Genus": "Equus",
"Species": "E. ferus",
"Subspecies": "E. f. caballus",
}
A list of subjevkos
of a jevko
can then be seen as a collection of key-value pairs. It is very straightforward to turn such a collection into a proper associative array or a map, such as a JavaScript Map, a plain JavaScript object, or an equivalent in any programming language.
const jevkoToValue = (jevko) => {
return Object.fromEntries(
jevko.subjevkos.map(
({prefix, jevko}) => [prefix.trim(), jevkoToValue(jevko)]
)
)
}
const jevkoToValue = (jevko) => {
const {subjevkos} = jevko
if (subjevkos.length === 0) return jevko.suffix
const {prefix} = subjevkos[0]
if (prefix.trim() === '') return subjevkos.map(({jevko}) => jevkoToValue(jevko))
return Object.fromEntries(
subjevkos.map(({prefix, jevko}) => [prefix.trim(), jevkoToValue(jevko)])
)
}