Modulo:spec-picker-en

Purpose
-------

This specification defines a system for 1-dimensional, 2-dimensional
and 2+1/2-dimensional plain text tables containing elements that can
subsequently be picked in various manners, including reverse searches.
The specification is not bound to a programming language, but LUA is
a viable choice.

Terminology
-----------

Structure on the block:
* raw block
  * (optional) strippable area preceding content
  * (conditional) begin marker
  * (optional) upper blank lines that are stripped
  * table content area
    * (optional) extra line at begin with "minwidth" and "maxwidth"
    * table rows
      * (optional) index markers
      * table elements
        * useful content
        * placeholder for "empty element"
    * (optional) section headers
    * (optional) blank lines
  * (optional) lower blank lines that are stripped
  * (conditional) termination marker
  * (optional) strippable area following content

Columns:
* left-most column usable for access in opposite direction
* other column of interest usable for access in opposite direction

Index marker by dimension:
* y-index marker (row index marker) placed in the table content area
* x-index marker (column index marker) placed in the table content area
section header acts like an index marker in the z-dimension

Index marker by type:
* digit index marker (only digits)
* text index marker (ASCII letters plus a bit more)

Request index string by dimension:
* request y-index string
* request x-index string
there is no request z-index string

Request index string by type (automatically evaluated to):
* string indexing
* numerical indexing

Relation:
* string indexing     <-->  text index marker
* numerical indexing  <-->  digit index marker, or no index
                            marker and counting

Processing steps:
* preprocessing (conversion of the source text table with raw
  text into a smarter destination structure such as a LUA table
  or several LUA tables, even nested)
  * reading line with space reduction performed at same time
  * stripping off the y-index marker
  * split into elements
  * optional pluprocessing specific to columns

Absolute limits
---------------

- minimal size of the raw block : 32 ... 1'000'000 octet:s
- maximal size of the raw block : 100 ... 8'000'000 octet:s
- minimal size of the content area : 32 ... 1'000'000 octet:s
- maximal size of the content area : 100 ... 8'000'000 octet:s
- minimal length of line "minwidth" :  2 ... 40'000 octet:s
- maximal length of line "maxwidth" : 22 ... 80'000 octet:s
- minimal number of lines : 2...10'000
- maximal number of lines : 10...100'000
- minimal number of elements in a row : 1 ... 100
- maximal number of elements in a row : 1 ... 10'000
- charset for table : subset of Unicode, BOM prohibited, legal range 32
  space and above, codes below 32 absolutely prohibited except ONE
  dedicated code for EOL, #### [[[ ]]] ((( ))) absolutely prohibited,
  [[ ]] (( )) ### reserved
- charset for markers : subset of ASCII, 45 "-" ... 122 "z" (see below)
- separators between elements : comma "," or semicolon ";"
  or wall "|" (fixed in advance)
- placeholder for "empty element" : fixed to "-"
- placeholder for "not found" : 1 ... 20 octet:s, default "="
- end-of-line-character (EOL) : either LF or ZERO (fixed in advance)
- leading spaces: disallowed
- trailing spaces: disallowed
- max number of consecutive empty lines : ONE (does not apply to very
  begin above and very end below the table where EOL:s are unlimited)
- size of begin marker and termination marker: ONE or TWO lines
  with suitably attached EOL:s
- length of index markers : 2 ... 12 octet:s (+ 4 char:s of brackets)
- length of section headers : 2 ... 12 octet:s (+ 4 char:s of
  introducing "### ")

    Rationale:
    * minimal "minwidth" of 2 octet:s can be useful if a table row
      contains one element with one char and no index markers, one
      char + EOL gives 2
    * minimal "maxwidth" of 22 octet:s is due to the line holding the
      definition of "minwidth" and "maxwidth" that happens to be 21
      char:s long, 21 + EOL gives 22

Character encoding and EOL:s
----------------------------

