1 ! Copyright (C) 2006 Chris Double. All Rights Reserved.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel lazy-lists parser-combinators parser-combinators.simple
4 strings promises sequences math math.parser namespaces words
5 quotations arrays hashtables io io.streams.string assocs ;
8 TUPLE: ast-number value ;
9 C: <ast-number> ast-number
11 TUPLE: ast-identifier value vocab ;
12 C: <ast-identifier> ast-identifier
14 TUPLE: ast-string value ;
15 C: <ast-string> ast-string
17 TUPLE: ast-quotation values ;
18 C: <ast-quotation> ast-quotation
20 TUPLE: ast-array elements ;
21 C: <ast-array> ast-array
23 TUPLE: ast-define name stack-effect expression ;
24 C: <ast-define> ast-define
26 TUPLE: ast-expression values ;
27 C: <ast-expression> ast-expression
29 TUPLE: ast-word value vocab ;
30 C: <ast-word> ast-word
33 C: <ast-comment> ast-comment
35 TUPLE: ast-stack-effect in out ;
36 C: <ast-stack-effect> ast-stack-effect
41 TUPLE: ast-using names ;
42 C: <ast-using> ast-using
47 TUPLE: ast-hashtable elements ;
48 C: <ast-hashtable> ast-hashtable
50 : identifier-middle? ( ch -- bool )
52 [ CHAR: } = not ] keep
53 [ CHAR: ] = not ] keep
54 [ CHAR: ;" = not ] keep
55 [ CHAR: " = not ] keep
59 LAZY: 'identifier-ends' ( -- parser )
62 [ CHAR: " = not ] keep
63 [ CHAR: ;" = not ] keep
66 identifier-middle? not
70 LAZY: 'identifier-middle' ( -- parser )
71 [ identifier-middle? ] satisfy <!+> ;
73 LAZY: 'identifier' ( -- parser )
75 'identifier-middle' <&>
76 'identifier-ends' <:&>
77 [ concat >string f <ast-identifier> ] <@ ;
82 LAZY: 'effect-name' ( -- parser )
87 ] satisfy <!+> [ >string ] <@ ;
89 LAZY: 'stack-effect' ( -- parser )
91 'effect-name' sp <*> &>
93 'effect-name' sp <*> <&>
94 ")" token sp <& [ first2 <ast-stack-effect> ] <@ ;
96 LAZY: 'define' ( -- parser )
98 'identifier' sp [ ast-identifier-value ] <@ &>
99 'stack-effect' sp <!?> <&>
101 ";" token sp <& [ first3 <ast-define> ] <@ ;
103 LAZY: 'quotation' ( -- parser )
105 'expression' [ ast-expression-values ] <@ &>
106 "]" token sp <& [ <ast-quotation> ] <@ ;
108 LAZY: 'array' ( -- parser )
110 'expression' [ ast-expression-values ] <@ &>
111 "}" token sp <& [ <ast-array> ] <@ ;
113 LAZY: 'word' ( -- parser )
115 'identifier' sp &> [ ast-identifier-value f <ast-word> ] <@ ;
117 LAZY: 'atom' ( -- parser )
118 'identifier' 'integer' [ <ast-number> ] <@ <|> 'string' [ <ast-string> ] <@ <|> ;
120 LAZY: 'comment' ( -- parser )
123 dup CHAR: \n = swap CHAR: \r = or not
124 ] satisfy <*> <&> [ drop <ast-comment> ] <@ ;
126 LAZY: 'USE:' ( -- parser )
128 'identifier' sp &> [ ast-identifier-value <ast-use> ] <@ ;
130 LAZY: 'IN:' ( -- parser )
132 'identifier' sp &> [ ast-identifier-value <ast-in> ] <@ ;
134 LAZY: 'USING:' ( -- parser )
136 'identifier' sp [ ast-identifier-value ] <@ <+> &>
137 ";" token sp <& [ <ast-using> ] <@ ;
139 LAZY: 'hashtable' ( -- parser )
141 'expression' [ ast-expression-values ] <@ &>
142 "}" token sp <& [ <ast-hashtable> ] <@ ;
144 LAZY: 'parsing-word' ( -- parser )
149 LAZY: 'expression' ( -- parser )
151 'parsing-word' sp <|>
158 <*> [ <ast-expression> ] <@ ;
160 LAZY: 'statement' ( -- parser )
163 GENERIC: (compile) ( ast -- )
164 GENERIC: (literal) ( ast -- )
166 M: ast-number (literal)
167 ast-number-value number>string , ;
169 M: ast-number (compile)
170 "factor.push_data(" ,
174 M: ast-string (literal)
179 M: ast-string (compile)
180 "factor.push_data(" ,
184 M: ast-identifier (literal)
185 dup ast-identifier-vocab [
186 "factor.get_word(\"" ,
187 dup ast-identifier-vocab ,
189 ast-identifier-value ,
192 "factor.find_word(\"" , ast-identifier-value , "\")" ,
195 M: ast-identifier (compile)
196 (literal) ".execute(" , ;
198 M: ast-define (compile)
199 "factor.define_word(\"" ,
200 dup ast-define-name ,
202 ast-define-expression (compile)
205 : do-expressions ( seq -- )
208 dup ast-comment? not [
217 drop "factor.cont.next" ,
220 M: ast-quotation (literal)
221 "factor.make_quotation(\"source\"," ,
222 ast-quotation-values do-expressions
225 M: ast-quotation (compile)
226 "factor.push_data(factor.make_quotation(\"source\"," ,
227 ast-quotation-values do-expressions
230 M: ast-array (literal)
232 ast-array-elements [ "," , ] [ (literal) ] interleave
235 M: ast-array (compile)
236 "factor.push_data(" , (literal) "," , ;
238 M: ast-hashtable (literal)
239 "new Hashtable().fromAlist([" ,
240 ast-hashtable-elements [ "," , ] [ (literal) ] interleave
243 M: ast-hashtable (compile)
244 "factor.push_data(" , (literal) "," , ;
247 M: ast-expression (literal)
248 ast-expression-values [
252 M: ast-expression (compile)
253 ast-expression-values do-expressions ;
255 M: ast-word (literal)
257 "factor.get_word(\"" ,
263 "factor.find_word(\"" , ast-word-value , "\")" ,
266 M: ast-word (compile)
267 "factor.push_data(" ,
271 M: ast-comment (compile)
274 M: ast-stack-effect (compile)
287 M: ast-using (compile)
296 GENERIC: (parse-factor-quotation) ( object -- ast )
298 M: number (parse-factor-quotation) ( object -- ast )
301 M: symbol (parse-factor-quotation) ( object -- ast )
302 dup >string swap word-vocabulary <ast-identifier> ;
304 M: word (parse-factor-quotation) ( object -- ast )
305 dup word-name swap word-vocabulary <ast-identifier> ;
307 M: string (parse-factor-quotation) ( object -- ast )
310 M: quotation (parse-factor-quotation) ( object -- ast )
312 [ (parse-factor-quotation) , ] each
313 ] { } make <ast-quotation> ;
315 M: array (parse-factor-quotation) ( object -- ast )
317 [ (parse-factor-quotation) , ] each
318 ] { } make <ast-array> ;
320 M: hashtable (parse-factor-quotation) ( object -- ast )
322 [ (parse-factor-quotation) , ] each
323 ] { } make <ast-hashtable> ;
325 M: wrapper (parse-factor-quotation) ( object -- ast )
326 wrapped dup word-name swap word-vocabulary <ast-word> ;
328 GENERIC: fjsc-parse ( object -- ast )
330 M: string fjsc-parse ( object -- ast )
331 'expression' parse-1 ;
333 M: quotation fjsc-parse ( object -- ast )
335 [ (parse-factor-quotation) , ] each
336 ] { } make <ast-expression> ;
338 : fjsc-compile ( ast -- string )
344 ] { } make [ write ] each
347 : fjsc-compile* ( string -- string )
348 'statement' parse-1 fjsc-compile ;
350 : fc* ( string -- string )
352 'statement' parse-1 ast-expression-values do-expressions
353 ] { } make [ write ] each ;
356 : fjsc-literal ( ast -- string )
358 [ (literal) ] { } make [ write ] each