-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcpp.frt
211 lines (183 loc) · 4.09 KB
/
cpp.frt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
(
The entries in the include stack look as follows:
0 - 12 Saved FILENAME (counted string)
13 - 16 Saved LINE
17 - 20 Saved >IN
21 - 24 Saved LENGTH
25 - 28 Saved BLK
)
64 CONSTANT INCSTK-SIZE
25 CONSTANT INCSTK-ESIZE
VARIABLE INCSTK-DEPTH
CREATE INCSTK INCSTK-SIZE INCSTK-ESIZE * ALLOT
0 INCSTK-DEPTH !
: INCSTK-CURR ( -- include-stack-pointer ) INCSTK INCSTK-ESIZE INCSTK-DEPTH @ * + ;
VARIABLE LINE
DEFER MAIN-EOF
CREATE FILENAME 13 ALLOT
: PRINT-LOC
FILENAME COUNT TYPE
." :"
LINE @ .X
." : "
;
: QUOTE-TILL-EOL CR BEGIN KEY DUP #CR <> WHILE EMIT REPEAT DROP ;
: SAVE-LOC ( -- )
INCSTK-DEPTH @ INCSTK-SIZE >= IF
PRINT-LOC ." include stack overflow" ABORT
THEN
INCSTK-CURR
FILENAME OVER 13 CMOVE 13 +
LINE @ OVER ! CELL+
>IN @ OVER ! CELL+
LENGTH @ OVER ! CELL+
BLK @ SWAP !
1 INCSTK-DEPTH +!
;
: RESTORE-LOC
INCSTK-DEPTH @ 0= IF
MAIN-EOF
ELSE
1 INCSTK-DEPTH -!
INCSTK-CURR
DUP FILENAME 13 CMOVE 13 +
DUP @ LINE ! CELL+
DUP @ >IN ! CELL+
DUP @ LENGTH ! CELL+
@ LOAD
THEN
;
: PEEK KEY UNGETC ;
: UNGETC
UNGETC
PEEK #CR = IF
1 LINE -!
THEN
;
: KEY
KEY
DUP #CR = IF
1 LINE +!
THEN
DUP 0= IF
DROP #CR RESTORE-LOC
THEN
;
HIDE KEY-NOEOF
: OPEN-FILE ( filename length -- )
FILENAME 13 0 FILL
DUP FILENAME C!
FILENAME 1+ SWAP CMOVE
ROOT
FILENAME COUNT FILE
1 LINE !
;
: IDENT? DUP [CHAR] _ = SWAP ALNUM? OR ;
: SKIP-LINE BEGIN KEY #CR = UNTIL ;
: SKIP-WHITE BEGIN KEY BL > UNTIL UNGETC ;
: SKIP-WHITE-ONE-LINE BEGIN KEY DUP BL > SWAP #CR = OR UNTIL UNGETC ;
: ASSERT-CR
SKIP-WHITE-ONE-LINE
KEY #CR <> IF
PRINT-LOC ." expected newline, got:" UNGETC QUOTE-TILL-EOL
ABORT
THEN
;
: PARSE-IDENT
HERE
BEGIN
KEY DUP IDENT?
WHILE
C,
REPEAT
DROP UNGETC
HERE OVER -
OVER HERE!
;
0 CONSTANT DIR-NONE
1 CONSTANT DIR-IF
2 CONSTANT DIR-IFDEF
3 CONSTANT DIR-IFNDEF
4 CONSTANT DIR-ELSE
5 CONSTANT DIR-ELIF
6 CONSTANT DIR-ENDIF
7 CONSTANT DIR-INCLUDE
8 CONSTANT DIR-DEFINE
9 CONSTANT DIR-UNDEF
10 CONSTANT DIR-LINE
11 CONSTANT DIR-ERROR
12 CONSTANT DIR-PRAGMA
: GET-DIRECTIVE
SKIP-WHITE-ONE-LINE
PARSE-IDENT
SCASE
S" if" SOF DIR-IF SENDOF
S" ifdef" SOF DIR-IFDEF SENDOF
S" ifndef" SOF DIR-IFNDEF SENDOF
S" else" SOF DIR-ELSE SENDOF
S" elif" SOF DIR-ELIF SENDOF
S" endif" SOF DIR-ENDIF SENDOF
S" include" SOF DIR-INCLUDE SENDOF
S" define" SOF DIR-DEFINE SENDOF
S" undef" SOF DIR-UNDEF SENDOF
S" line" SOF DIR-LINE SENDOF
S" error" SOF DIR-ERROR SENDOF
S" pragma" SOF DIR-PRAGMA SENDOF
CR PRINT-LOC ." unknown preprocessor directive: " TYPE ABORT
SENDCASE
;
: SKIP-TILL-ENDIF
BEGIN
KEY [CHAR] # = IF
GET-DIRECTIVE DIR-ENDIF = IF EXIT THEN
THEN
SKIP-LINE
AGAIN
;
DEFER HANDLE-IFCOND
: FIND-OTHER-IF-BRANCH
BEGIN
KEY [CHAR] # = IF
GET-DIRECTIVE CASE
DIR-ELSE OF ASSERT-CR EXIT ENDOF
DIR-ELIF OF HANDLE-IFCOND EXIT ENDOF
DIR-IF OF HANDLE-IFCOND EXIT ENDOF
DIR-IFDEF OF SKIP-TILL-ENDIF EXIT ENDOF
DIR-IFNDEF OF SKIP-TILL-ENDIF EXIT ENDOF
ENDCASE
THEN
AGAIN
;
:NONAME
SKIP-WHITE-ONE-LINE PARSE-IDENT S" TRUE" S= SKIP-LINE ( TODO: EVALUATE CONDITION )
INVERT IF FIND-OTHER-IF-BRANCH THEN
; IS HANDLE-IFCOND
: MAYBE-HANDLE-DIR
KEY [CHAR] # <> IF UNGETC EXIT THEN
GET-DIRECTIVE CASE
DIR-NONE OF EXIT ENDOF
DIR-IF OF HANDLE-IFCOND ENDOF
DIR-IFDEF OF SKIP-TILL-ENDIF ENDOF
DIR-IFNDEF OF SKIP-TILL-ENDIF ENDOF
( If you encounter else or elif in this state, it means you've just finished the branch you aren't
supposed to ignore, and therefore, you want to ignore all other branches of the conditional )
DIR-ELSE OF ASSERT-CR SKIP-TILL-ENDIF ENDOF
DIR-ELIF OF SKIP-TILL-ENDIF ENDOF
DIR-ENDIF OF ASSERT-CR ENDOF
PRINT-LOC ." unhandled directive #" . ABORT
ENDCASE
;
: TEST
S" TEST.C" OPEN-FILE
BEGIN
MAYBE-HANDLE-DIR
PRINT-LOC
BEGIN
KEY DUP #CR <>
WHILE
EMIT
REPEAT
CR
AGAIN
;
TEST