Index markers may contain only a strictly defined subset of ASCII
char set (see below). Table elements may contain UTF8. There is a
single type of EOL defined in advance, either LF or ZERO. More than
2 subsequent EOL:s ie more than one empty line is an error. Char codes
0...31 except ZERO or LF used as EOL are prohibited, this includes TAB.
All length limits refer to octet:s, thus for example 48 octet:s may be
as few as 12 visible char:s (for example Chinese ones).

Access
------

Principally 3 access methods exist:
* access by search in raw text as-is
* access by search in cleaned-up text (empty lines
  removed, multiple inner spaces reduced to single ones)
* access to fully preprocessed text converted to a "smarter"
  structure such as one or several LUA tables

Without preprocessing a query incurs exhaustive counting, exhaustive
search, exhaustive counting plus search, binary search, or direct
access (pos = y * width + x or at least pos = y * width) depending
most notably on what type of index markers are used and whether they
are sorted. Direct access is indeed possible but less useful since it
requires fixed length of table lines.

Generally a request consists of a request y-index string and
a request x-index string, failure to find them both results
in "not found". It can be useful to implement an y-only request
that either checks whether a row exists, returning a boolean,
or returns the complete line with the row if such can be found.

Full preprocessing opens for the possibility of reverse access,
ie content of table element in a given column (x-index) comes in,
and the y-index is the output. To make this working, the elements
in the given column must be unique (free of dupes), but they still
may miss in some rows, in favor of the standard placeholder "-".

The z-dimension, section headers
--------------------------------

The table content area may contain section headers de facto adding
a 3rd dimension to the table. The advantages of this design are a
more readable table, less typing, and a possibility to define sorting
requirements separately for the y-index markers and section headers.
Section headers must NOT be used together with numerical indexing
in the y-dimension. Thus string indexing applies, and the y-index
markers must be obligatory. To access a row, the section header
and the y-index marker are attached together by the dash "-" sign,
forming the y-index string. There is no request z-index string. For
example, in order to reach a line located in section "NONE" and carrying
an y-index marker "here", the requested y-index string is "NONE-here".
Base rules for the structure of a section header are same as for a text
index marker. A section must not be empty, it must contain at least
one line, and no particular maximum is defined. The minimal and maximal
number of lines (Q15 and Q16, see below) applies globally and to all
lines, but not to section headers. In other words, those values limit
the number of different valid y-index strings that can pick something
from the table.

Index markers
-------------

An index marker is used to label (separately) a vertical or horizontal
position in the table. There are y-index markers (row index markers)
and x-index markers (column index markers). They are optional by this
specification. If an index marker is missing then ZERO-based counting
of lines or elements in a line applies. An implementation may choose
not to support or make obligatory one of them or both. Additionally
section headers can be either obligatory or disallowed.

In the table an index marker must be enclosed in double brackets
without inner spaces:

* double rectangular brackets "[["..."]]" for y-index markers
* double arc brackets "(("..."))" for x-index markers

Section headers are instead preceded by "### ".

An index marker (y-index marker, x-index marker, section header)
contains only ASCII char:s and its length can be 2 ... 12 octet:s.
An implementation may impose stricter limits and an additional
validation.

For y-dimension and x-dimension there are text index markers and
digit index markers. Only the text type is legal as section header.

Text index markers begin with an ASCII letter. Subsequent char:s
may also be digits (even the last char), or dashes "-" (but not
the last char).

Digit index markers are built of decimal digits and nothing
else. Apo:s "'" are not permitted. For indexes 0...9 the digit
index markers must be ZERO-padded to be valid: "00" ... "09".

For y-dimension and x-dimension:

* probably good: [[aa]], [[ZERO]], ((perpustakaan)), ((00)),
                 [[012345678901]]
* maybe good: ((be3z)), [[t8i]], ((ling-kung-an)), [[a2-z]]
* bad: [[x]], [[seven+seven]], [[abc ]], [[ de]], [[CRAP-]], [[3d]],
       [[memutakhirkan]], [[??]], [[]]aa

