Last active 1758126370

Thue for Oberon

Thue.Mod Raw Playground
1MODULE Thue;
2 IMPORT Texts, Oberon;
3
4 CONST MaxB = 10000;
5 MaxRules = 1000;
6
7 VAR W: Texts.Writer;
8 B: ARRAY MaxB OF CHAR;
9 S, NS, NR: INTEGER;
10 L, R: ARRAY MaxRules OF RECORD s, n: INTEGER END;
11
12 PROCEDURE Write(s, n: INTEGER);
13 VAR i: INTEGER;
14 BEGIN
15 FOR i := s TO s+n-1 DO Texts.Write(W, B[i]) END;
16 Texts.Append(Oberon.Log, W.buf)
17 END Write;
18
19 PROCEDURE Find(s: ARRAY OF CHAR; start, n: INTEGER; VAR pos: INTEGER): BOOLEAN;
20 VAR i, j: INTEGER;
21 f: BOOLEAN;
22 BEGIN
23 IF NS < n THEN f := FALSE
24 ELSE
25 i := 0;
26 WHILE i <= NS-n DO
27 f := TRUE; j := 0;
28 WHILE j < n DO
29 IF B[S+i+j] # s[start+j] THEN f := FALSE; j := n ELSE INC(j) END
30 END;
31 IF f THEN pos := i; i := NS ELSE INC(i) END
32 END
33 END;
34 RETURN f
35 END Find;
36
37 PROCEDURE Reset;
38 BEGIN
39 NR := 0; S := 0; NS := 0
40 END Reset;
41
42 PROCEDURE Read*;
43 VAR Rr: Texts.Reader;
44 i, sep: INTEGER;
45 f: BOOLEAN;
46
47 PROCEDURE ReadLine(VAR R: Texts.Reader);
48 VAR i: INTEGER;
49 ch: CHAR;
50 BEGIN
51 i := 0; Texts.Read(R, ch);
52 WHILE (S+i < MaxB) & ~R.eot & (ch # 0DX) DO
53 B[S+i] := ch; INC(i); Texts.Read(R, ch)
54 END;
55 NS := i;
56 IF S+i = MaxB THEN Texts.WriteString(W, "Out of space"); Texts.WriteLn(W) END
57 END ReadLine;
58
59 BEGIN
60 Reset;
61 Texts.OpenReader(Rr, Oberon.Par.text, Oberon.Par.pos);
62 f := FALSE;
63 REPEAT ReadLine(Rr);
64 IF Find("::=", 0, 3, sep) THEN
65 IF NS = 3 THEN ReadLine(Rr); Rr.eot := TRUE
66 ELSIF NR < MaxRules THEN
67 L[NR].s := S; L[NR].n := sep;
68 R[NR].s := S + sep + 3; R[NR].n := NS - sep - 3;
69 INC(NR); INC(S, NS)
70 ELSE Texts.WriteString(W, "Too many rules"); Texts.WriteLn(W); f := TRUE END
71 ELSE
72 i := 0;
73 WHILE i < NS DO
74 IF B[S+i] # " " THEN f := TRUE; i := NS ELSE INC(i) END
75 END;
76 IF f THEN Texts.WriteString(W, "Invalid rule"); Texts.WriteLn(W) END
77 END
78 UNTIL Rr.eot OR f;
79 IF f THEN Reset ELSE Write(S, NS); Texts.WriteLn(W) END;
80 Texts.Append(Oberon.Log, W.buf)
81 END Read;
82
83 PROCEDURE Go*;
84 VAR i, j, k: INTEGER;
85 BEGIN
86 i := 0;
87 WHILE i < NR DO
88 IF Find(B, L[i].s, L[i].n, j) THEN
89 IF NS - L[i].n + R[i].n <= MaxB THEN
90 IF L[i].n < R[i].n THEN
91 FOR k := S+NS-L[i].n-1 TO S+j BY -1 DO B[k+R[i].n] := B[k+L[i].n] END
92 ELSE
93 FOR k := S+j TO S+NS-L[i].n-1 DO B[k+R[i].n] := B[k+L[i].n] END
94 END;
95 FOR k := 0 TO R[i].n-1 DO B[S+j+k] := B[R[i].s+k] END;
96 NS := NS - L[i].n + R[i].n;
97 Write(S, NS); Texts.WriteLn(W);
98 i := 0
99 ELSE Texts.WriteString(W, "Out of space"); Texts.WriteLn(W); i := NR END
100 ELSE INC(i) END
101 END;
102 Texts.Append(Oberon.Log, W.buf)
103 END Go;
104
105BEGIN Texts.OpenWriter(W);
106END Thue.
107
108~~~
109
110To compile: System.Free Thue~ ORP.Compile Thue.Mod/s~
111
112To load a program: Thue.Read
113kingdom, no knight.::=A kingdom was lost, all for the want of a nail.
114no horse::=no knight
115no shoe::=no horse
116no nail::=no shoe
117::=
118kingdom, no nail.
119
120To run: Thue.Go