Project P024

Bracket checker

Checks the round, square and curly brackets of a typed text of up to 20 lines: the first error with its line, column and reason - a bracket that closes nothing, one of the wrong kind, or one never closed - the deepest nesting, and an outline of the text broken at its brackets.

3 modules · 2 recorded sessionstext-menu UI in the terminalupdated 2026-10-05

Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.

About

Checks the round, square and curly brackets of a typed text of up to 20 lines. It finds the first error and says where it is and why: a closing bracket with nothing to close, a closing bracket of the wrong kind, or brackets still open when the text ends. For a text whose brackets all match, it gives the number of pairs of each kind and the deepest nesting, and it can outline the text by its brackets.

  • main.eml - the menu, reading the lines of a text, and what the screen shows
  • brackets.eml - the scan for the first error and the deepest nesting, and the outline
  • text.eml - trimming, spaces, lists in words and plurals

How each part works:

  • The scan: every opening bracket goes on a stack with its line and column. A closing bracket must match the bracket on top of the stack, which it removes. The first one that does not - because the stack is empty, or because the top is another kind - is the error; the line is shown with a caret under the column. Brackets still on the stack at the end were never closed: they are listed outermost first (five at most, then "and N more"), with the closing brackets they need, innermost first.
  • The deepest nesting is the stack's greatest height, with the line and column of the bracket that first reached it.
  • The outline joins the lines with spaces and breaks the text after every opening bracket and before every closing one, indenting each piece two spaces per level. An empty pair such as () or [] stays where it is.

What is checked: a text is 1 to 20 lines, ended by an empty line (or a line of spaces); a line longer than 120 characters is asked for again; at 20 lines the text ends by itself. The outline needs every bracket matched. A menu choice other than 1, 2 or 3 is asked again.