For section headers:

* good: ### yes-we-canon, ### SS
* bad (fails identification): ### nope ###, ### nope ##, ###ggg, ### MY##BUG
* bad (fails later validation): ### yes-we-cannon, ### 999, ### MY#BUG

Types of lines
--------------

Based on above there are 3 possible types of line:
* section headers
* content lines beginning with y-index marker
* content lines not beginning with y-index marker (still can
  begin with an x-index marker then)

Identification criteria for type of line section header:
* length excl EOL >=6
* "##" found exactly ONE time at position ZERO and followed by "# "
  at position TWO

Identification criteria for type of line y-index marker:
* length excl EOL >=6
* "[[" found exactly ONE time at position ZERO and "]]" found exactly
  ONE time somewhere

Since ### and [[ are reserved, a content line not beginning with
y-index marker cannot be misidentified as something else. Failure
to identify the type of line gives E18.

An identified line still can be faulty, for example "[[]]aa" gets
identified as content line beginning with y-index marker, but then
the validation fails with E25. Similarly "### 999" gives E20.

Table elements and placeholders
-------------------------------

Empty elements (containing empty string or whitespace only) are not
possible, the "-" placeholder for "empty element" is used instead.
Rows may have different lengths, access to missing elements on the
right returns the placeholder for "not found". A row consisting of
placeholders "-" only in all elements is legal. Pluprocessing of missing
elements can result in another suitable placeholder (empty string, type
"nil", ...) different from both the "-" placeholder as well as from the
placeholder for "not found". The user of the preprocessed table must
bother with the difference between a missing element and the "-"
placeholder for "empty element", unless they are deliberately
considered as equivalent.

Indexing models
---------------

There is numerical indexing and string indexing. The incoming
requested indexes are considered as lacking data type ie always raw
strings, and the type is autodetected based on the definition of index
markers. The unambiguous conclusion can be either numerical indexing
(only digits found), or string indexing (letters or maybe a bit more
found), or invalid request.

Numerical indexing can match both digit index markers and counted
indexes. Comparisons are numerical, thus for example "0014" and
"14" are equal. Leading ZERO:s are tolerable as long as the maximal
length of an index marker is not exceeded. Discovering a digit index
marker mismatching the counted value is a critical error. For the
y-index word, empty lines and section headers DO NOT count. For
the x-index word, unused columns containing "-" DO count.

String indexing can be used only with text index markers.

Index markers are optional, independently for
y-dimension and x-dimension.

It is possible (and potentially useful) to mix elements with x-index
markers and elements without them. This allows to "jump" over many empty
columns using text index markers (not digit index markers) without
having to provide the correct number of empty elements with the "-"
placeholder. This also allows to label columns with digit index
markers to make the table more readable, empty elements with the "-"
placeholder may be needed then.

This does not hold for y-index markers. They can either be used in all
lines, or prohibited. Without y-index markers in all lines an exhaustive
counting is needed which can be a performance problem with a large not
preprocessed table. Thus prohibited y-index markers can be useful only
with small tables, where neither "jumping" over many empty lines, nor
marking such with digit index markers would be useful. With sorted
y-index markers in all lines a binary search is possible.

Sorting and dupes
-----------------

Table content may be picked either by index markers or by "ordinary"
content in left-most column or other column of interest usable for
access in opposite direction.

3 levels of sorting are defined:
* S0 no sorting requirement
* S1 sorting with a privileged role for one entry at the beginning
     and one entry at the end than can deviate
* S2 sorting without exceptions

3 levels of dupe prevention are defined:
* D0 dupes permitted
* D1 dupes prohibited but placeholder "-" permitted even multiple use
* D2 dupes prohibited and placeholder "-" prohibited, not even
     a single occurrence

