1 ! Copyright (C) 2006 Chris Double. All Rights Reserved.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel peg strings promises sequences math math.parser
4 namespaces words quotations arrays hashtables io
5 io.streams.string assocs memoize ;
8 TUPLE: ast-number value ;
9 TUPLE: ast-identifier value vocab ;
10 TUPLE: ast-string value ;
11 TUPLE: ast-quotation values ;
12 TUPLE: ast-array elements ;
13 TUPLE: ast-define name stack-effect expression ;
14 TUPLE: ast-expression values ;
15 TUPLE: ast-word value vocab ;
17 TUPLE: ast-stack-effect in out ;
19 TUPLE: ast-using names ;
21 TUPLE: ast-hashtable elements ;
23 C: <ast-number> ast-number
24 C: <ast-identifier> ast-identifier
25 C: <ast-string> ast-string
26 C: <ast-quotation> ast-quotation
27 C: <ast-array> ast-array
28 C: <ast-define> ast-define
29 C: <ast-expression> ast-expression
30 C: <ast-word> ast-word
31 C: <ast-comment> ast-comment
32 C: <ast-stack-effect> ast-stack-effect
34 C: <ast-using> ast-using
36 C: <ast-hashtable> ast-hashtable
38 : identifier-middle? ( ch -- bool )
40 [ CHAR: } = not ] keep
41 [ CHAR: ] = not ] keep
42 [ CHAR: ;" = not ] keep
43 [ CHAR: " = not ] keep
47 MEMO: 'identifier-ends' ( -- parser )
50 [ CHAR: " = not ] keep
51 [ CHAR: ;" = not ] keep
54 identifier-middle? not
58 MEMO: 'identifier-middle' ( -- parser )
59 [ identifier-middle? ] satisfy repeat1 ;
61 MEMO: 'identifier' ( -- parser )
67 concat >string f <ast-identifier>
73 MEMO: 'effect-name' ( -- parser )
76 [ CHAR: ) = not ] keep
79 ] satisfy repeat1 [ >string ] action ;
81 MEMO: 'stack-effect' ( -- parser )
84 'effect-name' sp repeat0 ,
86 'effect-name' sp repeat0 ,
89 first2 <ast-stack-effect>
92 MEMO: 'define' ( -- parser )
95 'identifier' sp [ ast-identifier-value ] action ,
96 'stack-effect' sp optional ,
99 ] { } make seq [ first3 <ast-define> ] action ;
101 MEMO: 'quotation' ( -- parser )
104 'expression' [ ast-expression-values ] action ,
106 ] { } make seq [ first <ast-quotation> ] action ;
108 MEMO: 'array' ( -- parser )
111 'expression' [ ast-expression-values ] action ,
113 ] { } make seq [ first <ast-array> ] action ;
115 MEMO: 'word' ( -- parser )
119 ] { } make seq [ first ast-identifier-value f <ast-word> ] action ;
121 MEMO: 'atom' ( -- parser )
124 'integer' [ <ast-number> ] action ,
125 'string' [ <ast-string> ] action ,
128 MEMO: 'comment' ( -- parser )
133 ] { } make choice hide ,
135 dup CHAR: \n = swap CHAR: \r = or not
137 ] { } make seq [ drop <ast-comment> ] action ;
139 MEMO: 'USE:' ( -- parser )
141 "USE:" token sp hide ,
143 ] { } make seq [ first ast-identifier-value <ast-use> ] action ;
145 MEMO: 'IN:' ( -- parser )
147 "IN:" token sp hide ,
149 ] { } make seq [ first ast-identifier-value <ast-in> ] action ;
151 MEMO: 'USING:' ( -- parser )
153 "USING:" token sp hide ,
154 'identifier' sp [ ast-identifier-value ] action repeat1 ,
156 ] { } make seq [ first <ast-using> ] action ;
158 MEMO: 'hashtable' ( -- parser )
161 'expression' [ ast-expression-values ] action ,
163 ] { } make seq [ first <ast-hashtable> ] action ;
165 MEMO: 'parsing-word' ( -- parser )
172 MEMO: 'expression' ( -- parser )
183 ] { } make choice repeat0 [ <ast-expression> ] action
186 MEMO: 'statement' ( -- parser )
189 GENERIC: (compile) ( ast -- )
190 GENERIC: (literal) ( ast -- )
192 M: ast-number (literal)
193 ast-number-value number>string , ;
195 M: ast-number (compile)
196 "factor.push_data(" ,
200 M: ast-string (literal)
205 M: ast-string (compile)
206 "factor.push_data(" ,
210 M: ast-identifier (literal)
211 dup ast-identifier-vocab [
212 "factor.get_word(\"" ,
213 dup ast-identifier-vocab ,
215 ast-identifier-value ,
218 "factor.find_word(\"" , ast-identifier-value , "\")" ,
221 M: ast-identifier (compile)
222 (literal) ".execute(" , ;
224 M: ast-define (compile)
225 "factor.define_word(\"" ,
226 dup ast-define-name ,
228 ast-define-expression (compile)
231 : do-expressions ( seq -- )
234 dup ast-comment? not [
243 drop "factor.cont.next" ,
246 M: ast-quotation (literal)
247 "factor.make_quotation(\"source\"," ,
248 ast-quotation-values do-expressions
251 M: ast-quotation (compile)
252 "factor.push_data(factor.make_quotation(\"source\"," ,
253 ast-quotation-values do-expressions
256 M: ast-array (literal)
258 ast-array-elements [ "," , ] [ (literal) ] interleave
261 M: ast-array (compile)
262 "factor.push_data(" , (literal) "," , ;
264 M: ast-hashtable (literal)
265 "new Hashtable().fromAlist([" ,
266 ast-hashtable-elements [ "," , ] [ (literal) ] interleave
269 M: ast-hashtable (compile)
270 "factor.push_data(" , (literal) "," , ;
273 M: ast-expression (literal)
274 ast-expression-values [
278 M: ast-expression (compile)
279 ast-expression-values do-expressions ;
281 M: ast-word (literal)
283 "factor.get_word(\"" ,
289 "factor.find_word(\"" , ast-word-value , "\")" ,
292 M: ast-word (compile)
293 "factor.push_data(" ,
297 M: ast-comment (compile)
300 M: ast-stack-effect (compile)
313 M: ast-using (compile)
322 GENERIC: (parse-factor-quotation) ( object -- ast )
324 M: number (parse-factor-quotation) ( object -- ast )
327 M: symbol (parse-factor-quotation) ( object -- ast )
328 dup >string swap word-vocabulary <ast-identifier> ;
330 M: word (parse-factor-quotation) ( object -- ast )
331 dup word-name swap word-vocabulary <ast-identifier> ;
333 M: string (parse-factor-quotation) ( object -- ast )
336 M: quotation (parse-factor-quotation) ( object -- ast )
338 [ (parse-factor-quotation) , ] each
339 ] { } make <ast-quotation> ;
341 M: array (parse-factor-quotation) ( object -- ast )
343 [ (parse-factor-quotation) , ] each
344 ] { } make <ast-array> ;
346 M: hashtable (parse-factor-quotation) ( object -- ast )
348 [ (parse-factor-quotation) , ] each
349 ] { } make <ast-hashtable> ;
351 M: wrapper (parse-factor-quotation) ( object -- ast )
352 wrapped dup word-name swap word-vocabulary <ast-word> ;
354 GENERIC: fjsc-parse ( object -- ast )
356 M: string fjsc-parse ( object -- ast )
357 'expression' parse parse-result-ast ;
359 M: quotation fjsc-parse ( object -- ast )
361 [ (parse-factor-quotation) , ] each
362 ] { } make <ast-expression> ;
364 : fjsc-compile ( ast -- string )
370 ] { } make [ write ] each
373 : fjsc-compile* ( string -- string )
374 'statement' parse parse-result-ast fjsc-compile ;
376 : fc* ( string -- string )
378 'statement' parse parse-result-ast ast-expression-values do-expressions
379 ] { } make [ write ] each ;
382 : fjsc-literal ( ast -- string )
384 [ (literal) ] { } make [ write ] each