Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2020, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE SCAN;
  9.  
  10. IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS, ERRORS, LISTS;
  11.  
  12.  
  13. CONST
  14.  
  15.     LEXLEN = 1024;
  16.  
  17.     lxUNDEF*   =  0;  lxIDENT*   =  1;  lxINTEGER*   =  2;  lxHEX*     =  3;
  18.     lxCHAR*    =  4;  lxFLOAT*   =  5;  lxSTRING*    =  6;  lxCOMMENT* =  7;
  19.     lxEOF*     =  8;
  20.  
  21.     lxPLUS*    = 21;  lxMINUS*   = 22;  lxMUL*       = 23;  lxSLASH*   = 24;
  22.     lxNOT*     = 25;  lxAND*     = 26;  lxPOINT*     = 27;  lxCOMMA*   = 28;
  23.     lxSEMI*    = 29;  lxBAR*     = 30;  lxLROUND*    = 31;  lxLSQUARE* = 32;
  24.     lxLCURLY*  = 33;  lxCARET*   = 34;  lxEQ*        = 35;  lxNE*      = 36;
  25.     lxLT*      = 37;  lxGT*      = 38;  lxCOLON*     = 39;  lxRROUND*  = 40;
  26.     lxRSQUARE* = 41;  lxRCURLY*  = 42;  lxLE*        = 43;  lxGE*      = 44;
  27.     lxASSIGN*  = 45;  lxRANGE*   = 46;
  28.  
  29.     lxKW       = 51;
  30.  
  31.     lxARRAY*   = 51;  lxBEGIN*   = 52;  lxBY*        = 53;  lxCASE*    = 54;
  32.     lxCONST*   = 55;  lxDIV*     = 56;  lxDO*        = 57;  lxELSE*    = 58;
  33.     lxELSIF*   = 59;  lxEND*     = 60;  lxFALSE*     = 61;  lxFOR*     = 62;
  34.     lxIF*      = 63;  lxIMPORT*  = 64;  lxIN*        = 65;  lxIS*      = 66;
  35.     lxMOD*     = 67;  lxMODULE*  = 68;  lxNIL*       = 69;  lxOF*      = 70;
  36.     lxOR*      = 71;  lxPOINTER* = 72;  lxPROCEDURE* = 73;  lxRECORD*  = 74;
  37.     lxREPEAT*  = 75;  lxRETURN*  = 76;  lxTHEN*      = 77;  lxTO*      = 78;
  38.     lxTRUE*    = 79;  lxTYPE*    = 80;  lxUNTIL*     = 81;  lxVAR*     = 82;
  39.     lxWHILE*   = 83;
  40.  
  41.     lxERROR01* =  -1;  lxERROR02* =  -2;  lxERROR03* =  -3;  lxERROR04* =  -4;
  42.     lxERROR05* =  -5;  lxERROR06* =  -6;  lxERROR07* =  -7;  lxERROR08* =  -8;
  43.     lxERROR09* =  -9;  lxERROR10* = -10;  lxERROR11* = -11;  lxERROR12* = -12;
  44.     lxERROR13* = -13;
  45.  
  46.  
  47. TYPE
  48.  
  49.     LEXSTR* = ARRAY LEXLEN OF CHAR;
  50.  
  51.     DEF = POINTER TO RECORD (LISTS.ITEM)
  52.  
  53.         ident: LEXSTR
  54.  
  55.     END;
  56.  
  57.     IDENT* = POINTER TO RECORD (AVL.DATA)
  58.  
  59.         s*: LEXSTR;
  60.         offset*, offsetW*: INTEGER;
  61.         key: INTEGER
  62.  
  63.     END;
  64.  
  65.     POSITION* = RECORD
  66.  
  67.         line*, col*: INTEGER
  68.  
  69.     END;
  70.  
  71.     LEX* = RECORD
  72.  
  73.         s*:         LEXSTR;
  74.         length*:    INTEGER;
  75.         sym*:       INTEGER;
  76.         pos*:       POSITION;
  77.         ident*:     IDENT;
  78.         string*:    IDENT;
  79.         value*:     ARITH.VALUE;
  80.         error*:     INTEGER;
  81.  
  82.         over:       BOOLEAN
  83.  
  84.     END;
  85.  
  86.     SCANNER* = TXT.TEXT;
  87.  
  88.  
  89. VAR
  90.  
  91.     idents: AVL.NODE;
  92.  
  93.     delimiters: ARRAY 256 OF BOOLEAN;
  94.  
  95.     NewIdent: IDENT;
  96.  
  97.     upto, LowerCase, _if: BOOLEAN;
  98.  
  99.     def: LISTS.LIST;
  100.  
  101.  
  102. PROCEDURE nodecmp (a, b: AVL.DATA): INTEGER;
  103.     RETURN ORD(a(IDENT).s > b(IDENT).s) - ORD(a(IDENT).s < b(IDENT).s)
  104. END nodecmp;
  105.  
  106.  
  107. PROCEDURE enterid* (s: LEXSTR): IDENT;
  108. VAR
  109.     newnode: BOOLEAN;
  110.     node:    AVL.NODE;
  111.  
  112. BEGIN
  113.     NewIdent.s := s;
  114.     idents := AVL.insert(idents, NewIdent, nodecmp, newnode, node);
  115.  
  116.     IF newnode THEN
  117.         NEW(NewIdent);
  118.         NewIdent.offset  := -1;
  119.         NewIdent.offsetW := -1;
  120.         NewIdent.key := 0
  121.     END
  122.  
  123.     RETURN node.data(IDENT)
  124. END enterid;
  125.  
  126.  
  127. PROCEDURE putchar (VAR lex: LEX; c: CHAR);
  128. BEGIN
  129.     IF lex.length < LEXLEN - 1 THEN
  130.         lex.s[lex.length] := c;
  131.         INC(lex.length);
  132.         lex.s[lex.length] := 0X
  133.     ELSE
  134.         lex.over := TRUE
  135.     END
  136. END putchar;
  137.  
  138.  
  139. PROCEDURE nextc (text: TXT.TEXT): CHAR;
  140. BEGIN
  141.     TXT.next(text)
  142.     RETURN text.peak
  143. END nextc;
  144.  
  145.  
  146. PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX);
  147. VAR
  148.     c: CHAR;
  149.  
  150. BEGIN
  151.     c := text.peak;
  152.     ASSERT(S.letter(c));
  153.  
  154.     WHILE S.letter(c) OR S.digit(c) DO
  155.         putchar(lex, c);
  156.         c := nextc(text)
  157.     END;
  158.  
  159.     IF lex.over THEN
  160.         lex.sym := lxERROR06
  161.     ELSE
  162.         lex.ident := enterid(lex.s);
  163.         IF lex.ident.key # 0 THEN
  164.             lex.sym := lex.ident.key
  165.         ELSE
  166.             lex.sym := lxIDENT
  167.         END
  168.     END
  169.  
  170. END ident;
  171.  
  172.  
  173. PROCEDURE number (text: TXT.TEXT; VAR lex: LEX);
  174. VAR
  175.     c: CHAR;
  176.     hex: BOOLEAN;
  177.     error, sym: INTEGER;
  178.  
  179. BEGIN
  180.     c := text.peak;
  181.     ASSERT(S.digit(c));
  182.  
  183.     error := 0;
  184.  
  185.     sym := lxINTEGER;
  186.     hex := FALSE;
  187.  
  188.     WHILE S.digit(c) DO
  189.         putchar(lex, c);
  190.         c := nextc(text)
  191.     END;
  192.  
  193.     WHILE S.hexdigit(c) DO
  194.         putchar(lex, c);
  195.         c := nextc(text);
  196.         hex := TRUE
  197.     END;
  198.  
  199.     IF c = "H" THEN
  200.         putchar(lex, c);
  201.         TXT.next(text);
  202.         sym := lxHEX
  203.  
  204.     ELSIF c = "X" THEN
  205.         putchar(lex, c);
  206.         TXT.next(text);
  207.         sym := lxCHAR
  208.  
  209.     ELSIF c = "." THEN
  210.  
  211.         IF hex THEN
  212.             sym := lxERROR01
  213.         ELSE
  214.  
  215.             c := nextc(text);
  216.  
  217.             IF c # "." THEN
  218.                 putchar(lex, ".");
  219.                 sym := lxFLOAT
  220.             ELSE
  221.                 sym := lxINTEGER;
  222.                 text.peak := 7FX;
  223.                 upto := TRUE
  224.             END;
  225.  
  226.             WHILE S.digit(c) DO
  227.                 putchar(lex, c);
  228.                 c := nextc(text)
  229.             END;
  230.  
  231.             IF c = "E" THEN
  232.  
  233.                 putchar(lex, c);
  234.                 c := nextc(text);
  235.                 IF (c = "+") OR (c = "-") THEN
  236.                     putchar(lex, c);
  237.                     c := nextc(text)
  238.                 END;
  239.  
  240.                 IF S.digit(c) THEN
  241.                     WHILE S.digit(c) DO
  242.                         putchar(lex, c);
  243.                         c := nextc(text)
  244.                     END
  245.                 ELSE
  246.                     sym := lxERROR02
  247.                 END
  248.  
  249.             END
  250.  
  251.         END
  252.  
  253.     ELSIF hex THEN
  254.         sym := lxERROR01
  255.  
  256.     END;
  257.  
  258.     IF lex.over & (sym >= 0) THEN
  259.         sym := lxERROR07
  260.     END;
  261.  
  262.     IF sym = lxINTEGER THEN
  263.         ARITH.iconv(lex.s, lex.value, error)
  264.     ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN
  265.         ARITH.hconv(lex.s, lex.value, error)
  266.     ELSIF sym = lxFLOAT THEN
  267.         ARITH.fconv(lex.s, lex.value, error)
  268.     END;
  269.  
  270.     CASE error OF
  271.     |0:
  272.     |1: sym := lxERROR08
  273.     |2: sym := lxERROR09
  274.     |3: sym := lxERROR10
  275.     |4: sym := lxERROR11
  276.     |5: sym := lxERROR12
  277.     END;
  278.  
  279.     lex.sym := sym
  280. END number;
  281.  
  282.  
  283. PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR);
  284. VAR
  285.     c: CHAR;
  286.     n: INTEGER;
  287.  
  288. BEGIN
  289.     c  := nextc(text);
  290.     n  := 0;
  291.  
  292.     WHILE (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO
  293.         putchar(lex, c);
  294.         c := nextc(text);
  295.         INC(n)
  296.     END;
  297.  
  298.     IF c = quot THEN
  299.         TXT.next(text);
  300.         IF lex.over THEN
  301.             lex.sym := lxERROR05
  302.         ELSE
  303.             IF n # 1 THEN
  304.                 lex.sym := lxSTRING
  305.             ELSE
  306.                 lex.sym := lxCHAR;
  307.                 ARITH.setChar(lex.value, ORD(lex.s[0]))
  308.             END
  309.         END
  310.     ELSE
  311.         lex.sym := lxERROR03
  312.     END;
  313.  
  314.     IF lex.sym = lxSTRING THEN
  315.         lex.string := enterid(lex.s);
  316.         lex.value.typ := ARITH.tSTRING;
  317.         lex.value.string := lex.string
  318.     END
  319.  
  320. END string;
  321.  
  322.  
  323. PROCEDURE comment (text: TXT.TEXT);
  324. VAR
  325.     c: CHAR;
  326.     cond, depth: INTEGER;
  327.  
  328. BEGIN
  329.     cond  := 0;
  330.     depth := 1;
  331.  
  332.     REPEAT
  333.  
  334.         c := text.peak;
  335.         TXT.next(text);
  336.  
  337.         IF c = "*" THEN
  338.             IF cond = 1 THEN
  339.                 cond := 0;
  340.                 INC(depth)
  341.             ELSE
  342.                cond := 2
  343.             END
  344.         ELSIF c = ")" THEN
  345.             IF cond = 2 THEN
  346.                 DEC(depth)
  347.             END;
  348.             cond := 0
  349.         ELSIF c = "(" THEN
  350.             cond := 1
  351.         ELSE
  352.             cond := 0
  353.         END
  354.  
  355.     UNTIL (depth = 0) OR text.eof
  356.  
  357. END comment;
  358.  
  359.  
  360. PROCEDURE delimiter (text: TXT.TEXT; VAR lex: LEX; c: CHAR);
  361. VAR
  362.     sym: INTEGER;
  363.  
  364. BEGIN
  365.     putchar(lex, c);
  366.     c := nextc(text);
  367.  
  368.     CASE lex.s[0] OF
  369.     |"+":
  370.         sym := lxPLUS
  371.  
  372.     |"-":
  373.         sym := lxMINUS
  374.  
  375.     |"*":
  376.         sym := lxMUL
  377.  
  378.     |"/":
  379.         sym := lxSLASH;
  380.  
  381.         IF c = "/" THEN
  382.             sym := lxCOMMENT;
  383.             REPEAT
  384.                 TXT.next(text)
  385.             UNTIL text.eol OR text.eof
  386.         END
  387.  
  388.     |"~":
  389.         sym := lxNOT
  390.  
  391.     |"&":
  392.         sym := lxAND
  393.  
  394.     |".":
  395.         sym := lxPOINT;
  396.  
  397.         IF c = "." THEN
  398.             sym := lxRANGE;
  399.             putchar(lex, c);
  400.             TXT.next(text)
  401.         END
  402.  
  403.     |",":
  404.         sym := lxCOMMA
  405.  
  406.     |";":
  407.         sym := lxSEMI
  408.  
  409.     |"|":
  410.         sym := lxBAR
  411.  
  412.     |"(":
  413.         sym := lxLROUND;
  414.  
  415.         IF c = "*" THEN
  416.             sym := lxCOMMENT;
  417.             TXT.next(text);
  418.             comment(text)
  419.         END
  420.  
  421.     |"[":
  422.         sym := lxLSQUARE
  423.  
  424.     |"{":
  425.         sym := lxLCURLY
  426.  
  427.     |"^":
  428.         sym := lxCARET
  429.  
  430.     |"=":
  431.         sym := lxEQ
  432.  
  433.     |"#":
  434.         sym := lxNE
  435.  
  436.     |"<":
  437.         sym := lxLT;
  438.  
  439.         IF c = "=" THEN
  440.             sym := lxLE;
  441.             putchar(lex, c);
  442.             TXT.next(text)
  443.         END
  444.  
  445.     |">":
  446.         sym := lxGT;
  447.  
  448.         IF c = "=" THEN
  449.             sym := lxGE;
  450.             putchar(lex, c);
  451.             TXT.next(text)
  452.         END
  453.  
  454.     |":":
  455.         sym := lxCOLON;
  456.  
  457.         IF c = "=" THEN
  458.             sym := lxASSIGN;
  459.             putchar(lex, c);
  460.             TXT.next(text)
  461.         END
  462.  
  463.     |")":
  464.         sym := lxRROUND
  465.  
  466.     |"]":
  467.         sym := lxRSQUARE
  468.  
  469.     |"}":
  470.         sym := lxRCURLY
  471.  
  472.     END;
  473.  
  474.     lex.sym := sym
  475.  
  476. END delimiter;
  477.  
  478.  
  479. PROCEDURE Next* (text: SCANNER; VAR lex: LEX);
  480. VAR
  481.     c: CHAR;
  482.  
  483.  
  484.     PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER);
  485.     BEGIN
  486.         IF ~cond THEN
  487.             ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno)
  488.         END
  489.     END check;
  490.  
  491.  
  492.     PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN;
  493.     VAR
  494.         cur: DEF;
  495.  
  496.     BEGIN
  497.         cur := def.first(DEF);
  498.         WHILE (cur # NIL) & (cur.ident # str) DO
  499.             cur := cur.next(DEF)
  500.         END
  501.  
  502.         RETURN cur # NIL
  503.     END IsDef;
  504.  
  505.  
  506.     PROCEDURE Skip (text: SCANNER);
  507.     VAR
  508.         i: INTEGER;
  509.  
  510.     BEGIN
  511.         i := 0;
  512.         WHILE (i <= text.ifc) & ~text._skip[i] DO
  513.             INC(i)
  514.         END;
  515.         text.skip := i <= text.ifc
  516.     END Skip;
  517.  
  518.  
  519.     PROCEDURE prep_if (text: SCANNER; VAR lex: LEX);
  520.     VAR
  521.         skip: BOOLEAN;
  522.  
  523.     BEGIN
  524.         INC(text.ifc);
  525.         text._elsif[text.ifc] := lex.sym = lxELSIF;
  526.         IF lex.sym = lxIF THEN
  527.             INC(text.elsec);
  528.             text._else[text.elsec] := FALSE
  529.         END;
  530.         _if := TRUE;
  531.         skip := TRUE;
  532.         text.skip := FALSE;
  533.  
  534.         Next(text, lex);
  535.         check(lex.sym = lxLROUND, text, lex, 64);
  536.  
  537.         Next(text, lex);
  538.         check(lex.sym = lxIDENT, text, lex, 22);
  539.  
  540.         REPEAT
  541.             IF IsDef(lex.s) THEN
  542.                 skip := FALSE
  543.             END;
  544.  
  545.             Next(text, lex);
  546.             IF lex.sym = lxBAR THEN
  547.                 Next(text, lex);
  548.                 check(lex.sym = lxIDENT, text, lex, 22)
  549.             ELSE
  550.                 check(lex.sym = lxRROUND, text, lex, 33)
  551.             END
  552.         UNTIL lex.sym = lxRROUND;
  553.  
  554.         _if := FALSE;
  555.         text._skip[text.ifc] := skip;
  556.         Skip(text);
  557.         Next(text, lex)
  558.     END prep_if;
  559.  
  560.  
  561.     PROCEDURE prep_end (text: SCANNER; VAR lex: LEX);
  562.     BEGIN
  563.         check(text.ifc > 0, text, lex, 118);
  564.         IF lex.sym = lxEND THEN
  565.             WHILE text._elsif[text.ifc] DO
  566.                 DEC(text.ifc)
  567.             END;
  568.             DEC(text.ifc);
  569.             DEC(text.elsec)
  570.         ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
  571.             check(~text._else[text.elsec], text, lex, 118);
  572.             text._skip[text.ifc] := ~text._skip[text.ifc];
  573.             text._else[text.elsec] := lex.sym = lxELSE
  574.         END;
  575.         Skip(text);
  576.         IF lex.sym = lxELSIF THEN
  577.             prep_if(text, lex)
  578.         ELSE
  579.             Next(text, lex)
  580.         END
  581.     END prep_end;
  582.  
  583.  
  584. BEGIN
  585.  
  586.     REPEAT
  587.         c := text.peak;
  588.  
  589.         WHILE S.space(c) DO
  590.             c := nextc(text)
  591.         END;
  592.  
  593.         lex.s[0]     := 0X;
  594.         lex.length   := 0;
  595.         lex.pos.line := text.line;
  596.         lex.pos.col  := text.col;
  597.         lex.ident    := NIL;
  598.         lex.over     := FALSE;
  599.  
  600.         IF S.letter(c) THEN
  601.             ident(text, lex)
  602.         ELSIF S.digit(c) THEN
  603.             number(text, lex)
  604.         ELSIF (c = '"') OR (c = "'") THEN
  605.             string(text, lex, c)
  606.         ELSIF delimiters[ORD(c)] THEN
  607.             delimiter(text, lex, c)
  608.         ELSIF c = "$" THEN
  609.             IF S.letter(nextc(text)) THEN
  610.                 ident(text, lex);
  611.                 IF lex.sym = lxIF THEN
  612.                     IF ~_if THEN
  613.                         prep_if(text, lex)
  614.                     END
  615.                 ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
  616.                     IF ~_if THEN
  617.                         prep_end(text, lex)
  618.                     END
  619.                 ELSE
  620.                     check(FALSE, text, lex, 119)
  621.                 END
  622.             ELSE
  623.                 check(FALSE, text, lex, 119)
  624.             END
  625.         ELSIF c = 0X THEN
  626.             lex.sym := lxEOF;
  627.             text.skip := FALSE;
  628.             IF text.eof THEN
  629.                 INC(lex.pos.col)
  630.             END
  631.         ELSIF (c = 7FX) & upto THEN
  632.             upto := FALSE;
  633.             lex.sym := lxRANGE;
  634.             putchar(lex, ".");
  635.             putchar(lex, ".");
  636.             DEC(lex.pos.col);
  637.             TXT.next(text)
  638.         ELSE
  639.             putchar(lex, c);
  640.             TXT.next(text);
  641.             lex.sym := lxERROR04
  642.         END;
  643.  
  644.         IF lex.sym < 0 THEN
  645.             lex.error := -lex.sym
  646.         ELSE
  647.             lex.error := 0
  648.         END
  649.  
  650.     UNTIL (lex.sym # lxCOMMENT) & ~text.skip
  651.  
  652. END Next;
  653.  
  654.  
  655. PROCEDURE open* (name: ARRAY OF CHAR): SCANNER;
  656.     RETURN TXT.open(name)
  657. END open;
  658.  
  659.  
  660. PROCEDURE close* (VAR scanner: SCANNER);
  661. BEGIN
  662.     TXT.close(scanner)
  663. END close;
  664.  
  665.  
  666. PROCEDURE init* (lower: BOOLEAN);
  667. VAR
  668.     i: INTEGER;
  669.     delim: ARRAY 23 OF CHAR;
  670.  
  671.  
  672.     PROCEDURE enterkw (key: INTEGER; kw: LEXSTR);
  673.     VAR
  674.         id: IDENT;
  675.         upper: LEXSTR;
  676.  
  677.     BEGIN
  678.         IF LowerCase THEN
  679.             id := enterid(kw);
  680.             id.key := key
  681.         END;
  682.         upper := kw;
  683.         S.UpCase(upper);
  684.         id := enterid(upper);
  685.         id.key := key
  686.     END enterkw;
  687.  
  688.  
  689. BEGIN
  690.     upto := FALSE;
  691.     LowerCase := lower;
  692.  
  693.     FOR i := 0 TO 255 DO
  694.         delimiters[i] := FALSE
  695.     END;
  696.  
  697.     delim := "+-*/~&.,;|([{^=#<>:)]}";
  698.  
  699.     FOR i := 0 TO LEN(delim) - 2 DO
  700.         delimiters[ORD(delim[i])] := TRUE
  701.     END;
  702.  
  703.     NEW(NewIdent);
  704.     NewIdent.s       := "";
  705.     NewIdent.offset  := -1;
  706.     NewIdent.offsetW := -1;
  707.     NewIdent.key     := 0;
  708.  
  709.     idents := NIL;
  710.  
  711.     enterkw(lxARRAY, "array");
  712.     enterkw(lxBEGIN, "begin");
  713.     enterkw(lxBY, "by");
  714.     enterkw(lxCASE, "case");
  715.     enterkw(lxCONST, "const");
  716.     enterkw(lxDIV, "div");
  717.     enterkw(lxDO, "do");
  718.     enterkw(lxELSE, "else");
  719.     enterkw(lxELSIF, "elsif");
  720.     enterkw(lxEND, "end");
  721.     enterkw(lxFALSE, "false");
  722.     enterkw(lxFOR, "for");
  723.     enterkw(lxIF, "if");
  724.     enterkw(lxIMPORT, "import");
  725.     enterkw(lxIN, "in");
  726.     enterkw(lxIS, "is");
  727.     enterkw(lxMOD, "mod");
  728.     enterkw(lxMODULE, "module");
  729.     enterkw(lxNIL, "nil");
  730.     enterkw(lxOF, "of");
  731.     enterkw(lxOR, "or");
  732.     enterkw(lxPOINTER, "pointer");
  733.     enterkw(lxPROCEDURE, "procedure");
  734.     enterkw(lxRECORD, "record");
  735.     enterkw(lxREPEAT, "repeat");
  736.     enterkw(lxRETURN, "return");
  737.     enterkw(lxTHEN, "then");
  738.     enterkw(lxTO, "to");
  739.     enterkw(lxTRUE, "true");
  740.     enterkw(lxTYPE, "type");
  741.     enterkw(lxUNTIL, "until");
  742.     enterkw(lxVAR, "var");
  743.     enterkw(lxWHILE, "while")
  744.  
  745. END init;
  746.  
  747.  
  748. PROCEDURE NewDef* (str: ARRAY OF CHAR);
  749. VAR
  750.     item: DEF;
  751.  
  752. BEGIN
  753.     NEW(item);
  754.     COPY(str, item.ident);
  755.     LISTS.push(def, item)
  756. END NewDef;
  757.  
  758.  
  759. BEGIN
  760.     def := LISTS.create(NIL)
  761. END SCAN.