Sorting makes dupes essentially impossible. S2 makes them absolutely
impossible, thus a separate check for dupes can be skipped. S1 makes
dupes unlikely, but not impossible, therefore keeping the need for a
separate check.

Dupes are absolutely prohibited D2 for all markers, ie section headers,
y-index markers and x-index markers. For section headers the scope is
the whole table, for y-index markers it is a section (same marker in
different sections is legal), for x-index markers it is a line.
D1-level doesn't make sense for markers since they must NOT be
equal "-" anyway.

The dupe levels are useful for certain table columns if access in
opposite direction is needed.

For section headers, if used, dupes are prohibited to D2-level, but
there is no sorting requirement ie S0 applies.

For y-index markers, if used (then in all lines), dupes are prohibited
to D2-level, and sorting is required to either S1-level (only if
sections are NOT used) or S2-level.

    Rationale: Section headers and y-index markers are used to
    find a line, allowing dupes would break their purpose. Allowing
    S1 together with sections would cause implementation difficulties
    (hard to find out whether the item is last or not, need for an
    extra pass) for little benefit, ie a mess. If sections are used,
    then S0 or S2 applies to section headers, and only S2
    to y-index markers.

For x-index markers, if used (selectively possible), dupes are
prohibited to D2-level, but no sorting is required.

No requirements arise for table elements as long as access in opposite
direction id not desired. If it is, then dupes must be prohibited to
D1-level or D2-level in the affected column. There is obviously no
sorting for ordinary table elements.

Dimension-specific possibilities selectable by the implementation
-----------------------------------------------------------------

There are 3 options in the y-dimension but 4 options in the x-dimension
related to presence and sorting of markers.

y-index markers (lines)                 search
----------------------                  ------
Y2 prohibited and fixed width of table  direct access
Y3 prohibited                           exhaustive counting needed
Y4 obligatory and sorted                binary search possible

On Y4 further details:
* type D (digit) or T (text) or B (both)
* sorting S1 or S2

x-index markers (columns)          search
-------------------------          ------
X6 prohibited                      exhaustive counting needed
X7 optional                        exhaustive counting and search needed
X8 obligatory                      exhaustive search needed
X9 obligatory and sorted           binary search possible

On X7...X9 further details:
* type D (digit) or T (text) or B (both)

On X9 further details:
* sorting S1 or S2

With optional or obligatory markers in a given dimension the
implementation has to define whether digit index markers or text
index markers or both, as well as whether string indexing or numerical
indexing or both are supported. Mixing digit index markers and text
index markers is tolerable by this specification, but less useful
particularly for y-index markers that must be sorted, and thus
all digit index markers precede all text index markers. Mismatching
digit index markers are always prohibited.

With prohibited markers in a given dimension the implementation
must support numerical indexing.

Parameters "minwidth" and "maxwidth"
------------------------------------

They can be needed for searching inside the table. The table content
area may contain a special line at the beginning defining them.

The line looks like this:

minw=00010 maxw=00200

The length is 21 char:s plus EOL, the strings "minw=" and "maxw=" are
fixed to their positions, leading ZERO:s are obligatory, apo:s "'"
are prohibited, trailing spaces are prohibited, EOL is obligatory.

