]> gitweb.factorcode.org Git - factor.git/blob - core/parser/parser-docs.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / core / parser / parser-docs.factor
1 USING: help.markup help.syntax kernel sequences words
2 math strings vectors quotations generic effects classes
3 vocabs.loader definitions io vocabs source-files
4 quotations namespaces compiler.units assocs ;
5 IN: parser
6
7 ARTICLE: "vocabulary-search-shadow" "Shadowing word names"
8 "If adding a vocabulary to the search path results in a word in another vocabulary becoming inaccessible due to the new vocabulary defining a word with the same name, we say that the old word has been " { $emphasis "shadowed" } "."
9 $nl
10 "Here is an example where shadowing occurs:"
11 { $code
12     "IN: foe"
13     "USING: sequences io ;"
14     ""
15     ": append"
16     "    \"foe::append calls sequences:append\" print  append ;"
17     ""
18     "IN: fee"
19     ""
20     ": append"
21     "    \"fee::append calls fee:append\" print  append ;"
22     ""
23     "IN: fox"
24     "USE: foe"
25     ""
26     ": append"
27     "    \"fox::append calls foe:append\" print  append ;"
28     ""
29     "\"1234\" \"5678\" append print"
30     ""
31     "USE: fox"
32     "\"1234\" \"5678\" append print"
33 }
34 "When placed in a source file and run, the above code produces the following output:"
35 { $code
36     "foe:append calls sequences:append"
37     "12345678"
38     "fee:append calls foe:append"
39     "foe:append calls sequences:append"
40     "12345678"
41 }
42 "The " { $vocab-link "qualified" } " vocabulary contains some tools for helping with shadowing." ;
43
44 ARTICLE: "vocabulary-search-errors" "Word lookup errors"
45 "If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies. Then, one of three things happen:"
46 { $list
47     { "If there are no words having this name at all, an error is thrown and parsing stops." }
48     { "If there are vocabularies which contain words with this name, a restartable error is thrown, with a restart for each vocabulary in question. The restarts add the vocabulary to the search path and continue parsing." }
49 }
50 "When writing a new vocabulary, one approach is to ignore " { $link POSTPONE: USING: } " declarations altogether, then to load the vocabulary and observe any parser notes and restarts and use this information to write the correct " { $link POSTPONE: USING: } " declaration." ;
51
52 ARTICLE: "vocabulary-search" "Vocabulary search path"
53 "When the parser reads a token, it attempts to look up a word named by that token. The lookup is performed by searching each vocabulary in the search path, in order."
54 $nl
55 "For a source file the vocabulary search path starts off with one vocabulary:"
56 { $code "syntax" }
57 "The " { $vocab-link "syntax" } " vocabulary consists of a set of parsing words for reading Factor data and defining new words."
58 $nl
59 "In the listener, the " { $vocab-link "scratchpad" } " is the default vocabulary for new word definitions. However, when loading source files, there is no default vocabulary. Defining words before declaring a vocabulary with " { $link POSTPONE: IN: } " results in an error."
60 $nl
61 "At the interactive listener, the default search path contains many more vocabularies. Details on the default search path and parser invocation are found in " { $link "parser" } "."
62 $nl
63 "Three parsing words deal with the vocabulary search path:"
64 { $subsection POSTPONE: USE: }
65 { $subsection POSTPONE: USING: }
66 { $subsection POSTPONE: IN: }
67 "Private words can be defined; note that this is just a convention and they can be called from other vocabularies anyway:"
68 { $subsection POSTPONE: <PRIVATE }
69 { $subsection POSTPONE: PRIVATE> }
70 { $subsection "vocabulary-search-errors" }
71 { $subsection "vocabulary-search-shadow" }
72 { $see-also "words" } ;
73
74 ARTICLE: "reading-ahead" "Reading ahead"
75 "Parsing words can consume input:"
76 { $subsection scan }
77 { $subsection scan-word }
78 "For example, the " { $link POSTPONE: HEX: } " word uses this feature to read hexadecimal literals:"
79 { $see POSTPONE: HEX: }
80 "It is defined in terms of a lower-level word that takes the numerical base on the data stack, but reads the number from the parser and then adds it to the parse tree:"
81 { $see parse-base }
82 "Another simple example is the " { $link POSTPONE: \ } " word:"
83 { $see POSTPONE: \ } ;
84
85 ARTICLE: "parsing-word-nest" "Nested structure"
86 "Recall that the parser loop calls parsing words with an accumulator vector on the stack. The parser loop can be invoked recursively with a new, empty accumulator; the result can then be added to the original accumulator. This is how parsing words for object literals are implemented; object literals can nest arbitrarily deep."
87 $nl
88 "A simple example is the parsing word that reads a quotation:"
89 { $see POSTPONE: [ }
90 "This word uses a utility word which recursively invokes the parser, reading objects into a new accumulator until an occurrence of " { $link POSTPONE: ] } ":"
91 { $subsection parse-literal }
92 "There is another, lower-level word for reading nested structure, which is also useful when called directly:"
93 { $subsection parse-until }
94 "Words such as " { $link POSTPONE: ] } " use a declaration which causes them to throw an error when an unpaired occurrence is encountered:"
95 { $subsection POSTPONE: delimiter }
96 { $see-also POSTPONE: { POSTPONE: H{ POSTPONE: V{ POSTPONE: W{ POSTPONE: T{ POSTPONE: } } ;
97
98 ARTICLE: "defining-words" "Defining words"
99 "Defining words add definitions to the dictionary without modifying the parse tree. The simplest example is the " { $link POSTPONE: SYMBOL: } " word."
100 { $see POSTPONE: SYMBOL: }
101 "The key factor in the definition of " { $link POSTPONE: SYMBOL: } " is " { $link CREATE } ", which reads a token from the input and creates a word with that name. This word is then passed to " { $link define-symbol } "."
102 { $subsection CREATE }
103 "Colon definitions are defined in a more elaborate way:"
104 { $subsection POSTPONE: : }
105 "The " { $link POSTPONE: : } " word first calls " { $link CREATE } ", and then reads input until reaching " { $link POSTPONE: ; } " using a utility word:"
106 { $subsection parse-definition }
107 "The " { $link POSTPONE: ; } " word is just a delimiter; an unpaired occurrence throws a parse error:"
108 { $see POSTPONE: ; }
109 "There are additional parsing words whose syntax is delimited by  " { $link POSTPONE: ; } ", and they are all implemented by calling " { $link parse-definition } "." ;
110
111 ARTICLE: "parsing-tokens" "Parsing raw tokens"
112 "So far we have seen how to read individual tokens, or read a sequence of parsed objects until a delimiter. It is also possible to read raw tokens from the input and perform custom processing."
113 $nl
114 "One example is the " { $link POSTPONE: USING: } " parsing word."
115 { $see POSTPONE: USING: } 
116 "It reads a list of vocabularies terminated by " { $link POSTPONE: ; } ". However, the vocabulary names do not name words, except by coincidence; so " { $link parse-until } " cannot be used here. Instead, a lower-level word is called:"
117 { $subsection parse-tokens } ;
118
119 ARTICLE: "parsing-words" "Parsing words"
120 "The Factor parser is follows a simple recursive-descent design. The parser reads successive tokens from the input; if the token identifies a number or an ordinary word, it is added to an accumulator vector. Otherwise if the token identifies a parsing word, the parsing word is executed immediately."
121 $nl
122 "Parsing words are marked by suffixing the definition with a " { $link POSTPONE: parsing } " declaration. Here is the simplest possible parsing word; it prints a greeting at parse time:"
123 { $code ": hello \"Hello world\" print ; parsing" }
124 "Parsing words must have stack effect " { $snippet "( accum -- accum )" } ", where " { $snippet "accum" } " is the accumulator vector supplied by the parser. Parsing words can read input, add word definitions to the dictionary, and do anything an ordinary word can."
125 $nl
126 "Parsing words cannot be called from the same source file where they are defined, because new definitions are only compiled at the end of the source file. An attempt to use a parsing word in its own source file raises an error:"
127 { $link staging-violation }
128 "Tools for implementing parsing words:"
129 { $subsection "reading-ahead" }
130 { $subsection "parsing-word-nest" }
131 { $subsection "defining-words" }
132 { $subsection "parsing-tokens" } ;
133
134 ARTICLE: "parser-lexer" "The lexer"
135 "Two variables that encapsulate internal parser state:"
136 { $subsection file }
137 { $subsection lexer }
138 "Creating a default lexer:"
139 { $subsection <lexer> }
140 "A word to test of the end of input has been reached:"
141 { $subsection still-parsing? }
142 "A word to advance the lexer to the next line:"
143 { $subsection next-line }
144 "Two generic words to override the lexer's token boundary detection:"
145 { $subsection skip-blank }
146 { $subsection skip-word }
147 "A utility used when parsing string literals:"
148 { $subsection parse-string }
149 "The parser can be invoked with a custom lexer:"
150 { $subsection (parse-lines) }
151 { $subsection with-parser } ;
152
153 ARTICLE: "parser-files" "Parsing source files"
154 "The parser can run source files:"
155 { $subsection run-file }
156 { $subsection parse-file }
157 { $subsection bootstrap-file }
158 "The parser cross-references source files and definitions. This allows it to keep track of removed definitions, and prevent forward references and accidental redefinitions."
159 $nl
160 "While the above words are useful for one-off experiments, real programs should be written to use the vocabulary system instead; see " { $link "vocabs.loader" } "."
161 { $see-also "source-files" } ;
162
163 ARTICLE: "parser-usage" "Reflective parser usage"
164 "The parser can be called on a string:"
165 { $subsection eval }
166 "The parser can also parse from a stream:"
167 { $subsection parse-stream } ;
168
169 ARTICLE: "top-level-forms" "Top level forms"
170 "Any code outside of a definition is known as a " { $emphasis "top-level form" } "; top-level forms are run after the entire source file has been parsed, regardless of their position in the file."
171 $nl
172 "Top-level forms do not have access to the " { $link in } " and " { $link use } " variables that were set at parse time, nor do they run inside " { $link with-compilation-unit } "; so meta-programming might require extra work in a top-level form compared with a parsing word."
173 $nl
174 "Also, top-level forms run in a new dynamic scope, so using " { $link set } " to store values is almost always wrong, since the values will be lost after the top-level form completes. To save values computed by a top-level form, either use " { $link set-global } " or define a new word with the value." ;
175
176 ARTICLE: "parser" "The parser"
177 "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies."
178 $nl
179 "This section concerns itself with usage and extension of the parser. Standard syntax is described in " { $link "syntax" } "."
180 { $subsection "vocabulary-search" }
181 { $subsection "parser-files" }
182 { $subsection "parser-usage" }
183 { $subsection "top-level-forms" }
184 "The parser can be extended."
185 { $subsection "parsing-words" }
186 { $subsection "parser-lexer" }
187 { $see-also "definitions" "definition-checking" } ;
188
189 ABOUT: "parser"
190
191 : $parsing-note ( children -- )
192     drop
193     "This word should only be called from parsing words."
194     $notes ;
195
196 HELP: lexer
197 { $var-description "Stores the current " { $link lexer } " instance." }
198 { $class-description "An object for tokenizing parser input. It has the following slots:"
199     { $list
200         { { $link lexer-text } " - the lines being parsed; an array of strings" }
201         { { $link lexer-line } " - the line number being parsed; unlike most indices this is 1-based for friendlier error reporting and integration with text editors" }
202         { { $link lexer-column } " - the current column position, zero-based" }
203     }
204 "Custom lexing can be implemented by delegating a tuple to an instance of this class and implementing the " { $link skip-word } " and " { $link skip-blank } " generic words." } ;
205
206 HELP: <lexer>
207 { $values { "text" "a sequence of strings" } { "lexer" lexer } }
208 { $description "Creates a new lexer for tokenizing the given sequence of lines." } ;
209
210 HELP: location
211 { $values { "loc" "a " { $snippet "{ path line# }" } " pair" } }
212 { $description "Outputs the current parser location. This value can be passed to " { $link set-where } " or " { $link remember-definition } "." } ;
213
214 HELP: save-location
215 { $values { "definition" "a definition specifier" } }
216 { $description "Saves the location of a definition and associates this definition with the current source file." } ;
217
218 HELP: parser-notes
219 { $var-description "A boolean controlling whether the parser will print various notes and warnings. Switched on by default. If a source file is being run for its effect on " { $link output-stream } ", this variable should be switched off, to prevent parser notes from polluting the output." } ;
220
221 HELP: parser-notes?
222 { $values { "?" "a boolean" } }
223 { $description "Tests if the parser will print various notes and warnings. To disable parser notes, either set " { $link parser-notes } " to " { $link f } ", or pass the " { $snippet "-quiet" } " command line switch." } ;
224
225 HELP: next-line
226 { $values { "lexer" lexer } }
227 { $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ;
228
229 HELP: parse-error
230 { $error-description "Thrown when the parser encounters invalid input. A parse error wraps an underlying error and holds the file being parsed, line number, and column number." } ;
231
232 HELP: <parse-error>
233 { $values { "msg" "an error" } { "error" parse-error } }
234 { $description "Creates a new " { $link parse-error } ", filling in the location information from the current " { $link lexer } "." } ;
235
236 HELP: skip
237 { $values { "i" "a starting index" } { "seq" sequence } { "?" "a boolean" } { "n" integer } }
238 { $description "Skips to the first space character (if " { $snippet "boolean" } " is " { $link f } ") or the first non-space character (otherwise)." } ;
239
240 HELP: change-lexer-column
241 { $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( col line -- newcol )" } } }
242 { $description "Applies a quotation to the current column and line text to produce a new column, and moves the lexer position." } ;
243
244 HELP: skip-blank
245 { $values { "lexer" lexer } }
246 { $contract "Skips whitespace characters." }
247 { $notes "Custom lexers can implement this generic word." } ;
248
249 HELP: skip-word
250 { $values { "lexer" lexer } }
251 { $contract
252     "Skips until the end of the current token."
253     $nl
254     "The default implementation treats a single " { $snippet "\"" } " as a word by itself; otherwise it searches forward until a whitespace character or the end of the line."
255 }
256 { $notes "Custom lexers can implement this generic word." } ;
257
258 HELP: still-parsing-line?
259 { $values { "lexer" lexer } { "?" "a boolean" } }
260 { $description "Outputs " { $link f } " if the end of the current line has been reached, " { $link t } " otherwise." } ;
261
262 HELP: parse-token
263 { $values { "lexer" lexer } { "str/f" "a " { $link string } " or " { $link f } } }
264 { $description "Reads the next token from the lexer. Tokens are delimited by whitespace, with the exception that " { $snippet "\"" } " is treated like a single token even when not followed by whitespace." } ;
265
266 HELP: scan
267 { $values { "str/f" "a " { $link string } " or " { $link f } } }
268 { $description "Reads the next token from the lexer. See " { $link parse-token } " for details." }
269 $parsing-note ;
270
271 HELP: bad-escape
272 { $error-description "Indicates the parser encountered an invalid escape code following a backslash (" { $snippet "\\" } ") in a string literal. See " { $link "escape" } " for a list of valid escape codes." } ;
273
274 HELP: bad-number
275 { $error-description "Indicates the parser encountered an invalid numeric literal." } ;
276
277 HELP: escape
278 { $values { "escape" "a single-character escape" } { "ch" "a character" } }
279 { $description "Converts from a single-character escape code and the corresponding character." }
280 { $examples { $example "USING: kernel parser prettyprint ;" "CHAR: n escape CHAR: \\n = ." "t" } } ;
281
282 HELP: parse-string
283 { $values { "str" "a new " { $link string } } }
284 { $description "Parses the line until a quote (\"), interpreting escape codes along the way." }
285 { $errors "Throws an error if the string contains an invalid escape sequence." }
286 $parsing-note ;
287
288 HELP: still-parsing?
289 { $values { "lexer" lexer } { "?" "a boolean" } }
290 { $description "Outputs " { $link f } " if end of input has been reached, " { $link t } " otherwise." } ;
291
292 HELP: use
293 { $var-description "A variable holding the current vocabulary search path as a sequence of assocs." } ;
294
295 { use in use+ (use+) set-use set-in POSTPONE: USING: POSTPONE: USE: with-file-vocabs with-interactive-vocabs } related-words
296
297 HELP: in
298 { $var-description "A variable holding the name of the current vocabulary for new definitions." } ;
299
300 HELP: current-vocab
301 { $values { "str" "a vocabulary" } }
302 { $description "Returns the vocabulary stored in the " { $link in } " symbol. Throws an error if the current vocabulary is " { $link f } "." } ;
303
304 HELP: (use+)
305 { $values { "vocab" "an assoc mapping strings to words" } }
306 { $description "Adds an assoc at the front of the search path." }
307 $parsing-note ;
308
309 HELP: use+
310 { $values { "vocab" string } }
311 { $description "Adds a new vocabulary at the front of the search path after loading it if necessary. Subsequent word lookups by the parser will search this vocabulary first." }
312 $parsing-note
313 { $errors "Throws an error if the vocabulary does not exist." } ;
314
315 HELP: set-use
316 { $values { "seq" "a sequence of strings" } }
317 { $description "Sets the vocabulary search path. Later vocabularies take precedence." }
318 { $errors "Throws an error if one of the vocabularies does not exist." }
319 $parsing-note ;
320
321 HELP: add-use
322 { $values { "seq" "a sequence of strings" } }
323 { $description "Adds multiple vocabularies to the search path, with later vocabularies taking precedence." }
324 { $errors "Throws an error if one of the vocabularies does not exist." }
325 $parsing-note ;
326
327 HELP: set-in
328 { $values { "name" string } }
329 { $description "Sets the current vocabulary where new words will be defined, creating the vocabulary first if it does not exist." }
330 $parsing-note ;
331
332 HELP: create-in
333 { $values { "str" "a word name" } { "word" "a new word" } }
334 { $description "Creates a word in the current vocabulary. Until re-defined, the word throws an error when invoked." }
335 $parsing-note ;
336
337 HELP: parse-tokens
338 { $values { "end" string } { "seq" "a new sequence of strings" } }
339 { $description "Reads a sequence of tokens until the first occurrence of " { $snippet "end" } ". The tokens remain as strings and are not processed in any way." }
340 { $examples "This word is used to implement " { $link POSTPONE: USING: } "." }
341 $parsing-note ;
342
343 HELP: CREATE
344 { $values { "word" word } }
345 { $description "Reads the next token from the line currently being parsed, and creates a word with that name in the current vocabulary." }
346 { $errors "Throws an error if the end of the line is reached." }
347 $parsing-note ;
348
349 HELP: no-word-error
350 { $error-description "Thrown if the parser encounters a token which does not name a word in the current vocabulary search path. If any words with this name exist in vocabularies not part of the search path, a number of restarts will offer to add those vocabularies to the search path and use the chosen word." }
351 { $notes "Apart from a missing " { $link POSTPONE: USE: } ", this error can also indicate an ordering issue. In Factor, words must be defined before they can be called. Mutual recursion can be implemented via " { $link POSTPONE: DEFER: } "." } ;
352
353 HELP: no-word
354 { $values { "name" string } { "newword" word } }
355 { $description "Throws a " { $link no-word-error } "." } ;
356
357 HELP: search
358 { $values { "str" string } { "word/f" "a word or " { $link f } } }
359 { $description "Searches for a word by name in the current vocabulary search path. If no such word could be found, outputs " { $link f } "." }
360 $parsing-note ;
361
362 HELP: scan-word
363 { $values { "word/number/f" "a word, number or " { $link f } } }
364 { $description "Reads the next token from parser input. If the token is a valid number literal, it is converted to a number, otherwise the dictionary is searched for a word named by the token. Outputs " { $link f } " if the end of the input has been reached." }
365 { $errors "Throws an error if the token does not name a word, and does not parse as a number." }
366 $parsing-note ;
367
368 HELP: invalid-slot-name
369 { $values { "name" string } }
370 { $description "Throws an " { $link invalid-slot-name } " error." }
371 { $error-description "Thrown by " { $link POSTPONE: TUPLE: } " and " { $link POSTPONE: ERROR: } " if a suspect token appears as a slot name." }
372 { $notes "The suspect tokens are chosen so that the following code raises this parse error, instead of silently greating a tuple with garbage slots:"
373     { $code
374         "TUPLE: my-mistaken-tuple slot-a slot-b"
375         ""
376         ": some-word ( a b c -- ) ... ;"
377     }
378 } ;
379
380 HELP: unexpected
381 { $values { "want" "a " { $link word } " or " { $link f } } { "got" word } }
382 { $description "Throws an " { $link unexpected } " error." }
383 { $error-description "Thrown by the parser if an unmatched closing delimiter is encountered." }
384 { $examples
385     "Parsing the following snippet will throw this error:"
386     { $code "[ 1 2 3 }" }
387 } ;
388
389 HELP: unexpected-eof
390 { $values { "word" "a " { $link word } } }
391 { $description "Throws an " { $link unexpected } " error indicating the parser was looking for an occurrence of " { $snippet "word" } " but encountered end of file." } ;
392
393 HELP: parse-step
394 { $values { "accum" vector } { "end" word } { "?" "a boolean" } }
395 { $description "Parses a token. If the token is a number or an ordinary word, it is added to the accumulator. If it is a parsing word, calls the parsing word with the accumulator on the stack. Outputs " { $link f } " if " { $snippet "end" } " is encountered, " { $link t } " otherwise." }
396 $parsing-note ;
397
398 HELP: (parse-until)
399 { $values { "accum" vector } { "end" word } }
400 { $description "Parses objects from parser input until " { $snippet "end" } " is encountered, adding them to the accumulator." }
401 $parsing-note ;
402
403 HELP: parse-until
404 { $values { "end" word } { "vec" "a new vector" } }
405 { $description "Parses objects from parser input until " { $snippet "end" } ". Outputs a new vector with the results." }
406 { $examples "This word is used to implement " { $link POSTPONE: ARTICLE: } "." }
407 $parsing-note ;
408
409 { parse-tokens (parse-until) parse-until } related-words
410
411 HELP: parsed
412 { $values { "accum" vector } { "obj" object } }
413 { $description "Convenience word for parsing words. It behaves exactly the same as " { $link push } ", except the accumulator remains on the stack." }
414 $parsing-note ;
415
416 HELP: with-parser
417 { $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( -- accum )" } } { "newquot" "a new " { $link quotation } } }
418 { $description "Sets up the parser and calls the quotation. The quotation can make use of parsing words such as " { $link scan } " and " { $link parse-until } ". It must yield a sequence, which is converted to a quotation and output. Any errors thrown by the quotation are wrapped in parse errors." } ;
419
420 HELP: (parse-lines)
421 { $values { "lexer" lexer } { "quot" "a new " { $link quotation } } }
422 { $description "Parses Factor source code using a custom lexer. The vocabulary search path is taken from the current scope." }
423 { $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
424
425 HELP: parse-lines
426 { $values { "lines" "a sequence of strings" } { "quot" "a new " { $link quotation } } }
427 { $description "Parses Factor source code which has been tokenized into lines. The vocabulary search path is taken from the current scope." }
428 { $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
429
430 HELP: lexer-factory
431 { $var-description "A variable holding a quotation with stack effect " { $snippet "( lines -- lexer )" } ". This quotation is called by the parser to create " { $link lexer } " instances. This variable can be rebound to a quotation which outputs a custom tuple delegating to " { $link lexer } " to customize syntax." } ;
432
433 HELP: parse-effect
434 { $values { "end" string } { "effect" "an instance of " { $link effect } } }
435 { $description "Parses a stack effect from the current input line." }
436 { $examples "This word is used by " { $link POSTPONE: ( } " and " { $link POSTPONE: (( } " to parse stack effect declarations." }
437 $parsing-note ;
438
439 HELP: parse-base
440 { $values { "base" "an integer between 2 and 36" } { "parsed" integer } }
441 { $description "Reads an integer in a specific numerical base from the parser input." }
442 $parsing-note ;
443
444 HELP: parse-literal
445 { $values { "accum" vector } { "end" word } { "quot" "a quotation with stack effect " { $snippet "( seq -- obj )" } } }
446 { $description "Parses objects from parser input until " { $snippet "end" } ", applies the quotation to the resulting sequence, and adds the output value to the accumulator." }
447 { $examples "This word is used to implement " { $link POSTPONE: [ } "." }
448 $parsing-note ;
449
450 HELP: parse-definition
451 { $values { "quot" "a new " { $link quotation } } }
452 { $description "Parses objects from parser input until " { $link POSTPONE: ; } " and outputs a quotation with the results." }
453 { $examples "This word is used to implement " { $link POSTPONE: : } "." }
454 $parsing-note ;
455
456 HELP: bootstrap-syntax
457 { $var-description "Only set during bootstrap. Stores a copy of the " { $link vocab-words } " of the host's syntax vocabulary; this allows the host's parsing words to be used during bootstrap source parsing, not the target's." } ;
458
459 HELP: with-file-vocabs
460 { $values { "quot" quotation } }
461 { $description "Calls the quotation in a scope with the initial the vocabulary search path for parsing a file. This consists of just the " { $snippet "syntax" } " vocabulary." } ;
462
463 HELP: parse-fresh
464 { $values { "lines" "a sequence of strings" } { "quot" quotation } }
465 { $description "Parses Factor source code in a sequence of lines. The initial vocabulary search path is used (see " { $link with-file-vocabs } ")." }
466 { $errors "Throws a parse error if the input is malformed." } ;
467
468 HELP: eval
469 { $values { "str" string } }
470 { $description "Parses Factor source code from a string, and calls the resulting quotation." }
471 { $errors "Throws an error if the input is malformed, or if the evaluation itself throws an error." } ;
472
473 HELP: filter-moved
474 { $values { "assoc1" assoc } { "assoc2" assoc } { "seq" "an seqence of definitions" } }
475 { $description "Removes all definitions from " { $snippet "assoc2" } " which are in " { $snippet "assoc1" } " or are are no longer present in the current " { $link file } "." } ;
476
477 HELP: forget-smudged
478 { $description "Forgets removed definitions and prints a warning message if any of them are still referenced from other source files." } ;
479
480 HELP: finish-parsing
481 { $values { "lines" "the lines of text just parsed" } { "quot" "the quotation just parsed" } }
482 { $description "Records information to the current " { $link file } " and prints warnings about any removed definitions which are still in use." }
483 { $notes "This is one of the factors of " { $link parse-stream } "." } ;
484
485 HELP: parse-stream
486 { $values { "stream" "an input stream" } { "name" "a file name for error reporting and cross-referencing" } { "quot" quotation } }
487 { $description "Parses Factor source code read from the stream. The initial vocabulary search path is used." }
488 { $errors "Throws an I/O error if there was an error reading from the stream. Throws a parse error if the input is malformed." } ;
489
490 HELP: parse-file
491 { $values { "file" "a pathname string" } { "quot" quotation } }
492 { $description "Parses the Factor source code stored in a file. The initial vocabulary search path is used." }
493 { $errors "Throws an I/O error if there was an error reading from the file. Throws a parse error if the input is malformed." } ;
494
495 HELP: run-file
496 { $values { "file" "a pathname string" } }
497 { $description "Parses the Factor source code stored in a file and runs it. The initial vocabulary search path is used." }
498 { $errors "Throws an error if loading the file fails, there input is malformed, or if a runtime error occurs while calling the parsed quotation." }  ;
499
500 HELP: ?run-file
501 { $values { "path" "a pathname string" } }
502 { $description "If the file exists, runs it with " { $link run-file } ", otherwise does nothing." } ;
503
504 HELP: bootstrap-file
505 { $values { "path" "a pathname string" } }
506 { $description "If bootstrapping, parses the source file and adds its top level form to the quotation being constructed with " { $link make } "; the bootstrap code uses this to build up a boot quotation to be run on image startup. If not bootstrapping, just runs the file normally." } ;
507
508 HELP: eval>string
509 { $values { "str" string } { "output" string } }
510 { $description "Evaluates the Factor code in " { $snippet "str" } " with " { $link output-stream } " rebound to a string output stream, then outputs the resulting string." } ;
511
512 HELP: staging-violation
513 { $values { "word" word } }
514 { $description "Throws a " { $link staging-violation } " error." }
515 { $error-description "Thrown by the parser if a parsing word is used in the same compilation unit as where it was defined; see " { $link "compilation-units" } "." }
516 { $notes "One possible workaround is to use the " { $link POSTPONE: << } " word to execute code at parse time. However, executing words defined in the same source file at parse time is still prohibited." } ;