32 poolDictionaries:'' |
32 poolDictionaries:'' |
33 category:'System-Compiler' |
33 category:'System-Compiler' |
34 ! |
34 ! |
35 |
35 |
36 Parser comment:' |
36 Parser comment:' |
37 |
|
38 COPYRIGHT (c) 1989 by Claus Gittinger |
37 COPYRIGHT (c) 1989 by Claus Gittinger |
39 All Rights Reserved |
38 All Rights Reserved |
40 |
|
41 $Header: /cvs/stx/stx/libcomp/Parser.st,v 1.10 1994-03-30 10:10:24 claus Exp $ |
|
42 '! |
39 '! |
43 |
40 |
44 !Parser class methodsFor:'documentation'! |
41 !Parser class methodsFor:'documentation'! |
|
42 |
|
43 copyright |
|
44 " |
|
45 COPYRIGHT (c) 1989 by Claus Gittinger |
|
46 All Rights Reserved |
|
47 |
|
48 This software is furnished under a license and may be used |
|
49 only in accordance with the terms of that license and with the |
|
50 inclusion of the above copyright notice. This software may not |
|
51 be provided or otherwise made available to, or used by, any |
|
52 other person. No title to or ownership of the software is |
|
53 hereby transferred. |
|
54 " |
|
55 ! |
|
56 |
|
57 version |
|
58 " |
|
59 $Header: /cvs/stx/stx/libcomp/Parser.st,v 1.11 1994-06-02 20:26:08 claus Exp $ |
|
60 " |
|
61 ! |
45 |
62 |
46 documentation |
63 documentation |
47 " |
64 " |
48 Parser is used for both parsing and evaluating smalltalk expressions; |
65 Parser is used for both parsing and evaluating smalltalk expressions; |
49 it first builds a parseTree which is then interpreted (evaluate) or |
66 it first builds a parseTree which is then interpreted (evaluate) or |
64 the parser for referencedXVars or modifiedXVars (see SystemBrowser). |
81 the parser for referencedXVars or modifiedXVars (see SystemBrowser). |
65 |
82 |
66 You can also use parsers for all kinds of other things (ChangesBrowser for |
83 You can also use parsers for all kinds of other things (ChangesBrowser for |
67 example analyzes the expressions in the changelist ...) by looking at the |
84 example analyzes the expressions in the changelist ...) by looking at the |
68 parsers tree. (Although this is somewhat dangerous, since it exports the |
85 parsers tree. (Although this is somewhat dangerous, since it exports the |
69 compilers internals ... better style would be to add specialized query |
86 compilers internals ... better style is to add specialized query methods here, |
70 methods here.) |
87 which will be done incrementally.) |
71 |
88 |
72 One instance of Parser is created to parse one method or expression - i.e. |
89 One instance of Parser is created to parse one method or expression - i.e. |
73 its not suggested to reuse parsers. |
90 its not suggested to reuse parsers. |
74 |
91 |
75 Instance variables: |
92 Instance variables: |
148 ^ self |
165 ^ self |
149 evaluate:aStringOrStream |
166 evaluate:aStringOrStream |
150 in:nil |
167 in:nil |
151 receiver:nil |
168 receiver:nil |
152 notifying:nil |
169 notifying:nil |
|
170 logged:false |
153 ifFail:nil |
171 ifFail:nil |
154 |
172 |
155 " |
173 " |
156 Compiler evaluate:'1 + 2' |
174 Compiler evaluate:'1 + 2' |
157 Compiler evaluate:'''hello world'' asSortedCollection displayString printNL' |
175 Compiler evaluate:'''hello world'' asSortedCollection displayString printNL' |
158 Compiler evaluate:'''hello world'' asSortedCollection printNL' |
176 Compiler evaluate:'''hello world'' asSortedCollection printNL' |
159 " |
177 " |
|
178 ! |
|
179 |
|
180 evaluate:aStringOrStream ifFail:failBlock |
|
181 "return the result of evaluating an expression in aStringOrStream. |
|
182 In case of any syntax errors, return the value of failBlock." |
|
183 |
|
184 ^ self |
|
185 evaluate:aStringOrStream |
|
186 in:nil |
|
187 receiver:nil |
|
188 notifying:nil |
|
189 logged:false |
|
190 ifFail:failBlock |
|
191 |
|
192 " |
|
193 Compiler evaluate:'1 +' ifFail:['oops'] |
|
194 |
|
195 " |
|
196 ! |
|
197 |
|
198 evaluate:aStringOrStream logged:logged |
|
199 "return the result of evaluating an expression in aStringOrStream" |
|
200 |
|
201 ^ self |
|
202 evaluate:aStringOrStream |
|
203 in:nil |
|
204 receiver:nil |
|
205 notifying:nil |
|
206 logged:logged |
|
207 ifFail:nil |
160 ! |
208 ! |
161 |
209 |
162 evaluate:aStringOrStream notifying:requestor |
210 evaluate:aStringOrStream notifying:requestor |
163 "return the result of evaluating aString, |
211 "return the result of evaluating aString, |
164 errors are reported to requestor" |
212 errors are reported to requestor" |
166 ^ self |
214 ^ self |
167 evaluate:aStringOrStream |
215 evaluate:aStringOrStream |
168 in:nil |
216 in:nil |
169 receiver:nil |
217 receiver:nil |
170 notifying:requestor |
218 notifying:requestor |
|
219 logged:false |
171 ifFail:nil |
220 ifFail:nil |
172 |
221 |
173 ! |
222 ! |
174 |
223 |
175 evaluate:aString receiver:anObject notifying:requestor |
224 evaluate:aStringOrStream receiver:anObject notifying:requestor |
176 "return the result of evaluating aString, |
225 "return the result of evaluating aString, |
177 errors are reported to requestor. Allow access to |
226 errors are reported to requestor. Allow access to |
178 anObject as self and to its instVars (used in the inspector)" |
227 anObject as self and to its instVars (used in the inspector)" |
179 |
228 |
180 ^ self |
229 ^ self |
181 evaluate:aString |
230 evaluate:aStringOrStream |
182 in:nil |
231 in:nil |
183 receiver:anObject |
232 receiver:anObject |
184 notifying:requestor |
233 notifying:requestor |
|
234 logged:false |
185 ifFail:nil |
235 ifFail:nil |
186 ! |
236 ! |
187 |
237 |
188 evaluate:aStringOrStream in:aContext receiver:anObject |
238 evaluate:aStringOrStream in:aContext receiver:anObject |
189 notifying:requestor |
239 notifying:requestor |
190 ifFail:failBlock |
240 ifFail:failBlock |
|
241 ^ self |
|
242 evaluate:aStringOrStream |
|
243 in:nil |
|
244 receiver:anObject |
|
245 notifying:requestor |
|
246 logged:false |
|
247 ifFail:nil |
|
248 ! |
|
249 |
|
250 evaluate:aStringOrStream in:aContext receiver:anObject notifying:requestor logged:logged ifFail:failBlock |
|
251 "return the result of evaluating aStringOrStream, errors are reported to requestor. |
|
252 Allow access to anObject as self and to its instVars (used in the inspector). |
|
253 If logged is true, an entry is added to the change-file. If the failBlock argument |
|
254 is non-nil, it is evaluated if an error occurs." |
|
255 |
|
256 "XXX: logging is not yet implemented" |
|
257 |
191 |parser tree mustBackup| |
258 |parser tree mustBackup| |
192 |
259 |
193 aStringOrStream isNil ifTrue:[^ nil]. |
260 aStringOrStream isNil ifTrue:[^ nil]. |
194 aStringOrStream isStream ifTrue:[ |
261 aStringOrStream isStream ifTrue:[ |
195 parser := self for:aStringOrStream. |
262 parser := self for:aStringOrStream. |
236 |
303 |
237 !Parser class methodsFor:'parsing'! |
304 !Parser class methodsFor:'parsing'! |
238 |
305 |
239 selectorInExpression:aString |
306 selectorInExpression:aString |
240 "parse an expression - return the selector. Used for |
307 "parse an expression - return the selector. Used for |
241 SystemBrowsers implementors/senders query-box initial text" |
308 SystemBrowsers implementors/senders query-box initial text." |
242 |
309 |
243 |tree parser| |
310 |tree parser| |
244 |
311 |
245 (aString isNil or:[aString isEmpty]) ifTrue:[^ nil]. |
312 (aString isNil or:[aString isEmpty]) ifTrue:[^ nil]. |
246 |
313 |
263 parser ignoreErrors. |
330 parser ignoreErrors. |
264 parser nextToken. |
331 parser nextToken. |
265 ^ parser degeneratedKeywordExpressionForSelector |
332 ^ parser degeneratedKeywordExpressionForSelector |
266 |
333 |
267 " |
334 " |
268 Parser selectorInExpression:'foo at:1 put:(5 * bar)' |
335 Parser selectorInExpression:'foo at:1 put:(5 * bar)' |
269 Parser selectorInExpression:'(foo at:1) at:1' |
336 Parser selectorInExpression:'(foo at:1) at:1' |
270 Parser selectorInExpression:'1 + 4' |
337 Parser selectorInExpression:'1 + 4' |
271 Parser selectorInExpression:'1 negated' |
338 Parser selectorInExpression:'1 negated' |
272 Parser selectorInExpression:'at:1 put:5' |
339 Parser selectorInExpression:'at:1 put:5' |
273 Parser selectorInExpression:'a := foo at:1 put:5' |
340 Parser selectorInExpression:'a := foo at:1 put:5' |
274 " |
341 " |
275 ! |
342 ! |
276 |
343 |
277 parseExpression:aString |
344 parseExpression:aString |
278 "parse aString as an expression; return the parseTree, nil or #error" |
345 "parse aString as an expression; return the parseTree, nil or #error" |
307 parseMethodSpecification:aString |
374 parseMethodSpecification:aString |
308 "parse a methods selector & arg specification; |
375 "parse a methods selector & arg specification; |
309 return the parser, nil or #error" |
376 return the parser, nil or #error" |
310 |
377 |
311 ^ self parseMethodSpecification:aString in:nil |
378 ^ self parseMethodSpecification:aString in:nil |
|
379 |
|
380 " |
|
381 |p| |
|
382 |
|
383 p := Parser parseMethodSpecification:'foo:arg1 bar:arg2 baz:arg3'. |
|
384 'nArgs: ' print. p numberOfMethodArgs printNL. |
|
385 'args: ' print. p methodArgs printNL. |
|
386 'sel: ' print. p selector printNL |
|
387 " |
312 ! |
388 ! |
313 |
389 |
314 parseMethodSpecification:aString in:aClass |
390 parseMethodSpecification:aString in:aClass |
315 "parse a methods selector & arg spec for a given class; |
391 "parse a methods selector & arg spec for a given class; |
316 return the parser, nil or #error" |
392 return the parser, nil or #error" |
328 parseMethodArgAndVarSpecification:aString |
404 parseMethodArgAndVarSpecification:aString |
329 "parse a methods selector, arg and var spec; |
405 "parse a methods selector, arg and var spec; |
330 return the parser, nil or #error" |
406 return the parser, nil or #error" |
331 |
407 |
332 ^ self parseMethodArgAndVarSpecification:aString in:nil |
408 ^ self parseMethodArgAndVarSpecification:aString in:nil |
|
409 |
|
410 " |
|
411 |p| |
|
412 |
|
413 p := Parser parseMethodArgAndVarSpecification:'foo:arg1 bar:arg2 baz:arg3 |l1 l2|'. |
|
414 'nArgs: ' print. p numberOfMethodArgs printNL. |
|
415 'args: ' print. p methodArgs printNL. |
|
416 'sel: ' print. p selector printNL. |
|
417 'nLocal: ' print. p numberOfMethodVars printNL. |
|
418 'locals: ' print. p methodVars printNL. |
|
419 " |
333 ! |
420 ! |
334 |
421 |
335 parseMethodArgAndVarSpecification:aString in:aClass |
422 parseMethodArgAndVarSpecification:aString in:aClass |
336 "parse a methods selector, arg and var spec for a given class; |
423 "parse a methods selector, arg and var spec for a given class; |
337 return the parser, nil or #error" |
424 return the parser, nil or #error" |
349 |
436 |
350 parseMethod:aString |
437 parseMethod:aString |
351 "parse a method; return parser, nil or #error" |
438 "parse a method; return parser, nil or #error" |
352 |
439 |
353 ^ self parseMethod:aString in:nil |
440 ^ self parseMethod:aString in:nil |
|
441 |
|
442 " |
|
443 |p| |
|
444 |
|
445 p := Parser parseMethod:'foo:arg1 bar:arg2 baz:arg3 |l1 l2| l1 := 0. l2 := arg1. ^ self'. |
|
446 'nArgs: ' print. p numberOfMethodArgs printNL. |
|
447 'args: ' print. p methodArgs printNL. |
|
448 'sel: ' print. p selector printNL. |
|
449 'nLocal: ' print. p numberOfMethodVars printNL. |
|
450 'locals: ' print. p methodVars printNL. |
|
451 'tree: ' printNL. p tree printAllOn:Stdout. Stdout cr. |
|
452 " |
354 ! |
453 ! |
355 |
454 |
356 parseMethod:aString in:aClass |
455 parseMethod:aString in:aClass |
357 "parse a method for a given class; return , nil or #error" |
456 "parse a method for a given class; return , nil or #error" |
358 |
457 |
361 aString isNil ifTrue:[^ nil]. |
460 aString isNil ifTrue:[^ nil]. |
362 parser := self for:(ReadStream on:aString) in:aClass. |
461 parser := self for:(ReadStream on:aString) in:aClass. |
363 tree := parser parseMethod. |
462 tree := parser parseMethod. |
364 (parser errorFlag or:[tree == #Error]) ifTrue:[^ nil]. |
463 (parser errorFlag or:[tree == #Error]) ifTrue:[^ nil]. |
365 ^ parser |
464 ^ parser |
|
465 ! ! |
|
466 |
|
467 !Parser class methodsFor:'unparsing'! |
|
468 |
|
469 methodSpecificationForSelector:aSelector |
|
470 "given a selector such as #foo:bar:, return a string that could |
|
471 serve as a methods specification source code. |
|
472 To be used for code generators" |
|
473 |
|
474 ^ self methodSpecificationForSelector:aSelector |
|
475 argNames:#('arg1' 'arg2' 'arg3' 'arg4' 'arg5' 'arg6' |
|
476 'arg7' 'arg8' 'arg9' 'arg10' 'arg11' 'arg12' |
|
477 'arg13' 'arg14' 'arg15') |
|
478 " |
|
479 Parser methodSpecificationForSelector:#foo:bar: |
|
480 Parser methodSpecificationForSelector:#+ |
|
481 Parser methodSpecificationForSelector:#negated |
|
482 " |
|
483 ! |
|
484 |
|
485 methodSpecificationForSelector:aSelector argNames:argNames |
|
486 "given a selector such as #foo:bar:, return a string that could |
|
487 serve as a methods specification source code. |
|
488 To be used for code generators" |
|
489 |
|
490 |s nargs parts| |
|
491 |
|
492 s := WriteStream on:String new. |
|
493 nargs := aSelector nArgsIfSelector. |
|
494 nargs == 0 ifTrue:[ |
|
495 s nextPutAll:aSelector |
|
496 ] ifFalse:[ |
|
497 parts := aSelector partsIfSelector. |
|
498 1 to:nargs do:[:i | |
|
499 s nextPutAll:(parts at:i); space; |
|
500 nextPutAll:(argNames at:i); space. |
|
501 ] |
|
502 ]. |
|
503 ^ s contents |
|
504 |
|
505 " |
|
506 Parser methodSpecificationForSelector:#foo:bar: argNames:#('one' 'two' 'three') |
|
507 Parser methodSpecificationForSelector:#+ argNames:#('one') |
|
508 Parser methodSpecificationForSelector:#negated |
|
509 " |
366 ! ! |
510 ! ! |
367 |
511 |
368 !Parser class methodsFor:'controlling compilation'! |
512 !Parser class methodsFor:'controlling compilation'! |
369 |
513 |
370 compileLazy:aBoolean |
514 compileLazy:aBoolean |
1097 ]. |
1241 ]. |
1098 sel := self selectorCheck:sel for:receiver position:pos1 to:pos2. |
1242 sel := self selectorCheck:sel for:receiver position:pos1 to:pos2. |
1099 try := MessageNode receiver:receiver selector:sel args:args. |
1243 try := MessageNode receiver:receiver selector:sel args:args. |
1100 (try isMemberOf:String) ifTrue:[ |
1244 (try isMemberOf:String) ifTrue:[ |
1101 self parseError:try position:pos1 to:pos2. |
1245 self parseError:try position:pos1 to:pos2. |
1102 receiver := MessageNode receiver:receiver selector:sel args:args fold:false |
1246 receiver := MessageNode receiver:receiver selector:sel args:args fold:false. |
|
1247 note := receiver plausibilityCheck. |
|
1248 note notNil ifTrue:[ |
|
1249 self warning:note position:pos1 to:pos2 |
|
1250 ]. |
|
1251 receiver lineNumber:lno |
1103 ] ifFalse:[ |
1252 ] ifFalse:[ |
1104 receiver := try |
1253 receiver := try |
1105 ]. |
1254 ]. |
1106 note := receiver plausibilityCheck. |
|
1107 note notNil ifTrue:[ |
|
1108 self warning:note position:pos1 to:pos2 |
|
1109 ]. |
|
1110 receiver lineNumber:lno |
|
1111 ]. |
1255 ]. |
1112 ^ receiver |
1256 ^ receiver |
1113 ! |
1257 ! |
1114 |
1258 |
1115 degeneratedKeywordExpressionForSelector |
1259 degeneratedKeywordExpressionForSelector |
1167 arg := self unaryExpression. |
1311 arg := self unaryExpression. |
1168 (arg == #Error) ifTrue:[^ #Error]. |
1312 (arg == #Error) ifTrue:[^ #Error]. |
1169 try := BinaryNode receiver:receiver selector:sel arg:arg. |
1313 try := BinaryNode receiver:receiver selector:sel arg:arg. |
1170 (try isMemberOf:String) ifTrue:[ |
1314 (try isMemberOf:String) ifTrue:[ |
1171 self parseError:try position:pos to:tokenPosition. |
1315 self parseError:try position:pos to:tokenPosition. |
1172 receiver := BinaryNode receiver:receiver selector:sel arg:arg fold:false |
1316 receiver := BinaryNode receiver:receiver selector:sel arg:arg fold:false. |
|
1317 note := receiver plausibilityCheck. |
|
1318 note notNil ifTrue:[ |
|
1319 self warning:note position:pos to:tokenPosition |
|
1320 ]. |
|
1321 receiver lineNumber:lno |
1173 ] ifFalse:[ |
1322 ] ifFalse:[ |
1174 receiver := try |
1323 receiver := try |
1175 ]. |
1324 ]. |
1176 note := receiver plausibilityCheck. |
|
1177 note notNil ifTrue:[ |
|
1178 self warning:note position:pos to:tokenPosition |
|
1179 ]. |
|
1180 receiver lineNumber:lno |
|
1181 ]. |
1325 ]. |
1182 ^ receiver |
1326 ^ receiver |
1183 ! |
1327 ! |
1184 |
1328 |
1185 unaryExpression |
1329 unaryExpression |
1194 pos2 := pos + tokenName size - 1. |
1338 pos2 := pos + tokenName size - 1. |
1195 sel := self selectorCheck:tokenName for:receiver position:pos to:pos2. |
1339 sel := self selectorCheck:tokenName for:receiver position:pos to:pos2. |
1196 try := UnaryNode receiver:receiver selector:sel. |
1340 try := UnaryNode receiver:receiver selector:sel. |
1197 (try isMemberOf:String) ifTrue:[ |
1341 (try isMemberOf:String) ifTrue:[ |
1198 self warning:try position:pos to:pos2. |
1342 self warning:try position:pos to:pos2. |
1199 receiver := UnaryNode receiver:receiver selector:sel fold:false |
1343 receiver := UnaryNode receiver:receiver selector:sel fold:false. |
|
1344 receiver lineNumber:tokenLineNr. |
1200 ] ifFalse:[ |
1345 ] ifFalse:[ |
1201 receiver := try |
1346 receiver := try |
1202 ]. |
1347 ]. |
1203 receiver lineNumber:tokenLineNr. |
|
1204 self nextToken. |
1348 self nextToken. |
1205 ]. |
1349 ]. |
1206 ^ receiver |
1350 ^ receiver |
1207 ! |
1351 ! |
1208 |
1352 |
1726 |
1870 |
1727 array |
1871 array |
1728 |arr elem pos1| |
1872 |arr elem pos1| |
1729 |
1873 |
1730 pos1 := tokenPosition. |
1874 pos1 := tokenPosition. |
1731 arr := OrderedCollection new:200. |
1875 arr := OrderedCollection new:20. |
1732 [tokenType ~~ $) ] whileTrue:[ |
1876 [tokenType ~~ $) ] whileTrue:[ |
1733 elem := self arrayConstant. |
1877 elem := self arrayConstant. |
1734 (elem == #Error) ifTrue:[ |
1878 (elem == #Error) ifTrue:[ |
1735 (tokenType == #EOF) ifTrue:[ |
1879 (tokenType == #EOF) ifTrue:[ |
1736 self syntaxError:'unterminated array-constant; '')'' expected' |
1880 self syntaxError:'unterminated array-constant; '')'' expected' |
1748 "started with ST-80 R4 - allow byteArray constants as #[ ... ]" |
1892 "started with ST-80 R4 - allow byteArray constants as #[ ... ]" |
1749 |
1893 |
1750 |arr elem pos1 pos2| |
1894 |arr elem pos1 pos2| |
1751 |
1895 |
1752 pos1 := tokenPosition. |
1896 pos1 := tokenPosition. |
1753 arr := OrderedCollection new. |
1897 arr := OrderedCollection new:50. |
1754 [tokenType ~~ $] ] whileTrue:[ |
1898 [tokenType ~~ $] ] whileTrue:[ |
1755 pos2 := tokenPosition. |
1899 pos2 := tokenPosition. |
1756 elem := self arrayConstant. |
1900 elem := self arrayConstant. |
1757 (elem == #Error) ifTrue:[ |
1901 (elem == #Error) ifTrue:[ |
1758 (tokenType == #EOF) ifTrue:[ |
1902 (tokenType == #EOF) ifTrue:[ |
1967 (dists size ~~ 0) ifTrue:[ |
2111 (dists size ~~ 0) ifTrue:[ |
1968 dists sortWith:names. |
2112 dists sortWith:names. |
1969 dists := dists reverse. |
2113 dists := dists reverse. |
1970 names := names reverse. |
2114 names := names reverse. |
1971 n := names size min:10. |
2115 n := names size min:10. |
1972 ^ names copyTo:n |
2116 names := names copyTo:n. |
|
2117 |
|
2118 "if it starts with a lower case character, add all local & instvar names" |
|
2119 (aString at:1) isLowercase ifTrue:[ |
|
2120 methodVarNames size > 0 ifTrue:[ |
|
2121 names add:'---- method locals ----'. |
|
2122 methodVarNames do:[:methodVarName | |
|
2123 names add:methodVarName. |
|
2124 ]. |
|
2125 ]. |
|
2126 |
|
2127 |
|
2128 methodArgs notNil ifTrue:[ |
|
2129 names add:'---- method arguments ----'. |
|
2130 methodArgNames do:[:methodArgName | |
|
2131 names add:methodArgName. |
|
2132 ] |
|
2133 ]. |
|
2134 |
|
2135 names add:'---- instance variables ----'. |
|
2136 PrevInstVarNames do:[:instVarName | |
|
2137 (names includes:instVarName) ifFalse:[ |
|
2138 names add:instVarName. |
|
2139 ] |
|
2140 ] |
|
2141 ]. |
|
2142 |
|
2143 ^ names |
1973 ]. |
2144 ]. |
1974 ^ nil |
2145 ^ nil |
1975 ! |
2146 ! |
1976 |
2147 |
1977 correctVariable |
2148 correctVariable |