Validation stage zero (violation gives discovery "not this
type of line", may soon result in E18):
* length 21 + EOL
* strings "minw=" and "maxw=" and EOL exact
* 2 numbers consist of "0" ... "9"

Validation stage one (violation gives error E14):
* no other non-empty line found before
* 2 numbers are within range

Purpose of the parameters "minwidth" and "maxwidth":

They restrict the length of a complete table line. After adding 2 for
up to 2 EOL:s we get the distance between two table line beginnings,
including one possible blank line between them. Quasi-blank lines
containing only spaces are not permitted. Minimum of 22 for "maxwidth"
does not mean that lines may not be shorter than 22 char:s.

Strippable areas and EOL:s preceding and following table content area
---------------------------------------------------------------------

Strippable areas are either obligatory or absent, chosen by Q02. An
implementation-specific begin marker plus a termination marker must
be defined if strippable areas are used. Those markers must be different
from each other. One marker must consist of one or two lines with
one or two EOL:s. Those EOL:s must follow the lines for the begin
marker, and precede the lines for the termination marker. This means
that BOF and EOF of the raw block may lie immediately outside of those
markers. The validation criteria are:
* begin marker is found exactly one time in the raw block
* termination marker is found exactly one time in the raw block
* the implementation-specific range for minimal and maximal size
  of the table content area between them is met

Irrespective of whether strippable areas are used or not, possible
blank lines above and below the table (but not yet inside) are always
stripped early, and are not subject to the restriction of maximally one
subsequent blank line. The table content area will get exactly ONE EOL
attached at the bottom, even if such was missing. These steps are needed
for reliable parsing, and consistent reporting of length as well as
position of possible error.

Overall structure of the source text table
------------------------------------------

* table lines are separated by EOL:s (see above)
* optional section headers begin with reserved string "### "
* table elements within lines are separated by dedicated separators
  (comma "," or semicolon ";" or wall "|", fixed in advance)
* double rectangular brackets "[[" and "]]" are reserved for y-index
  markers, and such may occur only at the beginning of line
- usage of single rectangular brackets "[" and "]" is not limited
- double arc brackets "((" and "))" are reserved for x-index markers
- usage of single arc brackets "(" and ")" is not limited
- more than two subsequent brackets, thus for example
  "[[[" or ")))" are absolutely prohibited
- no dedicated separator (such as comma ",") following index markers
  [[...]] and ((...)), space instead is recommended but not required
- index markers must be 2...12 char:s long and consist of either
  letters plus maybe more (text index marker, see above) or only decimal
  digits (digit index marker), it's possible (but probably barely
  useful) to mix the 2 types
- if digit index markers are used then they must match the counted index
  numbers for both lines and columns, ie a digit index marker inside
  [[...]] and ((...)) is optional (in all lines or in no
  lines for y-index markers), but cannot hold a value different from what
  it would be anyway based on ZERO-based counting
- redundant whitespace is not a problem as long as "maxwidth" is not
  exceeded, there are no leading or trailing spaces, and not more than
  one consecutive blank line, ie not more than 2 consecutive EOL:s
- a table line must not be empty, there must be at least ONE element
  following an y-index marker, placeholder "-" can be accepted as valid
- truncated table lines, ie lines shorter than other lines (having less
  elements) are tolerable, they can end with element data, but not with
  a separator, nor an orphaned x-index marker
- a table element must NOT be equal to the placeholder for
  "not found" defined by Q22
- a table element must NOT be empty, dash "-" is the placeholder for
  "empty element", alternatively text x-index markers ((...)) can be used
  to "jump" over columns, every x-index marker ((...)) must be followed
  by at least one char of table data

Destination structure
---------------------

Preprocessing converts a source text table into a suitable
destination structure that can be seen as one or several tables.

Following types of tables are defined:
* T75   enumeration        ZERO-based integer enumeration index -> y-index
* T76   simple one-to-one  y-index -> element in left-most column
* T77   preserve text      y-index -> complete line
* T78   full nested        y-index -> subtable
* T80   left reverse       element in left-most column ie ZERO -> y-index
* T81-n extra reverse      element in other column of interest -> y-index
  * T81-1                  element in column ONE -> y-index
  * T81-2                  element in column TWO -> y-index

In T77 the returned complete line is space-reduced, but the y-index
marker is still present, and no pluprocessing has been done.

Pluprocessing affects T76 T78 T80 and T81-n:
* in T75 pluprocessing is obviously pointless
* T77 is explicitly excluded from pluprocessing
* pluprocessing indeed affects T80 and T81-n too, if for example UTF8
  codepoint $FF ($C3,$BF) is for technical reasons stored as "\u00ff"
  in the source text table, then indeed ($C3,$BF) is stored in T80 or
  T81-n and must be used when accessing that table

