basic.p.1
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:47k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. $ sysprog, ucsd, heap_dispose, partial_eval $
  2. {$ debug$}
  3. program basic(input, output);
  4. const
  5.    checking = true;
  6.    varnamelen = 20;
  7.    maxdims = 4;
  8. type
  9.    varnamestring = string[varnamelen];
  10.    string255 = string[255];
  11.    string255ptr = ^string255;
  12.    tokenkinds = (tokvar, toknum, tokstr, toksnerr,
  13.                  tokplus, tokminus, toktimes, tokdiv, tokup, toklp, tokrp, 
  14.                  tokcomma, toksemi, tokcolon, tokeq, toklt, tokgt,
  15.                  tokle, tokge, tokne,
  16.                  tokand, tokor, tokxor, tokmod, toknot, toksqr, toksqrt, toksin,
  17.                  tokcos, toktan, tokarctan, toklog, tokexp, tokabs, toksgn,
  18.                  tokstr_, tokval, tokchr_, tokasc, toklen, tokmid_, tokpeek,
  19.                  tokrem, toklet, tokprint, tokinput, tokgoto, tokif, tokend, 
  20.                  tokstop, tokfor, toknext, tokwhile, tokwend, tokgosub,
  21.                  tokreturn, tokread, tokdata, tokrestore, tokgotoxy, tokon,
  22.                  tokdim, tokpoke,
  23.                  toklist, tokrun, toknew, tokload, tokmerge, toksave, tokbye,
  24.                  tokdel, tokrenum,
  25.                  tokthen, tokelse, tokto, tokstep);
  26.    realptr = ^real;
  27.    basicstring = string255ptr;
  28.    stringptr = ^basicstring;
  29.    numarray = array[0..maxint] of real;
  30.    arrayptr = ^numarray;
  31.    strarray = array[0..maxint] of basicstring;
  32.    strarrayptr = ^strarray;
  33.    tokenptr = ^tokenrec;
  34.    lineptr = ^linerec;
  35.    varptr = ^varrec;
  36.    loopptr = ^looprec;
  37.    tokenrec =
  38.       record
  39.          next : tokenptr;
  40.          case kind : tokenkinds of
  41.             tokvar : (vp : varptr);
  42.             toknum : (num : real);
  43.             tokstr, tokrem : (sp : string255ptr);
  44.             toksnerr : (snch : char);
  45.       end;
  46.    linerec =
  47.       record
  48.          num, num2 : integer;
  49.          txt : tokenptr;
  50.          next : lineptr;
  51.       end;
  52.    varrec =
  53.       record
  54.          name : varnamestring;
  55.          next : varptr;
  56.          dims : array [1..maxdims] of integer;
  57.          numdims : 0..maxdims;
  58.          case stringvar : boolean of
  59.             false : (arr : arrayptr;  val : realptr;  rv : real);
  60.             true : (sarr : strarrayptr;  sval : stringptr;  sv : basicstring);
  61.       end;
  62.    valrec =
  63.       record
  64.          case stringval : boolean of
  65.             false : (val : real);
  66.             true : (sval : basicstring);
  67.       end;
  68.    loopkind = (forloop, whileloop, gosubloop);
  69.    looprec =
  70.       record
  71.          next : loopptr;
  72.          homeline : lineptr;
  73.          hometok : tokenptr;
  74.          case kind : loopkind of
  75.             forloop :
  76.                ( vp : varptr;
  77.                  max, step : real );
  78.       end;
  79. var
  80.    inbuf : string255ptr;
  81.    linebase : lineptr;
  82.    varbase : varptr;
  83.    loopbase : loopptr;
  84.    curline : integer;
  85.    stmtline, dataline : lineptr;
  86.    stmttok, datatok, buf : tokenptr;
  87.    exitflag : boolean;
  88.    excp_line ['EXCP_LINE'] : integer;
  89. $if not checking$
  90.    $range off$
  91. $end$
  92. procedure misc_getioerrmsg(var s : string; io : integer);
  93.    external;
  94. procedure misc_printerror(er, io : integer);
  95.    external;
  96. function asm_iand(a, b : integer) : integer;
  97.    external;
  98. function asm_ior(a, b : integer) : integer;
  99.    external;
  100. procedure hpm_new(var p : anyptr; size : integer);
  101.    external;
  102. procedure hpm_dispose(var p : anyptr; size : integer);
  103.    external;
  104. procedure restoredata;
  105.    begin
  106.       dataline := nil;
  107.       datatok := nil;
  108.    end;
  109. procedure clearloops;
  110.    var
  111.       l : loopptr;
  112.    begin
  113.       while loopbase <> nil do
  114.          begin
  115.             l := loopbase^.next;
  116.             dispose(loopbase);
  117.             loopbase := l;
  118.          end;
  119.    end;
  120. function arraysize(v : varptr) : integer;
  121.    var
  122.       i, j : integer;
  123.    begin
  124.       with v^ do
  125.          begin
  126.             if stringvar then
  127.                j := 4
  128.             else
  129.                j := 8;
  130.             for i := 1 to numdims do
  131.                j := j * dims[i];
  132.          end;
  133.       arraysize := j;
  134.    end;
  135. procedure clearvar(v : varptr);
  136.    begin
  137.       with v^ do
  138.          begin
  139.             if numdims <> 0 then
  140.                hpm_dispose(arr, arraysize(v))
  141.             else if stringvar and (sv <> nil) then
  142.                dispose(sv);
  143.             numdims := 0;
  144.             if stringvar then
  145.                begin
  146.                   sv := nil;
  147.                   sval := addr(sv);
  148.                end
  149.             else
  150.                begin
  151.                   rv := 0;
  152.                   val := addr(rv);
  153.                end;
  154.          end;
  155.    end;
  156. procedure clearvars;
  157.    var
  158.       v : varptr;
  159.    begin
  160.       v := varbase;
  161.       while v <> nil do
  162.          begin
  163.             clearvar(v);
  164.             v := v^.next;
  165.          end;
  166.    end;
  167. function numtostr(n : real) : string255;
  168.    var
  169.       s : string255;
  170.       i : integer;
  171.    begin
  172.       setstrlen(s, 255);
  173.       if (n <> 0) and (abs(n) < 1e-2) or (abs(n) >= 1e12) then
  174.          begin
  175.             strwrite(s, 1, i, n);
  176.             setstrlen(s, i-1);
  177.             numtostr := s;
  178.          end
  179.       else
  180.          begin
  181.             strwrite(s, 1, i, n:30:10);
  182.             repeat
  183.                i := i - 1;
  184.             until s[i] <> '0';
  185.             if s[i] = '.' then
  186.                i := i - 1;
  187.             setstrlen(s, i);
  188.             numtostr := strltrim(s);
  189.          end;
  190.    end;
  191. procedure parse(inbuf : string255ptr; var buf : tokenptr);
  192.    const
  193.       toklength = 20;
  194.    type
  195.       chset = set of char;
  196.    const
  197.       idchars = chset ['A'..'Z','a'..'z','0'..'9','_','$'];
  198.    var
  199.       i, j, k : integer;
  200.       token : string[toklength];
  201.       t, tptr : tokenptr;
  202.       v : varptr;
  203.       ch : char;
  204.       n, d, d1 : real;
  205.    begin
  206.       tptr := nil;
  207.       buf := nil;
  208.       i := 1;
  209.       repeat
  210.          ch := ' ';
  211.          while (i <= strlen(inbuf^)) and (ch = ' ') do
  212.             begin
  213.                ch := inbuf^[i];
  214.                i := i + 1;
  215.             end;
  216.          if ch <> ' ' then
  217.             begin
  218.                new(t);
  219.                if tptr = nil then
  220.                   buf := t
  221.                else
  222.                   tptr^.next := t;
  223.                tptr := t;
  224.                t^.next := nil;
  225.                case ch of
  226.                   'A'..'Z', 'a'..'z' :
  227.                      begin
  228.                         i := i - 1;
  229.                         j := 0;
  230.                         setstrlen(token, strmax(token));
  231.                         while (i <= strlen(inbuf^)) and (inbuf^[i] in idchars) do
  232.                            begin
  233.                               if j < toklength then
  234.                                  begin
  235.                                     j := j + 1;
  236.                                     token[j] := inbuf^[i];
  237.                                  end;
  238.                               i := i + 1;
  239.                            end;
  240.                         setstrlen(token, j);
  241.                         if (token = 'and')     or (token = 'AND')     then t^.kind := tokand     
  242.                    else if (token = 'or')      or (token = 'OR')      then t^.kind := tokor      
  243.                    else if (token = 'xor')     or (token = 'XOR')     then t^.kind := tokxor     
  244.                    else if (token = 'not')     or (token = 'NOT')     then t^.kind := toknot     
  245.                    else if (token = 'mod')     or (token = 'MOD')     then t^.kind := tokmod     
  246.                    else if (token = 'sqr')     or (token = 'SQR')     then t^.kind := toksqr     
  247.                    else if (token = 'sqrt')    or (token = 'SQRT')    then t^.kind := toksqrt    
  248.                    else if (token = 'sin')     or (token = 'SIN')     then t^.kind := toksin     
  249.                    else if (token = 'cos')     or (token = 'COS')     then t^.kind := tokcos     
  250.                    else if (token = 'tan')     or (token = 'TAN')     then t^.kind := toktan     
  251.                    else if (token = 'arctan')  or (token = 'ARCTAN')  then t^.kind := tokarctan  
  252.                    else if (token = 'log')     or (token = 'LOG')     then t^.kind := toklog     
  253.                    else if (token = 'exp')     or (token = 'EXP')     then t^.kind := tokexp     
  254.                    else if (token = 'abs')     or (token = 'ABS')     then t^.kind := tokabs     
  255.                    else if (token = 'sgn')     or (token = 'SGN')     then t^.kind := toksgn     
  256.                    else if (token = 'str$')    or (token = 'STR$')    then t^.kind := tokstr_    
  257.                    else if (token = 'val')     or (token = 'VAL')     then t^.kind := tokval     
  258.                    else if (token = 'chr$')    or (token = 'CHR$')    then t^.kind := tokchr_    
  259.                    else if (token = 'asc')     or (token = 'ASC')     then t^.kind := tokasc     
  260.                    else if (token = 'len')     or (token = 'LEN')     then t^.kind := toklen     
  261.                    else if (token = 'mid$')    or (token = 'MID$')    then t^.kind := tokmid_    
  262.                    else if (token = 'peek')    or (token = 'PEEK')    then t^.kind := tokpeek    
  263.                    else if (token = 'let')     or (token = 'LET')     then t^.kind := toklet     
  264.                    else if (token = 'print')   or (token = 'PRINT')   then t^.kind := tokprint   
  265.                    else if (token = 'input')   or (token = 'INPUT')   then t^.kind := tokinput   
  266.                    else if (token = 'goto')    or (token = 'GOTO')    then t^.kind := tokgoto    
  267.                    else if (token = 'go to')   or (token = 'GO TO')   then t^.kind := tokgoto    
  268.                    else if (token = 'if')      or (token = 'IF')      then t^.kind := tokif      
  269.                    else if (token = 'end')     or (token = 'END')     then t^.kind := tokend     
  270.                    else if (token = 'stop')    or (token = 'STOP')    then t^.kind := tokstop    
  271.                    else if (token = 'for')     or (token = 'FOR')     then t^.kind := tokfor     
  272.                    else if (token = 'next')    or (token = 'NEXT')    then t^.kind := toknext    
  273.                    else if (token = 'while')   or (token = 'WHILE')   then t^.kind := tokwhile   
  274.                    else if (token = 'wend')    or (token = 'WEND')    then t^.kind := tokwend    
  275.                    else if (token = 'gosub')   or (token = 'GOSUB')   then t^.kind := tokgosub   
  276.                    else if (token = 'return')  or (token = 'RETURN')  then t^.kind := tokreturn  
  277.                    else if (token = 'read')    or (token = 'READ')    then t^.kind := tokread    
  278.                    else if (token = 'data')    or (token = 'DATA')    then t^.kind := tokdata    
  279.                    else if (token = 'restore') or (token = 'RESTORE') then t^.kind := tokrestore 
  280.                    else if (token = 'gotoxy')  or (token = 'GOTOXY')  then t^.kind := tokgotoxy  
  281.                    else if (token = 'on')      or (token = 'ON')      then t^.kind := tokon      
  282.                    else if (token = 'dim')     or (token = 'DIM')     then t^.kind := tokdim     
  283.                    else if (token = 'poke')    or (token = 'POKE')    then t^.kind := tokpoke    
  284.                    else if (token = 'list')    or (token = 'LIST')    then t^.kind := toklist    
  285.                    else if (token = 'run')     or (token = 'RUN')     then t^.kind := tokrun     
  286.                    else if (token = 'new')     or (token = 'NEW')     then t^.kind := toknew     
  287.                    else if (token = 'load')    or (token = 'LOAD')    then t^.kind := tokload    
  288.                    else if (token = 'merge')   or (token = 'MERGE')   then t^.kind := tokmerge   
  289.                    else if (token = 'save')    or (token = 'SAVE')    then t^.kind := toksave    
  290.                    else if (token = 'bye')     or (token = 'BYE')     then t^.kind := tokbye     
  291.                    else if (token = 'quit')    or (token = 'QUIT')    then t^.kind := tokbye     
  292.                    else if (token = 'del')     or (token = 'DEL')     then t^.kind := tokdel     
  293.                    else if (token = 'renum')   or (token = 'RENUM')   then t^.kind := tokrenum   
  294.                    else if (token = 'then')    or (token = 'THEN')    then t^.kind := tokthen    
  295.                    else if (token = 'else')    or (token = 'ELSE')    then t^.kind := tokelse    
  296.                    else if (token = 'to')      or (token = 'TO')      then t^.kind := tokto      
  297.                    else if (token = 'step')    or (token = 'STEP')    then t^.kind := tokstep    
  298.                    else if (token = 'rem')     or (token = 'REM')     then
  299.                            begin
  300.                               t^.kind := tokrem;
  301.                               new(t^.sp);
  302.                               t^.sp^ := str(inbuf^, i, strlen(inbuf^)-i+1);
  303.                               i := strlen(inbuf^)+1;
  304.                            end
  305.                         else
  306.                            begin
  307.                               t^.kind := tokvar;
  308.                               v := varbase;
  309.                               while (v <> nil) and (v^.name <> token) do
  310.                                  v := v^.next;
  311.                               if v = nil then
  312.                                  begin
  313.                                     new(v);
  314.                                     v^.next := varbase;
  315.                                     varbase := v;
  316.                                     v^.name := token;
  317.                                     v^.numdims := 0;
  318.                                     if token[strlen(token)] = '$' then
  319.                                        begin
  320.                                           v^.stringvar := true;
  321.                                           v^.sv := nil;
  322.                                           v^.sval := addr(v^.sv);
  323.                                        end
  324.                                     else
  325.                                        begin
  326.                                           v^.stringvar := false;
  327.                                           v^.rv := 0;
  328.                                           v^.val := addr(v^.rv);
  329.                                        end;
  330.                                  end;
  331.                               t^.vp := v;
  332.                            end;
  333.                      end;
  334.                   '"', '''' :
  335.                      begin
  336.                         t^.kind := tokstr;
  337.                         new(t^.sp);
  338.                         setstrlen(t^.sp^, 255);
  339.                         j := 0;
  340.                         while (i <= strlen(inbuf^)) and (inbuf^[i] <> ch) do
  341.                            begin
  342.                               j := j + 1;
  343.                               t^.sp^[j] := inbuf^[i];
  344.                               i := i + 1;
  345.                            end;
  346.                         setstrlen(t^.sp^, j);
  347.                         i := i + 1;
  348.                      end;
  349.                   '0'..'9', '.' :
  350.                      begin
  351.                         t^.kind := toknum;
  352.                         n := 0;
  353.                         d := 1;
  354.                         d1 := 1;
  355.                         i := i - 1;
  356.                         while (i <= strlen(inbuf^)) and ((inbuf^[i] in ['0'..'9'])
  357.                                     or ((inbuf^[i] = '.') and (d1 = 1))) do
  358.                            begin
  359.                               if inbuf^[i] = '.' then
  360.                                  d1 := 10
  361.                               else
  362.                                  begin
  363.                                     n := n * 10 + ord(inbuf^[i]) - 48;
  364.                                     d := d * d1;
  365.                                  end;
  366.                               i := i + 1;
  367.                            end;
  368.                         n := n / d;
  369.                         if (i <= strlen(inbuf^)) and (inbuf^[i] in ['e','E']) then
  370.                            begin
  371.                               i := i + 1;
  372.                               d1 := 10;
  373.                               if (i <= strlen(inbuf^)) and (inbuf^[i] in ['+','-']) then
  374.                                  begin
  375.                                     if inbuf^[i] = '-' then
  376.                                        d1 := 0.1;
  377.                                     i := i + 1;
  378.                                  end;
  379.                               j := 0;
  380.                               while (i <= strlen(inbuf^)) and (inbuf^[i] in ['0'..'9']) do
  381.                                  begin
  382.                                     j := j * 10 + ord(inbuf^[i]) - 48;
  383.                                     i := i + 1;
  384.                                  end;
  385.                               for k := 1 to j do
  386.                                  n := n * d1;
  387.                            end;
  388.                         t^.num := n;
  389.                      end;
  390.                   '+' : t^.kind := tokplus;
  391.                   '-' : t^.kind := tokminus;
  392.                   '*' : t^.kind := toktimes;
  393.                   '/' : t^.kind := tokdiv;
  394.                   '^' : t^.kind := tokup;
  395.                   '(', '[' : t^.kind := toklp;
  396.                   ')', ']' : t^.kind := tokrp;
  397.                   ',' : t^.kind := tokcomma;
  398.                   ';' : t^.kind := toksemi;
  399.                   ':' : t^.kind := tokcolon;
  400.                   '?' : t^.kind := tokprint;
  401.                   '=' : t^.kind := tokeq;
  402.                   '<' : 
  403.                      begin
  404.                         if (i <= strlen(inbuf^)) and (inbuf^[i] = '=') then
  405.                            begin
  406.                               t^.kind := tokle;
  407.                               i := i + 1;
  408.                            end
  409.                         else if (i <= strlen(inbuf^)) and (inbuf^[i] = '>') then
  410.                            begin
  411.                               t^.kind := tokne;
  412.                               i := i + 1;
  413.                            end
  414.                         else
  415.                            t^.kind := toklt;
  416.                      end;
  417.                   '>' :
  418.                      begin
  419.                         if (i <= strlen(inbuf^)) and (inbuf^[i] = '=') then
  420.                            begin
  421.                               t^.kind := tokge;
  422.                               i := i + 1;
  423.                            end
  424.                         else
  425.                            t^.kind := tokgt;
  426.                      end;
  427.                   otherwise
  428.                      begin
  429.                         t^.kind := toksnerr;
  430.                         t^.snch := ch;
  431.                      end;
  432.                end;
  433.             end;
  434.       until i > strlen(inbuf^);
  435.    end;
  436. procedure listtokens(var f : text; buf : tokenptr);
  437.    var
  438.       ltr, ltr0 : boolean;
  439.    begin
  440.       ltr := false;
  441.       while buf <> nil do
  442.          begin
  443.             if buf^.kind in [tokvar, toknum, toknot..tokrenum] then
  444.                begin
  445.                   if ltr then write(f, ' ');
  446.                   ltr := (buf^.kind <> toknot);
  447.                end
  448.             else
  449.                ltr := false;
  450.             case buf^.kind of
  451.                tokvar     : write(f, buf^.vp^.name);
  452.                toknum     : write(f, numtostr(buf^.num));
  453.                tokstr     : write(f, '"', buf^.sp^, '"');
  454.                toksnerr   : write(f, '{', buf^.snch, '}');
  455.                tokplus    : write(f, '+');
  456.                tokminus   : write(f, '-');
  457.                toktimes   : write(f, '*');
  458.                tokdiv     : write(f, '/');
  459.                tokup      : write(f, '^');
  460.                toklp      : write(f, '(');
  461.                tokrp      : write(f, ')');
  462.                tokcomma   : write(f, ',');
  463.                toksemi    : write(f, ';');
  464.                tokcolon   : write(f, ' : ');
  465.                tokeq      : write(f, ' = ');
  466.                toklt      : write(f, ' < ');
  467.                tokgt      : write(f, ' > ');
  468.                tokle      : write(f, ' <= ');
  469.                tokge      : write(f, ' >= ');
  470.                tokne      : write(f, ' <> ');
  471.                tokand     : write(f, ' AND ');
  472.                tokor      : write(f, ' OR ');
  473.                tokxor     : write(f, ' XOR ');
  474.                tokmod     : write(f, ' MOD ');
  475.                toknot     : write(f, 'NOT ');
  476.                toksqr     : write(f, 'SQR');
  477.                toksqrt    : write(f, 'SQRT');
  478.                toksin     : write(f, 'SIN');
  479.                tokcos     : write(f, 'COS');
  480.                toktan     : write(f, 'TAN');
  481.                tokarctan  : write(f, 'ARCTAN');
  482.                toklog     : write(f, 'LOG');
  483.                tokexp     : write(f, 'EXP');
  484.                tokabs     : write(f, 'ABS');
  485.                toksgn     : write(f, 'SGN');
  486.                tokstr_    : write(f, 'STR$');
  487.                tokval     : write(f, 'VAL');
  488.                tokchr_    : write(f, 'CHR$');
  489.                tokasc     : write(f, 'ASC');
  490.                toklen     : write(f, 'LEN');
  491.                tokmid_    : write(f, 'MID$');
  492.                tokpeek    : write(f, 'PEEK');
  493.                toklet     : write(f, 'LET');
  494.                tokprint   : write(f, 'PRINT');
  495.                tokinput   : write(f, 'INPUT');
  496.                tokgoto    : write(f, 'GOTO');
  497.                tokif      : write(f, 'IF');
  498.                tokend     : write(f, 'END');
  499.                tokstop    : write(f, 'STOP');
  500.                tokfor     : write(f, 'FOR');
  501.                toknext    : write(f, 'NEXT');
  502.                tokwhile   : write(f, 'WHILE');
  503.                tokwend    : write(f, 'WEND');
  504.                tokgosub   : write(f, 'GOSUB');
  505.                tokreturn  : write(f, 'RETURN');
  506.                tokread    : write(f, 'READ');
  507.                tokdata    : write(f, 'DATA');
  508.                tokrestore : write(f, 'RESTORE');
  509.                tokgotoxy  : write(f, 'GOTOXY');
  510.                tokon      : write(f, 'ON');
  511.                tokdim     : write(f, 'DIM');
  512.                tokpoke    : write(f, 'POKE');
  513.                toklist    : write(f, 'LIST');
  514.                tokrun     : write(f, 'RUN');
  515.                toknew     : write(f, 'NEW');
  516.                tokload    : write(f, 'LOAD');
  517.                tokmerge   : write(f, 'MERGE');
  518.                toksave    : write(f, 'SAVE');
  519.                tokdel     : write(f, 'DEL');
  520.                tokbye     : write(f, 'BYE');
  521.                tokrenum   : write(f, 'RENUM');
  522.                tokthen    : write(f, ' THEN ');
  523.                tokelse    : write(f, ' ELSE ');
  524.                tokto      : write(f, ' TO ');
  525.                tokstep    : write(f, ' STEP ');
  526.                tokrem     : write(f, 'REM', buf^.sp^);
  527.             end;
  528.             buf := buf^.next;
  529.          end;
  530.    end;
  531. procedure disposetokens(var tok : tokenptr);
  532.    var
  533.       tok1 : tokenptr;
  534.    begin
  535.       while tok <> nil do
  536.          begin
  537.             tok1 := tok^.next;
  538.             if tok^.kind in [tokstr, tokrem] then
  539.                dispose(tok^.sp);
  540.             dispose(tok);
  541.             tok := tok1;
  542.          end;
  543.    end;
  544. procedure parseinput(var buf : tokenptr);
  545.    var
  546.       l, l0, l1 : lineptr;
  547.    begin
  548.       inbuf^ := strltrim(inbuf^);
  549.       curline := 0;
  550.       while (strlen(inbuf^) <> 0) and (inbuf^[1] in ['0'..'9']) do
  551.          begin
  552.             curline := curline * 10 + ord(inbuf^[1]) - 48;
  553.             strdelete(inbuf^, 1, 1);
  554.          end;
  555.       parse(inbuf, buf);
  556.       if curline <> 0 then
  557.          begin
  558.             l := linebase;
  559.             l0 := nil;
  560.             while (l <> nil) and (l^.num < curline) do
  561.                begin
  562.                   l0 := l;
  563.                   l := l^.next;
  564.                end;
  565.             if (l <> nil) and (l^.num = curline) then
  566.                begin
  567.                   l1 := l;
  568.                   l := l^.next;
  569.                   if l0 = nil then
  570.                      linebase := l
  571.                   else
  572.                      l0^.next := l;
  573.                   disposetokens(l1^.txt);
  574.                   dispose(l1);
  575.                end;
  576.             if buf <> nil then
  577.                begin
  578.                   new(l1);
  579.                   l1^.next := l;
  580.                   if l0 = nil then
  581.                      linebase := l1
  582.                   else
  583.                      l0^.next := l1;
  584.                   l1^.num := curline;
  585.                   l1^.txt := buf;
  586.                end;
  587.             clearloops;
  588.             restoredata;
  589.          end;
  590.    end;
  591. procedure errormsg(s : string255);
  592.    begin
  593.       write(#7, s);
  594.       escape(42);
  595.    end;
  596. procedure snerr;
  597.    begin
  598.       errormsg('Syntax error');
  599.    end;
  600. procedure tmerr;
  601.    begin
  602.       errormsg('Type mismatch error');
  603.    end;
  604. procedure badsubscr;
  605.    begin
  606.       errormsg('Bad subscript');
  607.    end;
  608. procedure exec;
  609.    var
  610.       gotoflag, elseflag : boolean;
  611.       t : tokenptr;
  612.       ioerrmsg : string255ptr;
  613.    function factor : valrec;
  614.       forward;
  615.    function expr : valrec;
  616.       forward;
  617.    function realfactor : real;
  618.       var
  619.          n : valrec;
  620.       begin
  621.          n := factor;
  622.          if n.stringval then tmerr;
  623.          realfactor := n.val;
  624.       end;
  625.    function strfactor : basicstring;
  626.       var
  627.          n : valrec;
  628.       begin
  629.          n := factor;
  630.          if not n.stringval then tmerr;
  631.          strfactor := n.sval;
  632.       end;
  633.    function stringfactor : string255;
  634.       var
  635.          n : valrec;
  636.       begin
  637.          n := factor;
  638.          if not n.stringval then tmerr;
  639.          stringfactor := n.sval^;
  640.          dispose(n.sval);
  641.       end;
  642.    function intfactor : integer;
  643.       begin
  644.          intfactor := round(realfactor);
  645.       end;
  646.    function realexpr : real;
  647.       var
  648.          n : valrec;
  649.       begin
  650.          n := expr;
  651.          if n.stringval then tmerr;
  652.          realexpr := n.val;
  653.       end;
  654.    function strexpr : basicstring;
  655.       var
  656.          n : valrec;
  657.       begin
  658.          n := expr;
  659.          if not n.stringval then tmerr;
  660.          strexpr := n.sval;
  661.       end;
  662.    function stringexpr : string255;
  663.       var
  664.          n : valrec;
  665.       begin
  666.          n := expr;
  667.          if not n.stringval then tmerr;
  668.          stringexpr := n.sval^;
  669.          dispose(n.sval);
  670.       end;
  671.    function intexpr : integer;
  672.       begin
  673.          intexpr := round(realexpr);
  674.       end;
  675.    procedure require(k : tokenkinds);
  676.       begin
  677.          if (t = nil) or (t^.kind <> k) then
  678.             snerr;
  679.          t := t^.next;
  680.       end;
  681.    procedure skipparen;
  682.       label 1;
  683.       begin
  684.          repeat
  685.             if t = nil then snerr;
  686.             if (t^.kind = tokrp) or (t^.kind = tokcomma) then
  687.                goto 1;
  688.             if t^.kind = toklp then
  689.                begin
  690.                   t := t^.next;
  691.                   skipparen;
  692.                end;
  693.             t := t^.next;
  694.          until false;
  695.        1 :
  696.       end;
  697.    function findvar : varptr;
  698.       var
  699.          v : varptr;
  700.          i, j, k : integer;
  701.          tok : tokenptr;
  702.       begin
  703.          if (t = nil) or (t^.kind <> tokvar) then snerr;
  704.          v := t^.vp;
  705.          t := t^.next;
  706.          if (t <> nil) and (t^.kind = toklp) then
  707.             with v^ do
  708.                begin
  709.                   if numdims = 0 then
  710.                      begin
  711.                         tok := t;
  712.                         i := 0;
  713.                         j := 1;
  714.                         repeat
  715.                            if i >= maxdims then badsubscr;
  716.                            t := t^.next;
  717.                            skipparen;
  718.                            j := j * 11;
  719.                            i := i + 1;
  720.                            dims[i] := 11;
  721.                         until t^.kind = tokrp;
  722.                         numdims := i;
  723.                         if stringvar then
  724.                            begin
  725.                               hpm_new(sarr, j*4);
  726.                               for k := 0 to j-1 do
  727.                                  sarr^[k] := nil;
  728.                            end
  729.                         else
  730.                            begin
  731.                               hpm_new(arr, j*8);
  732.                               for k := 0 to j-1 do
  733.                                  arr^[k] := 0;
  734.                            end;
  735.                         t := tok;
  736.                      end;
  737.                   k := 0;
  738.                   t := t^.next;
  739.                   for i := 1 to numdims do
  740.                      begin
  741.                         j := intexpr;
  742.                         if (j < 0) or (j >= dims[i]) then
  743.                            badsubscr;
  744.                         k := k * dims[i] + j;
  745.                         if i < numdims then
  746.                            require(tokcomma);
  747.                      end;
  748.                   require(tokrp);
  749.                   if stringvar then
  750.                       sval := addr(sarr^[k])
  751.                   else
  752.                       val := addr(arr^[k]);
  753.                end
  754.          else
  755.             begin
  756.                if v^.numdims <> 0 then
  757.                   badsubscr;
  758.             end;
  759.          findvar := v;
  760.       end;
  761.    function inot(i : integer) : integer;
  762.       begin
  763.          inot := -1 - i;
  764.       end;
  765.    function ixor(a, b : integer) : integer;
  766.       begin
  767.          ixor := asm_ior(asm_iand(a, inot(b)), asm_iand(inot(a), b));
  768.       end;
  769.    function factor : valrec;
  770.       var
  771.          v : varptr;
  772.          facttok : tokenptr;
  773.          n : valrec;
  774.          i, j : integer;
  775.          tok, tok1 : tokenptr;
  776.          s : basicstring;
  777.          trick :
  778.             record
  779.                case boolean of
  780.                   true : (i : integer);
  781.                   false : (c : ^char);
  782.             end;
  783.       begin
  784.          if t = nil then snerr;
  785.          facttok := t;
  786.          t := t^.next;
  787.          n.stringval := false;
  788.          case facttok^.kind of
  789.             toknum :
  790.                n.val := facttok^.num;
  791.             tokstr :
  792.                begin
  793.                   n.stringval := true;
  794.                   new(n.sval);
  795.                   n.sval^ := facttok^.sp^;
  796.                end;
  797.             tokvar :
  798.                begin
  799.                   t := facttok;
  800.                   v := findvar;
  801.                   n.stringval := v^.stringvar;
  802.                   if n.stringval then
  803.                      begin
  804.                         new(n.sval);
  805.                         n.sval^ := v^.sval^^;
  806.                      end
  807.                   else
  808.                      n.val := v^.val^;
  809.                end;
  810.             toklp :
  811.                begin
  812.                   n := expr;
  813.                   require(tokrp);
  814.                end;
  815.             tokminus :
  816.                n.val := - realfactor;
  817.             tokplus :
  818.                n.val := realfactor;
  819.             toknot :
  820.                n.val := inot(intfactor);
  821.             toksqr :
  822.                n.val := sqr(realfactor);
  823.             toksqrt :
  824.                n.val := sqrt(realfactor);
  825.             toksin :
  826.                n.val := sin(realfactor);
  827.             tokcos :
  828.                n.val := cos(realfactor);
  829.             toktan :
  830.                begin
  831.                   n.val := realfactor;
  832.                   n.val := sin(n.val) / cos(n.val);
  833.                end;
  834.             tokarctan :
  835.                n.val := arctan(realfactor);
  836.             toklog:
  837.                n.val := ln(realfactor);
  838.             tokexp :
  839.                n.val := exp(realfactor);
  840.             tokabs :
  841.                n.val := abs(realfactor);
  842.             toksgn :
  843.                begin
  844.                   n.val := realfactor;
  845.                   n.val := ord(n.val > 0) - ord(n.val < 0);
  846.                end;
  847.             tokstr_ :
  848.                begin
  849.                   n.stringval := true;
  850.                   new(n.sval);
  851.                   n.sval^ := numtostr(realfactor);
  852.                end;
  853.             tokval :
  854.                begin
  855.                   s := strfactor;
  856.                   tok1 := t;
  857.                   parse(s, t);
  858.                   tok := t;
  859.                   if tok = nil then
  860.                      n.val := 0
  861.                   else
  862.                      n := expr;
  863.                   disposetokens(tok);
  864.                   t := tok1;
  865.                   dispose(s);
  866.                end;
  867.             tokchr_ :
  868.                begin
  869.                   n.stringval := true;
  870.                   new(n.sval);
  871.                   n.sval^ := ' ';
  872.                   n.sval^[1] := chr(intfactor);
  873.                end;
  874.             tokasc :
  875.                begin
  876.                   s := strfactor;
  877.                   if strlen(s^) = 0 then
  878.                      n.val := 0
  879.                   else
  880.                      n.val := ord(s^[1]);
  881.                   dispose(s);
  882.                end;
  883.             tokmid_ :
  884.                begin
  885.                   n.stringval := true;
  886.                   require(toklp);
  887.                   n.sval := strexpr;
  888.                   require(tokcomma);
  889.                   i := intexpr;
  890.                   if i < 1 then i := 1;
  891.                   j := 255;
  892.                   if (t <> nil) and (t^.kind = tokcomma) then
  893.                      begin
  894.                         t := t^.next;
  895.                         j := intexpr;
  896.                      end;
  897.                   if j > strlen(n.sval^)-i+1 then
  898.                      j := strlen(n.sval^)-i+1;
  899.                   if i > strlen(n.sval^) then
  900.                      n.sval^ := ''
  901.                   else
  902.                      n.sval^ := str(n.sval^, i, j);
  903.                   require(tokrp);
  904.                end;
  905.             toklen :
  906.                begin
  907.                   s := strfactor;
  908.                   n.val := strlen(s^);
  909.                   dispose(s);
  910.                end;
  911.             tokpeek :
  912.                begin
  913.                   $range off$
  914.                   trick.i := intfactor;
  915.                   n.val := ord(trick.c^);
  916.                   $if checking$ $range on$ $end$
  917.                end;
  918.             otherwise
  919.                snerr;
  920.          end;
  921.          factor := n;
  922.       end;
  923.    function upexpr : valrec;
  924.       var
  925.          n, n2 : valrec;
  926.       begin
  927.          n := factor;
  928.          while (t <> nil) and (t^.kind = tokup) do
  929.             begin
  930.                if n.stringval then tmerr;
  931.                t := t^.next;
  932.                n2 := upexpr;
  933.                if n2.stringval then tmerr;
  934.                if n.val < 0 then
  935.                   begin
  936.                      if n2.val <> trunc(n2.val) then n.val := ln(n.val);
  937.                      n.val := exp(n2.val * ln(-n.val));
  938.                      if odd(trunc(n2.val)) then
  939.                         n.val := - n.val;
  940.                   end
  941.                else
  942.                   n.val := exp(n2.val * ln(n.val));
  943.             end;
  944.          upexpr := n;
  945.       end;
  946.    function term : valrec;
  947.       var
  948.          n, n2 : valrec;
  949.          k : tokenkinds;
  950.       begin
  951.          n := upexpr;
  952.          while (t <> nil) and (t^.kind in [toktimes, tokdiv, tokmod]) do
  953.             begin
  954.                k := t^.kind;
  955.                t := t^.next;
  956.                n2 := upexpr;
  957.                if n.stringval or n2.stringval then tmerr;
  958.                if k = tokmod then
  959.                   n.val := round(n.val) mod round(n2.val)
  960.                else if k = toktimes then
  961.                   n.val := n.val * n2.val
  962.                else
  963.                   n.val := n.val / n2.val;
  964.             end;
  965.          term := n;
  966.       end;
  967.    function sexpr : valrec;
  968.       var
  969.          n, n2 : valrec;
  970.          k : tokenkinds;
  971.       begin
  972.          n := term;
  973.          while (t <> nil) and (t^.kind in [tokplus, tokminus]) do
  974.             begin
  975.                k := t^.kind;
  976.                t := t^.next;
  977.                n2 := term;
  978.                if n.stringval <> n2.stringval then tmerr;
  979.                if k = tokplus then
  980.                   if n.stringval then
  981.                      begin
  982.                         n.sval^ := n.sval^ + n2.sval^;
  983.                         dispose(n2.sval);
  984.                      end
  985.                   else
  986.                      n.val := n.val + n2.val
  987.                else
  988.                   if n.stringval then
  989.                      tmerr
  990.                   else
  991.                      n.val := n.val - n2.val;
  992.             end;
  993.          sexpr := n;
  994.       end;
  995.    function relexpr : valrec;
  996.       var
  997.          n, n2 : valrec;
  998.          f : boolean;
  999.          k : tokenkinds;
  1000.       begin
  1001.          n := sexpr;
  1002.          while (t <> nil) and (t^.kind in [tokeq..tokne]) do
  1003.             begin
  1004.                k := t^.kind;
  1005.                t := t^.next;
  1006.                n2 := sexpr;
  1007.                if n.stringval <> n2.stringval then tmerr;
  1008.                if n.stringval then
  1009.                   begin
  1010.                      f := ((n.sval^ = n2.sval^) and (k in [tokeq, tokge, tokle]) or
  1011.                            (n.sval^ < n2.sval^) and (k in [toklt, tokle, tokne]) or
  1012.                            (n.sval^ > n2.sval^) and (k in [tokgt, tokge, tokne]));
  1013.                      dispose(n.sval);
  1014.                      dispose(n2.sval);
  1015.                   end
  1016.                else
  1017.                   f := ((n.val = n2.val) and (k in [tokeq, tokge, tokle]) or
  1018.                         (n.val < n2.val) and (k in [toklt, tokle, tokne]) or
  1019.                         (n.val > n2.val) and (k in [tokgt, tokge, tokne]));
  1020.                n.stringval := false;
  1021.                n.val := ord(f);
  1022.             end;
  1023.          relexpr := n;
  1024.       end;
  1025.    function andexpr : valrec;
  1026.       var
  1027.          n, n2 : valrec;
  1028.       begin
  1029.          n := relexpr;
  1030.          while (t <> nil) and (t^.kind = tokand) do
  1031.             begin
  1032.                t := t^.next;
  1033.                n2 := relexpr;
  1034.                if n.stringval or n2.stringval then tmerr;
  1035.                n.val := asm_iand(trunc(n.val), trunc(n2.val));
  1036.             end;
  1037.          andexpr := n;
  1038.       end;
  1039.    function expr : valrec;
  1040.       var
  1041.          n, n2 : valrec;
  1042.          k : tokenkinds;
  1043.       begin
  1044.          n := andexpr;
  1045.          while (t <> nil) and (t^.kind in [tokor, tokxor]) do
  1046.             begin
  1047.                k := t^.kind;
  1048.                t := t^.next;
  1049.                n2 := andexpr;
  1050.                if n.stringval or n2.stringval then tmerr;
  1051.                if k = tokor then
  1052.                   n.val := asm_ior(trunc(n.val), trunc(n2.val))
  1053.                else
  1054.                   n.val := ixor(trunc(n.val), trunc(n2.val));
  1055.             end;
  1056.          expr := n;
  1057.       end;
  1058.    procedure checkextra;
  1059.       begin
  1060.          if t <> nil then
  1061.             errormsg('Extra information on line');
  1062.       end;
  1063.    function iseos : boolean;
  1064.       begin
  1065.          iseos := (t = nil) or (t^.kind in [tokcolon, tokelse]);
  1066.       end;
  1067.    procedure skiptoeos;
  1068.       begin
  1069.          while not iseos do
  1070.             t := t^.next;
  1071.       end;
  1072.    function findline(n : integer) : lineptr;
  1073.       var
  1074.          l : lineptr;
  1075.       begin
  1076.          l := linebase;
  1077.          while (l <> nil) and (l^.num <> n) do
  1078.             l := l^.next;
  1079.          findline := l;
  1080.       end;
  1081.    function mustfindline(n : integer) : lineptr;
  1082.       var
  1083.          l : lineptr;
  1084.       begin
  1085.          l := findline(n);
  1086.          if l = nil then
  1087.             errormsg('Undefined line');
  1088.          mustfindline := l;
  1089.       end;
  1090.    procedure cmdend;
  1091.       begin
  1092.          stmtline := nil;
  1093.          t := nil;
  1094.       end;
  1095.    procedure cmdnew;
  1096.       var
  1097.          p : anyptr;
  1098.       begin
  1099.          cmdend;
  1100.          clearloops;
  1101.          restoredata;
  1102.          while linebase <> nil do
  1103.             begin
  1104.                p := linebase^.next;
  1105.                disposetokens(linebase^.txt);
  1106.                dispose(linebase);
  1107.                linebase := p;
  1108.             end;
  1109.          while varbase <> nil do
  1110.             begin
  1111.                p := varbase^.next;
  1112.                if varbase^.stringvar then
  1113.                   if varbase^.sval^ <> nil then
  1114.                      dispose(varbase^.sval^);
  1115.                dispose(varbase);
  1116.                varbase := p;
  1117.             end;
  1118.       end;
  1119.    procedure cmdlist;
  1120.       var
  1121.          l : lineptr;
  1122.          n1, n2 : integer;
  1123.       begin
  1124.          repeat
  1125.             n1 := 0;
  1126.             n2 := maxint;
  1127.             if (t <> nil) and (t^.kind = toknum) then
  1128.                begin
  1129.                   n1 := trunc(t^.num);
  1130.                   t := t^.next;
  1131.                   if (t = nil) or (t^.kind <> tokminus) then
  1132.                      n2 := n1;
  1133.                end;
  1134.             if (t <> nil) and (t^.kind = tokminus) then
  1135.                begin
  1136.                   t := t^.next;
  1137.                   if (t <> nil) and (t^.kind = toknum) then
  1138.                      begin
  1139.                         n2 := trunc(t^.num);
  1140.                         t := t^.next;
  1141.                      end
  1142.                   else
  1143.                      n2 := maxint;
  1144.                end;
  1145.             l := linebase;
  1146.             while (l <> nil) and (l^.num <= n2) do
  1147.                begin
  1148.                   if (l^.num >= n1) then
  1149.                      begin
  1150.                         write(l^.num:1, ' ');
  1151.                         listtokens(output, l^.txt);
  1152.                         writeln;
  1153.                      end;
  1154.                   l := l^.next;
  1155.                end;
  1156.             if not iseos then
  1157.                require(tokcomma);
  1158.          until iseos;
  1159.       end;
  1160.    procedure cmdload(merging : boolean; name : string255);
  1161.       var
  1162.          f : text;
  1163.          buf : tokenptr;
  1164.       begin
  1165.          if not merging then
  1166.             cmdnew;
  1167.          reset(f, name + '.TEXT', 'shared');
  1168.          while not eof(f) do
  1169.             begin
  1170.                readln(f, inbuf^);
  1171.                parseinput(buf);
  1172.                if curline = 0 then
  1173.                   begin
  1174.                      writeln('Bad line in file');
  1175.                      disposetokens(buf);
  1176.                   end;
  1177.             end;
  1178.          close(f);
  1179.       end;
  1180.    procedure cmdrun;
  1181.       var
  1182.          l : lineptr;
  1183.          i : integer;
  1184.          s : string255;
  1185.       begin
  1186.          l := linebase;
  1187.          if not iseos then
  1188.             begin
  1189.                if t^.kind = toknum then
  1190.                   l := mustfindline(intexpr)
  1191.                else
  1192.                   begin
  1193.                      s := stringexpr;
  1194.                      i := 0;
  1195.                      if not iseos then
  1196.                         begin
  1197.                            require(tokcomma);
  1198.                            i := intexpr;
  1199.                         end;
  1200.                      checkextra;
  1201.                      cmdload(false, s);
  1202.                      if i = 0 then
  1203.                         l := linebase
  1204.                      else
  1205.                         l := mustfindline(i)
  1206.                   end
  1207.             end;
  1208.          stmtline := l;
  1209.          gotoflag := true;
  1210.          clearvars;
  1211.          clearloops;
  1212.          restoredata;
  1213.       end;
  1214.    procedure cmdsave;
  1215.       var
  1216.          f : text;
  1217.          l : lineptr;
  1218.       begin
  1219.          rewrite(f, stringexpr + '.TEXT');
  1220.          l := linebase;
  1221.          while l <> nil do
  1222.             begin
  1223.                write(f, l^.num:1, ' ');
  1224.                listtokens(f, l^.txt);
  1225.                writeln(f);
  1226.                l := l^.next;
  1227.             end;
  1228.          close(f, 'save');
  1229.       end;
  1230.    procedure cmdbye;
  1231.       begin
  1232.          exitflag := true;
  1233.       end;
  1234.    procedure cmddel;
  1235.       var
  1236.          l, l0, l1 : lineptr;
  1237.          n1, n2 : integer;
  1238.       begin
  1239.          repeat
  1240.             if iseos then snerr;
  1241.             n1 := 0;
  1242.             n2 := maxint;
  1243.             if (t <> nil) and (t^.kind = toknum) then
  1244.                begin
  1245.                   n1 := trunc(t^.num);
  1246.                   t := t^.next;
  1247.                   if (t = nil) or (t^.kind <> tokminus) then
  1248.                      n2 := n1;
  1249.                end;
  1250.             if (t <> nil) and (t^.kind = tokminus) then
  1251.                begin
  1252.                   t := t^.next;
  1253.                   if (t <> nil) and (t^.kind = toknum) then
  1254.                      begin
  1255.                         n2 := trunc(t^.num);
  1256.                         t := t^.next;
  1257.                      end
  1258.                   else
  1259.                      n2 := maxint;
  1260.                end;
  1261.             l := linebase;
  1262.             l0 := nil;
  1263.             while (l <> nil) and (l^.num <= n2) do
  1264.                begin
  1265.                   l1 := l^.next;
  1266.                   if (l^.num >= n1) then
  1267.                      begin
  1268.                         if l = stmtline then
  1269.                            begin
  1270.                               cmdend;
  1271.                               clearloops;
  1272.                               restoredata;
  1273.                            end;
  1274.                         if l0 = nil then
  1275.                            linebase := l^.next
  1276.                         else
  1277.                            l0^.next := l^.next;
  1278.                         disposetokens(l^.txt);
  1279.                         dispose(l);
  1280.                      end
  1281.                   else
  1282.                      l0 := l;
  1283.                   l := l1;
  1284.                end;
  1285.             if not iseos then
  1286.                require(tokcomma);
  1287.          until iseos;
  1288.       end;
  1289.    procedure cmdrenum;
  1290.       var
  1291.          l, l1 : lineptr;
  1292.          tok : tokenptr;
  1293.          lnum, step : integer;
  1294.       begin
  1295.          lnum := 10;
  1296.          step := 10;
  1297.          if not iseos then
  1298.             begin
  1299.                lnum := intexpr;
  1300.                if not iseos then
  1301.                   begin
  1302.                      require(tokcomma);
  1303.                      step := intexpr;
  1304.                   end;
  1305.             end;
  1306.          l := linebase;
  1307.          if l <> nil then
  1308.             begin
  1309.                while l <> nil do
  1310.                   begin
  1311.                      l^.num2 := lnum;
  1312.                      lnum := lnum + step;
  1313.                      l := l^.next;
  1314.                   end;
  1315.                l := linebase;
  1316.                repeat
  1317.                   tok := l^.txt;
  1318.                   repeat
  1319.                      if tok^.kind in [tokgoto, tokgosub, tokthen, tokelse, 
  1320.                                       tokrun, toklist, tokrestore, tokdel] then
  1321.                         while (tok^.next <> nil) and (tok^.next^.kind = toknum) do
  1322.                            begin
  1323.                               tok := tok^.next;
  1324.                               lnum := round(tok^.num);
  1325.                               l1 := linebase;
  1326.                               while (l1 <> nil) and (l1^.num <> lnum) do
  1327.                                  l1 := l1^.next;
  1328.                               if l1 = nil then
  1329.                                  writeln('Undefined line ', lnum:1, ' in line ', l^.num2:1)
  1330.                               else
  1331.                                  tok^.num := l1^.num2;
  1332.                               if (tok^.next <> nil) and (tok^.next^.kind = tokcomma) then
  1333.                                  tok := tok^.next;
  1334.                            end;
  1335.                      tok := tok^.next;
  1336.                   until tok = nil;
  1337.                   l := l^.next;
  1338.                until l = nil;
  1339.                l := linebase;
  1340.                while l <> nil do
  1341.                   begin
  1342.                      l^.num := l^.num2;
  1343.                      l := l^.next;
  1344.                   end;
  1345.             end;
  1346.       end;
  1347.    procedure cmdprint;
  1348.       var
  1349.          semiflag : boolean;
  1350.          n : valrec;
  1351.       begin
  1352.          semiflag := false;
  1353.          while not iseos do
  1354.             begin
  1355.                semiflag := false;
  1356.                if t^.kind in [toksemi, tokcomma] then
  1357.                   begin
  1358.                      semiflag := true;
  1359.                      t := t^.next;
  1360.                   end
  1361.                else
  1362.                   begin
  1363.                      n := expr;
  1364.                      if n.stringval then
  1365.                         begin
  1366.                            write(n.sval^);
  1367.                            dispose(n.sval);
  1368.                         end
  1369.                      else
  1370.                         write(numtostr(n.val), ' ');
  1371.                   end;
  1372.             end;
  1373.          if not semiflag then 
  1374.             writeln;
  1375.       end;
  1376.    procedure cmdinput;
  1377.       var
  1378.          v : varptr;
  1379.          s : string255;
  1380.          tok, tok0, tok1 : tokenptr;
  1381.          strflag : boolean;
  1382.       begin
  1383.          if (t <> nil) and (t^.kind = tokstr) then
  1384.             begin
  1385.                write(t^.sp^);
  1386.                t := t^.next;
  1387.                require(toksemi);
  1388.             end
  1389.          else
  1390.             begin
  1391.                write('? ');
  1392.             end;
  1393.          tok := t;
  1394.          if (t = nil) or (t^.kind <> tokvar) then snerr;
  1395.          strflag := t^.vp^.stringvar;
  1396.          repeat
  1397.             if (t <> nil) and (t^.kind = tokvar) then
  1398.                if t^.vp^.stringvar <> strflag then snerr;
  1399.             t := t^.next;
  1400.          until iseos;
  1401.          t := tok;
  1402.          if strflag then
  1403.             begin
  1404.                repeat
  1405.                   readln(s);
  1406.                   v := findvar;