The T-Regs Programming Language
T-Regs is a Next Generation Regular Expression Based Programming Language,
brought to you by the world leader in Next Generation Regular Expression Based Programming Languages.
T-Regs (Pronounced "T-Regs") stands for Text and Regular Expressions.
We feel strongly that free text is the most natural way of expressing one's thoughts.
Therefore T-Regs does away with the restrictions found in traditional programming languages and
is entirely based on free text. Free text which is conveniently manipulated by lots and lots of regular expressions.
Quick examples
Hello world
See, pretty straightforward. You can try this out right here.
10 /.*/Hello world!/
Subtracting 2 numbers
This is admittedly more advanced, but will become clear enough once you step through it in the online interpreter.
# Goto main program (skip functions)
1 /.*/$0;1000/
2 /^(.*?);(?<goto>1000)$/$1/
# Minus 1
# input: number;returnlabel;rest
# output: result;rest
10 /^(\d+)(;.*)$/$1;15$2/
15 /^(?<left>[1-9]\d*?-*)0(?=0*;)(?<right>.*(?<goto>15).*)/${left}-${right}/
20 /(\d*);15(;.*)/$1;0123456789$2/
25 /^(\d*)(?<lastDigit>\d)(?<lookup>-*;\d*(?<newLastDigit>\d)\2.*)(;.*)$/$1${newLastDigit}${lookup}$5/
30 /(\d*);\d+(;.*)/$1;35$2/
35 /-(?=-*;)(?<right>.*(?<goto>35).*)/9${right}/
40 /^0+([^0;])/$1/
45 /^(\d*);[^;]+;(?<goto>\d+)(;.*)$/$1$3/
# Main calculate "a - b" for positive integers
# infinite loop when b>9
1000 /^(\d+)\s*-\s*(\d+)$/$1;$2;0;1050/
1003 /^(\d+);([^0]\d*);\1;(?<goto>\d+)$/-$2/
1005 /^(\d+);(\d+);\2;(?<goto>\d+)$/$1/
1010 /^(\d+);(\d+).*$/10;$1;1020;$2/
1015 /^(?<goto>10);(.*)$/$2/
1020 /^(\d+);(\d+)$/10;$2;1040;$1/
1030 /^(?<goto>10);(.*)$/$2/
1040 /^(\d+);(\d+)$/$2-$1;1000/
1045 /^(\d+-\d+);(?<goto>\d+)$/$1/
1050 /^(\d+).*$/$1/
Learn more about the syntax
Taking it further
The T-Regs Language Commitee will soon set forth guidelines for the Certified T-Regs Programmer Initiative.
Follow @ProgramTRegs for further information.
The T-Regs Language Specification
Overview
T-Regs programs consist of lines of find and replace instructions,
which are applied to one body of text, which exists as long as the program runs.
This body of text is either input passed to the program on startup or an empty string if no input was defined.
When the program has executed its last line, this text is returned as output.
Syntax
Comments start with a hash.
# this is a comment
Code starts with a unique numeric label like this:
10 /.*/Hello World/
followed by a find regular expression
10 /.*/Hello World/
and a replace string.
10 /.*/Hello World/
These are separated by slashes
10 /.*/Hello World/
and optionally followed by flags
10 /^(?<greetings>h(a?i|ello)).*$/${greetings} world/in
Program flow
The lines in a program are executed in order of their numerical label.
The program
10 /.*/aaa/
30 /.*/bbb/
20 /.*/ccc/
will be executed in order 10, 20, 30 and as such result in bbb.
And then there was goto…
All looping and decision making is done using goto.
If a find has a named capture "goto", the program will attempt to jump to that label.
10 /.*/hello 40/
20 /(?<greeting>\w+) (?<goto>\d+)/${greeting}/
30 /.*/$0 cruel/
40 /.*/$0 world/
# output: "hello world"
In this example at label 20 the value "40" is captured with name goto and the program will jump to label 40 as a consequence.
Regular Expression Specifics
The Regex dialect
used in this implementation is the one as implemented by xregexp.
The important thing to know is that it has named captures which are used like this:
# given an input "3 + 4"
# outputs "4 + 3"
10 /^(?<left>\d+)(?<operator>\s*[-+\/*]\s*)(?<right>\d+)$/
${right}${operator}${left}/
But of course nameless captures are equally fine.
# given an input "3 + 4"
# outputs "4 + 3"
10 /^(\d+)(\s*[-+\/*]\s*)(\d+)$/$3$2$1/
Matching behaviour
By default the regular expression is case sensitive and applied only once
# input "aaaa"
10 /a/b/
# results in "baaa"
# input "AAAA"
10 /a/b/
# results in "AAAA"
By setting flags the matching behaviour can be modified.
g is for global
# input "aaaa"
10 /a/b/g
# results in "bbbb"
i is for ignore case
# input "AAAA"
10 /a/b/i
# results in "bAAA"
m is for multiline anchors
Which makes ^ and $ match at the begining and end of lines, rather than at the begining and end of the whole string.
So this:
# input "aa\naa"
10 /^a/b/gm
# results in "ba\nba
instead of this:
# input "aa\naa"
10 /^a/b/g
# results in "ba\naa"
n is for explicit capture
Making only named groups capturing groups.
In the following example the second group does not capture.
This is a great technique for writing highly performant T-Regs
and is widely used in enterprise applications.
10 /^(?<greetings>H(a?i|ello)).*$/${greetings} World/n
The above is basically a shorthand for this:
10 /^(?<greetings>H(?:a?i|ello)).*$/${greetings} World/
s is for singleline
where dot matches all characters, including linebreaks.
So we get this:
# input "aaa\nbbb"
10 /./c/gs
# results in "ccccccc"
Instead of this:
# input "aaa\nbbb"
10 /./c/g
# results in "ccc\nccc"
For more information on regular expressions we recommend
regular-expressions.info
T-Regs demonstration code
Hello world run
Observe T-Regs' concise syntax.
10 /.*/Hello world!/
Object Oriented T-Regs run
Being a modern language, T-Regs is absolutely multi paradigm and adapts well to an object-oriented programming style.
10 /"greetings"\s*:\s*"(?<greetings>[^"]+)"\s*,\s*"planet"\s*:\s*"(?<planet>[^"]+)"/"output" : "${greetings} ${planet}"/s
Palindrome checker run
T-Regs is exceptionally well suited for natural language processing tasks, as demonstrated here.
### Palindrome
10 /.*/$0;20;yes,no/
20 /^(?<ZeroOrOneCharacter>.?;.*(?<yes>yes))|(?<FirstSameAsLast>(.)(?<middle>.*)\4;(?<goto>20)(?<remainder>.*))|(?<NotAPalindrome>.*(?<no>no)).*$/${yes}${no}${middle};${goto}${remainder}/
30 /^(?<output>[^;]+);.*/${output}/
Conway's Game of Life run
T-Regs is gaining popularity in the scientific community. It has become to be recognized as a pragmatic tool for a wide variety of simulations. It's expressive power is illustrated here by this 13 line Game of Life implementation.
1 /^([^\n]+).*\n([^\n]+)$/$2\n$0\n$1/s
2 /^(.).*(.)$/$2$0$1/mg
3 /(#)|-/$0w$1W/g
4 /w(?=\W*W(?:\Ww\W*W\n?){0}#)/w#/gs
5 /w(?=\W*W(?:\Ww\W*W\n?){1}#)/w#/gs
6 /w(?=\W*W(?:\Ww\W*W\n?){41}#)/w#/gs
7 /w(?=\W*W(?:\Ww\W*W\n?){43}#)/w#/gs
8 /w(?=\W*W(?:\Ww\W*W\n?){83}#)/w#/gs
9 /w(?=\W*W(?:\Ww\W*W\n?){84}#)/w#/gs
10 /w(?=\W*W(?:\Ww\W*W\n?){85}#)/w#/gs
11 /\Ww(?:###|#(#))W(?=(?:\Ww\W*W\n?){42}\1)/#/gs
12 /\Ww#*W/-/g
13 /(?:\n[^\n]+){2}$|.{2}(?=\n|$)//gs
99 Bottles of beer run
T-Regs can hold up a conversation, while attentively commenting on real world events:
### 99 Bottles of beer
1 /.*/100/
2 /(?<goto>.*)//
# Minus 1
# input: number;returnlabel;rest
# output: result;rest
10 /^(\d+)/$1;15/
15 /^(?<left>[1-9]\d*?-*)0(?=0*;)(?<right>.*(?<goto>15).*)/${left}-${right}/
20 /(\d*);15(;.*)/$1;0123456789$2/
25 /^(\d*)(?<lastDigit>\d)(?<lookup>-*;\d*(?<newLastDigit>\d)\2.*)/$1${newLastDigit}${lookup}/
30 /(\d*);\d+/$1;35/
35 /-(?=-*;)(?<right>.*(?<goto>35).*)/9${right}/
40 /^0+([^0;])/$1/
45 /^(\d*);[^;]+;(?<goto>\d+)/$1/
# init at 99
100 /.*/98;01Nno more bottles;\n99 bottles of beer on the wall, 99 bottles of beer./
# add next line of lyrics
# input: number;rest
110 /^(?:(\d+)(;\k<1>1(N)(n)([^;]+))|(\d+)(;0\6N.*?( b[^s]+).)|(\d+)(;01N.*?( b[^;]+)));(.*)$/$1$6$9;10-110-150$2$7$10;$12\nTake one down and pass it around, $4$6$9$5$8$11 of beer on the wall.\n\n$3$6$9$5$8$11 of beer on the wall, $4$6$9$5$8$11 of beer./s
# if at 0, skip to end
120 /^0;\d+-\d+-(?<goto>\d+);/$0/
# minus 1 and goto print line
140 /^(\d+;)(?<goto>\d+)-(\d+)-\d+/$1$3/
150 /^[^\n]+\n(.*)/$1\nGo to the store and buy some more, 99 bottles of beer on the wall./s
Fibonacci sequence run
In T-Regs one can easily define custom libraries to solve advanced mathematical problems.
### Fibonacci
1 /.*/100;$0/
2 /(?<goto>\d+);//
# Main
100 /.*/500;1000;200;7;0 1/
110 /^(?<goto>\d+);//
# Add Fibonacci number
200 /^(?<return>\d+);(([ 0-9]+ )?(\d+) (\d+))/500;220;50;$4;$5;$2;${return}/
210 /^(?<goto>\d+);//
220 /^(\d+);([ 0-9]+);(?<goto>\d+)/${goto};$2 $1/
1000 ///
# Minus 1
# input: returnlabel;number;rest
# output: returnlabel;result;rest
10 /^(\d+);(\d+)(;.*)?$/$2;15;$1$3/
15 /^(?<left>[1-9]\d*?-*)0(?=0*;)(?<right>.*(?<goto>15).*)/${left}-${right}/
20 /(\d*);15(;.*)/$1;0123456789$2/
25 /^(\d*)(?<lastDigit>\d)(?<lookup>-*;\d*(?<newLastDigit>\d)\2.*)(;.*)$/$1${newLastDigit}${lookup}$5/
30 /(\d*);\d+(;.*)/$1;35$2/
35 /-(?=-*;)(?<right>.*(?<goto>35).*)/9${right}/
40 /^(\d*);[^;]+;(?<goto>\d+)(;.*)?$/$2;$1$3/
# Plus 1
# input: returnlabel;number;rest
# output: returnlabel;result;rest
50 /^(\d+);(\d+)(;.*)$/$2;0123456789;60;$1$3/
55 /^9+;/0$0/
60 /^(?<left>[0-8]\d*?-*)9(?=9*;)(?<right>.*(?<goto>60).*)/${left}-${right}/
65 /^(\d*)(?<lastDigit>\d)(?<lookup>-*;\d*\2(?<newLastDigit>\d).*)(;.*)$/$1${newLastDigit}${lookup}$5/
75 /(\d*);\d+;\d+(;.*)/$1;80$2/
80 /-(?=-*;)(?<right>.*(?<goto>80).*)/0${right}/
85 /^(\d*);[^;]+;(?<goto>\d+)(.*)$/$2;$1$3/
# repeatedly calls a function
# input: returnlabel;label;itterations;input for function
# output: ouput from function
# the function will get it's own exact output as input again, so should in- and out-put in the same format
# 1. initialize
500 /^(?<returnlabel>\d+);(?<label>\d+);(?<itterations>\d+);(?<rest>.*)$/${label};${rest};${itterations}-0;10-530-${label}-${returnlabel}/s
# 2. goto returnlabel if itterations == 0
510 /^(\d+);(?<result>.*?);(?<itterations>\d+)-\3;(\d+)-(\d+)-(\d+)-(?<goto>\d+)$/${result}/
# 3. itterations--
520 /^(.*);(?<itterations>\d+)-0;(?<goto>\d+)-(?<return>\d+)-(\d+)-(\d+)$/${return};${itterations};$0/
530 /^(\d+);(?<itterations>\d+);(.*);(\d+)(-0;)\d+-\d+(-\d+-\d+)$/$3;${itterations}${5}550$6/
# 4. call function
540 /^(?<goto>\d+);(?<arguments>.*;(?<return>\d+)-\d+-\d+)$/${return};${arguments}/
550 /^\d+;(?<arguments>.*);(?<itterations>\d+)-0;\d+-(?<label>\d+)-(?<return>\d+)$/500;${return};${label};${itterations};${arguments}/
560 /^(?<goto>\d+);//
Prime numbers run
This is left as an exercise for the reader.
Challenge! a Quine has not yet been written
# ...
About
T-Regs was designed by @mathiasbaert and fits in a long tradition of Esoteric Programming Languages of which is said
Some languages are designed to solve a problem.
Others are designed to prove a point.
— Dennis M. Ritchie
Thanks
Several existing libraries made this implementation rather easy.
- The extended Regular Expressions syntax was delivered by the excellent xregexp by Steven Levithan.
- The beautiful editor is CodeMirror by Marijn Haverbeke.
Prior art
T-Regs is not the first language to be based on regular expressions.
Several different approaches can be found for instance on the esolangs wiki
like
RegexPL and
Thutu
(which added regular expressions to Thue's mechanism of computation through text replacement).
Compared to these languages T-Regs stays very close to plain regular expressions.
T-Regs is not intentionally hard or unreadable,
but to the contrary is trying to be as practical as possible.
Given of course, that you want to do general purpose programming through text manipulation.