Implementation-specific parameters
----------------------------------

The hard limits of the range are "Q00" to "Q99".

An instance of extra validation is controlled by two values, namely
type and parameter. Extra validation can be applied to section headers
(Q30,Q31), y-index markers (Q39,Q40), x-index markers (Q49,Q50), and
any column of the table (Q66 with triples).

Q02 (boolean) use of stripping, if yes
    * Q03,Q04 (integer) range for size of the raw block, subrange
              of 32 ... 8'000'000 octet:s
    * Q05 (string) begin marker
    * Q06 (string) termination marker

Q08,Q09 (integer) size of the table content area,
        subrange of 32 ... 8'000'000 octet:s

Q11 (tristate) whether to pick extra line at begin with "minwidth"
    and "maxwidth" (obligatory, optional, disallowed)

Q13 minimal length of line "minwidth" :  2 ... 40'000 octet:s, before
    and after possible reduction, applies also to sections
Q14 maximal length of line "maxwidth" : 22 ... 80'000 octet:s, before
    and after possible reduction
Q15 minimal number of lines 2...10'000 (globally, not in section,
    and section headers do not count)
Q16 maximal number of lines 10...100'000 (globally, not in section,
    and section headers do not count)
Q17 minimal number of elements in a line : 1 ... 100
Q18 maximal number of elements in a line : 1 ... 10'000

Q20 (UINT8) end-of-line-character (EOL) : either 10 for LF or ZERO
Q21 (UINT8) separator between elements : 44 for comma "," (CSV)
    or semicolon ";" or wall "|"
Q22 (string) placeholder for "not found", 1 ... 20 octet:s,
    default "=", abuse of it gives E41

Q25,Q26 (integer) range for length of index markers, common for y-dimension
        and x-dimension, also applies to section headers if used,
        subrange of 2 ... 12 octet:s

Q28 (boolean) whether sections and section headers are used, if yes
    * Q29 sorting requirement S0 or S2 (S1 prohibited)
    * Q30,Q31 extra validation if desired, restricting allowable
              content (must be subset of Q25,Q26)
    (sections must not be used together with reverse access (Q56
    or Q62), sections must not be used together with sorting S1
    for y-index markers in Q37)

Q36 (enumeration of 3) whether y-index markers are to be
    used, values "Y2" to "Y4"
    if Y4
      * Q37 S1 or S2 (must be S2 if sections are used)
      * Q38 D digit or T text or B both
    if T text in Q38
      * Q39,Q40 extra validation if desired, restricting allowable
                content (must be subset of Q25,Q26), such as only
                UPPERcase, only lowercase, language code, ...

Q46 (enumeration of 4) whether x-index markers are to be
    used, values "X6" to "X9"
    if X9
      * Q47 S1 or S2
    if X7 to X9
      * Q48 D digit or T text or B both
    if T text in Q48
      * Q49,Q50 extra validation if desired, restricting allowable
                content (must be subset of Q25,Q26)

Q55 (enumeration of 3) dupe prevention level in left-most
    column, D1 or D2, also D0 possible if reverse access not needed
Q56 (boolean) whether reverse access via the left-most column
    is desired (NOT to be used together with Q28 sections)

Q60 (integer) other column of interest, column number >=1, ZERO if none
Q61 (enumeration of 3) dupe prevention level in that
    column, D1 or D2, also D0 possible if reverse access not needed
Q62 (boolean) whether reverse access via that column
    is desired (NOT to be used together with Q28 sections)

Q66 (table) extra validation of values in the table, triples (number
    of column <-> type of extra validation <-> parameter for extra
    validation), failure gives E66
Q67 (table) pluprocessing of values in the table, before they are
    stored into T76 T78 T80 T81, does NOT affect T75 and T77, triples
    (number of column <-> type of pluprocessing <-> parameter for
    pluprocessing), cannot give any error

