fb-doc  0.4.0
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  ParTok = 0
215  CalTok = 0
216  AliTok = 0
217  TypTok = 0
218  As_Tok = 0
219  ShaTok = 0
220  Co1Tok = 0
221  Co2Tok = 0
222  PtrTok = 0
223  PtrCount = 0
224 
225  IF 0 = DeclMod THEN
226  DivTok = 0
227  IF *Tk = TOK_AS THEN As_Tok = Tk : SKIP ELSE RETURN MSG_ERROR
228 
229  SELECT CASE AS CONST *Tk
230  CASE TOK_SUB : FunTok = Tk
231  CASE TOK_FUNC : FunTok = Tk
232  CASE ELSE
233  IF *Tk = TOK_CONS THEN Co1Tok = Tk : SKIP
234  IF *Tk < TOK_BYTE ORELSE *Tk > TOK_WORD THEN RETURN MSG_ERROR
235  TypTok = Tk : FunTok = 0
236  END SELECT : SKIP
237  END IF
238 
239  SELECT CASE AS CONST *Tk
240  CASE TOK_EQUAL
241  IF FunTok THEN TypTok = 0 : RETURN MSG_ERROR
242  IniTok = Tk : RETURN Tk - t
243  CASE TOK_BROPN : IF 0 = FunTok THEN RETURN Tk - t
244  ParTok = Tk : skipOverBrclo()
245  CASE ELSE
246  IF 0 = FunTok THEN
247  IF *Tk = TOK_CONS THEN
248  Co2Tok = Tk : SKIP
249  IF *Tk <> TOK_PTR THEN TypTok = 0 : RETURN MSG_ERROR
250  ELSE
251  IF *Tk <> TOK_PTR THEN RETURN Tk - t
252  END IF
253 
254  PtrTok = Tk : WHILE *Tk = TOK_PTR : PtrCount += 1 : SKIP : WEND
255 
256  IF *Tk = TOK_EQUAL THEN IniTok = Tk
257  RETURN Tk - t
258  END IF
259 
260  IF *Tk = TOK_EOS THEN RETURN IIF(*FunTok = TOK_FUNC, MSG_ERROR, TOK_EOS)
261 
262  SELECT CASE AS CONST *Tk
263  CASE TOK_CDEC, TOK_STCL, TOK_PASC : CalTok = Tk : SKIP
264  END SELECT
265 
266  IF *Tk = TOK_OVER THEN SKIP
267  IF *Tk = TOK_ALIA THEN
268  AliTok = Tk
269  SKIP : IF *Tk <> TOK_QUOTE THEN TypTok = 0 : RETURN MSG_ERROR
270  SKIP
271  END IF
272 
273  IF *Tk = TOK_BROPN THEN ParTok = Tk : skipOverBrclo()
274  END SELECT
275 
276  IF *Tk = TOK_AS THEN
277  As_Tok = Tk : SKIP
278  IF *Tk = TOK_CONS THEN Co1Tok = Tk : SKIP
279  TypTok = Tk : SKIP
280  IF *Tk = TOK_CONS THEN
281  Co2Tok = Tk : SKIP
282  IF *Tk <> TOK_PTR THEN FunTok = 0: TypTok = 0 : RETURN MSG_ERROR
283  END IF
284  PtrTok = Tk : WHILE *Tk = TOK_PTR : PtrCount += 1 : SKIP : WEND
285  ELSE
286  IF *FunTok = TOK_FUNC THEN RETURN MSG_ERROR
287  END IF
288 
289  IF *Tk = TOK_STAT THEN
290  SKIP : IF *Tk = TOK_EXPO THEN SKIP
291  ELSE
292  IF *Tk = TOK_EXPO THEN SKIP : IF *Tk = TOK_STAT THEN SKIP
293  END IF : RETURN Tk - t
294 END FUNCTION
295 
296 
297 
305 SUB Parser.parseListNam(BYVAL Export_ AS EmitFunc) EXPORT
306  VAR count = 1
307  TypTok = 0 : FunTok = 0
308  DO
309  Tk1 = Tk
310  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverComma() : CONTINUE DO
311  skipOverComma() : ListCount = count : Export_(@THIS) : count += 1
312  LOOP UNTIL *Tk <= TOK_COMMA
313 END SUB
314 
315 
316 
324 SUB Parser.parseListNamTyp(BYVAL Export_ AS EmitFunc) EXPORT
325  VAR count = 1
326  DO
327  Tk1 = Tk
328  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverComma() : CONTINUE DO
329  IF MSG_ERROR >= demuxTyp() THEN Errr("type expected") : skipOverComma() : CONTINUE DO
330  skipOverComma() : ListCount = count : Export_(@THIS) : count += 1
331  LOOP UNTIL *Tk <= TOK_COMMA
332 END SUB
333 
334 
335 
343 SUB Parser.parseBlockEnum(BYVAL Export_ AS EmitFunc) EXPORT
344  VAR lico = 0
345  TypTok = 0 : FunTok = 0 : LevelCount += 1
346  WHILE Tk < EndTok
347  Tk1 = Tk
348  SELECT CASE AS CONST *Tk
349  CASE TOK_END
350  SKIP : IF *Tk = TOK_ENUM THEN EXIT WHILE
351  Errr("END ENUM expected") : EXIT WHILE
352  CASE TOK_LATTE : skipOverColon()
353  CASE ELSE
354  IF MSG_ERROR >= demuxNam() THEN Errr("name expected") : skipOverColon() : EXIT SELECT
355  ListCount = lico
356  skipOverComma() : IF *Tk = TOK_EOS THEN lico = 0 : skipOverColon() ELSE lico += 1
357  Export_(@THIS)
358  END SELECT
359  WEND : skipOverColon() : LevelCount -= 1
360 END SUB
361 
362 
363 
371 SUB Parser.parseBlockTyUn(BYVAL Export_ AS EmitFunc) EXPORT
372  VAR in_tk1 = iif(LevelCount, *Tk1, *StaTok)
373  LevelCount += 1
374  DO
375  Tk1 = Tk
376  VAR nextok = Tk[3]
377  SELECT CASE AS CONST nextok
378  CASE TOK_AS, TOK_BROPN
379  BitTok = 0
380  SELECT CASE AS CONST *Tk1
381  CASE TOK_DIM, TOK_RDIM : SKIP
382  IF MSG_ERROR >= demuxTyp() THEN _
383  IF Errr("type expected1") = MSG_ERROR THEN CONTINUE DO _
384  ELSE EXIT DO
385  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
386  IF Errr("name expected1") = MSG_ERROR THEN CONTINUE DO _
387  ELSE EXIT DO
388  skipOverComma()
389  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
390  IF *Tk >= TOK_ABST THEN parseListNam(Export_)
391  CASE ELSE
392  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
393  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
394  ELSE EXIT DO
395  IF MSG_ERROR >= demuxTyp() THEN _
396  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
397  ELSE EXIT DO
398  skipOverComma()
399  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
400  IF *Tk >= TOK_ABST THEN parseListNamTyp(Export_)
401  END SELECT
402  skipOverColon()
403  CASE ELSE
404  SELECT CASE AS CONST *Tk1
405  CASE TOK_LATTE : skipOverColon()
406  CASE TOK_DIM, TOK_RDIM : SKIP
407  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
408  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
409  ELSE EXIT DO
410  IF *Tk <> TOK_AS THEN _
411  IF Errr("'AS' expected->" & SubStr(Tk) & "<-") = MSG_ERROR THEN CONTINUE DO _
412  ELSE EXIT DO
413  IF MSG_ERROR >= demuxTyp() THEN _
414  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
415  ELSE EXIT DO
416  skipOverComma()
417  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
418  IF *Tk >= TOK_ABST THEN parseListNamTyp(Export_)
419  skipOverColon()
420  CASE TOK_AS
421  BitTok = 0
422  IF MSG_ERROR >= demuxTyp() THEN _
423  IF Errr("type expected") = MSG_ERROR THEN CONTINUE DO _
424  ELSE EXIT DO
425  IF MSG_ERROR >= demuxNam(TOK_ABST) THEN _
426  IF Errr("name expected") = MSG_ERROR THEN CONTINUE DO _
427  ELSE EXIT DO
428  skipOverComma()
429  *NamTok = TOK_WORD : ListCount = 0 : Export_(@THIS)
430  IF *Tk >= TOK_ABST THEN parseListNam(Export_)
431  skipOverColon()
432  CASE TOK_END
433  IF nextok = in_tk1 THEN EXIT DO
434  IF Errr("not supported") < MSG_ERROR THEN EXIT DO
435  skipOverColon()
436 
437  CASE TOK_DECL : SKIP
438  IF MSG_ERROR >= demuxDecl() THEN IF Errr("syntax error " & SubStr(NamTok)) = MSG_ERROR _
439  THEN skipOverColon() : EXIT SELECT ELSE EXIT DO
440  skipOverColon() : Export_(@THIS)
441 
442  CASE TOK_PUBL, TOK_PRIV, TOK_PROT
443  skipOverColon() : Export_(@THIS)
444 
445  CASE TOK_ENUM, TOK_TYPE, TOK_UNIO, TOK_CLAS
446  VAR n = BlockNam
447  IF nextok = TOK_WORD THEN SKIP : BlockNam = SubStr ELSE BlockNam = ""
448  skipOverColon() : Export_(@THIS) : BlockNam = n
449  CASE ELSE
450  skipOverColon() : IF Errr("not supported: " & SubStr(Tk1)) < MSG_ERROR THEN EXIT DO
451  END SELECT
452  END SELECT
453  LOOP UNTIL Tk >= EndTok : skipOverColon() : LevelCount -= 1
454 END SUB
455 
456 
457 
465 SUB Parser.parseListPara(BYVAL Export_ AS EmitFunc) EXPORT
466  VAR count = 0, t = Tk
467  Tk = ParTok
468  SKIP
469  DO
470  Tk1 = Tk
471  By_Tok = 0
472  SELECT CASE AS CONST *Tk
473  CASE TOK_BRCLO : IF count > 0 THEN Errr("parameter expected")
474  ListCount = count : EXIT DO
475  CASE TOK_3DOT : NamTok = Tk : TypTok = 0 : FunTok = 0
476  CASE ELSE
477  IF *Tk = TOK_BYVA ORELSE *Tk = TOK_BYRE THEN By_Tok = Tk : SKIP
478  IF *Tk <> TOK_AS ANDALSO *Tk >= TOK_ABST THEN
479  NamTok = Tk : SKIP
480  IF *Tk = TOK_BROPN THEN DimTok = Tk : skipOverBrclo()
481  ELSE
482  NamTok = 0
483  END IF
484  IF MSG_ERROR >= demuxTyp() THEN Errr("type expected") : skipOverComma() : CONTINUE DO
485  END SELECT
486  skipOverComma() : count += 1 : ListCount = count : Export_(@THIS)
487  LOOP UNTIL *Tk < TOK_COMMA : By_Tok = 0 : Tk = t
488 END SUB
489 
490 
491 
505 FUNCTION Parser.TYPE_() AS INTEGER
506  IF 3 > tokenize(TO_COLON) THEN RETURN Errr("syntax error")
507 
508  DimTok = 0 : IniTok = 0 : BitTok = 0
509  IF *StaTok = TOK_TYPE THEN
510  IF *Tk = TOK_AS THEN
511  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
512  IF *Tk = TOK_WORD THEN NamTok = Tk ELSE RETURN Errr("name expected")
513  skipOverComma()
514  IF Emit->Decl_ THEN Emit->Decl_(@THIS) :
515  RETURN MSG_ERROR
516  ELSE
517  IF *Tk = TOK_WORD THEN NamTok = Tk : SKIP ELSE RETURN Errr("name expected")
518  IF *Tk = TOK_AS THEN
519  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
520  skipOverComma()
521  IF Emit->Decl_ THEN Emit->Decl_(@THIS) :
522  RETURN MSG_ERROR
523  END IF
524  END IF
525  ELSE
526  IF *Tk = TOK_WORD THEN NamTok = Tk ELSE RETURN Errr("name expected")
527  END IF
528  IF 0 = Emit->Clas_ THEN RETURN MSG_ERROR
529  BlockNam = SubStr(NamTok)
530  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
531  Emit->Clas_(@THIS) : RETURN MSG_ERROR
532 END FUNCTION
533 
534 
535 
543 FUNCTION Parser.VAR_() AS INTEGER
544  IF 3 > tokenize(TO_COLON) THEN _
545  RETURN IIF(*StaTok = TOK_EXRN, MSG_ERROR, Errr("syntax error"))
546  IF *Tk <> TOK_PRES THEN DivTok = 0 ELSE DivTok = Tk : SKIP
547  IF *Tk <> TOK_SHAR THEN ShaTok = 0 ELSE ShaTok = Tk : SKIP
548 
549  IF *Tk = TOK_AS THEN
550  IF MSG_ERROR >= demuxTyp() THEN RETURN Errr("type expected")
551  IF MSG_ERROR >= demuxNam() THEN RETURN Errr("name expected")
552  ELSE
553  IF *StaTok = TOK_EXRN THEN RETURN MSG_ERROR
554  IF MSG_ERROR >= demuxNam() THEN RETURN Errr("name expected")
555  IF *Tk = TOK_AS THEN demuxTyp() ELSE TypTok = 0 : FunTok = 0
556  IF 0 = TypTok ANDALSO 0 = FunTok THEN
557  SELECT CASE AS CONST *StaTok
558  CASE TOK_VAR, TOK_CONS
559  IF 0 = IniTok THEN RETURN Errr("initialization expected")
560  CASE ELSE : RETURN Errr("type expected")
561  END SELECT
562  END IF
563  END IF
564 
565  skipOverComma()
566  Emit->Decl_(@THIS)
567  IF *Tk <= TOK_EOS THEN RETURN MSG_ERROR
568  IF NamTok > TypTok THEN parseListNam(Emit->Decl_) _
569  ELSE parseListNamTyp(Emit->Decl_)
570  RETURN MSG_ERROR
571 END FUNCTION
572 
573 
574 
582 FUNCTION Parser.ENUM_() AS INTEGER
583  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
584  IF *Tk = TOK_WORD THEN BlockNam = SubStr : SKIP ELSE BlockNam = ""
585  IF *Tk = TOK_EOS THEN skipOverColon() ELSE RETURN Errr("syntax error")
586  Tk1 = StaTok
587  Emit->Enum_(@THIS)
588  RETURN MSG_ERROR
589 END FUNCTION
590 
591 
592 
600 FUNCTION Parser.UNION_() AS INTEGER
601  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
602  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
603  BlockNam = SubStr()
604  skipOverColon()
605  Tk1 = StaTok
606  Emit->Unio_(@THIS)
607  RETURN MSG_ERROR
608 END FUNCTION
609 
610 
611 
620 FUNCTION Parser.FUNCTION_() AS INTEGER
621  SELECT CASE AS CONST ToLast
622  CASE TOK_PUBL, TOK_PRIV, TOK_ABST, TOK_VIRT : DivTok = StaTok
623  CASE ELSE : DivTok = 0
624  END SELECT
625  IF 9 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
626  FunTok = StaTok
627 
628  IF DivTok THEN DivTok = Tk1
629  IF MSG_ERROR >= demuxNam(TOK_WORD, 1) THEN RETURN Errr("name expected")
630  IF MSG_ERROR >= demuxTyp(1) THEN RETURN Errr("syntax error")
631 
632  FOR i AS INTEGER = 0 TO 1
633  SELECT CASE AS CONST *Tk
634  CASE TOK_STAT : SKIP ' !!! ToDo
635  CASE TOK_EXPO : SKIP ' !!! ToDo
636  CASE ELSE : EXIT FOR
637  END SELECT
638  NEXT
639  skipOverBrclo()
640  Emit->Func_(@THIS)
641  RETURN MSG_ERROR
642 END FUNCTION
643 
644 
645 
653 FUNCTION Parser.DECLARE_() AS INTEGER
654  IF 3 > tokenize(TO_COLON) THEN RETURN Errr("syntax error")
655  IF MSG_ERROR >= demuxDecl() THEN RETURN Errr("syntax error")
656  Emit->Decl_(@THIS)
657  RETURN MSG_ERROR
658 END FUNCTION
659 
660 
661 
670 FUNCTION Parser.INCLUDE_() AS INTEGER
671  IF 3 > tokenize(TO_EOL) THEN RETURN Errr("syntax error")
672  IF *Tk = TOK_ONCE THEN DivTok = Tk : SKIP ELSE DivTok = 0
673  IF *Tk <> TOK_QUOTE THEN RETURN Errr("file name expected")
674  NamTok = Tk
675  Emit->Incl_(@THIS)
676 END FUNCTION
677 
678 
679 
686 FUNCTION Parser.MACRO_() AS INTEGER
687  IF 3 > tokenize(TO_END_BLOCK) THEN RETURN Errr("syntax error")
688  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
689  NamTok = Tk : SKIP
690  IF *Tk <> TOK_BROPN THEN RETURN Errr("'()' expected")
691  ParTok = Tk
692  skipOverBrclo()
693  Emit->Defi_(@THIS)
694  RETURN MSG_ERROR
695 END FUNCTION
696 
697 
698 
705 FUNCTION Parser.DEFINE_() AS INTEGER
706  IF 3 > tokenize(TO_EOL) THEN RETURN Errr("syntax error")
707  IF *Tk <> TOK_WORD THEN RETURN Errr("name expected")
708  NamTok = Tk : SKIP
709  IF *Tk = TOK_BROPN ANDALSO Tk[1] = NamTok[1] + NamTok[2] _
710  THEN ParTok = Tk : skipOverBrclo() _
711  ELSE ParTok = 0
712  DivTok = Tk
713  Tk = EndTok - 3
714  Emit->Defi_(@THIS)
715  RETURN MSG_ERROR
716 END FUNCTION
717 
718 
719 
727 FUNCTION Parser.Errr(BYREF E AS STRING) AS INTEGER
728  VAR z = LineNo
729  IF LevelCount THEN ' adapt line number counter
730  FOR i AS INTEGER = Tk[1] TO EndTok[1]
731  IF Buf[i] = ASC(!"\n") THEN z -= 1
732  NEXT
733  END IF
734  ErrMsg = "-error(" & z & "): " & E & ", found '" & SubStr(Tk) & "' "
735 
736  SELECT CASE AS CONST *StaTok
737  CASE TOK_DIM : ErrMsg &= "(DIM)"
738  CASE TOK_RDIM : ErrMsg &= "(REDIM)"
739  CASE TOK_VAR : ErrMsg &= "(VAR)"
740  CASE TOK_CONS : ErrMsg &= "(CONST)"
741  CASE TOK_STAT : ErrMsg &= "(STATIC)"
742  CASE TOK_COMM : ErrMsg &= "(COMMON)"
743  CASE TOK_EXRN : ErrMsg &= "(EXTERN)"
744  CASE TOK_TYPE : ErrMsg &= "(TYPE)"
745  CASE TOK_CLAS : ErrMsg &= "(CLASS)"
746  CASE TOK_SUB : ErrMsg &= "(SUB)"
747  CASE TOK_FUNC : ErrMsg &= "(FUNCTION)"
748  CASE TOK_PROP : ErrMsg &= "(PROPERTY)"
749  CASE TOK_CTOR : ErrMsg &= "(CONSTRUCTOR)"
750  CASE TOK_DTOR : ErrMsg &= "(DESTRUCTOR)"
751  CASE TOK_NAMS : ErrMsg &= "(NAMESPACE)"
752  CASE TOK_SCOP : ErrMsg &= "(SCOPE)"
753  CASE TOK_ENUM : ErrMsg &= "(ENUM)"
754  CASE TOK_UNIO : ErrMsg &= "(UNION)"
755  CASE TOK_DECL : ErrMsg &= "(DECLARE)"
756  CASE TOK_DEFI : ErrMsg &= "(#DEFINE)"
757  CASE TOK_MACR : ErrMsg &= "(#MACRO)"
758  CASE ELSE : ErrMsg &= "(???)"
759  END SELECT
760  IF Emit->Error_ THEN Emit->Error_(@THIS)
761  ErrMsg = ""
762 
763  RETURN IIF(Buf[Po] = 0, MSG_STOP, MSG_ERROR)
764 END FUNCTION
765 
766 
767 
775 FUNCTION Parser.getToken() AS INTEGER
776  SELECT CASE AS CONST Buf[*A]
777  CASE ASC("A"), ASC("a")
778  SELECT CASE USubStr()
779  CASE "AS" : RETURN TOK_AS
780  CASE "ALIAS" : RETURN TOK_ALIA
781  CASE "ANY" : RETURN TOK_ANY
782  CASE "ABSTRACT" : RETURN TOK_ABST
783  END SELECT
784  CASE ASC("B"), ASC("b")
785  SELECT CASE USubStr()
786  CASE "BYTE" : RETURN TOK_BYTE
787  CASE "BYREF" : RETURN TOK_BYRE
788  CASE "BYVAL" : RETURN TOK_BYVA
789  END SELECT
790  CASE ASC("C"), ASC("c")
791  SELECT CASE USubStr()
792  CASE "CAST" : RETURN TOK_CAST
793  CASE "CDECL" : RETURN TOK_CDEC
794  CASE "CLASS" : RETURN TOK_CLAS
795  CASE "CONST" : RETURN TOK_CONS
796  CASE "COMMON" : RETURN TOK_COMM
797  CASE "CONSTRUCTOR" : RETURN TOK_CTOR
798  END SELECT
799  CASE ASC("D"), ASC("d")
800  SELECT CASE USubStr()
801  CASE "DIM" : RETURN TOK_DIM
802  CASE "DOUBLE" : RETURN TOK_DOUB
803  CASE "DEFINE" : IF ToLast = TOK_LATTE THEN RETURN TOK_DEFI
804  CASE "DECLARE" : RETURN TOK_DECL
805  CASE "DESTRUCTOR" : RETURN TOK_DTOR
806  END SELECT
807  CASE ASC("E"), ASC("e")
808  SELECT CASE USubStr()
809  CASE "END" : RETURN TOK_END
810  CASE "ENUM" : RETURN TOK_ENUM
811  CASE "EXTERN" : RETURN TOK_EXRN
812  CASE "EXPORT" : RETURN TOK_EXPO
813  CASE "EXTENDS" : RETURN TOK_EXDS
814  CASE "ENDMACRO" : IF ToLast = TOK_LATTE THEN RETURN TOK_EMAC
815  END SELECT
816  CASE ASC("F"), ASC("f")
817  SELECT CASE USubStr()
818  CASE "FUNCTION" : RETURN TOK_FUNC
819  CASE "FIELD" : RETURN TOK_FILD
820  END SELECT
821  CASE ASC("I"), ASC("i")
822  SELECT CASE USubStr()
823  CASE "INCLUDE" : IF ToLast = TOK_LATTE THEN RETURN TOK_INCL
824  CASE "INTEGER" : RETURN TOK_INT
825  END SELECT
826  CASE ASC("L"), ASC("l")
827  SELECT CASE USubStr()
828  CASE "LIB" : RETURN TOK_LIB
829  CASE "LONG" : RETURN TOK_LONG
830  CASE "LONGINT" : RETURN TOK_LINT
831  END SELECT
832  CASE ASC("M"), ASC("m") : IF USubStr() = "MACRO" THEN IF ToLast = TOK_LATTE THEN RETURN TOK_MACR
833  CASE ASC("N"), ASC("n") : IF USubStr() = "NAMESPACE" THEN RETURN TOK_NAMS
834  CASE ASC("O"), ASC("o")
835  SELECT CASE USubStr()
836  CASE "ONCE" : RETURN TOK_ONCE
837  CASE "OPERATOR" : RETURN TOK_OPER
838  CASE "OVERLOAD" : RETURN TOK_OVER
839  END SELECT
840  CASE ASC("P"), ASC("p")
841  SELECT CASE USubStr()
842  CASE "PTR" : RETURN TOK_PTR
843  CASE "PEEK" : RETURN TOK_PEEK
844  CASE "POINTER" : RETURN TOK_PTR
845  CASE "PRESERVE" : RETURN TOK_PRES
846  CASE "PROPERTY" : RETURN TOK_PROP
847  CASE "PUBLIC" : RETURN TOK_PUBL
848  CASE "PRIVATE" : RETURN TOK_PRIV
849  CASE "PROTECTED" : RETURN TOK_PROT
850  CASE "PASCAL" : RETURN TOK_PASC
851  END SELECT
852  CASE ASC("R"), ASC("r") : IF USubStr() = "REDIM" THEN RETURN TOK_RDIM
853  CASE ASC("S"), ASC("s")
854  SELECT CASE USubStr()
855  CASE "SUB" : RETURN TOK_SUB
856  CASE "SCOPE" : RETURN TOK_SCOP
857  CASE "SHORT" : RETURN TOK_SHOR
858  CASE "SINGLE" : RETURN TOK_SING
859  CASE "SHARED" : RETURN TOK_SHAR
860  CASE "STRING" : RETURN TOK_STRI
861  CASE "STATIC" : RETURN TOK_STAT
862  CASE "STDCALL" : RETURN TOK_STCL
863  END SELECT
864  CASE ASC("T"), ASC("t") : IF USubStr() = "TYPE" THEN RETURN TOK_TYPE
865  CASE ASC("U"), ASC("u")
866  SELECT CASE USubStr()
867  CASE "UNION" : RETURN TOK_UNIO
868  CASE "UBYTE" : RETURN TOK_UBYT
869  CASE "ULONG" : RETURN TOK_ULNG
870  CASE "ULONGINT" : RETURN TOK_ULIN
871  CASE "UINTEGER" : RETURN TOK_UINT
872  CASE "USHORT" : RETURN TOK_USHO
873  END SELECT
874  CASE ASC("V"), ASC("v")
875  SELECT CASE USubStr()
876  CASE "VAR" : RETURN TOK_VAR
877  CASE "VIRTUAL" : RETURN TOK_VIRT
878  END SELECT
879  CASE ASC("W"), ASC("w")
880  SELECT CASE USubStr()
881  CASE "WITH" : RETURN TOK_WITH
882  CASE "WSTRING" : RETURN TOK_WSTR
883  END SELECT
884  CASE ASC("Z"), ASC("z") : IF USubStr() = "ZSTRING" THEN RETURN TOK_ZSTR
885  END SELECT : RETURN TOK_WORD
886 END FUNCTION
887 
888 
889 
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