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