Q70 (tristate) what types of request index string are supported (string
    indexing, numerical indexing, both)
Q72 (tristate) whether y-only requests are permitted (0 no, 1 boolean
    result, 2 complete line)
Q75 (boolean) whether prepocessing, if used, has to deliver
    an enumeration table T75
Q76 (boolean) whether prepocessing, if used, has to deliver
    a table y-index -> left-most column T76
Q77 (boolean) whether prepocessing, if used, has to deliver
    a table y-index -> complete line T77 (NOT pluprocessed by Q67)
Q78 (boolean) whether prepocessing, if used, has to deliver
    a table y-index -> subtable T78
Q80 (boolean) whether prepocessing, if used, has to deliver
    a table left-most column -> y-index T80
Q81 (boolean) whether prepocessing, if used, has to deliver
    a table other column of interest -> y-index T81-n, number
    of that column is in Q60

Errors
------

The hard limits of the range are "E03" to "Q79". Values 0, 1, 2
are reserved for other purposes: 0 is success, 1 is internal error
of the implementation outside of preprocessing, 2 is other error of
the implementation not covered by this specification such as target
not found.

The errors refer to possible faults in the incoming raw block. Above
listed parameters are assumed to be always valid and consistent. As a
last resort, E43 or E79 can be thrown in opposite case.

During full preprocessing:

E04 bad size before stripping (restricted by Q03 Q04)
E05 stripping failed or bad size after stripping (restricted by Q08 Q09)
E06 triple bracket ((( ))) [[[ ]]] found after stripping
E07 invalid char:s including TAB found after stripping

E09 leading or trailing spaces or line consisting of spaces only
E10 more than one subsequent empty line (does not apply at
    very top and very bottom outside of the table content area)
E11 last line does not end with EOL as defined by Q20
E12 bad length of line (restricted by Q13 Q14)

E14 "width"-line found and faulty

E16 section with no lines, if sections enabled
E17 line outside of section, if sections enabled
E18 line not identifiable as a valid type, also missing
    "[[" & "]]" if y-index markers are obligatory, or "[[" & "]]"
    found elsewhere than around y-index marker, still an undesirable
    y-index marker gives E24 instead

E19 section header found while sections NOT enabled by Q28
E20 section header is structurally faulty (restricted by
    Q25,Q26), not type text
E21 dupe with section header if sections enabled
E22 sorting violation with section header if sections enabled
    and sorting obligatory
E23 section header failed extra validation (restricted and
    defined by Q30,Q31)

E24 y-index marker found while NOT enabled by Q36
E25 y-index marker is structurally faulty (restricted by
    Q25,Q26), neither type text nor type digit
E26 y-index marker is structurally valid but its type is not
    permissible in given context
E27 dupe with y-index marker
E28 sorting violation with y-index marker
E29 y-index marker failed extra validation (restricted and
    defined by Q39,Q40)
E30 digit y-index marker mismatch with counting

E31 x-index marker found while NOT enabled by Q46
E32 x-index marker is structurally faulty (restricted by
    Q25,Q26), neither type text nor type digit
E33 x-index marker is structurally valid but its type is not
    permissible in given context
E34 dupe with x-index marker
E35 sorting violation with x-index marker
E36 x-index marker failed extra validation (restricted and
    defined by Q49,Q50)
E37 digit x-index marker mismatch with counting

E40 discovered an empty element, including missing final
    element after separator
E41 discovered an element literally equal placeholder
    for "not found" defined by Q22
E42 wrong number of elements in a line, restricted by Q17,Q18
E43 failed to extract separated values of a line for reasons
    other than E40 E41 E42

E46 wrong number of lines (restricted by Q15 and Q16, section
    headers do not count)

E50 dupe violation in left-most column, if restricted by Q55
E51 prohibited placeholder "-" found on "D2" in left-most
    column, if restricted by Q55
