fbdoc  1.0.1
FreeBASIC documentation tool
fbdoc_parser.bas
Go to the documentation of this file.
1 
9 
10 #INCLUDE ONCE "fbdoc_options.bi"
11 #INCLUDE ONCE "fbdoc_version.bi"
12 
13 
14 
23 CONSTRUCTOR Parser(BYVAL Em AS EmitterIF PTR)
24  STATIC AS LONG ToLi(...) = {0, 0, 0, 0, 0, 0}
25 
26  Emit = Em
27  StaTok = @ToLi(0)
28  A = @ToLi(1)
29  L = @ToLi(2)
30 END CONSTRUCTOR
31 
32 
33 
34 #DEFINE SKIP Tk += 3
35 
36 
37 
47 FUNCTION Parser.skipOverComma() AS INTEGER
48  VAR t = Tk, kl = 0
49  WHILE Tk < EndTok
50  SELECT CASE AS CONST *Tk
51  CASE MSG_ERROR, TOK_EOS : RETURN Tk - t
52  CASE TOK_COMMA : IF kl <= 0 THEN SKIP : RETURN Tk - t
53  CASE TOK_BROPN, TOK_KLOPN : kl += 1
54  CASE TOK_BRCLO, TOK_KLCLO : kl -= 1 : IF kl < 0 THEN RETURN Tk - t
55  END SELECT : SKIP
56  WEND
57 END FUNCTION
58 
59 
60 
70 FUNCTION Parser.skipOverBrclo() AS INTEGER
71  VAR t = Tk, kl = 0
72  WHILE Tk < EndTok
73  SELECT CASE AS CONST *Tk
74  CASE MSG_ERROR, TOK_EOS : RETURN Tk - t
75  CASE TOK_BROPN : kl += 1
76  CASE TOK_BRCLO : kl -= 1 : IF kl <= 0 THEN SKIP : RETURN Tk - t
77  END SELECT : SKIP
78  WEND
79 END FUNCTION
80 
81 
82 
90 FUNCTION Parser.skipOverColon() AS INTEGER
91  VAR t = Tk, fl = 0
92  WHILE Tk < EndTok
93  IF *Tk = TOK_EOS THEN fl = 1 ELSE IF fl THEN RETURN Tk - t
94  SKIP
95  WEND : RETURN Tk - t
96 END FUNCTION
97 
98 
99 
114 FUNCTION Parser.demuxNam(BYVAL MinTk AS INTEGER = TOK_WORD, BYVAL DeclMod AS INTEGER = 0) AS INTEGER
115  DimTok = 0 : IniTok = 0 : BitTok = 0
116 
117  IF *Tk >= MinTk THEN NamTok = Tk ELSE NamTok = 0 : RETURN MSG_ERROR
118  DO
119  SELECT CASE AS CONST *Tk
120  CASE TOK_BROPN, TOK_EQUAL
121  IF Tk > NamTok THEN EXIT DO ELSE NamTok = 0 : RETURN MSG_ERROR
122  CASE TOK_DOT : IF Tk[3] < MinTk THEN NamTok = 0 : RETURN MSG_ERROR
123  CASE TOK_WORD : IF Tk[3] <> TOK_DOT THEN SKIP : EXIT DO
124  CASE ELSE
125  IF 0 = LevelCount ORELSE *Tk < MinTk THEN NamTok = 0 : RETURN MSG_ERROR
126  SKIP : EXIT DO
127  END SELECT : SKIP
128  LOOP : IF DeclMod THEN RETURN Tk - NamTok
129 
130  IF *Tk = TOK_BROPN THEN DimTok = Tk : skipOverBrclo()
131 
132  IF *Tk = TOK_AS THEN RETURN Tk - NamTok
133 
134  IF *Tk = TOK_EQUAL THEN IniTok = Tk : RETURN Tk - NamTok
135  IF 0 = LevelCount ORELSE _
136  *Tk <> TOK_EOS ORELSE _
137  Buf[Tk[1]] <> ASC(":") THEN RETURN Tk - NamTok
138 
139  VAR x = Tk + 3 ' check for bitfield declaration
140  IF *x >= MinTk THEN
141  x += 3
142  IF *x = TOK_EOS ANDALSO Buf[x[1]] <> ASC(":") THEN _
143  BitTok = Tk : Tk = x : RETURN Tk - NamTok
144  END IF
145 
146  SELECT CASE AS CONST *x
147  CASE TOK_EQUAL : BitTok = Tk : Tk = x : IniTok = x
148  CASE TOK_COMMA : BitTok = Tk : Tk = x
149  CASE ELSE
150  FOR i AS INTEGER = Tk[1] + 1 TO Tk[4] - 1
151  SELECT CASE AS CONST Buf[i]
152  CASE ASC(" "), ASC(!"\t"), ASC(!"\v")
153  CASE ASC("0") TO ASC("9") : BitTok = Tk : EXIT FOR
154  CASE ELSE : EXIT FOR
155  END SELECT
156  NEXT
157  END SELECT : RETURN Tk - NamTok
158 END FUNCTION
159 
160 
161 
170 FUNCTION Parser.demuxDecl() AS INTEGER
171  SELECT CASE AS CONST *Tk
172  CASE TOK_CONS, TOK_STAT, TOK_VIRT, TOK_ABST : DivTok = Tk : SKIP
173  CASE ELSE : DivTok = 0
174  END SELECT
175 
176  FunTok = Tk : DimTok = 0 : IniTok = 0 : BitTok = 0
177  SELECT CASE AS CONST *Tk
178  CASE TOK_CTOR, TOK_DTOR
179  SKIP : IF *Tk = TOK_WORD THEN NamTok = Tk : SKIP ELSE NamTok = 0
180  IF *Tk = TOK_EOS THEN RETURN TOK_EOS ELSE RETURN demuxTyp(1)
181  CASE TOK_OPER
182  DO
183  SKIP
184  IF *Tk = TOK_BROPN THEN EXIT DO
185  IF *Tk < TOK_BROPN THEN EXIT SELECT
186  LOOP UNTIL Tk >= EndTok : RETURN demuxTyp(1)
187  CASE TOK_PROP
188  SKIP : IF *Tk = TOK_WORD THEN NamTok = Tk ELSE EXIT SELECT
189  SKIP : IF *Tk = TOK_EOS THEN RETURN TOK_EOS ELSE RETURN demuxTyp(1)
190  CASE TOK_SUB, TOK_FUNC
191  SKIP : IF *Tk = TOK_WORD THEN NamTok = Tk ELSE EXIT SELECT
192  SKIP : IF *Tk = TOK_LIB THEN SKIP : IF *Tk = TOK_QUOTE THEN SKIP ELSE EXIT SELECT
193  IF *Tk = TOK_EOS THEN RETURN TOK_EOS ELSE RETURN demuxTyp(1)
194  END SELECT : TypTok = 0 : FunTok = 0 : NamTok = 0 : RETURN MSG_ERROR
195 END FUNCTION
196 
197 
198 
212 FUNCTION Parser.demuxTyp(BYVAL DeclMod AS INTEGER = 0) AS INTEGER
213  VAR t = Tk
214  CalTok = 0
215  AliTok = 0
216  TypTok = 0
217  As_Tok = 0
218  ShaTok = 0
219  Co1Tok = 0
220  Co2Tok = 0
221  PtrTok = 0
222  PtrCount = 0
223 
224  IF 0 = DeclMod THEN
225  DivTok = 0
226  IF *Tk = TOK_AS THEN As_Tok = Tk : SKIP ELSE RETURN MSG_ERROR
227 
228  SELECT CASE AS CONST *Tk
229  CASE TOK_SUB : FunTok = Tk
230  CASE TOK_FUNC : FunTok = Tk
231  CASE ELSE
232  IF *Tk = TOK_CONS THEN Co1Tok = Tk : SKIP
233  IF *Tk < TOK_BYTE ORELSE *Tk > TOK_WORD THEN RETURN MSG_ERROR
234  TypTok = Tk : FunTok = 0
235  END SELECT : SKIP
236  END IF
237 
238  SELECT CASE AS CONST *Tk
239  CASE TOK_EQUAL
240  IF FunTok THEN TypTok = 0 : RETURN MSG_ERROR
241  IniTok = Tk : RETURN Tk - t
242  CASE TOK_BROPN : IF 0 = FunTok THEN RETURN Tk - t
243  ParTok = Tk : skipOverBrclo()
244  CASE ELSE
245  IF 0 = FunTok THEN
246  IF *Tk = TOK_CONS THEN
247  Co2Tok = Tk : SKIP
248  IF *Tk <> TOK_PTR THEN TypTok = 0 : RETURN MSG_ERROR
249  ELSE
250  IF *Tk <> TOK_PTR THEN RETURN Tk - t
251  END IF
252 
253  PtrTok = Tk : WHILE *Tk = TOK_PTR : PtrCount += 1 : SKIP : WEND
254 
255  IF *Tk = TOK_EQUAL THEN IniTok = Tk
256  RETURN Tk - t
257  END IF
258 
259  IF *Tk = TOK_EOS THEN RETURN IIF(*FunTok = TOK_FUNC, MSG_ERROR, TOK_EOS)
260 
261  SELECT CASE AS CONST *Tk
262  CASE TOK_CDEC, TOK_STCL, TOK_PASC : CalTok = Tk : SKIP
263  END SELECT
264 
265  IF *Tk = TOK_OVER THEN SKIP
266  IF *Tk = TOK_ALIA THEN
267  AliTok = Tk
268  SKIP : IF *Tk <> TOK_QUOTE THEN TypTok = 0 : RETURN MSG_ERROR
269  SKIP
270  END IF
271 
272  IF *Tk = TOK_BROPN THEN ParTok = Tk : skipOverBrclo()
273  END SELECT
274 
275  IF *Tk = TOK_AS THEN
276  As_Tok = Tk : SKIP
277  IF *Tk = TOK_CONS THEN Co1Tok = Tk : SKIP
278  TypTok = Tk : SKIP
279  IF *Tk = TOK_CONS THEN
280  Co2Tok = Tk : SKIP
281  IF *Tk <> TOK_PTR THEN FunTok = 0: TypTok = 0 : RETURN MSG_ERROR
282  END IF
283  PtrTok = Tk : WHILE *Tk = TOK_PTR : PtrCount += 1 : SKIP : WEND
284  ELSE
285  IF *FunTok = TOK_FUNC THEN RETURN MSG_ERROR
286  END IF
287 
288  IF *Tk = TOK_STAT THEN
289  SKIP : IF *Tk = TOK_EXPO THEN SKIP
290  ELSE
291  IF *Tk = TOK_EXPO THEN SKIP : IF *Tk = TOK_STAT THEN SKIP
292  END IF : RETURN Tk - t
293 END FUNCTION
294 
295 
296 
304 SUB Parser.parseListNam(BYVAL Export_ AS EmitFunc) EXPORT
305  VAR count = 1
306  TypTok = 0 : FunTok = 0
307  DO
308  Tk1 = Tk
309  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverComma() : CONTINUE DO
310  skipOverComma() : ListCount = count : Export_(@THIS) : count += 1
311  LOOP UNTIL *Tk <= TOK_COMMA
312 END SUB
313 
314 
315 
323 SUB Parser.parseListNamTyp(BYVAL Export_ AS EmitFunc) EXPORT
324  VAR count = 1
325  DO
326  Tk1 = Tk
327  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverComma() : CONTINUE DO
328  IF MSG_ERROR >= demuxTyp() THEN Errr("type expected") : skipOverComma() : CONTINUE DO
329  skipOverComma() : ListCount = count : Export_(@THIS) : count += 1
330  LOOP UNTIL *Tk <= TOK_COMMA
331 END SUB
332 
333 
334 
342 SUB Parser.parseBlockEnum(BYVAL Export_ AS EmitFunc) EXPORT
343  VAR lico = 0
344  TypTok = 0 : FunTok = 0 : LevelCount += 1
345  WHILE Tk < EndTok
346  Tk1 = Tk
347  SELECT CASE AS CONST *Tk
348  CASE TOK_END
349  SKIP : IF *Tk = TOK_ENUM THEN EXIT WHILE
350  Errr("END ENUM expected") : EXIT WHILE
351  CASE TOK_LATTE : skipOverColon()
352  CASE ELSE
353  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverColon() : EXIT SELECT
354  ListCount = lico
355  skipOverComma() : IF *Tk = TOK_EOS THEN lico = 0 : skipOverColon() ELSE lico += 1
356  Export_(@THIS)
357  END SELECT
358  WEND : skipOverColon() : LevelCount -= 1
359 END SUB
360 
361 
362 
370 SUB Parser.parseBlockTyUn(BYVAL Export_ AS EmitFunc) EXPORT
371  VAR in_tk1 = iif(LevelCount, *Tk1, *StaTok)
372  LevelCount += 1
373  DO
374  Tk1 = Tk
375  VAR nextok = Tk[3]
376  SELECT CASE AS CONST nextok
377  CASE TOK_AS, TOK_BROPN
378  BitTok = 0
379  SELECT CASE AS CONST *Tk1
380  CASE TOK_DIM, TOK_RDIM : SKIP
381  IF MSG_ERROR >= demuxTyp() THEN _
382  IF Errr("type expected1") = MSG_ERROR THEN CONTINUE DO _
383  ELSE EXIT DO
384  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
385  IF Errr("name expected1") = MSG_ERROR THEN CONTINUE DO _
386  ELSE EXIT DO
387  skipOverComma()
388  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
389  IF *Tk >= TOK_ABST THEN parseListNam(Export_)
390  CASE ELSE
391  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
392  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
393  ELSE EXIT DO
394  IF MSG_ERROR >= demuxTyp() THEN _
395  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
396  ELSE EXIT DO
397  skipOverComma()
398  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
399  IF *Tk >= TOK_ABST THEN parseListNamTyp(Export_)
400  END SELECT
401  skipOverColon()
402  CASE ELSE
403  SELECT CASE AS CONST *Tk1
404  CASE TOK_LATTE : skipOverColon()
405  CASE TOK_DIM, TOK_RDIM : SKIP
406  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
407  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
408  ELSE EXIT DO
409  IF *Tk <> TOK_AS THEN _
410  IF Errr("'AS' expected->" & SubStr(Tk) & "<-") = MSG_ERROR THEN CONTINUE DO _
411  ELSE EXIT DO
412  IF MSG_ERROR >= demuxTyp() THEN _
413  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
414  ELSE EXIT DO
415  skipOverComma()
416  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
417  IF *Tk >= TOK_ABST THEN parseListNamTyp(Export_)
418  skipOverColon()
419  CASE TOK_AS
420  BitTok = 0
421  IF MSG_ERROR >= demuxTyp() THEN _
422  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
423  ELSE EXIT DO
424  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
425  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
426  ELSE EXIT DO
427  skipOverComma()
428  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
429  IF *Tk >= TOK_ABST THEN parseListNam(Export_)
430  skipOverColon()
431  CASE TOK_END
432  IF nextok = in_tk1 THEN EXIT DO
433  IF Errr("not supported") < MSG_ERROR THEN EXIT DO
434  skipOverColon()
435 
436  CASE TOK_DECL : SKIP
437  IF MSG_ERROR >= demuxDecl() THEN _
438  IF Errr("syntax error " & SubStr(NamTok)) = MSG_ERROR _
439  THEN skipOverColon() : EXIT SELECT _
440  ELSE EXIT DO
441  skipOverColon() : Export_(@THIS)
442 
443  CASE TOK_PUBL, TOK_PRIV, TOK_PROT
444  skipOverColon() : Export_(@THIS)
445 
446  CASE TOK_ENUM, TOK_TYPE, TOK_UNIO, TOK_CLAS
447  VAR n = BlockNam
448  IF nextok = TOK_WORD THEN SKIP : BlockNam = SubStr ELSE BlockNam = ""
449  skipOverColon() : Export_(@THIS) : BlockNam = n
450  CASE ELSE
451  skipOverColon() : IF Errr("not supported: " & SubStr(Tk1)) < MSG_ERROR THEN EXIT DO
452  END SELECT
453  END SELECT
454  LOOP UNTIL Tk >= EndTok : skipOverColon() : LevelCount -= 1
455 END SUB
456 
457 
458 
466 SUB Parser.parseListPara(BYVAL Export_ AS EmitFunc) EXPORT
467  VAR count = 0, t = Tk
468  Tk = ParTok
469  SKIP
470  DO
471  Tk1 = Tk
472  By_Tok = 0
473  SELECT CASE AS CONST *Tk
474  CASE TOK_BRCLO : IF count > 0 THEN Errr("parameter expected")
475  ListCount = count : EXIT DO
476  CASE TOK_3DOT : NamTok = Tk : TypTok = 0 : FunTok = 0
477  CASE ELSE
478  IF *Tk = TOK_BYVA ORELSE *Tk = TOK_BYRE THEN By_Tok = Tk : SKIP
479  IF *Tk <> TOK_AS ANDALSO *Tk >= TOK_ABST THEN
480  NamTok = Tk : SKIP
481  IF *Tk = TOK_BROPN THEN DimTok = Tk : skipOverBrclo()
482  ELSE
483  NamTok = 0
484  END IF
485  IF MSG_ERROR >= demuxTyp() THEN Errr("type expected") : skipOverComma() : CONTINUE DO
486  END SELECT
487  skipOverComma() : count += 1 : ListCount = count : Export_(@THIS)
488  LOOP UNTIL *Tk < TOK_COMMA : By_Tok = 0 : Tk = t
489 END SUB
490 
491 
492 
506 FUNCTION Parser.TYPE_() AS INTEGER
507  IF 3 > tokenize(TO_COLON) THEN RETURN Errr("syntax error")
508 
509  DimTok = 0 : IniTok = 0 : BitTok = 0
510  IF *StaTok = TOK_TYPE THEN
511  IF *Tk = TOK_AS THEN
512  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
513  IF *Tk = TOK_WORD THEN NamTok = Tk ELSE RETURN Errr("name expected")
514  skipOverComma()
515  IF Emit->Decl_ THEN Emit->Decl_(@THIS)
516  RETURN MSG_ERROR
517  ELSE
518  IF *Tk = TOK_WORD THEN NamTok = Tk : SKIP ELSE RETURN Errr("name expected")
519  IF *Tk = TOK_AS THEN
520  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
521  skipOverComma()
522  IF Emit->Decl_ THEN Emit->Decl_(@THIS)
523  RETURN MSG_ERROR
524  END IF
525  END IF
526  ELSE
527  IF *Tk = TOK_WORD THEN NamTok = Tk ELSE RETURN Errr("name expected")
528  END IF
529  IF 0 = Emit->Clas_ THEN RETURN MSG_ERROR
530  BlockNam = SubStr(NamTok)
531  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
532  Emit->Clas_(@THIS) : RETURN MSG_ERROR
533 END FUNCTION
534 
535 
536 
544 FUNCTION Parser.VAR_() AS INTEGER
545  IF 3 > tokenize(TO_COLON) THEN _
546  RETURN IIF(*StaTok = TOK_EXRN, MSG_ERROR, Errr("syntax error"))
547  IF *Tk <> TOK_PRES THEN DivTok = 0 ELSE DivTok = Tk : SKIP
548  IF *Tk <> TOK_SHAR THEN ShaTok = 0 ELSE ShaTok = Tk : SKIP
549 
550  IF *Tk = TOK_AS THEN
551  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
552  IF MSG_ERROR >= demuxNam() THEN RETURN Errr("name expected")
553  ELSE
554  IF *StaTok = TOK_EXRN THEN RETURN MSG_ERROR
555  IF MSG_ERROR >= demuxNam() THEN RETURN Errr("name expected")
556  IF *Tk = TOK_AS THEN demuxTyp() ELSE TypTok = 0 : FunTok = 0
557  IF 0 = TypTok ANDALSO 0 = FunTok THEN
558  SELECT CASE AS CONST *StaTok
559  CASE TOK_VAR, TOK_CONS
560  IF 0 = IniTok THEN RETURN Errr("initialization expected")
561  CASE ELSE : RETURN Errr("type expected")
562  END SELECT
563  END IF
564  END IF
565 
566  skipOverComma()
567  Emit->Decl_(@THIS)
568  IF *Tk <= TOK_EOS THEN RETURN MSG_ERROR
569  IF NamTok > TypTok THEN parseListNam(Emit->Decl_) _
570  ELSE parseListNamTyp(Emit->Decl_)
571  RETURN MSG_ERROR
572 END FUNCTION
573 
574 
575 
583 FUNCTION Parser.ENUM_() AS INTEGER
584  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
585  IF *Tk = TOK_WORD THEN BlockNam = SubStr : SKIP ELSE BlockNam = ""
586  IF *Tk = TOK_EOS THEN skipOverColon() ELSE RETURN Errr("syntax error")
587  Tk1 = StaTok
588  Emit->Enum_(@THIS)
589  RETURN MSG_ERROR
590 END FUNCTION
591 
592 
593 
601 FUNCTION Parser.UNION_() AS INTEGER
602  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
603  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
604  BlockNam = SubStr()
605  skipOverColon()
606  Tk1 = StaTok
607  Emit->Unio_(@THIS)
608  RETURN MSG_ERROR
609 END FUNCTION
610 
611 
612 
621 FUNCTION Parser.FUNCTION_() AS INTEGER
622  SELECT CASE AS CONST ToLast
623  CASE TOK_PUBL, TOK_PRIV, TOK_ABST, TOK_VIRT : DivTok = StaTok
624  CASE ELSE : DivTok = 0
625  END SELECT
626  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
627  FunTok = StaTok
628 
629  IF DivTok THEN DivTok = Tk1
630  IF MSG_ERROR >= demuxNam(TOK_WORD, 1) THEN RETURN Errr("name expected")
631  IF MSG_ERROR >= demuxTyp(1) THEN RETURN Errr("syntax error")
632 
633  FOR i AS INTEGER = 0 TO 1
634  SELECT CASE AS CONST *Tk
635  CASE TOK_STAT : SKIP ' !!! ToDo
636  CASE TOK_EXPO : SKIP ' !!! ToDo
637  CASE ELSE : EXIT FOR
638  END SELECT
639  NEXT
640  skipOverBrclo()
641  Emit->Func_(@THIS)
642  RETURN MSG_ERROR
643 END FUNCTION
644 
645 
646 
654 FUNCTION Parser.DECLARE_() AS INTEGER
655  IF 3 > tokenize(TO_COLON) THEN RETURN Errr("syntax error")
656  IF MSG_ERROR >= demuxDecl() THEN RETURN Errr("syntax error")
657  Emit->Decl_(@THIS)
658  RETURN MSG_ERROR
659 END FUNCTION
660 
661 
662 
671 FUNCTION Parser.INCLUDE_() AS INTEGER
672  IF 3 > tokenize(TO_EOL) THEN RETURN Errr("syntax error")
673  IF *Tk = TOK_ONCE THEN DivTok = Tk : SKIP ELSE DivTok = 0
674  IF *Tk <> TOK_QUOTE THEN RETURN Errr("file name expected")
675  NamTok = Tk
676  Emit->Incl_(@THIS)
677 END FUNCTION
678 
679 
680 
687 FUNCTION Parser.MACRO_() AS INTEGER
688  IF 3 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
689  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
690  NamTok = Tk : SKIP
691  IF *Tk <> TOK_BROPN THEN RETURN Errr("'()' expected")
692  ParTok = Tk
693  skipOverBrclo()
694  Emit->Defi_(@THIS)
695  RETURN MSG_ERROR
696 END FUNCTION
697 
698 
699 
706 FUNCTION Parser.DEFINE_() AS INTEGER
707  IF 3 > tokenize(TO_EOL) THEN RETURN Errr("syntax error")
708  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
709  NamTok = Tk : SKIP
710  IF *Tk = TOK_BROPN ANDALSO Tk[1] = NamTok[1] + NamTok[2] _
711  THEN ParTok = Tk : skipOverBrclo() _
712  ELSE ParTok = 0
713  DivTok = Tk
714  Tk = EndTok - 3
715  Emit->Defi_(@THIS)
716  RETURN MSG_ERROR
717 END FUNCTION
718 
719 
720 
728 FUNCTION Parser.Errr(BYREF E AS STRING) AS INTEGER
729  VAR z = LineNo
730  IF LevelCount THEN ' adapt line number counter
731  FOR i AS INTEGER = Tk[1] TO EndTok[1]
732  IF Buf[i] = ASC(!"\n") THEN z -= 1
733  NEXT
734  END IF
735  ErrMsg = "-error(" & z & "): " & E & ", found '" & SubStr(Tk) & "' "
736 
737  SELECT CASE AS CONST *StaTok
738  CASE TOK_DIM : ErrMsg &= "(DIM)"
739  CASE TOK_RDIM : ErrMsg &= "(REDIM)"
740  CASE TOK_VAR : ErrMsg &= "(VAR)"
741  CASE TOK_CONS : ErrMsg &= "(CONST)"
742  CASE TOK_STAT : ErrMsg &= "(STATIC)"
743  CASE TOK_COMM : ErrMsg &= "(COMMON)"
744  CASE TOK_EXRN : ErrMsg &= "(EXTERN)"
745  CASE TOK_TYPE : ErrMsg &= "(TYPE)"
746  CASE TOK_CLAS : ErrMsg &= "(CLASS)"
747  CASE TOK_SUB : ErrMsg &= "(SUB)"
748  CASE TOK_FUNC : ErrMsg &= "(FUNCTION)"
749  CASE TOK_PROP : ErrMsg &= "(PROPERTY)"
750  CASE TOK_CTOR : ErrMsg &= "(CONSTRUCTOR)"
751  CASE TOK_DTOR : ErrMsg &= "(DESTRUCTOR)"
752  CASE TOK_NAMS : ErrMsg &= "(NAMESPACE)"
753  CASE TOK_SCOP : ErrMsg &= "(SCOPE)"
754  CASE TOK_ENUM : ErrMsg &= "(ENUM)"
755  CASE TOK_UNIO : ErrMsg &= "(UNION)"
756  CASE TOK_DECL : ErrMsg &= "(DECLARE)"
757  CASE TOK_DEFI : ErrMsg &= "(#DEFINE)"
758  CASE TOK_MACR : ErrMsg &= "(#MACRO)"
759  CASE ELSE : ErrMsg &= "(???)"
760  END SELECT
761  IF Emit->Error_ THEN Emit->Error_(@THIS)
762  ErrMsg = ""
763 
764  RETURN IIF(Buf[Po] = 0, MSG_STOP, MSG_ERROR)
765 END FUNCTION
766 
767 
768 
776 FUNCTION Parser.getToken() AS INTEGER
777  SELECT CASE AS CONST Buf[*A]
778  CASE ASC("A"), ASC("a")
779  SELECT CASE USubStr()
780  CASE "AS" : RETURN TOK_AS
781  CASE "ALIAS" : RETURN TOK_ALIA
782  CASE "ANY" : RETURN TOK_ANY
783  CASE "ABSTRACT" : RETURN TOK_ABST
784  END SELECT
785  CASE ASC("B"), ASC("b")
786  SELECT CASE USubStr()
787  CASE "BYTE" : RETURN TOK_BYTE
788  CASE "BYREF" : RETURN TOK_BYRE
789  CASE "BYVAL" : RETURN TOK_BYVA
790  END SELECT
791  CASE ASC("C"), ASC("c")
792  SELECT CASE USubStr()
793  CASE "CAST" : RETURN TOK_CAST
794  CASE "CDECL" : RETURN TOK_CDEC
795  CASE "CLASS" : RETURN TOK_CLAS
796  CASE "CONST" : RETURN TOK_CONS
797  CASE "COMMON" : RETURN TOK_COMM
798  CASE "CONSTRUCTOR" : RETURN TOK_CTOR
799  END SELECT
800  CASE ASC("D"), ASC("d")
801  SELECT CASE USubStr()
802  CASE "DIM" : RETURN TOK_DIM
803  CASE "DOUBLE" : RETURN TOK_DOUB
804  CASE "DEFINE" : IF ToLast = TOK_LATTE THEN RETURN TOK_DEFI
805  CASE "DECLARE" : RETURN TOK_DECL
806  CASE "DESTRUCTOR" : RETURN TOK_DTOR
807  END SELECT
808  CASE ASC("E"), ASC("e")
809  SELECT CASE USubStr()
810  CASE "END" : RETURN TOK_END
811  CASE "ENUM" : RETURN TOK_ENUM
812  CASE "EXTERN" : RETURN TOK_EXRN
813  CASE "EXPORT" : RETURN TOK_EXPO
814  CASE "EXTENDS" : RETURN TOK_EXDS
815  CASE "ENDMACRO" : IF ToLast = TOK_LATTE THEN RETURN TOK_EMAC
816  END SELECT
817  CASE ASC("F"), ASC("f")
818  SELECT CASE USubStr()
819  CASE "FUNCTION" : RETURN TOK_FUNC
820  CASE "FIELD" : RETURN TOK_FILD
821  END SELECT
822  CASE ASC("I"), ASC("i")
823  SELECT CASE USubStr()
824  CASE "INCLUDE" : IF ToLast = TOK_LATTE THEN RETURN TOK_INCL
825  CASE "INTEGER" : RETURN TOK_INT
826  END SELECT
827  CASE ASC("L"), ASC("l")
828  SELECT CASE USubStr()
829  CASE "LIB" : RETURN TOK_LIB
830  CASE "LONG" : RETURN TOK_LONG
831  CASE "LONGINT" : RETURN TOK_LINT
832  END SELECT
833  CASE ASC("M"), ASC("m") : IF USubStr() = "MACRO" THEN IF ToLast = TOK_LATTE THEN RETURN TOK_MACR
834  CASE ASC("N"), ASC("n") : IF USubStr() = "NAMESPACE" THEN RETURN TOK_NAMS
835  CASE ASC("O"), ASC("o")
836  SELECT CASE USubStr()
837  CASE "ONCE" : RETURN TOK_ONCE
838  CASE "OPERATOR" : RETURN TOK_OPER
839  CASE "OVERLOAD" : RETURN TOK_OVER
840  END SELECT
841  CASE ASC("P"), ASC("p")
842  SELECT CASE USubStr()
843  CASE "PTR" : RETURN TOK_PTR
844  CASE "PEEK" : RETURN TOK_PEEK
845  CASE "POINTER" : RETURN TOK_PTR
846  CASE "PRESERVE" : RETURN TOK_PRES
847  CASE "PROPERTY" : RETURN TOK_PROP
848  CASE "PUBLIC" : RETURN TOK_PUBL
849  CASE "PRIVATE" : RETURN TOK_PRIV
850  CASE "PROTECTED" : RETURN TOK_PROT
851  CASE "PASCAL" : RETURN TOK_PASC
852  END SELECT
853  CASE ASC("R"), ASC("r") : IF USubStr() = "REDIM" THEN RETURN TOK_RDIM
854  CASE ASC("S"), ASC("s")
855  SELECT CASE USubStr()
856  CASE "SUB" : RETURN TOK_SUB
857  CASE "SCOPE" : RETURN TOK_SCOP
858  CASE "SHORT" : RETURN TOK_SHOR
859  CASE "SINGLE" : RETURN TOK_SING
860  CASE "SHARED" : RETURN TOK_SHAR
861  CASE "STRING" : RETURN TOK_STRI
862  CASE "STATIC" : RETURN TOK_STAT
863  CASE "STDCALL" : RETURN TOK_STCL
864  END SELECT
865  CASE ASC("T"), ASC("t") : IF USubStr() = "TYPE" THEN RETURN TOK_TYPE
866  CASE ASC("U"), ASC("u")
867  SELECT CASE USubStr()
868  CASE "UNION" : RETURN TOK_UNIO
869  CASE "UBYTE" : RETURN TOK_UBYT
870  CASE "ULONG" : RETURN TOK_ULNG
871  CASE "ULONGINT" : RETURN TOK_ULIN
872  CASE "UINTEGER" : RETURN TOK_UINT
873  CASE "USHORT" : RETURN TOK_USHO
874  END SELECT
875  CASE ASC("V"), ASC("v")
876  SELECT CASE USubStr()
877  CASE "VAR" : RETURN TOK_VAR
878  CASE "VIRTUAL" : RETURN TOK_VIRT
879  END SELECT
880  CASE ASC("W"), ASC("w")
881  SELECT CASE USubStr()
882  CASE "WITH" : RETURN TOK_WITH
883  CASE "WSTRING" : RETURN TOK_WSTR
884  END SELECT
885  CASE ASC("Z"), ASC("z") : IF USubStr() = "ZSTRING" THEN RETURN TOK_ZSTR
886  END SELECT : RETURN TOK_WORD
887 END FUNCTION
888 
889 
890 
896 #MACRO SCAN_ML_COMM()
897  Po += 2
898  DO
899  SELECT CASE AS CONST Buf[Po]
900  CASE 0 : EXIT DO
901  CASE ASC(!"\n") : LineNo += 1
902  CASE ASC("'")
903  SELECT CASE AS CONST Buf[Po + 1]
904  CASE 0 : EXIT DO
905  CASE ASC("/") : Po += 1 : EXIT DO
906  END SELECT
907  END SELECT : Po += 1
908  LOOP
909 #ENDMACRO
910 
911 
912 
918 #MACRO SCAN_WORD()
919  *A = Po
920  Po += 1
921  DO
922  SELECT CASE AS CONST Buf[Po]
923  CASE ASC("0") TO ASC("9"), _
924  ASC("A") TO ASC("Z"), _
925  ASC("a") TO ASC("z"), ASC("_") : Po += 1
926  CASE ELSE : EXIT DO
927  END SELECT
928  LOOP
929 #ENDMACRO
930 
931 
932 #DEFINE SETOK(_T_,_A_,_L_) Tok &= MKL(_T_) & MKL(_A_) & MKL(_L_) : ToLast = _T_
933 
934 
935 #DEFINE EXIT_STOP SETOK(MSG_STOP, Po, 1) : Po -= 1 : EXIT DO
936 
937 
950 FUNCTION Parser.tokenize(BYVAL Stop_ AS EoS_Modi) AS INTEGER
951  VAR coca = 0, endcount = 0, newblock = 0 ', currTok = MSG_ERROR, fl_end = 0
952  VAR tok_begin = LEN(Tok) SHR 2
953  ToLast = IIF(*StaTok = TOK_TYPE, TOK_EOS, MSG_ERROR)
954  A += 3 : L += 3
955  DO
956  SELECT CASE AS CONST Buf[Po]
957  CASE 0 : EXIT_STOP
958  CASE ASC(!"\n") : LineNo += 1 : IF coca THEN coca = 0 : EXIT SELECT
959  IF ToLast = TOK_EOS THEN EXIT SELECT
960  SETOK(TOK_EOS, Po, 1) : IF Stop_ >= TO_EOL THEN EXIT DO
961  IF newblock THEN endcount += 1 : newblock = 0
962  CASE ASC(":")
963  SETOK(TOK_EOS, Po, 1) : IF Stop_ >= TO_COLON THEN EXIT DO
964  IF newblock THEN endcount += 1 : newblock = 0
965  CASE ASC(",") : SETOK(TOK_COMMA, Po, 1)
966  CASE ASC("-") : IF Buf[Po + 1] <> ASC(">") THEN EXIT SELECT
967  SETOK(TOK_MEOP, Po, 2) : Po += 2 : CONTINUE DO
968  CASE ASC(".")
969  IF Buf[Po + 1] = ASC(".") ANDALSO _
970  Buf[Po + 2] = ASC(".") ANDALSO _
971  Buf[Po + 3] <> ASC(".") _
972  THEN SETOK(TOK_3DOT, Po, 3) : Po += 3 : CONTINUE DO
973  SETOK(TOK_DOT, Po, 1)
974  CASE ASC("=") : SETOK(TOK_EQUAL, Po, 1)
975  CASE ASC("{"), ASC("[") : SETOK(TOK_KLOPN, Po, 1)
976  CASE ASC("}"), ASC("]") : SETOK(TOK_KLCLO, Po, 1)
977  CASE ASC("(") : SETOK(TOK_BROPN, Po, 1)
978  CASE ASC(")") : SETOK(TOK_BRCLO, Po, 1)
979  CASE ASC("#") : SETOK(TOK_LATTE, Po, 1)
980 
981  CASE ASC("A") TO ASC("Z"), ASC("a") TO ASC("z"), ASC("_")
982  SCAN_WORD()
983  *L = Po - *A : IF *L = 1 ANDALSO Buf[*A] = ASC("_") THEN coca = *A : CONTINUE DO
984 
985  VAR pretok = ToLast
986  SETOK(getToken(), *A, *L)
987  newblock = 0
988  IF pretok = TOK_END THEN
989  SELECT CASE AS CONST *StaTok
990  CASE TOK_SUB, TOK_FUNC, TOK_PROP, TOK_OPER, TOK_CTOR, TOK_DTOR, TOK_ENUM
991  IF ToLast = *StaTok THEN Stop_ = TO_COLON
992  CONTINUE DO
993  CASE TOK_UNIO, TOK_TYPE, TOK_CLAS
994  IF ToLast <> *StaTok THEN CONTINUE DO
995  CASE ELSE : CONTINUE DO
996  END SELECT
997  endcount -= 1 : IF endcount < 0 THEN Stop_ = TO_COLON
998  ELSE
999  SELECT CASE AS CONST *StaTok
1000  CASE TOK_UNIO, TOK_TYPE, TOK_CLAS
1001  IF pretok <> TOK_EOS THEN CONTINUE DO
1002  IF ToLast = *StaTok THEN newblock = 1
1003  CASE TOK_MACR : IF ToLast = TOK_EMAC THEN Stop_ = TO_COLON
1004  END SELECT
1005  END IF : CONTINUE DO
1006 
1007  CASE ASC("""")
1008  *A = Po
1009  SCAN_QUOTE(Buf,Po)
1010  SETOK(TOK_QUOTE, *A, Po - *A + 1)
1011  IF Buf[Po] <> ASC("""") THEN EXIT_STOP
1012  CASE ASC("'")
1013  SCAN_SL_COMM(Buf,Po)
1014  CONTINUE DO
1015  CASE ASC("/") : IF Buf[Po + 1] <> ASC("'") THEN EXIT SELECT
1016  SCAN_ML_COMM()
1017  IF Buf[Po] <> ASC("/") THEN EXIT_STOP
1018  END SELECT : Po += 1
1019  LOOP : A -= 3 : L -= 3 : Po += 1
1020 
1021  Tk1 = CAST(LONG PTR, SADD(Tok))
1022  EndTok = Tk1 + (LEN(Tok) SHR 2) - 3
1023  Tk = Tk1 + tok_begin
1024  RETURN EndTok - Tk
1025 END FUNCTION
1026 
1027 
1028 
1035 SUB Parser.pre_parse()
1036  *L = 0
1037  Po = 0
1038  ToLast = MSG_ERROR
1039  LineNo = 1
1040  Tok = ""
1041  IF Emit->Init_ THEN Emit->Init_(@THIS)
1042  DO
1043  SELECT CASE AS CONST Buf[Po] ' search word
1044  CASE 0 : EXIT DO
1045  CASE ASC(!"\n") : *L = 0 : LineNo += 1
1046  CASE ASC(":") : *L = 0 : ToLast = 0
1047  CASE ASC("#") : ToLast = TOK_LATTE
1048  CASE ASC("""")
1049  SCAN_QUOTE(Buf,Po)
1050  ToLast = TOK_QUOTE : IF Buf[Po] <> ASC("""") THEN EXIT DO
1051  CASE ASC("'")
1052  SCAN_SL_COMM(Buf,Po)
1053  CONTINUE DO
1054  CASE ASC("/") : IF Buf[Po + 1] <> ASC("'") THEN EXIT SELECT
1055  SCAN_ML_COMM()
1056  IF Buf[Po] <> ASC(!"/") THEN EXIT DO
1057 
1058  CASE ASC("_"), ASC("A") TO ASC("Z"), ASC("a") TO ASC("z")
1059  SCAN_WORD() : IF *L THEN ToLast = 0 : CONTINUE DO ' skip word, if not first
1060  *L = Po - *A : IF *L = 1 ANDALSO Buf[*A] = ASC("_") THEN ToLast = 0 : *L = 0 : CONTINUE DO
1061 
1062  ListCount = 0
1063  LevelCount = 0
1064  *StaTok = getToken()
1065  SELECT CASE AS CONST *StaTok
1066  CASE TOK_SUB, TOK_FUNC, TOK_PROP, TOK_OPER, TOK_CTOR, TOK_DTOR
1067  IF Emit->Func_ ANDALSO FUNCTION_() = MSG_STOP THEN EXIT DO
1068  CASE TOK_DIM, TOK_RDIM, TOK_VAR, TOK_CONS, TOK_COMM, TOK_EXRN, TOK_EXPO, TOK_STAT
1069  IF Emit->Decl_ ANDALSO VAR_() = MSG_STOP THEN EXIT DO
1070  CASE TOK_TYPE, TOK_CLAS
1071  IF TYPE_() = MSG_STOP THEN EXIT DO
1072  CASE TOK_UNIO : IF Emit->Unio_ ANDALSO UNION_() = MSG_STOP THEN EXIT DO
1073  CASE TOK_ENUM : IF Emit->Enum_ ANDALSO ENUM_() = MSG_STOP THEN EXIT DO
1074  CASE TOK_DECL
1075  IF 0 = Emit->Decl_ THEN ToLast = *StaTok : Tok = "" : CONTINUE DO
1076  IF DECLARE_() = MSG_STOP THEN EXIT DO
1077  CASE TOK_DEFI : IF Emit->Defi_ ANDALSO DEFINE_() = MSG_STOP THEN EXIT DO
1078  CASE TOK_MACR : IF Emit->Defi_ ANDALSO MACRO_() = MSG_STOP THEN EXIT DO
1079  CASE TOK_INCL : IF Emit->Incl_ ANDALSO INCLUDE_() = MSG_STOP THEN EXIT DO
1080  CASE TOK_PUBL, TOK_PRIV, TOK_ABST, TOK_VIRT
1081  SETOK(*StaTok, *A, *L) : *L = 0 : CONTINUE DO
1082  'CASE TOK_NAMS : ' !!! ToDo
1083  'CASE TOK_SCOP : ' !!! ToDo
1084  CASE ELSE : ToLast = *StaTok : CONTINUE DO
1085  END SELECT : ToLast = *StaTok : Tok = "" : *L = 0 : CONTINUE DO
1086  END SELECT : Po += 1
1087  LOOP : IF Emit->Exit_ THEN Emit->Exit_(@THIS)
1088 END SUB
1089 
1090 
1091 
1101 SUB Parser.File_(BYREF File AS STRING, BYVAL Tree AS INTEGER)
1102  VAR fnr = FREEFILE
1103  IF OPEN(File FOR INPUT AS #fnr) _
1104  THEN ErrMsg = "couldn't read file """ & File & """ " &_
1105  "(ERR = " & ERR & "), currdir=" & CURDIR : EXIT SUB
1106  Buf = STRING(LOF(fnr), 0)
1107  GET #fnr, , Buf
1108  CLOSE #fnr
1109 
1110  InTree = Tree
1111  Fin = LEN(Buf) - 1
1112  IF OPT->InTree THEN InPath = LEFT(File, INSTRREV(File, SLASH))
1113  Fnam = File
1114  pre_parse()
1115  ErrMsg = "done"
1116 END SUB
1117 
1118 
1119 
1127 SUB Parser.StdIn()
1128  Buf = ""
1129  VAR fnr = FREEFILE
1130  OPEN CONS FOR INPUT AS #fnr
1131  WHILE NOT EOF(fnr)
1132  DIM AS UBYTE z
1133  GET #fnr, , z
1134  Buf &= CHR(z)
1135  WEND
1136  CLOSE #fnr
1137 
1138  IF LEN(Buf) < 3 THEN
1139  IF Emit->Empty_ THEN Emit->Empty_(@THIS)
1140  EXIT SUB
1141  END IF
1142 
1143  Fin = LEN(Buf) - 1
1144  pre_parse() : IF Po THEN EXIT SUB
1145 
1146  Code( "' " & PROJ_NAME & ": no --geany-mode output:" & _
1147  NL & "' select either a line" & _
1148  NL & "' DIM, COMMON, CONST, EXTERN, STATIC, DECLARE, #DEFINE" & _
1149  NL & "' or a block" & _
1150  NL & "' ENUM, UNION, TYPE, #MACRO" & _
1151  NL & "' or a" & _
1152  NL & "' SUB, FUNCTION or PROPERTY" & _
1153  NL & "' declaration or" & _
1154  NL & "' place the cursor in an empty line" & _
1155  NL)
1156 END SUB
1157 
1158 
1159 
1167 SUB Parser.writeOut(BYREF T AS STRING) EXPORT
1168  Code(T)
1169 END SUB
1170 
1171 
1172 
1179 PROPERTY Parser.CurTok() AS LONG PTR EXPORT
1180  RETURN Tk
1181 END PROPERTY
1182 
1183 
1191 PROPERTY Parser.BitIni() AS STRING EXPORT
1192  IF BitTok[3] = TOK_WORD THEN RETURN ": " & SubStr(BitTok + 3)
1193  VAR a = BitTok[1] + 1, l = 0
1194  FOR i AS INTEGER = a TO BitTok[4] - 1
1195  SELECT CASE AS CONST Buf[i]
1196  CASE ASC(" "), ASC(!"\t"), ASC(!"\v") : IF l THEN EXIT FOR
1197  CASE ASC("0") TO ASC("9") : IF l THEN l += 1 ELSE a = i : l = 1
1198  CASE ELSE : EXIT FOR
1199  END SELECT
1200  NEXT : RETURN ": " & MID(Buf, a + 1, l)
1201 END PROPERTY
1202 
1203 
1210 PROPERTY Parser.SubStr() AS STRING EXPORT
1211  IF 0 = Tk THEN RETURN " ?? 0 ?? "
1212  RETURN MID(Buf, Tk[1] + 1, Tk[2])
1213 END PROPERTY
1214 
1215 
1223 PROPERTY Parser.SubStr(BYVAL T AS LONG PTR) AS STRING EXPORT
1224  IF 0 = T THEN RETURN " ?? 0 ?? "
1225  RETURN MID(Buf, T[1] + 1, T[2])
1226 END PROPERTY
1227 
1228 
1229 
1236 PROPERTY Parser.USubStr() AS STRING
1237  RETURN UCASE(MID(Buf, *A + 1, Po - *A))
1238 END PROPERTY
1239 
1240 
1241 
1252 SUB Parser.Include(BYVAL N AS STRING)
1253  WITH *OPT ' & typedef Options* Options_PTR;
1254  IF .RunMode = .GEANY_MODE THEN EXIT SUB
1255 
1256  VAR i = INSTRREV(N, SLASH)
1257  VAR fnam = .addPath(InPath, LEFT(N, i)) & MID(N, i + 1)
1258 
1259  IF DivTok ANDALSO INSTR(.FileIncl, !"\n" & fnam & !"\r") THEN _
1260  MSG_LINE(fnam) : _
1261  MSG_CONT("skipped (already done)") : EXIT SUB
1262 
1263  VAR fnr = FREEFILE
1264  IF OPEN(fnam FOR INPUT AS #fnr) THEN _
1265  MSG_LINE(fnam) : _
1266  MSG_CONT("skipped (couldn't open)") : EXIT SUB
1267  CLOSE #fnr
1268  .FileIncl &= !"\n" & fnam & !"\r"
1269 
1270  VAR pars_old = .Pars : .Pars = NEW Parser(.EmitIF)
1271  .Pars->UserTok = pars_old->UserTok
1272 
1273  MSG_CONT("include ...")
1274  .Level += 1
1275  .doFile(fnam)
1276  .Level -= 1
1277  MSG_CONT("done")
1278 
1279  DELETE .Pars : .Pars = pars_old
1280  END WITH
1281 END SUB
1282