Sessions: sessions/basic.in checks a three-line if block (6 pairs, deepest nesting 3), outlines a JSON object with nested lists and objects, finds print(a[1)] closing a [ with ), finds a ( and a [ left open at the end of a function, and outlines a while loop; sessions/bad-input.in types menu choices that are not 1 to 3, empty texts, a ) with nothing to close, text with no brackets to check or to outline, a mismatch where an outline was asked for, seven nested pairs, a line of 121 characters, six brackets never closed, and 20 lines.

Built on the verified corpus cases balanced-brackets-checker (a list used as a stack: push on an opener, compare and pop on a closer) and bracket-tree-outline (a bracketed text shown as an indented outline).

Recorded sessions

What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.

bad-input

interpreter: byte-equal

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 7
Pick 1, 2 or 3.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> hello
Pick 1, 2 or 3.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> 
No text.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> 
No text.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> a = b)
> 
Line 1, column 6: ')' has nothing to close.
  1 | a = b)
    |      ^

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> just words, no brackets
> here either
> 
No brackets in 2 lines.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> plain text
> 
No brackets to outline.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> ((a + b) * [c - d}
> 
Line 1, column 18: '}' does not match the '[' opened at line 1, column 12.
  1 | ((a + b) * [c - d}
    |                  ^
The outline needs every bracket matched.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> (((((((x)))))))
> 
(
  (
    (
      (
        (
          (
            (
              x
            )
          )
        )
      )
    )
  )
)

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
That line has 121 characters; a line can have at most 120. Type it again.
> short (line)
> 
1 line, 1 pair of brackets: 1 ( ).
Deepest nesting: 1, first reached at line 1, column 7.
Every bracket is closed, in the right order.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> {a
> [b
> (c
> {d
> [e
> (f
> 
End of text: 6 brackets are never closed - '{' at line 1, column 1, '[' at line 2, column 1, '(' at line 3, column 1, '{' at line 4, column 1, '[' at line 5, column 1 and 1 more.
Add )]})]} to close them, innermost first.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> x1 = (1)
> x2 = (2)
> x3 = (3)
> x4 = (4)
> x5 = (5)
> x6 = (6)
> x7 = (7)
> x8 = (8)
> x9 = (9)
> x10 = (10)
> x11 = (11)
> x12 = (12)
> x13 = (13)
> x14 = (14)
> x15 = (15)
> x16 = (16)
> x17 = (17)
> x18 = (18)
> x19 = (19)
> x20 = (20)
That is 20 lines, the most a text can have.
20 lines, 20 pairs of brackets: 20 ( ).
Deepest nesting: 1, first reached at line 1, column 6.
Every bracket is closed, in the right order.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
>    
No text.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 3
Bye.
What was typed (58 lines)
7
hello
1

2

1
a = b)

1
just words, no brackets
here either

2
plain text

2
((a + b) * [c - d}

2
(((((((x)))))))

1
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
short (line)

1
{a
[b
(c
{d
[e
(f

1
x1 = (1)
x2 = (2)
x3 = (3)
x4 = (4)
x5 = (5)
x6 = (6)
x7 = (7)
x8 = (8)
x9 = (9)
x10 = (10)
x11 = (11)
x12 = (12)
x13 = (13)
x14 = (14)
x15 = (15)
x16 = (16)
x17 = (17)
x18 = (18)
x19 = (19)
x20 = (20)
2
   
3

basic

interpreter: byte-equal

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> if (total > limit[0]) {
>   report(items[i], {name: "x"})
> }
> 
3 lines, 6 pairs of brackets: 2 ( ), 2 [ ] and 2 { }.
Deepest nesting: 3, first reached at line 2, column 15.
Every bracket is closed, in the right order.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> {"name": "Ana", "tags": ["a", "b"], "box": {"w": 2, "h": [1, 2]}, "none": []}
> 
{
  "name": "Ana", "tags": [
    "a", "b"
  ], "box": {
    "w": 2, "h": [
      1, 2
    ]
  }, "none": []
}

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> print(a[1)]
> 
Line 1, column 10: ')' does not match the '[' opened at line 1, column 8.
  1 | print(a[1)]
    |          ^

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 1
Type the text one line at a time (at most 20 lines); an empty line ends it.
> def f(x):
>   return g(x, [1, 2
> 
End of text: 2 brackets are never closed - '(' at line 2, column 11 and '[' at line 2, column 15.
Add ]) to close them, innermost first.

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 2
Type the text one line at a time (at most 20 lines); an empty line ends it.
> while (n > 0) { total = total + f(n, [n - 1]); n = n - 1 }
> 
while (
  n > 0
) {
  total = total + f(
    n, [
      n - 1
    ]
  ); n = n - 1
}

== Bracket checker ==
1) check a text  2) outline a text  3) quit
choice> 3
Bye.
What was typed (19 lines)
1
if (total > limit[0]) {
  report(items[i], {name: "x"})
}

2
{"name": "Ana", "tags": ["a", "b"], "box": {"w": 2, "h": [1, 2]}, "none": []}

1
print(a[1)]

1
def f(x):
  return g(x, [1, 2

2
while (n > 0) { total = total + f(n, [n - 1]); n = n - 1 }

3

Modules

The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.

main.eml(entry)

eml
# P024 bracket checker: the first bracket error in a text, with its line and
# column, the deepest nesting, and an outline of the text by its brackets.
import brackets
import text

20 => most_lines
120 => widest_line

def read_text():
    # Lines until an empty one: at most most_lines, each at most widest_line
    # characters. Columns count from the start of a line as typed.
    ("Type the text one line at a time (at most " + str(most_lines) + " lines); an empty line ends it.") ^0
    [] => lines
    while len(lines) < most_lines:
        input("> ") => line
        if text.trim(line) == "":
            return lines
        if len(line) > widest_line:
            ("That line has " + str(len(line)) + " characters; a line can have at most " + str(widest_line) + ". Type it again.") ^0
        else:
            lines + [line] => lines
    ("That is " + str(most_lines) + " lines, the most a text can have.") ^0
    return lines

def where(line_no, col):
    return "line " + str(line_no) + ", column " + str(col)

def show_at(lines, line_no, col):
    # The line, numbered, with a caret under the column.
    str(line_no) => num
    ("  " + num + " | " + lines[line_no - 1]) ^0
    ("  " + text.spaces(len(num)) + " | " + text.spaces(col - 1) + "^") ^0

def pair_kinds(pairs):
    [] => parts
    ["( )", "[ ]", "{ }"] => shapes
    for k in [0:2]:
        if pairs[k] > 0:
            parts + [str(pairs[k]) + " " + shapes[k]] => parts
    return text.listed(parts)

def report(lines, r):
    # Shows a scan result; True when every bracket matched.
    if r[0] == "stray":
        ("Line " + str(r[1]) + ", column " + str(r[2]) + ": '" + r[3] + "' has nothing to close.") ^0
        show_at(lines, r[1], r[2])
        return False
    if r[0] == "mismatch":
        ("Line " + str(r[1]) + ", column " + str(r[2]) + ": '" + r[3] + "' does not match the '" + r[4] + "' opened at " + where(r[5], r[6]) + ".") ^0
        show_at(lines, r[1], r[2])
        return False
    if r[0] == "unclosed":
        r[1] => still_open
        if len(still_open) == 1:
            ("End of text: the '" + still_open[0][0] + "' opened at " + where(still_open[0][1], still_open[0][2]) + " is never closed.") ^0
            ("Add " + brackets.still_to_close(still_open) + " to close it.") ^0
        else:
            [] => named
            for o in still_open:
                if len(named) < 5:
                    named + ["'" + o[0] + "' at " + where(o[1], o[2])] => named
            if len(still_open) > 5:
                named + [str(len(still_open) - 5) + " more"] => named
            ("End of text: " + str(len(still_open)) + " brackets are never closed - " + text.listed(named) + ".") ^0
            ("Add " + brackets.still_to_close(still_open) + " to close them, innermost first.") ^0
        return False
    r[1] => pairs
    pairs[0] + pairs[1] + pairs[2] => total
    if total == 0:
        ("No brackets in " + text.plural(len(lines), "line") + ".") ^0
    else:
        (text.plural(len(lines), "line") + ", " + text.plural(total, "pair") + " of brackets: " + pair_kinds(pairs) + ".") ^0
        ("Deepest nesting: " + str(r[2]) + ", first reached at " + where(r[3], r[4]) + ".") ^0
        "Every bracket is closed, in the right order." ^0
    return True

True => running
while running:
    "" ^0
    "== Bracket checker ==" ^0
    "1) check a text  2) outline a text  3) quit" ^0
    text.trim(input("choice> ")) => choice
    if choice == "1":
        read_text() => lines
        if len(lines) == 0:
            "No text." ^0
        else:
            report(lines, brackets.scan(lines)) => ok
    elif choice == "2":
        read_text() => lines
        if len(lines) == 0:
            "No text." ^0
        else:
            brackets.scan(lines) => r
            if r[0] != "ok":
                report(lines, r) => ok
                "The outline needs every bracket matched." ^0
            elif r[1][0] + r[1][1] + r[1][2] == 0:
                "No brackets to outline." ^0
            else:
                for line in brackets.outline(lines):
                    line ^0
    elif choice == "3":
        False => running
    else:
        "Pick 1, 2 or 3." ^0
"Bye." ^0
Python projection (main.py)
import brackets
import text
most_lines = 20
widest_line = 120

def read_text():
    print("Type the text one line at a time (at most " + str(most_lines) + " lines); an empty line ends it.")
    lines = []
    while len(lines) < most_lines:
        line = input("> ")
        if text.trim(line) == "":
            return lines
        if len(line) > widest_line:
            print("That line has " + str(len(line)) + " characters; a line can have at most " + str(widest_line) + ". Type it again.")
        else:
            lines = lines + [line]
    print("That is " + str(most_lines) + " lines, the most a text can have.")
    return lines

def where(line_no, col):
    return "line " + str(line_no) + ", column " + str(col)

def show_at(lines, line_no, col):
    num = str(line_no)
    print("  " + num + " | " + lines[line_no - 1])
    print("  " + text.spaces(len(num)) + " | " + text.spaces(col - 1) + "^")

def pair_kinds(pairs):
    parts = []
    shapes = ["( )", "[ ]", "{ }"]
    for k in range(0, 3):
        if pairs[k] > 0:
            parts = parts + [str(pairs[k]) + " " + shapes[k]]
    return text.listed(parts)

def report(lines, r):
    if r[0] == "stray":
        print("Line " + str(r[1]) + ", column " + str(r[2]) + ": '" + r[3] + "' has nothing to close.")
        show_at(lines, r[1], r[2])
        return False
    if r[0] == "mismatch":
        print("Line " + str(r[1]) + ", column " + str(r[2]) + ": '" + r[3] + "' does not match the '" + r[4] + "' opened at " + where(r[5], r[6]) + ".")
        show_at(lines, r[1], r[2])
        return False
    if r[0] == "unclosed":
        still_open = r[1]
        if len(still_open) == 1:
            print("End of text: the '" + still_open[0][0] + "' opened at " + where(still_open[0][1], still_open[0][2]) + " is never closed.")
            print("Add " + brackets.still_to_close(still_open) + " to close it.")
        else:
            named = []
            for o in still_open:
                if len(named) < 5:
                    named = named + ["'" + o[0] + "' at " + where(o[1], o[2])]
            if len(still_open) > 5:
                named = named + [str(len(still_open) - 5) + " more"]
            print("End of text: " + str(len(still_open)) + " brackets are never closed - " + text.listed(named) + ".")
            print("Add " + brackets.still_to_close(still_open) + " to close them, innermost first.")
        return False
    pairs = r[1]
    total = pairs[0] + pairs[1] + pairs[2]
    if total == 0:
        print("No brackets in " + text.plural(len(lines), "line") + ".")
    else:
        print(text.plural(len(lines), "line") + ", " + text.plural(total, "pair") + " of brackets: " + pair_kinds(pairs) + ".")
        print("Deepest nesting: " + str(r[2]) + ", first reached at " + where(r[3], r[4]) + ".")
        print("Every bracket is closed, in the right order.")
    return True

running = True
while running:
    print("")
    print("== Bracket checker ==")
    print("1) check a text  2) outline a text  3) quit")
    choice = text.trim(input("choice> "))
    if choice == "1":
        lines = read_text()
        if len(lines) == 0:
            print("No text.")
        else:
            ok = report(lines, brackets.scan(lines))
    elif choice == "2":
        lines = read_text()
        if len(lines) == 0:
            print("No text.")
        else:
            r = brackets.scan(lines)
            if r[0] != "ok":
                ok = report(lines, r)
                print("The outline needs every bracket matched.")
            elif r[1][0] + r[1][1] + r[1][2] == 0:
                print("No brackets to outline.")
            else:
                for line in brackets.outline(lines):
                    print(line)
    elif choice == "3":
        running = False
    else:
        print("Pick 1, 2 or 3.")
print("Bye.")

brackets.eml

eml
# P024 bracket checker - walking the brackets of a text: the first error, the
# deepest nesting, and an outline that breaks the text at its brackets.

def closer_for(c):
    # The bracket that closes c, or "" if c does not open one.
    if c == "(":
        return ")"
    if c == "[":
        return "]"
    if c == "{":
        return "}"
    return ""

def opener_for(c):
    # The bracket that c closes, or "" if c does not close one.
    if c == ")":
        return "("
    if c == "]":
        return "["
    if c == "}":
        return "{"
    return ""

def kind_index(c):
    # 0 for round, 1 for square, 2 for curly; c is an opening bracket.
    if c == "(":
        return 0
    if c == "[":
        return 1
    return 2

def scan(lines):
    # Every bracket in order, kept on a stack of [bracket, line, column]. The
    # result is one of:
    #   ["ok", pairs, deepest, line, column] - every bracket matched; pairs
    #       counts round, square and curly pairs, and the deepest nesting is
    #       first reached at line, column (both 0 when there are no brackets)
    #   ["stray", line, column, closer] - a closing bracket with nothing open
    #   ["mismatch", line, column, closer, opener, its line, its column]
    #   ["unclosed", stack] - the text ends with these still open, outermost
    #       first
    [] => stack
    [0, 0, 0] => pairs
    0 => deepest
    0 => deep_line
    0 => deep_col
    0 => li
    while li < len(lines):
        lines[li] => line
        0 => ci
        while ci < len(line):
            line[ci] => c
            if closer_for(c) != "":
                stack + [[c, li + 1, ci + 1]] => stack
                if len(stack) > deepest:
                    len(stack) => deepest
                    li + 1 => deep_line
                    ci + 1 => deep_col
            elif opener_for(c) != "":
                if len(stack) == 0:
                    return ["stray", li + 1, ci + 1, c]
                stack[len(stack) - 1] => top
                if top[0] != opener_for(c):
                    return ["mismatch", li + 1, ci + 1, c, top[0], top[1], top[2]]
                pairs[kind_index(top[0])] + 1 => pairs[kind_index(top[0])]
                stack[0:len(stack) - 1] => stack
            ci + 1 => ci
        li + 1 => li
    if len(stack) > 0:
        return ["unclosed", stack]
    return ["ok", pairs, deepest, deep_line, deep_col]

def still_to_close(stack):
    # The closing brackets the open ones need, innermost first: "])}".
    "" => out
    len(stack) - 1 => i
    while i >= 0:
        out + closer_for(stack[i][0]) => out
        i - 1 => i
    return out

def trimmed(s):
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def next_solid(s, i):
    # The first position from i on that is not a space (len(s) if none).
    while i < len(s) and s[i] == " ":
        i + 1 => i
    return i

def outline(lines):
    # The text, its lines joined by spaces, broken after every opening bracket
    # and before every closing one, each piece indented two spaces per level.
    # An empty pair such as () stays where it is. Only for text whose brackets
    # all match.
    "" => s
    for line in lines:
        if s != "":
            s + " " => s
        s + line => s
    [] => out
    "" => piece
    0 => depth
    0 => i
    while i < len(s):
        s[i] => c
        if closer_for(c) != "":
            next_solid(s, i + 1) => j
            if j < len(s) and opener_for(s[j]) != "":
                piece + s[i:j + 1] => piece
                j + 1 => i
            else:
                out + ["  " * depth + trimmed(piece + c)] => out
                "" => piece
                depth + 1 => depth
                i + 1 => i
        elif opener_for(c) != "":
            if trimmed(piece) != "":
                out + ["  " * depth + trimmed(piece)] => out
            depth - 1 => depth
            c => piece
            i + 1 => i
        else:
            if not (c == " " and piece == ""):
                piece + c => piece
            i + 1 => i
    if trimmed(piece) != "":
        out + ["  " * depth + trimmed(piece)] => out
    return out
Python projection (brackets.py)
def closer_for(c):
    if c == "(":
        return ")"
    if c == "[":
        return "]"
    if c == "{":
        return "}"
    return ""

def opener_for(c):
    if c == ")":
        return "("
    if c == "]":
        return "["
    if c == "}":
        return "{"
    return ""

def kind_index(c):
    if c == "(":
        return 0
    if c == "[":
        return 1
    return 2

def scan(lines):
    stack = []
    pairs = [0, 0, 0]
    deepest = 0
    deep_line = 0
    deep_col = 0
    li = 0
    while li < len(lines):
        line = lines[li]
        ci = 0
        while ci < len(line):
            c = line[ci]
            if closer_for(c) != "":
                stack = stack + [[c, li + 1, ci + 1]]
                if len(stack) > deepest:
                    deepest = len(stack)
                    deep_line = li + 1
                    deep_col = ci + 1
            elif opener_for(c) != "":
                if len(stack) == 0:
                    return ["stray", li + 1, ci + 1, c]
                top = stack[len(stack) - 1]
                if top[0] != opener_for(c):
                    return ["mismatch", li + 1, ci + 1, c, top[0], top[1], top[2]]
                pairs[kind_index(top[0])] = pairs[kind_index(top[0])] + 1
                stack = stack[0:len(stack) - 1]
            ci = ci + 1
        li = li + 1
    if len(stack) > 0:
        return ["unclosed", stack]
    return ["ok", pairs, deepest, deep_line, deep_col]

def still_to_close(stack):
    out = ""
    i = len(stack) - 1
    while i >= 0:
        out = out + closer_for(stack[i][0])
        i = i - 1
    return out

def trimmed(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def next_solid(s, i):
    while i < len(s) and s[i] == " ":
        i = i + 1
    return i

def outline(lines):
    s = ""
    for line in lines:
        if s != "":
            s = s + " "
        s = s + line
    out = []
    piece = ""
    depth = 0
    i = 0
    while i < len(s):
        c = s[i]
        if closer_for(c) != "":
            j = next_solid(s, i + 1)
            if j < len(s) and opener_for(s[j]) != "":
                piece = piece + s[i:j + 1]
                i = j + 1
            else:
                out = out + ["  " * depth + trimmed(piece + c)]
                piece = ""
                depth = depth + 1
                i = i + 1
        elif opener_for(c) != "":
            if trimmed(piece) != "":
                out = out + ["  " * depth + trimmed(piece)]
            depth = depth - 1
            piece = c
            i = i + 1
        else:
            if not (c == " " and piece == ""):
                piece = piece + c
            i = i + 1
    if trimmed(piece) != "":
        out = out + ["  " * depth + trimmed(piece)]
    return out

text.eml

eml
# P024 bracket checker - small text helpers. The interpreter that checks every
# session does not run string methods yet, so these are written out here.

def trim(s):
    # s without the spaces at either end.
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def spaces(n):
    return " " * n

def listed(items):
    # ["a", "b", "c"] as "a, b and c".
    "" => out
    0 => i
    while i < len(items):
        if i > 0 and i == len(items) - 1:
            out + " and " => out
        elif i > 0:
            out + ", " => out
        out + items[i] => out
        i + 1 => i
    return out

def plural(n, word):
    if n == 1:
        return "1 " + word
    return str(n) + " " + word + "s"
Python projection (text.py)
def trim(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def spaces(n):
    return " " * n

def listed(items):
    out = ""
    i = 0
    while i < len(items):
        if i > 0 and i == len(items) - 1:
            out = out + " and "
        elif i > 0:
            out = out + ", "
        out = out + items[i]
        i = i + 1
    return out

def plural(n, word):
    if n == 1:
        return "1 " + word
    return str(n) + " " + word + "s"

Built on these corpus cases

ΣEML 2026

Efficient New Language — a high-density semantic overlay for humans and AI agents.

This site’s demos run on the real EML toolchain, in your browser.

© 2026 EveMissLab (一言諾科技有限公司) / Neo.K. All rights reserved.