E52 no non-placeholder elements found in left-most
    column after whole table processed, if activated by Q80

E55 dupe violation in other column of interest,
    if enabled by Q60 and restricted by Q61
E56 prohibited placeholder "-" found on "D2" in other column of
    interest, if enabled by Q60 and restricted by Q61
E57 no non-placeholder elements found in other column of
    interest after whole table processed, if activated by Q81

E66 table element failed extra validation requested by Q66

E79 internal error of the implementation during preprocessing

Examples
--------

note the ("y","x") ie (line,column) order of indexes

--------------------

silly example, y-indexing is numerical (digit index markers used),
x-indexing is mixed (text index markers partially used)

[[00]] nol  , satu         , dua  , ((four)) tiga , empat , damn , - , 7
[[01]] nul  , unu          , du   , tri           , ((four)) kvar , kvin
[[02]] noll , ett          , tvaa , tre           , fyra
[[03]] zero , ((four)) one , two  , three         , four

element (0,2)       -> "dua"
element (0,"00003") -> "tiga"
element (0,"four")  -> "tiga" (this is silly and misleading but valid)
element (0,6)       -> "-"
element (3,5)       -> "=" (not found)

--------------------

y-indexing is numerical (index markers not used), x-indexing is
string / mixed (text index markers used)

((en)) zero , ((eo)) nul , ((id)) nol , ((sv)) noll
((en)) one , ((sv)) en/ett
((en)) two
((en)) three, ((id)) tiga

element (0,2)        -> "nol" (maybe not that useful to use
                               numerical x-index marker here)
element ("000","sv") -> "noll"
element (3,"id")     -> "tiga"
element (3,"sv")     -> "=" (not found)
element (0,0)        -> "zero" (less smart again)
element ("en",0)     -> "=" (not found)

--------------------

y-indexing is string (text index markers used), x-indexing is
numerical (x-index markers not used in the table)

[[en]] zero , one , two , three
[[eo]] nul , unu , du , tri
[[id]] nol , satu , dua , tiga
[[sv]] noll , en/ett , tvaa , tre

element ("en",0) -> "zero"
element ("en",4) -> "=" (not found)
element ("sv",3) -> "tre"

--------------------

y-indexing is string (text index markers used), x-indexing is
string (x-index markers partially used)

[[en]] zero , ((q1)) one , ((q2)) two , ((q7)) seven
[[sv]] noll , en/ett , tvaa , tre , - , - , - , sju

element ("en","q7") -> "seven"
element ("en",3) -> "seven"
element ("en",7) -> "=" (not found)
element ("sv",7) -> "sju"

--------------------

this table is invalid since the used digit index marker "((1))"
is not at least 2 char:s long

[[en]] zero , ((1)) three , four
[[sv]] noll , en/ett , tvaa , tre

--------------------

this table is invalid since the used digit index marker "((03))"
mismatches the effective counted index evaluating to 1

[[en]] zero , ((03)) three , four
[[sv]] noll , en/ett , tvaa , tre

--------------------

this table is valid since the digit index marker "((000000000001))"
matches the effective counted index evaluating to 1

[[en]] zero , ((000000000001)) three , four
[[sv]] noll , en/ett , tvaa , tre

element ("en","1")       -> "three" (misleading, numerical comparison)
element ("en","0000001") -> "three" (misleading, numerical comparison)
element ("en","0000000000001") -> "=" (not found, string
                                       "0000000000001" is too long)

--------------------

this table is valid since the index markers "((v03))" and "((v99))"
are of the text type and do not have to match the effective counted index

[[en]] zero , ((v03)) three
[[id]] nol , satu , dua , tiga , ((v99)) sembilan puluh sembilan

element ("id","3")    -> "tiga"
element ("id","99")   -> "=" (not found)
element ("id","v99")  -> "sembilan puluh sembilan"