]> gitweb.factorcode.org Git - factor.git/blob - core/parser/parser.factor
Fix comments to be ! not #!.
[factor.git] / core / parser / parser.factor
1 ! Copyright (C) 2005, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs classes combinators
4 compiler.units continuations definitions effects io
5 io.encodings.utf8 io.files kernel lexer math.parser namespaces
6 parser.notes quotations sequences sets slots source-files
7 vectors vocabs vocabs.parser words words.symbol ;
8 IN: parser
9
10 : location ( -- loc )
11     current-source-file get lexer get line>> 2dup and
12     [ [ path>> ] dip 2array ] [ 2drop f ] if ;
13
14 : save-location ( definition -- )
15     location remember-definition ;
16
17 M: parsing-word stack-effect drop ( parsed -- parsed ) ;
18
19 : create-word-in ( str -- word )
20     current-vocab create-word dup set-last-word dup save-location ;
21
22 SYMBOL: auto-use?
23
24 : auto-use ( -- ) auto-use? on ;
25
26 : no-word-restarted ( restart-value -- word )
27     dup word? [
28         dup vocabulary>>
29         [ auto-use-vocab ]
30         [ "Added \"" "\" vocabulary to search path" surround note. ] bi
31     ] [ create-word-in ] if ;
32
33 : ignore-forwards ( seq -- seq' )
34     [ forward-reference? ] reject ;
35
36 : private? ( word -- ? ) vocabulary>> ".private" tail? ;
37
38 : use-first-word? ( words -- ? )
39     [ length 1 = ] [ ?first dup [ private? not ] [ ] ?if ] bi and
40     auto-use? get and ;
41
42 ! True branch is a singleton public word with no name conflicts
43 ! False branch, singleton private words need confirmation regardless
44 ! of name conflicts
45 : no-word ( name -- newword )
46     dup words-named ignore-forwards
47     dup use-first-word? [ nip first ] [ <no-word-error> throw-restarts ] if
48     no-word-restarted ;
49
50 : parse-word ( string -- word )
51     dup search [ ] [ no-word ] ?if ;
52
53 ERROR: number-expected ;
54
55 : parse-number ( string -- number )
56     string>number [ number-expected ] unless* ;
57
58 : parse-datum ( string -- word/number )
59     dup search [ ] [
60         dup string>number [ ] [ no-word ] ?if
61     ] ?if ;
62
63 : ?scan-datum ( -- word/number/f )
64     ?scan-token dup [ parse-datum ] when ;
65
66 : scan-datum ( -- word/number )
67     ?scan-datum [ \ word throw-unexpected-eof ] unless* ;
68
69 : scan-word ( -- word )
70     ?scan-token parse-word ;
71
72 : scan-number ( -- number )
73     ?scan-token parse-number ;
74
75 ERROR: invalid-word-name string ;
76
77 : check-word-name ( string -- string )
78     dup "\"" = [ t ] [ dup string>number ] if
79     [ invalid-word-name ] when ;
80
81 : scan-word-name ( -- string )
82     scan-token check-word-name ;
83
84 : scan-new ( -- word )
85     scan-word-name create-word-in ;
86
87 : scan-new-word ( -- word )
88     scan-new dup reset-generic ;
89
90 ERROR: staging-violation word ;
91
92 : (execute-parsing) ( accum word -- accum )
93     dup push-parsing-word
94     execute( accum -- accum )
95     pop-parsing-word ; inline
96
97 : execute-parsing ( accum word -- accum )
98     dup changed-definitions get in? [ staging-violation ] when
99     (execute-parsing) ;
100
101 : scan-object ( -- object )
102     scan-datum
103     dup parsing-word? [
104         V{ } clone swap execute-parsing first
105     ] when ;
106
107 : scan-class ( -- class )
108     scan-object \ f or ;
109
110 : parse-until-step ( accum end -- accum ? )
111     ?scan-datum {
112         { [ 2dup eq? ] [ 2drop f ] }
113         { [ dup not ] [ drop throw-unexpected-eof t ] }
114         { [ dup delimiter? ] [ unexpected t ] }
115         { [ dup parsing-word? ] [ nip execute-parsing t ] }
116         [ pick push drop t ]
117     } cond ;
118
119 : (parse-until) ( accum end -- accum )
120     [ parse-until-step ] keep swap [ (parse-until) ] [ drop ] if ;
121
122 : parse-until ( end -- vec )
123     100 <vector> swap (parse-until) ;
124
125 SYMBOL: quotation-parser
126
127 HOOK: parse-quotation quotation-parser ( -- quot )
128
129 M: f parse-quotation \ ] parse-until >quotation ;
130
131 : (parse-lines) ( lexer -- quot )
132     [ f parse-until >quotation ] with-lexer ;
133
134 : parse-lines ( lines -- quot )
135     >array <lexer> (parse-lines) ;
136
137 : parse-literal ( accum end quot -- accum )
138     [ parse-until ] dip call suffix! ; inline
139
140 : parse-definition ( -- quot )
141     \ ; parse-until >quotation ;
142
143 ERROR: bad-number ;
144
145 : scan-base ( base -- n )
146     scan-token swap base> [ bad-number ] unless* ;
147
148 SYMBOL: bootstrap-syntax
149
150 : with-file-vocabs ( quot -- )
151     [
152         "syntax" use-vocab
153         bootstrap-syntax get [ use-words ] when*
154         call
155     ] with-manifest ; inline
156
157 SYMBOL: print-use-hook
158
159 print-use-hook [ [ ] ] initialize
160
161 : parse-fresh ( lines -- quot )
162     [
163         parse-lines
164         auto-used? [ print-use-hook get call( -- ) ] when
165     ] with-file-vocabs ;
166
167 : parsing-file ( path -- )
168     parser-quiet? get [ drop ] [ "Loading " write print flush ] if ;
169
170 : filter-moved ( set1 set2 -- seq )
171     swap diff members [
172         {
173             { [ dup where dup [ first ] when current-source-file get path>> = not ] [ f ] }
174             { [ dup reader-method? ] [ f ] }
175             { [ dup writer-method? ] [ f ] }
176             [ t ]
177         } cond nip
178     ] filter ;
179
180 : removed-definitions ( -- set1 set2 )
181     new-definitions old-definitions
182     [ get first2 union ] bi@ ;
183
184 : removed-classes ( -- set1 set2 )
185     new-definitions old-definitions
186     [ get second ] bi@ ;
187
188 : forget-removed-definitions ( -- )
189     removed-definitions filter-moved forget-all ;
190
191 : reset-removed-classes ( -- )
192     removed-classes
193     filter-moved [ class? ] filter [ forget-class ] each ;
194
195 : fix-class-words ( -- )
196     ! If a class word had a compound definition which was
197     ! removed, it must go back to being a symbol.
198     new-definitions get first2
199     filter-moved [ [ reset-generic ] [ define-symbol ] bi ] each ;
200
201 : forget-smudged ( -- )
202     forget-removed-definitions
203     reset-removed-classes
204     fix-class-words ;
205
206 : finish-parsing ( lines quot -- )
207     current-source-file get
208     [ record-top-level-form ]
209     [ record-definitions ]
210     [ record-checksum ]
211     tri ;
212
213 : parse-stream ( stream name -- quot )
214     [
215         [
216             stream-lines dup parse-fresh
217             [ nip ] [ finish-parsing ] 2bi
218             forget-smudged
219         ] with-source-file
220     ] with-compilation-unit ;
221
222 : parse-file-restarts ( path -- restarts )
223     "Load " " again" surround t 2array 1array ;
224
225 : parse-file ( path -- quot )
226     [
227         [ parsing-file ] keep
228         [ utf8 <file-reader> ] keep
229         parse-stream
230     ] [
231         over parse-file-restarts rethrow-restarts
232         drop parse-file
233     ] recover ;
234
235 : run-file ( path -- )
236     parse-file call( -- ) ;
237
238 : ?run-file ( path -- )
239     dup exists? [ run-file ] [ drop ] if ;
240
241 ERROR: version-control-merge-conflict ;