commit
e840718997
32 changed files with 11087 additions and 0 deletions
@ -0,0 +1,23 @@
|
||||
all: t0 t.elf |
||||
|
||||
t0: t.c t.t |
||||
cc -static -o t0 t.c
|
||||
|
||||
t.elf: test |
||||
cp t3 t.elf
|
||||
|
||||
test: t0 |
||||
touch t1 t2 t3; chmod +x t1 t2 t3
|
||||
./t0 <t.t >t1 && ./t1 <t.t >t2 && ./t2 <t.t >t3 && cmp t2 t3
|
||||
|
||||
mksums: clean |
||||
ls | grep -v t3x9.tgz | grep -v _csums | csum -m >_csums
|
||||
|
||||
csums: |
||||
csum -u <_csums >_csums.new && mv -f _csums.new _csums
|
||||
|
||||
clean: |
||||
rm -f t0 t1 t2 t3 a.out dump *.o *.core t3x9.tgz
|
||||
|
||||
arc: clean |
||||
(cd ..; tar cvf - t3x9 | gzip -9 >t3x9.tgz); mv -f ../t3x9.tgz .
|
@ -0,0 +1,20 @@
|
||||
|
||||
This is the T3X9 compiler, as described in the book |
||||
|
||||
"Write Your Own Compiler" |
||||
by Nils M Holm |
||||
|
||||
More details about the book can be found at T3X.ORG. |
||||
|
||||
To compile the compiler on FreeBSD, just do |
||||
|
||||
chmod +x t.elf && ./t.elf <t.t >t.new |
||||
|
||||
To compile it on any system providing a C89 compiler: |
||||
|
||||
cc -o t0 t.c && ./t0 <t.t >t.new |
||||
|
||||
NOTE: some patches have been applied to the compiler since |
||||
publication. The source code in the "t.t" file reflects the |
||||
latest patchlevel. Patches are contained in the files t.pl?. |
||||
|
@ -0,0 +1,14 @@
|
||||
41114 1 Makefile |
||||
50469 1 README |
||||
14051 1 dump.c |
||||
15789 26 t.c |
||||
55434 31 t.elf |
||||
16731 1 t.pl1 |
||||
41318 1 t.pl2 |
||||
55592 1 t.pl3 |
||||
47836 1 t.pl4 |
||||
9277 28 t.t |
||||
39214 3 t3x-history.txt |
||||
45560 3 t3x.bnf |
||||
58677 17 t3x.txt |
||||
50723 1 test.t |
@ -0,0 +1,21 @@
|
||||
#include <stdio.h> |
||||
|
||||
#define Z 65536 |
||||
#define byte unsigned char |
||||
|
||||
byte T[Z]; |
||||
|
||||
int main(void) { |
||||
int k, i; |
||||
|
||||
k = fread(T, 1, Z, stdin); |
||||
printf(".byte "); |
||||
for (i=0x74; i<k; i++) { |
||||
if (i % 10 == 0) |
||||
printf("\n.byte "); |
||||
printf("0x%02x", T[i]); |
||||
if ((i+1) % 10 != 0 && i+1 < k) |
||||
printf(","); |
||||
} |
||||
printf("\n"); |
||||
} |
Binary file not shown.
@ -0,0 +1,30 @@
|
||||
--- t.t.old 2017-05-18 10:13:35.000000000 +0200 |
||||
+++ t.t 2017-05-18 10:14:16.000000000 +0200 |
||||
@@ -1217,7 +1217,7 @@ |
||||
gen(CG_JMPFALSE, 0); |
||||
xrparen(); |
||||
stmt(); |
||||
- ie (alt) do |
||||
+ if (alt) do |
||||
gen(CG_JUMPFWD, 0); |
||||
swap(); |
||||
gen(CG_RESOLV, 0); |
||||
@@ -1225,9 +1225,6 @@ |
||||
T := scan(); |
||||
stmt(); |
||||
end |
||||
- else if (T = KELSE) do |
||||
- aw("ELSE without IE", 0); |
||||
- end |
||||
gen(CG_RESOLV, 0); |
||||
end |
||||
|
||||
@@ -1370,6 +1367,8 @@ |
||||
if_stmt(1); |
||||
else ie (T = KIF) |
||||
if_stmt(0); |
||||
+ else ie (T = KELSE) |
||||
+ aw("ELSE without IE", 0); |
||||
else ie (T = KLEAVE) |
||||
leave_stmt(); |
||||
else ie (T = KLOOP) |
@ -0,0 +1,11 @@
|
||||
--- t.t.old 2017-05-23 10:43:30.000000000 +0200 |
||||
+++ t.t 2017-05-23 10:43:50.000000000 +0200 |
||||
@@ -906,6 +906,8 @@ |
||||
fncall(fn) do var i; |
||||
T := scan(); |
||||
if (fn = 0) aw("call of non-function", 0); |
||||
+ if (fn[SFLAGS] & (FUNC|FORW) = 0) |
||||
+ aw("call of non-function", fn[SNAME]); |
||||
i := 0; |
||||
while (T \= RPAREN) do |
||||
expr(0); |
@ -0,0 +1,23 @@
|
||||
--- t.t.old 2018-03-22 08:59:31.000000000 +0100 |
||||
+++ t.t 2018-03-22 09:01:22.000000000 +0100 |
||||
@@ -1389,15 +1389,18 @@ |
||||
else |
||||
expect(%1, "statement"); |
||||
|
||||
-compound() do var oyp, olp, onp; |
||||
+compound() do var oyp, olp, onp, msg; |
||||
+ msg := "unexpected end of compound statement"; |
||||
T := scan(); |
||||
oyp := Yp; |
||||
onp := Np; |
||||
olp := Lp; |
||||
while (T = KVAR \/ T = KCONST \/ T = KSTRUCT) |
||||
declaration(0); |
||||
- while (T \= KEND) |
||||
+ while (T \= KEND) do |
||||
+ if (T = ENDFILE) aw(msg, 0); |
||||
stmt(); |
||||
+ end |
||||
T := scan(); |
||||
if (olp-Lp \= 0) |
||||
gen(CG_DEALLOC, olp-Lp); |
@ -0,0 +1,23 @@
|
||||
--- t.t.old 2019-07-20 12:04:34.000000000 +0200 |
||||
+++ t.t 2019-07-20 12:03:27.000000000 +0200 |
||||
@@ -1510,9 +1510,9 @@ |
||||
tfill := "8b7c240c8b4424088b4c2404fcf3aa31c0c3"; |
||||
tscan := |
||||
"8b7c240c8b4424088b4c24044189fafcf2ae09c90f840600000089f829d048c331c048c3"; |
||||
- Ops := [[ 7, 1, "mod", BINOP, CG_MOD ], |
||||
+ Ops := [[ 7, 3, "mod", BINOP, CG_MOD ], |
||||
[ 6, 1, "+", BINOP, CG_ADD ], |
||||
- [ 7, 2, "*", BINOP, CG_MUL ], |
||||
+ [ 7, 1, "*", BINOP, CG_MUL ], |
||||
[ 0, 1, ";", SEMI, 0 ], |
||||
[ 0, 1, ",", COMMA, 0 ], |
||||
[ 0, 1, "(", LPAREN, 0 ], |
||||
@@ -1539,7 +1539,7 @@ |
||||
[ 5, 2, ">>", BINOP, CG_SHR ], |
||||
[ 6, 1, "-", BINOP, CG_SUB ], |
||||
[ 0, 2, "->", COND, 0 ], |
||||
- [ 7, 2, "/", BINOP, CG_DIV ], |
||||
+ [ 7, 1, "/", BINOP, CG_DIV ], |
||||
[ 2, 2, "/\\", CONJ, 0 ], |
||||
[ 0, 0, 0, 0, 0 ] ]; |
||||
Equal_op := findop("="); |
@ -0,0 +1,59 @@
|
||||
|
||||
A SHORT HISTORY OF THE T3X LANGUAGE |
||||
|
||||
T3X is a tiny block-structured language that you probably |
||||
haven't heard about. It had a tiny community back in the |
||||
mid-1990's. Software written in T3X includes its own compiler |
||||
(of course), its own text-based IDE, a few LISP interpreters, |
||||
an assembler and linker for the 8086, and a database system |
||||
used by a local church community. It was also used in a few |
||||
college courses, most probably because its community was so |
||||
tiny that nobody could be bothered to do your homework |
||||
assignments for you. |
||||
|
||||
The T3X language started as a very minimalistic language |
||||
with a single-file compiler that targeted the 8086 and 386 |
||||
processors. It supported FreeBSD via the GNU binutils and |
||||
emitted DOS EXE files through its own assembler and linker. |
||||
|
||||
In its lifetime, several enhancements were made to both the |
||||
language and its implementation: |
||||
|
||||
- An object system was added to the language, and the entire |
||||
runtime support infrastructure was rewritten as a set of |
||||
classes. |
||||
- Tcode, an abstract target language, was added. It could be |
||||
interpreted, optimized, linked, and converted to native |
||||
code. |
||||
- A back-end for the AXP 21064 (Alpha) was added. |
||||
- A C back-end was added, allowing to use T3X on otherwise |
||||
unsupported processors. |
||||
- Runtime support for the following platforms was added: |
||||
NetBSD-386, NetBSD-Alpha, FreeBSD-386, Coherent-386, |
||||
Linux-386, and Plan 9 (via C). |
||||
|
||||
T3X is probably notable, because it is a typeless object |
||||
oriented language. Objects are distinguished by the methods |
||||
they implement, and the methods are typeless procedures. |
||||
The T3X object system is more similar to ADA packages than |
||||
to the C++ or Java approach. It implements reusable modules |
||||
rather than data types. |
||||
|
||||
T3X-8.1.7 was the last version of T3X and it was released in |
||||
2004 with some minor updates in 2011 and 2014. Its generic |
||||
(Tcode) port still runs on modern operating systems. |
||||
|
||||
T3X9 is a subset of the T3X language that compiles directly |
||||
from T3X to ELF-FreeBSD-386. |
||||
|
||||
If you are familiar with T3X, this is what the compiler omits |
||||
from the original language: modules, objects, classes, packed |
||||
vectors, function pointers and indirect function calls, meta |
||||
commands, unsigned operators. Also, constant expression syntax |
||||
is only a subset. |
||||
|
||||
The T3X9 compiler is under 1600 lines in size and compiles |
||||
itself from source to ELF in about 0.06 seconds on a 750MHz |
||||
notebook computer. The resulting binary has a size of less |
||||
than 32K bytes. |
||||
|
@ -0,0 +1,221 @@
|
||||
%token SYMBOL, INTEGER, CHARACTER, STRING |
||||
%token VAR, CONST, STRUCT, DECL, DO, END |
||||
%token IF, IE, ELSE, WHILE, FOR, LEAVE, LOOP, |
||||
%token RETURN, HALT, MODULO |
||||
|
||||
%% |
||||
|
||||
Program: |
||||
Declarations CompoundStmt |
||||
; |
||||
|
||||
Declarations: |
||||
Declaration |
||||
| Declaration Declarations |
||||
; |
||||
|
||||
Declaration: |
||||
VAR VarList ';' |
||||
| CONST ConstList ';' |
||||
| DECL DeclList ';' |
||||
| STRUCT SYMBOL '=' StructMembers ';' |
||||
| FunctionDecl |
||||
; |
||||
|
||||
VarList: |
||||
SYMBOL |
||||
| SYMBOL '[' ConstValue ']' |
||||
| VarList ',' SYMBOL |
||||
; |
||||
|
||||
ConstList: |
||||
ConstDef |
||||
| ConstDef ',' ConstList |
||||
; |
||||
|
||||
ConstDef: |
||||
SYMBOL '=' ConstValue |
||||
; |
||||
|
||||
DeclList: |
||||
Decl |
||||
| Decl ',' DeclList |
||||
; |
||||
|
||||
Decl: |
||||
SYMBOL '(' ConstValue ')' |
||||
; |
||||
|
||||
StructMembers: |
||||
SYMBOL |
||||
| SYMBOL ',' StructMembers ';' |
||||
; |
||||
|
||||
FunctionDecl: |
||||
SYMBOL '(' OptFormalArgs ')' Statement |
||||
; |
||||
|
||||
OptFormalArgs: |
||||
| ArgumentList |
||||
; |
||||
|
||||
ArgumentList: |
||||
SYMBOL |
||||
| SYMBOL ',' ArgumentList |
||||
; |
||||
|
||||
Statement: |
||||
CompoundStmt |
||||
| SYMBOL ':=' Expression ';' |
||||
| SYMBOL Subscripts ':=' Expression ';' |
||||
| FunctionCall |
||||
| IF '(' Expression ')' Statement |
||||
| IE '(' Expression ')' Statement |
||||
ELSE Statement |
||||
| WHILE '(' Expression ')' Statement |
||||
| FOR '(' SYMBOL '=' Expression ',' |
||||
Expression ')' |
||||
Statement |
||||
| FOR '(' SYMBOL '=' Expression ',' |
||||
Expression, |
||||
ConstValue ')' |
||||
Statement |
||||
| LEAVE ';' |
||||
| LOOP ';' |
||||
| RETURN Expression ';' |
||||
| HALT ConstValue ';' |
||||
| ';' |
||||
; |
||||
|
||||
CompoundStmt: |
||||
DO END |
||||
| DO LocalDecls END |
||||
| DO StatementList END |
||||
| DO LocalDecls StatementList END |
||||
; |
||||
|
||||
LocalDecls: |
||||
LocalDecl |
||||
| LocalDecl LocalDecls |
||||
; |
||||
|
||||
LocalDecl: |
||||
VAR VarList ';' |
||||
| CONST ConstList ';' |
||||
| STRUCT SYMBOL '=' StructMembers ';' |
||||
; |
||||
|
||||
StatementList: |
||||
Statement |
||||
| Statement StatementList |
||||
; |
||||
|
||||
ExprList: |
||||
Expression |
||||
| Expression ',' ExprList |
||||
; |
||||
|
||||
Expression: |
||||
Disjunction |
||||
| Disjunction '->' Expression ':' Expression |
||||
; |
||||
|
||||
Disjunction: |
||||
Conjunction |
||||
| Conjunction '/\\' Disjunction |
||||
; |
||||
|
||||
Conjunction: |
||||
Equation |
||||
| Equation '\\/' Conjunction |
||||
; |
||||
|
||||
Equation: |
||||
Relation |
||||
| Relation '=' Equation |
||||
| Relation '\\=' Equation |
||||
; |
||||
|
||||
Relation: |
||||
BitOperation |
||||
| BitOperation '<' Relation |
||||
| BitOperation '>' Relation |
||||
| BitOperation '<=' Relation |
||||
| BitOperation '>=' Relation |
||||
; |
||||
|
||||
BitOperation: |
||||
Sum |
||||
| Sum '&' BitOperation |
||||
| Sum '|' BitOperation |
||||
| Sum '^' BitOperation |
||||
| Sum '<<' BitOperation |
||||
| Sum '>>' BitOperation |
||||
; |
||||
|
||||
Sum: |
||||
Term |
||||
| Term '+' Sum |
||||
| Term '-' Sum |
||||
; |
||||
|
||||
Term: |
||||
Factor |
||||
| Factor '*' Term |
||||
| Factor '/' Term |
||||
| Factor MODULO Term |
||||
; |
||||
|
||||
Factor: |
||||
INTEGER |
||||
| FunctionCall |
||||
| STRING |
||||
| Table |
||||
| SYMBOL |
||||
| SYMBOL Subscripts |
||||
| '@' SYMBOL |
||||
| '@' SYMBOL Subscripts |
||||
| '-' Factor |
||||
| '\\' Factor |
||||
| '~' Factor |
||||
| '(' Expression ')' |
||||
; |
||||
|
||||
Subscripts: |
||||
'[' Expression ']' |
||||
| '[' Expression ']' Subscripts |
||||
| '::' Factor |
||||
; |
||||
|
||||
Table: |
||||
'[' MemberList ']' |
||||
; |
||||
|
||||
MemberList: |
||||
TableMember |
||||
| TableMember ',' MemberList |
||||
; |
||||
|
||||
TableMember: |
||||
ConstValue |
||||
| STRING |
||||
| Table |
||||
| '(' ExprList ')' |
||||
; |
||||
|
||||
FunctionCall: |
||||
SYMBOL '(' ')' |
||||
| SYMBOL '(' ExprList ')' |
||||
; |
||||
|
||||
ConstValue: |
||||
SYMBOL |
||||
| Integer |
||||
; |
||||
|
||||
Integer: |
||||
INTEGER |
||||
| CHARACTER |
||||
; |
||||
%% |
||||
|
@ -0,0 +1,689 @@
|
||||
|
||||
|
||||
################# ############ ###### ###### |
||||
## ## ## ## ## ## ## ## |
||||
####### ####### ####### ## ## ### ## |
||||
## ## ## ## ## ## |
||||
## ## ####### ## ## ### ## |
||||
## ## ## ## ## ## ## ## |
||||
####### ############ ###### ###### |
||||
|
||||
------- A MINIMAL PROCEDURAL LANGUAGE -------- |
||||
|
||||
|
||||
PROGRAM |
||||
------- |
||||
|
||||
A program is a set of declarations followed by a compound |
||||
statement. Here is the minimal T3X program: |
||||
|
||||
DO END |
||||
|
||||
|
||||
COMMENTS |
||||
-------- |
||||
|
||||
A comment is started with an exclamation point (!) and extends |
||||
up to the end of the current line. Example: |
||||
|
||||
DO END ! Do nothing |
||||
|
||||
|
||||
DECLARATIONS |
||||
------------ |
||||
|
||||
CONST name = cvalue, ... ; |
||||
|
||||
Assign names to constant values. |
||||
|
||||
Example: CONST false = 0, true = %1; |
||||
|
||||
|
||||
VAR name, ... ; |
||||
VAR name[cvalue], ... ; |
||||
VAR name::cvalue, ... ; |
||||
|
||||
Define variables, vectors, and byte vectors, respectively. |
||||
Different definitions may be mixed. Vector elements start at |
||||
an index of 0. |
||||
|
||||
Example: VAR stack[STACK_LEN], ptr; |
||||
|
||||
|
||||
STRUCT name = name_1, ..., name_N; |
||||
|
||||
Shorthand for CONST name_1 = 0, ..., name_N = N-1, name = N; |
||||
Used to impose structure on vectors and byte vectors. |
||||
|
||||
Example: STRUCT POINT = PX, PY, PCOLOR; |
||||
VAR p[POINT]; |
||||
|
||||
|
||||
DECL name(cvalue), ... ; |
||||
|
||||
Declare functions whose definitions follow later, where the |
||||
cvalue is the number of arguments. Used to implement mutual |
||||
recursion. |
||||
|
||||
Example: DECL odd(1); |
||||
even(x) RETURN x=0-> 1: odd(x-1); |
||||
odd(x) RETURN x=1-> 1: even(x-1); |
||||
|
||||
|
||||
name(name_1, ...) statement |
||||
|
||||
Define function "name" with arguments "name_1", ... and a |
||||
statement as its body. The number of arguments must match |
||||
any previous DECL of the same function. |
||||
|
||||
The arguments of a function are only visible within the |
||||
(statement) of the function. |
||||
|
||||
Example: hello(s, x) DO VAR i; |
||||
FOR (i=0, x) DO |
||||
writes(s); |
||||
writes("\n"); |
||||
END |
||||
END |
||||
|
||||
(Writes() writes a string; it is defined later in this text.) |
||||
|
||||
|
||||
STATEMENTS |
||||
---------- |
||||
|
||||
name := expression; |
||||
|
||||
Assign the value of an expression to a variable. |
||||
|
||||
Example: DO VAR x; x := 123; END |
||||
|
||||
|
||||
name[value]... := value; |
||||
name::value := value; |
||||
|
||||
Assign the value of an expression to an element of a vector |
||||
or a byte vector. Multiple subscripts may be applied to to a |
||||
vector: |
||||
|
||||
vec[i][j]... := i*j; |
||||
|
||||
In general, VEC[i][j] denotes the j'th element of the i'th |
||||
element of VEC. |
||||
|
||||
Note that the :: operator is right-associative, so v::x::i |
||||
equals v::(x::i). This is particularly important when mixing |
||||
subscripts, because |
||||
|
||||
vec[i]::j[k] := 0; |
||||
|
||||
would assign 0 to the j[k]'th element of vec[i]. (This makes |
||||
sense, because vec[i]::j would not deliver a valid address.) |
||||
|
||||
|
||||
name(); |
||||
name(expression_1, ...); |
||||
|
||||
Call the function with the given name, passing the values of the |
||||
expressions to the function. An empty set of parentheses is used |
||||
to pass zero arguments. The result of the function is discarded. |
||||
|
||||
For further details see the description of function calls in the |
||||
expression section. |
||||
|
||||
|
||||
IF (condition) statement_1 |
||||
IE (condition) statement_1 ELSE statement_2 |
||||
|
||||
Both of these statements run statement_1, if the given |
||||
condition is true. |
||||
|
||||
In addition, IE/ELSE runs statement_2, if the conditions is |
||||
false. In this case, IF just passes control to the subsequent |
||||
statement. |
||||
|
||||
Example: IE (0) |
||||
IF (1) RETURN 1; |
||||
ELSE |
||||
RETURN 2; |
||||
|
||||
The example always returns 2, because only an IE statement can |
||||
have an ELSE branch. There is no "dangling else" problem. |
||||
|
||||
|
||||
WHILE (condition) statement |
||||
|
||||
Repeat the statement while the condition is true. When the |
||||
condition is not true initially, never run the statement. |
||||
|
||||
Example: ! Count from 1 to 10 |
||||
DO VAR i; |
||||
i := 0; |
||||
WHILE (i < 10) |
||||
i := i+1; |
||||
END |
||||
|
||||
|
||||
FOR (name=expression_1, expression_2, cvalue) statement |
||||
FOR (name=expression_1, expression_2) statement |
||||
|
||||
Assign the value of expression_1 to name, then compare name to |
||||
expression_2. If cvalue is not negative, repeat the statement |
||||
while name < expression_2. Otherwise repeat the statement while |
||||
name > expression_2. After running the statement, add cvalue |
||||
to name. Formally: |
||||
|
||||
name := expression_1; |
||||
WHILE ( cvalue > 0 /\ name < expression \/ |
||||
cvalue < 0 /\ name > expression ) |
||||
DO |
||||
statement; |
||||
name := name + cvalue; |
||||
END |
||||
|
||||
When the cvalue is omitted, it defaults to 1. |
||||
|
||||
Examples: DO VAR i; |
||||
FOR (i=1, 11); ! count from 1 to 10 |
||||
FOR (i=10, 0, %1); ! count from 10 to 1 |
||||
END |
||||
|
||||
|
||||
LEAVE; |
||||
|
||||
Leave the innermost WHILE or FOR loop, passing control to the |
||||
first statement following the loop. |
||||
|
||||
Example: DO VAR i; ! Count from 1 to 50 |
||||
FOR (i=1, 100) IF (i=50) LEAVE; |
||||
END |
||||
|
||||
|
||||
LOOP; |
||||
|
||||
Re-enter the innermost WHILE or FOR loop. WHILE loops are |
||||
re-entered at the point where the condition is tested, and |
||||
FOR loops are re-entered at the point where the counter is |
||||
incremented. |
||||
|
||||
Example: DO VAR i; ! This program never prints X |
||||
FOR (i=1, 10) DO |
||||
LOOP; |
||||
T.WRITE(1, "x", 1); |
||||
END |
||||
END |
||||
|
||||
|
||||
RETURN expression; |
||||
|
||||
Return a value from a function. For further details see the |
||||
description of function calls in the expression section. |
||||
|
||||
Example: inc(x) RETURN x+1; |
||||
|
||||
|
||||
HALT cvalue; |
||||
|
||||
Halt program and return the given exit code to the operating |
||||
system. |
||||
|
||||
Example: HALT 1; |
||||
|
||||
|
||||
DO statement ... END |
||||
DO declaration ... statement ... END |
||||
|
||||
Compound statement of the form DO ... END are used to place |
||||
multiple statements in a context where only a single statement |
||||
is expected, like selection, loop, and function bodies. |
||||
|
||||
A compound statement may declare its own local variables, |
||||
constant, and structures (using VAR, CONST, or STRUCT). A |
||||
local variable of a compound statement is created and |
||||
allocated at the beginning of the statement is ceases to |
||||
exist at the end of the statement. |
||||
|
||||
Note that the form |
||||
|
||||
DO declaration ... END |
||||
|
||||
also exists, but is essentially an empty statement. |
||||
|
||||
Example: DO var i, x; ! Compute 10 factorial |
||||
x := 1; |
||||
for (i=1, 10) |
||||
x := x*i; |
||||
END |
||||
|
||||
|
||||
DO END |
||||
; |
||||
|
||||
These are both empty statements or null statements. They do not |
||||
do anything when run and may be used as placeholders where a |
||||
statement would be expected. They are also used to show that |
||||
nothing is to be done in a specific situation, like in |
||||
|
||||
IE (x = 0) |
||||
; |
||||
ELSE IE (x < 0) |
||||
statement; |
||||
ELSE |
||||
statement; |
||||
|
||||
Examples: FOR (i=0, 100000) DO END ! waste some time |
||||
|
||||
|
||||
EXPRESSIONS |
||||
----------- |
||||
|
||||
An expression is a variable or a literal or a function call or |
||||
a set of operators applied to one of these. There are unary, |
||||
binary, and ternary operators. |
||||
|
||||
Examples: -a ! negate a |
||||
b*c ! product of b and c |
||||
x->y:z ! if x then y else z |
||||
|
||||
In the following, the symbols X, Y, and Z denote variables or |
||||
literals. |
||||
|
||||
These operators exist (P denotes precedence, A associativity): |
||||
|
||||
OPERATOR P A DESCRIPTION |
||||
|
||||
X[Y] 9 L the Y'th element of the vector X |
||||
X::Y 9 R the Y'th byte of the byte vector X |
||||
|
||||
-X 8 - the negative value of X |
||||
~X 8 - the bitwise inverse of X |
||||
\X 8 - logical NOT of X |
||||
@X 8 - the address of X |
||||
|
||||
X*Y 7 L the product of X and Y |
||||
Y/Y 7 L the integer quotient of X and Y |
||||
X mod Y 7 L the division remainder of X and Y |
||||
|
||||
X+Y 6 L the sum of X and Y |
||||
X-Y 6 L the difference between X and Y |
||||
|
||||
X&Y 5 L the bitwise AND of X and Y |
||||
X|Y 5 L the bitwise OR of X and Y |
||||
X^Y 5 L the bitwise XOR of X and Y |
||||
X<<Y 5 L X shifted to the left by Y bits |
||||
X>>Y 5 L X shifted to the right by Y bits |
||||
|
||||
X<Y 4 L %1, if X is less than Y, else 0 |
||||
X>Y 4 L %1, if X is less than Y, else 0 |
||||
X<=Y 4 L %1, if X is less/equal Y, else 0 |
||||
X>=Y 4 L %1, if X is greater/equal Y, else 0 |
||||
|
||||
X=Y 3 L %1, if X equals Y, else 0 |
||||
X\=Y 3 L %1, if X does not equal Y, else 0 |
||||
|
||||
X/\Y 2 L if X then Y else 0 |
||||
(short-circuit logical AND) |
||||
|
||||
X\/Y 1 L if X then X else Y |
||||
(short-circuit logical OR) |
||||
|
||||
X->Y:Z 0 - if X then Y else Z |
||||
|
||||
Higher precedence means that an operator binds stronger, e.g. |
||||
-X::Y actually means -(X::Y). |
||||
|
||||
Left-associativity (L) means that x+y+z = (x+y)+z and |
||||
right-associativity (R) means that x::y::z = x::(y::z). |
||||
|
||||
|
||||
CONDITIONS |
||||
---------- |
||||
|
||||
A condition is an expression appearing in a condition context, |
||||
like the condition of an IF or WHILE statement or the first |
||||
operand of the X->Y:Z operator. |
||||
|
||||
In an expression context, the value 0 is considered to be |
||||
"false", and any other value is considered to be true. For |
||||
example: |
||||
|
||||
X=X is true |
||||
1=2 is false |
||||
"x" is true |
||||
5>7 is false |
||||
|
||||
The canonical truth value, as returned by 1=1, is %1. |
||||
|
||||
|
||||
FUNCTION CALLS |
||||
-------------- |
||||
|
||||
When a function call appears in an expression, the result of |
||||
the function, as returned by RETURN is used as an operand. |
||||
|
||||
A function call is performed as follows: |
||||
|
||||
Each actual argument in the call |
||||
|
||||
function(argument_1, ...) |
||||
|
||||
is passed to the function and bound to the corresponding formal |
||||
argument ("argument") of the receiving function. The function |
||||
then runs its statement, which may produce a value via RETURN. |
||||
When no RETURN statement exists in the statement, 0 is returned. |
||||
|
||||
Function arguments evaluate from the left to the right, so in |
||||
|
||||
f(a,b,c); |
||||
|
||||
A is guaranteed to evaluate before B and C and B is guaranteed |
||||
to evaluate before C. |
||||
|
||||
Example: pow(x, y) DO VAR a; |
||||
a := 1; |
||||
WHILE (y) DO |
||||
a := a*x; |
||||
y := y-1; |
||||
END |
||||
RETURN a; |
||||
END |
||||
|
||||
DO VAR x; |
||||
x := pow(2,10); |
||||
END |
||||
|
||||
|
||||
LITERALS |
||||
-------- |
||||
|
||||
INTEGERS |
||||
|
||||
An integer is a number representing its own value. Note that |
||||
negative numbers have a leading '%' sign rather than a '-' sign. |
||||
While the latter also works, it is, strictly speaking, the |
||||
application of the '-' operator to a positive number, so it may |
||||
not appear in cvalue contexts. |
||||
|
||||
Examples: 0 |
||||
12345 |
||||
%1 |
||||
|
||||
|
||||
CHARACTERS |
||||
|
||||
Characters are integers internally. They are represented by |
||||
single characters enclosed in single quotes. In addition, the |
||||
same escape sequences as in strings may be used. |
||||
|
||||
Examples: 'x' |
||||
'\\' |
||||
''' |
||||
'\e' |
||||
|
||||
|
||||
STRINGS |
||||
|
||||
A string is a byte vector filled with characters. Strings are |
||||
delimited by '"' characters and NUL-terminated internally. All |
||||
characters between the delimiting double quotes represent |
||||
themselves. In addition, the following escape sequences may be |
||||
used to include some special characters: |
||||
|
||||
\a BEL Bell |
||||
\b BS Backspace |
||||
\e ESC Escape |
||||
\f FF Form Feed |
||||
\n LF Line Feed (newline) |
||||
\q " Quote |
||||
\r CR Carriage Return |
||||
\s Space |
||||
\t HT Horizontal Tabulator |
||||
\v VT Vertical Tabulator |
||||
\\ \ Backslash |
||||
|
||||
Examples: "" |
||||
"hello, world!\n" |
||||
"\qhi!\q, she said" |
||||
|
||||
|
||||
TABLES |
||||
|
||||
A table is a vector literal, i.e. a sequence of subsequent |
||||
values. It is delimited by square brackets and elements are |
||||
separated by commas. Table elements can be cvalues, strings, |
||||
and tables. |
||||
|
||||
Examples: [1, 2, 3] |
||||
["5 times -7", %35] |
||||
[[1,0,0],[0,1,0],[0,0.1]] |
||||
|
||||
|
||||
DYNAMIC TABLES |
||||
|
||||
The dynamic table is a special case of the table in which one |
||||
or multiple elements are computed at program run time. Dynamic |
||||
table elements are enclosed in parentheses. E.g. in the table |
||||
|
||||
["x times 7", (x*7)] |
||||
|
||||
the value of the second element would be computed and filled |
||||
in when the table is being evaluated. Note that dynamic table |
||||
elements are being replaced in situ, and remain the same only |
||||
until they are replaced again. |
||||
|
||||
Multiple dynamic elements may be enclosed by a single pair of |
||||
parentheses. For instance, the following tables are the same: |
||||
|
||||
[(x), (y), (z)] |
||||
[(x, y, z)] |
||||
|
||||
|
||||
CVALUES |
||||
------- |
||||
|
||||
A cvalue (constant value) is an expression whose value is known |
||||
at compile time. In full T3X, this is a large subset of full |
||||
expressions, but in T3X9, it it limited to the following: |
||||
|
||||
* integers |
||||
* characters |
||||
* constants |
||||
|
||||
as well as (given that X and Y are one of the above): |
||||
|
||||
* X+Y |
||||
* X*Y |
||||
|
||||
|
||||
NAMING CONVENTIONS |
||||
------------------ |
||||
|
||||
Symbolic names for variables, constants, structures, and |
||||
functions are constructed from the following alphabet: |
||||
|
||||
* the characters a-z |
||||
* the digits 0-9 |
||||
* the special characters '_' and '.' |
||||
|
||||
The first character of a name must be non-numeric, the remaining |
||||
characters may be any of the above. |
||||
|
||||
Upper and lower case is not distinguished, the symbolic names |
||||
|
||||
FOO, Foo, foo |
||||
|
||||
are all considered to be equal. |
||||
|
||||
By convention, |
||||
|
||||
* CONST names are all upper-case |
||||
* STRUCT names are all upper-case |
||||
* global VAR names are capitalized |
||||
* local VAR names are all lower-case |
||||
* function names are all lower-case |
||||
|
||||
Keywords, like VAR, IF, DO, etc, are sometimes printed in upper |
||||
case in documentation, but are usually in lower case in actual |
||||
programs. |
||||
|
||||
|
||||
SHADOWING |
||||
--------- |
||||
|
||||
There is a single name space without any shadowing in T3X: |
||||
|
||||
* all global names must be different |
||||
* no local name may have the same name as a global name |
||||
* all local names in the same scope must be different |
||||
|
||||
The latter means that local names may be re-used in subsequent |
||||
scopes, e.g.: |
||||
|
||||
f(x) RETURN x; |
||||
g(x) RETURN x; |
||||
|
||||
would be a valid program. However, |
||||
|
||||
f(x) DO VAR x; END !!! WRONG !!! |
||||
|
||||
would not be a valid program, because VAR x; redefines the |
||||
argument of F. |
||||
|
||||
|
||||
BUILT-IN FUNCTIONS |
||||
------------------ |
||||
|
||||
The following built-in functions exist in T3X9. They resemble |
||||
the functions of the T3X core module of the full language, i.e. |
||||
a T3X9 program can be compiled by a T3X compiler by adding the |
||||
following code to the top of the program: |
||||
|
||||
MODULE name(t3x); |
||||
OBJECT t[t3x]. |
||||
|
||||
These functions are built into the T3X9 compiler, though, and |
||||
do not have to be declared in any way. The '.' in the function |
||||
names resembles the message operator of the full language. |
||||
|
||||
|
||||
T.READ(fd, buf, len) |
||||
|
||||
Read up to LEN characters from the file descriptor FD into the |
||||
buffer BUF. Return the number of characters actually read. |
||||
Return %1 in case of an error. |
||||
|
||||
|
||||
T.WRITE(fd, buf, len) |
||||
|
||||
Write LEN characters from the buffer BUF to the file descriptor |
||||
FD. Return the number of characters actually written. Return %1 |
||||
in case of an error. |
||||
|
||||
Example: t.write(1, "hello, world!\n", 14); |
||||
|
||||
|
||||
T.MEMCOMP(b1, b2, len) |
||||
|
||||
Compare the first LEN bytes of the byte vectors B1 and B2. |
||||
Return the difference of the first pair of mismatching bytes. |
||||
A return code of 0 means that the compared regions are equal. |
||||
|
||||
Example: t.memcomp("aaa", "aba", 3) ! gives 'b'-'a' = %1 |
||||
|
||||
|
||||
T.MEMCOPY(bs, bd, len) |
||||
|
||||
Copy LEN bytes from the byte vector BS (source) to the byte |
||||
vector BD (destination). Return 0. |
||||
|
||||
Example: DO VAR b:100; t.memcopy("hello", b, 5); END |
||||
|
||||
|
||||
T.MEMFILL(bv, b, len) |
||||
|
||||
Fill the first LEN bytes of the byte vector BV with the byte |
||||
value B. Return 0. |
||||
|
||||
Example: DO VAR b:100; t.memfill(b, 0, 100); END |
||||
|
||||
|
||||
T.MEMSCAN(bv, b, len) |
||||
|
||||
Locate the first occurrence of the byte value B in the first LEN |
||||
bytes of the byte vector BV and return its offset in the vector. |
||||
When B does not exist in the given region, return %1. |
||||
|
||||
Example: t.memscan("aaab", 'b', 4) ! returns 3 |
||||
|
||||
|
||||
VARIADIC FUNCTIONS |
||||
------------------ |
||||
|
||||
T3X implements variadic functions (i.e. functions of a variable |
||||
number of arguments) using dynamic tables. For instance, the |
||||
following function returns the sum of a vector of arguments: |
||||
|
||||
sum(k, v) DO var i, n; |
||||
n := 0; |
||||
FOR (i=0, k) |
||||
n := n+v[i]; |
||||
RETURN n; |
||||
END |
||||
|
||||
Its is an ordinary function returning the sum of a vector. It |
||||
can be considered to be a variadic function, because a dynamic |
||||
table can be passed to it in the V argument: |
||||
|
||||
sum(5, [(a,b,c,d,e)]) |
||||
|
||||
|
||||
EXAMPLE PROGRAM |
||||
--------------- |
||||
|
||||
var ntoa_buf::100; |
||||
|
||||
ntoa(x) do var i, k; |
||||
if (x = 0) return "0"; |
||||
i := 0; |
||||
k := x<0-> -x: x; |
||||
while (k > 0) do |
||||
i := i+1; |
||||
k := k/10; |
||||
end |
||||
i := i+1; |
||||
if (x < 0) i := i+1; |
||||
ntoa_buf::i := 0; |
||||
k := x<0-> -x: x; |
||||
while (k > 0) do |
||||
i := i-1; |
||||
ntoa_buf::i := '0' + k mod 10; |
||||
k := k/10; |
||||
end |
||||
if (x < 0) do |
||||
i := i-1; |
||||
ntoa_buf::i := '-'; |
||||
end |
||||
return @ntoa_buf::i; |
||||
end |
||||
|
||||
str.length(s) return t.memscan(s, 0, 32767); |
||||
|
||||
writes(s) t.write(1, s, str.length(s)); |
||||
|
||||
fib(n) do var r1, r2, i, t; |
||||
r1 := 0; |
||||
r2 := 1; |
||||
for (i=1, n) do |
||||
t := r2; |
||||
r2 := r2 + r1; |
||||
r1 := t; |
||||
end |
||||
return r2; |
||||
end |
||||
|
||||
do var i; |
||||
for (i=1, 11) do |
||||
writes(ntoa(fib(i))); |
||||
writes("\n"); |
||||
end |
||||
end |
@ -0,0 +1,47 @@
|
||||
var ntoa_buf::100; |
||||
|
||||
ntoa(x) do var i, k; |
||||
if (x = 0) return "0"; |
||||
i := 0; |
||||
k := x<0-> -x: x; |
||||
while (k > 0) do |
||||
i := i+1; |
||||
k := k/10; |
||||
end |
||||
i := i+1; |
||||
if (x < 0) i := i+1; |
||||
ntoa_buf::i := 0; |
||||
k := x<0-> -x: x; |
||||
while (k > 0) do |
||||
i := i-1; |
||||
ntoa_buf::i := '0' + k mod 10; |
||||
k := k/10; |
||||
end |
||||
if (x < 0) do |
||||
i := i-1; |
||||
ntoa_buf::i := '-'; |
||||
end |
||||
return @ntoa_buf::i; |
||||
end |
||||
|
||||
str.length(s) return t.memscan(s, 0, 32767); |
||||
|
||||
writes(s) t.write(1, s, str.length(s)); |
||||
|
||||
fib(n) do var r1, r2, i, t; |
||||
r1 := 0; |
||||
r2 := 1; |
||||
for (i=1, n) do |
||||
t := r2; |
||||
r2 := r2 + r1; |
||||
r1 := t; |
||||
end |
||||
return r2; |
||||
end |
||||
|
||||
do var i; |
||||
for (i=1, 11) do |
||||
writes(ntoa(fib(i))); |
||||
writes("\n"); |
||||
end |
||||
end |
@ -0,0 +1,29 @@
|
||||
************************************************************************ |
||||
IMPORTANT: |
||||
|
||||
The book version of the T3X compiler uses a T.MEMCOPY procedure with |
||||
the following arguments: |
||||
|
||||
T.MEMCOPY(SOURCE, DESTINATION, LENGTH) |
||||
|
||||
Note that this version is incompatible with the original T3X language, |
||||
which uses |
||||
|
||||
T.MEMCOPY(DESTINATION, SOURCE, LENGTH) |
||||
|
||||
The compiler in this archive uses the original T3X version with the |
||||
destination argument to the left of the source argument. Hence it is |
||||
slightly incompatible to the book version! |
||||
************************************************************************ |
||||
|
||||
20200304 Added MODULE and OBJECT dummy declarations (T3X compatibility). |
||||
20190913 Made T.MEMCOPY compatible with the original T3X version. |
||||
20190720 Fixed harmless minor inconsistency in operator table. |
||||
20170605 Add hexa-decimal integer literals to language. |
||||
20170605 Add T3X packed vectors (byte vectors) to language. |
||||
20170528 Add tcdis, Tcode9 disassembler. |
||||
20170528 Add tcvm, ad-hoc Tcode9 virtual machine. |
||||
20170523 Add t-vm.t, T3X9->Tcode9 compiler. |
||||
20170520 Fix: DO VAR x; x(); END would not report call of non-function. |
||||
20170518 Fix parser bug mis-parsing IE (x) IF (y) v; ELSE w;. |
||||
20170430 Add T.CREATE, T.OPEN, T.CLOSE, T.RENAME, T.REMOVE built-ins. |
@ -0,0 +1,17 @@
|
||||
CHANGES change log |
||||
MANIFEST this file |
||||
Makefile Makefile |
||||
README read me |
||||
_csums checksums |
||||
dump.c dump code part of a T3X9-generated ELF file |
||||
t-vm.t T3X9->Tcode9 compiler |
||||
t.c T3X9->ELF boostrapping compiler |
||||
t.elf T3X9->ELF compiler, FreeBSD-386-ELF executable |
||||
t.t T3X9->ELF compiler |
||||
t.vm T3X9->Tcode9 compiler, Tcode9 VM executable |
||||
t3x-history.txt short summary of T3X language |
||||
t3x.bnf yaccable T3X9 grammar |
||||
t3x.txt T3X9 micro manual |
||||
tcdis.c Tcode9 disassembler |
||||
tcvm.c ad-hoc Tcode9 virtual machine |
||||
test.t test program |
@ -0,0 +1,42 @@
|
||||
D= t3x9r3
|
||||
A= $D.tgz
|
||||
|
||||
all: t0 t.elf t.vm tcvm |
||||
|
||||
t0: t.c t.t |
||||
cc -static -o t0 t.c
|
||||
|
||||
t.vm: t-vm |
||||
./t-vm <t-vm.t >t.vm
|
||||
|
||||
t-vm: t-vm.t |
||||
./t3 <t-vm.t >t-vm && chmod +x t-vm
|
||||
|
||||
tcvm: tcvm.c |
||||
cc -O2 -g -o tcvm tcvm.c
|
||||
|
||||
t.elf: test |
||||
cp t3 t.elf
|
||||
|
||||
test: t0 |
||||
touch t1 t2 t3; chmod +x t1 t2 t3
|
||||
./t0 <t.t >t1 && ./t1 <t.t >t2 && ./t2 <t.t >t3 && cmp t2 t3
|
||||
|
||||
vmtest: tcvm |
||||
./tcvm t.vm <t-vm.t >t1.vm
|
||||
./tcvm t1.vm <t-vm.t >t2.vm
|
||||
./tcvm t2.vm <t-vm.t >t3.vm
|
||||
cmp t2.vm t3.vm
|
||||
|
||||
mksums: clean |
||||
ls | grep -v $A | grep -v _csums | csum -m >_csums
|
||||
|
||||
csums: |
||||
csum -u <_csums >_csums.new && mv -f _csums.new _csums
|
||||
|
||||
clean: |
||||
rm -f t0 t1 t2 t3 t1.vm t2.vm t3.vm t-vm a.out tcvm dump *.o *.core \
|
||||
$A
|
||||
|
||||
arc: clean |
||||
(cd ..; tar cvf - $D | gzip -9 >$A); mv -f ../$A .
|
@ -0,0 +1,30 @@
|
||||
|
||||
This is the T3X9 compiler, Release 2 |
||||
|
||||
It is superset of the compiler described in |
||||
|
||||
"Write Your Own Compiler" |
||||
by Nils M Holm |
||||
|
||||
More details about the book can be found at T3X.ORG. |
||||
|
||||
********************************************************* |
||||
Please consult the CHANGES file before usig this version! |
||||
********************************************************* |
||||
|
||||
To compile the compiler on FreeBSD-386, just do |
||||
|
||||
chmod +x t.elf && ./t.elf <t.t >t.new |
||||
|
||||
To compile it on any system providing a C89 compiler: |
||||
|
||||
cc -o t0 t.c && ./t0 <t.t >t.new |
||||
|
||||
Alternatively, use the Tcode9 virtual machine: |
||||
|
||||
cc -o tcvm tcvm.c && ./tcvm t.vm <t-vm.t >t.new |
||||
|
||||
You can then compile T3X9 programs using |
||||
|
||||
./tcvm t.new <t3x-program >vm-program |
||||
|
@ -0,0 +1,16 @@
|
||||
15731 2 CHANGES |
||||
46710 1 MANIFEST |
||||
13049 1 Makefile |
||||
62480 1 README |
||||
14051 1 dump.c |
||||
37533 29 t-vm.t |
||||
32747 27 t.c |
||||
10398 34 t.elf |
||||
26599 31 t.t |
||||
31885 19 t.vm |
||||
28851 3 t3x-history.txt |
||||
45560 3 t3x.bnf |
||||
32461 21 t3x.txt |
||||
33423 6 tcdis.c |
||||
7233 7 tcvm.c |
||||
33987 1 test.t |
@ -0,0 +1,21 @@
|
||||
#include <stdio.h> |
||||
|
||||
#define Z 65536 |
||||
#define byte unsigned char |
||||
|
||||
byte T[Z]; |
||||
|
||||
int main(void) { |
||||
int k, i; |
||||
|
||||
k = fread(T, 1, Z, stdin); |
||||
printf(".byte "); |
||||
for (i=0x74; i<k; i++) { |
||||
if (i % 10 == 0) |
||||
printf("\n.byte "); |
||||
printf("0x%02x", T[i]); |
||||
if ((i+1) % 10 != 0 && i+1 < k) |
||||
printf(","); |
||||
} |
||||
printf("\n"); |
||||
} |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,61 @@
|
||||
|
||||
A SHORT HISTORY OF THE T3X LANGUAGE |
||||
|
||||
T3X is a tiny block-structured language that you probably |
||||
haven't heard about. It had a tiny community back in the |
||||
mid-1990's. Software written in T3X includes its own compiler |
||||
(of course), its own text-based IDE, a few LISP interpreters, |
||||
an assembler and linker for the 8086, and a database system |
||||
used by a local church community. It was also used in a few |
||||
college courses, most probably because its community was so |
||||
tiny that nobody could be bothered to do your homework |
||||
assignments for you. |
||||
|
||||
The T3X language started as a very minimalistic language |
||||
with a single-file compiler that targeted the 8086 and 386 |
||||
processors. It supported FreeBSD via the GNU binutils and |
||||
emitted DOS EXE files through its own assembler and linker. |
||||
|
||||
In its lifetime, several enhancements were made to both the |
||||
language and its implementation: |
||||
|
||||
- An object system was added to the language, and the entire |
||||
runtime support infrastructure was rewritten as a set of |
||||
classes. |
||||
- Tcode, an abstract target language, was added. It could be |
||||
interpreted, optimized, linked, and converted to native |
||||
code. |
||||
- A back-end for the AXP 21064 (Alpha) was added. |
||||
- A C back-end was added, allowing to use T3X on otherwise |
||||
unsupported processors. |
||||
- Runtime support for the following platforms was added: |
||||
NetBSD-386, NetBSD-Alpha, FreeBSD-386, Coherent-386, |
||||
Linux-386, and Plan 9 (via C). |
||||
|
||||
T3X is probably notable, because it is a typeless object |
||||
oriented language. Objects are distinguished by the methods |
||||
they implement, and the methods are typeless procedures. |
||||
The T3X object system is more similar to ADA packages than |
||||
to the C++ or Java approach. It implements reusable modules |
||||
rather than data types. |
||||
|
||||
T3X-8.1.7 was the last version of T3X and it was released in |
||||
2004 with some minor updates in 2011 and 2014. Its generic |
||||
(Tcode) port still runs on modern operating systems. |
||||
|
||||
T3X9 is a subset of the T3X language that compiles directly |
||||
from T3X to ELF-FreeBSD-386. |
||||
|
||||
If you are familiar with T3X, this is what the compiler omits |
||||
from the original language: modules, objects, classes, packed |
||||
vectors, function pointers and indirect function calls, meta |
||||
commands, unsigned operators. Also, constant expression syntax |
||||
is only a subset. |
||||
|
||||
The T3X9 compiler is under 1600 lines in size and compiles |
||||
itself from source to ELF in about 0.06 seconds on a 750MHz |
||||
notebook computer. The resulting binary has a size of less |
||||
than 32K bytes. The T3X9r2 compiler has a slightly larger |
||||
size (about 33K bytes) and additional language constructs |
||||
(packed tables, hex literal prefixes) and runtime functions. |
||||
|
@ -0,0 +1,221 @@
|
||||
%token SYMBOL, INTEGER, CHARACTER, STRING |
||||
%token VAR, CONST, STRUCT, DECL, DO, END |
||||
%token IF, IE, ELSE, WHILE, FOR, LEAVE, LOOP, |
||||
%token RETURN, HALT, MODULO |
||||
|
||||
%% |
||||
|
||||
Program: |
||||
Declarations CompoundStmt |
||||
; |
||||
|
||||
Declarations: |
||||
Declaration |
||||
| Declaration Declarations |
||||
; |
||||
|
||||
Declaration: |
||||
VAR VarList ';' |
||||
| CONST ConstList ';' |
||||
| DECL DeclList ';' |
||||
| STRUCT SYMBOL '=' StructMembers ';' |
||||
| FunctionDecl |
||||
; |
||||
|
||||
VarList: |
||||
SYMBOL |
||||
| SYMBOL '[' ConstValue ']' |
||||
| VarList ',' SYMBOL |
||||
; |
||||
|
||||
ConstList: |
||||
ConstDef |
||||
| ConstDef ',' ConstList |
||||
; |
||||
|
||||
ConstDef: |
||||
SYMBOL '=' ConstValue |
||||
; |
||||
|
||||
DeclList: |
||||
Decl |
||||
| Decl ',' DeclList |
||||
; |
||||
|
||||
Decl: |
||||
SYMBOL '(' ConstValue ')' |
||||
; |
||||
|
||||
StructMembers: |
||||
SYMBOL |
||||
| SYMBOL ',' StructMembers ';' |
||||
; |
||||
|
||||
FunctionDecl: |
||||
SYMBOL '(' OptFormalArgs ')' Statement |
||||
; |
||||
|
||||
OptFormalArgs: |
||||
| ArgumentList |
||||
; |
||||
|
||||
ArgumentList: |
||||
SYMBOL |
||||
| SYMBOL ',' ArgumentList |
||||
; |
||||
|
||||
Statement: |
||||
CompoundStmt |
||||
| SYMBOL ':=' Expression ';' |
||||
| SYMBOL Subscripts ':=' Expression ';' |
||||
| FunctionCall |
||||
| IF '(' Expression ')' Statement |
||||
| IE '(' Expression ')' Statement |
||||
ELSE Statement |
||||
| WHILE '(' Expression ')' Statement |
||||
| FOR '(' SYMBOL '=' Expression ',' |
||||
Expression ')' |
||||
Statement |
||||
| FOR '(' SYMBOL '=' Expression ',' |
||||
Expression, |
||||
ConstValue ')' |
||||
Statement |
||||
| LEAVE ';' |
||||
| LOOP ';' |
||||
| RETURN Expression ';' |
||||
| HALT ConstValue ';' |
||||
| ';' |
||||
; |
||||
|
||||
CompoundStmt: |
||||
DO END |
||||
| DO LocalDecls END |
||||
| DO StatementList END |
||||
| DO LocalDecls StatementList END |
||||
; |
||||
|
||||
LocalDecls: |
||||
LocalDecl |
||||
| LocalDecl LocalDecls |
||||
; |
||||
|
||||
LocalDecl: |
||||
VAR VarList ';' |
||||
| CONST ConstList ';' |
||||
| STRUCT SYMBOL '=' StructMembers ';' |
||||
; |
||||
|
||||
StatementList: |
||||
Statement |
||||
| Statement StatementList |
||||
; |
||||
|
||||
ExprList: |
||||
Expression |
||||
| Expression ',' ExprList |
||||
; |
||||
|
||||
Expression: |
||||
Disjunction |
||||
| Disjunction '->' Expression ':' Expression |
||||
; |
||||
|
||||
Disjunction: |
||||
Conjunction |
||||
| Conjunction '/\\' Disjunction |
||||
; |
||||
|
||||
Conjunction: |
||||
Equation |
||||
| Equation '\\/' Conjunction |
||||
; |
||||
|
||||
Equation: |
||||
Relation |
||||
| Relation '=' Equation |
||||
| Relation '\\=' Equation |
||||
; |
||||
|
||||
Relation: |
||||
BitOperation |
||||
| BitOperation '<' Relation |
||||
| BitOperation '>' Relation |
||||
| BitOperation '<=' Relation |
||||
| BitOperation '>=' Relation |
||||
; |
||||
|
||||
BitOperation: |
||||
Sum |
||||
| Sum '&' BitOperation |
||||
| Sum '|' BitOperation |
||||
| Sum '^' BitOperation |
||||
| Sum '<<' BitOperation |
||||
| Sum '>>' BitOperation |
||||
; |
||||
|
||||
Sum: |
||||
Term |
||||
| Term '+' Sum |
||||
| Term '-' Sum |
||||
; |
||||
|
||||
Term: |
||||
Factor |
||||
| Factor '*' Term |
||||
| Factor '/' Term |
||||
| Factor MODULO Term |
||||
; |
||||
|
||||
Factor: |
||||
INTEGER |
||||
| FunctionCall |
||||
| STRING |
||||
| Table |
||||
| SYMBOL |
||||
| SYMBOL Subscripts |
||||
| '@' SYMBOL |
||||
| '@' SYMBOL Subscripts |
||||
| '-' Factor |
||||
| '\\' Factor |
||||
| '~' Factor |
||||
| '(' Expression ')' |
||||
; |
||||
|
||||
Subscripts: |
||||
'[' Expression ']' |
||||
| '[' Expression ']' Subscripts |
||||
| '::' Factor |
||||
; |
||||
|
||||
Table: |
||||
'[' MemberList ']' |
||||
; |
||||
|
||||
MemberList: |
||||
TableMember |
||||
| TableMember ',' MemberList |
||||
; |
||||
|
||||
TableMember: |
||||
ConstValue |
||||
| STRING |
||||
| Table |
||||
| '(' ExprList ')' |
||||
; |
||||
|
||||
FunctionCall: |
||||
SYMBOL '(' ')' |
||||
| SYMBOL '(' ExprList ')' |
||||
; |
||||
|
||||
ConstValue: |
||||
SYMBOL |
||||
| Integer |
||||
; |
||||
|
||||
Integer: |
||||
INTEGER |
||||
| CHARACTER |
||||
; |
||||
%% |
||||
|