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

编译器/解释器

开发平台:

C/C++

  1.                   if v^.sval^ <> nil then
  2.                      dispose(v^.sval^);
  3.                   new(v^.sval^);
  4.                   v^.sval^^ := s;
  5.                   if not iseos then
  6.                      begin
  7.                         require(tokcomma);
  8.                         write('?? ');
  9.                      end;
  10.                until iseos;
  11.             end
  12.          else
  13.             begin
  14.                readln(s);
  15.                parse(addr(s), tok);
  16.                tok0 := tok;
  17.                repeat
  18.                   v := findvar;
  19.                   while tok = nil do
  20.                      begin
  21.                         write('?? ');
  22.                         readln(s);
  23.                         disposetokens(tok0);
  24.                         parse(addr(s), tok);
  25.                         tok0 := tok;
  26.                      end;
  27.                   tok1 := t;
  28.                   t := tok;
  29.                   v^.val^ := realexpr;
  30.                   if t <> nil then
  31.                      if t^.kind = tokcomma then
  32.                         t := t^.next
  33.                      else
  34.                         snerr;
  35.                   tok := t;
  36.                   t := tok1;
  37.                   if not iseos then
  38.                      require(tokcomma);
  39.                until iseos;
  40.                disposetokens(tok0);
  41.             end;
  42.       end;
  43.    procedure cmdlet(implied : boolean);
  44.       var
  45.          v : varptr;
  46.  old : basicstring;
  47.       begin
  48.          if implied then
  49.             t := stmttok;
  50.          v := findvar;
  51.          require(tokeq);
  52.          if v^.stringvar then
  53.             begin
  54.                old := v^.sval^;
  55.                v^.sval^ := strexpr;
  56.                if old <> nil then
  57.                   dispose(old);
  58.             end
  59.          else
  60.             v^.val^ := realexpr;
  61.       end;
  62.    procedure cmdgoto;
  63.       begin
  64.          stmtline := mustfindline(intexpr);
  65.          t := nil;
  66.          gotoflag := true;
  67.       end;
  68.    procedure cmdif;
  69.       var
  70.          n : real;
  71.          i : integer;
  72.       begin
  73.          n := realexpr;
  74.          require(tokthen);
  75.          if n = 0 then
  76.             begin
  77.                i := 0;
  78.                repeat
  79.                   if t <> nil then
  80.                      begin
  81.                         if t^.kind = tokif then
  82.                            i := i + 1;
  83.                         if t^.kind = tokelse then
  84.                            i := i - 1;
  85.                         t := t^.next;
  86.                      end;
  87.                until (t = nil) or (i < 0);
  88.             end;
  89.          if (t <> nil) and (t^.kind = toknum) then
  90.             cmdgoto
  91.          else
  92.             elseflag := true;
  93.       end;
  94.    procedure cmdelse;
  95.       begin
  96.          t := nil;
  97.       end;
  98.    function skiploop(up, dn : tokenkinds) : boolean;
  99.       label 1;
  100.       var
  101.          i : integer;
  102.          saveline : lineptr;
  103.       begin
  104.          saveline := stmtline;
  105.          i := 0;
  106.          repeat
  107.             while t = nil do
  108.                begin
  109.                   if (stmtline = nil) or (stmtline^.next = nil) then
  110.                      begin
  111.                         skiploop := false;
  112.                         stmtline := saveline;
  113.                         goto 1;
  114.                      end;
  115.                   stmtline := stmtline^.next;
  116.                   t := stmtline^.txt;
  117.                end;
  118.             if t^.kind = up then
  119.                i := i + 1;
  120.             if t^.kind = dn then
  121.                i := i - 1;
  122.             t := t^.next;
  123.          until i < 0;
  124.          skiploop := true;
  125.      1 :
  126.       end;
  127.    procedure cmdfor;
  128.       var
  129.          l : loopptr;
  130.          lr : looprec;
  131.          saveline : lineptr;
  132.          i, j : integer;
  133.       begin
  134.          lr.vp := findvar;
  135.          if lr.vp^.stringvar then snerr;
  136.          require(tokeq);
  137.          lr.vp^.val^ := realexpr;
  138.          require(tokto);
  139.          lr.max := realexpr;
  140.          if (t <> nil) and (t^.kind = tokstep) then
  141.             begin
  142.                t := t^.next;
  143.                lr.step := realexpr;
  144.             end
  145.          else
  146.             lr.step := 1;
  147.          lr.homeline := stmtline;
  148.          lr.hometok := t;
  149.          lr.kind := forloop;
  150.          lr.next := loopbase;
  151.          with lr do
  152.             if ((step >= 0) and (vp^.val^ > max)) or ((step <= 0) and (vp^.val^ < max)) then
  153.                begin
  154.                   saveline := stmtline;
  155.                   i := 0;
  156.                   j := 0;
  157.                   repeat
  158.                      while t = nil do
  159.                         begin
  160.                            if (stmtline = nil) or (stmtline^.next = nil) then
  161.                               begin
  162.                                  stmtline := saveline;
  163.                                  errormsg('FOR without NEXT');
  164.                               end;
  165.                            stmtline := stmtline^.next;
  166.                            t := stmtline^.txt;
  167.                         end;
  168.                      if t^.kind = tokfor then
  169.                         if (t^.next <> nil) and (t^.next^.kind = tokvar) and (t^.next^.vp = vp) then
  170.                            j := j + 1
  171.                         else
  172.                            i := i + 1;
  173.                      if (t^.kind = toknext) then
  174.                         if (t^.next <> nil) and (t^.next^.kind = tokvar) and (t^.next^.vp = vp) then
  175.                            j := j - 1
  176.                         else
  177.                            i := i - 1;
  178.                      t := t^.next;
  179.                   until (i < 0) or (j < 0);
  180.                   skiptoeos;
  181.                end
  182.             else
  183.                begin
  184.                   new(l);
  185.                   l^ := lr;
  186.                   loopbase := l;
  187.                end;
  188.       end;
  189.    procedure cmdnext;
  190.       var
  191.          v : varptr;
  192.          found : boolean;
  193.          l : loopptr;
  194.       begin
  195.          if not iseos then
  196.             v := findvar
  197.          else
  198.             v := nil;
  199.          repeat
  200.             if (loopbase = nil) or (loopbase^.kind = gosubloop) then 
  201.                errormsg('NEXT without FOR');
  202.             found := (loopbase^.kind = forloop) and
  203.                      ((v = nil) or (loopbase^.vp = v));
  204.             if not found then
  205.                begin
  206.                   l := loopbase^.next;
  207.                   dispose(loopbase);
  208.                   loopbase := l;
  209.                end;
  210.          until found;
  211.          with loopbase^ do
  212.             begin
  213.                vp^.val^ := vp^.val^ + step;
  214.                if ((step >= 0) and (vp^.val^ > max)) or ((step <= 0) and (vp^.val^ < max)) then
  215.                   begin
  216.                      l := loopbase^.next;
  217.                      dispose(loopbase);
  218.                      loopbase := l;
  219.                   end
  220.                else
  221.                   begin
  222.                      stmtline := homeline;
  223.                      t := hometok;
  224.                   end;
  225.             end;
  226.       end;
  227.    procedure cmdwhile;
  228.       var
  229.          l : loopptr;
  230.       begin
  231.          new(l);
  232.          l^.next := loopbase;
  233.          loopbase := l;
  234.          l^.kind := whileloop;
  235.          l^.homeline := stmtline;
  236.          l^.hometok := t;
  237.          if not iseos then
  238.             if realexpr = 0 then
  239.                begin
  240.                   if not skiploop(tokwhile, tokwend) then 
  241.                      errormsg('WHILE without WEND');
  242.                   l := loopbase^.next;
  243.                   dispose(loopbase);
  244.                   loopbase := l;
  245.                   skiptoeos;
  246.                end;
  247.       end;
  248.    procedure cmdwend;
  249.       var
  250.          tok : tokenptr;
  251.          tokline : lineptr;
  252.          l : loopptr;
  253.          found : boolean;
  254.       begin
  255.          repeat
  256.             if (loopbase = nil) or (loopbase^.kind = gosubloop) then
  257.                errormsg('WEND without WHILE');
  258.             found := (loopbase^.kind = whileloop);
  259.             if not found then
  260.                begin
  261.                   l := loopbase^.next;
  262.                   dispose(loopbase);
  263.                   loopbase := l;
  264.                end;
  265.          until found;
  266.          if not iseos then
  267.             if realexpr <> 0 then
  268.                found := false;
  269.          tok := t;
  270.          tokline := stmtline;
  271.          if found then
  272.             begin
  273.                stmtline := loopbase^.homeline;
  274.                t := loopbase^.hometok;
  275.                if not iseos then
  276.                   if realexpr = 0 then
  277.                      found := false;
  278.             end;
  279.          if not found then
  280.             begin
  281.                t := tok;
  282.                stmtline := tokline;
  283.                l := loopbase^.next;
  284.                dispose(loopbase);
  285.                loopbase := l;
  286.             end;
  287.       end;
  288.    procedure cmdgosub;
  289.       var
  290.          l : loopptr;
  291.       begin
  292.          new(l);
  293.          l^.next := loopbase;
  294.          loopbase := l;
  295.          l^.kind := gosubloop;
  296.          l^.homeline := stmtline;
  297.          l^.hometok := t;
  298.          cmdgoto;
  299.       end;
  300.    procedure cmdreturn;
  301.       var
  302.          l : loopptr;
  303.          found : boolean;
  304.       begin
  305.          repeat
  306.             if loopbase = nil then
  307.                errormsg('RETURN without GOSUB');
  308.             found := (loopbase^.kind = gosubloop);
  309.             if not found then
  310.                begin
  311.                   l := loopbase^.next;
  312.                   dispose(loopbase);
  313.                   loopbase := l;
  314.                end;
  315.          until found;
  316.          stmtline := loopbase^.homeline;
  317.          t := loopbase^.hometok;
  318.          l := loopbase^.next;
  319.          dispose(loopbase);
  320.          loopbase := l;
  321.          skiptoeos;
  322.       end;
  323.    procedure cmdread;
  324.       var
  325.          v : varptr;
  326.          tok : tokenptr;
  327.          found : boolean;
  328.       begin
  329.          repeat
  330.             v := findvar;
  331.             tok := t;
  332.             t := datatok;
  333.             if dataline = nil then
  334.                begin
  335.                   dataline := linebase;
  336.                   t := dataline^.txt;
  337.                end;
  338.             if (t = nil) or (t^.kind <> tokcomma) then
  339.                repeat
  340.                   while t = nil do
  341.                      begin
  342.                         if (dataline = nil) or (dataline^.next = nil) then
  343.                            errormsg('Out of Data');
  344.                         dataline := dataline^.next;
  345.                         t := dataline^.txt;
  346.                      end;
  347.                   found := (t^.kind = tokdata);
  348.                   t := t^.next;
  349.                until found and not iseos
  350.             else
  351.                t := t^.next;
  352.             if v^.stringvar then
  353.                begin
  354.                   if v^.sval^ <> nil then
  355.                      dispose(v^.sval^);
  356.                   v^.sval^ := strexpr;
  357.                end
  358.             else
  359.                v^.val^ := realexpr;
  360.             datatok := t;
  361.             t := tok;
  362.             if not iseos then
  363.                require(tokcomma);
  364.          until iseos;
  365.       end;
  366.    procedure cmddata;
  367.       begin
  368.          skiptoeos;
  369.       end;
  370.    procedure cmdrestore;
  371.       begin
  372.          if iseos then
  373.             restoredata
  374.          else
  375.             begin
  376.                dataline := mustfindline(intexpr);
  377.                datatok := dataline^.txt;
  378.             end;
  379.       end;
  380.    procedure cmdgotoxy;
  381.       var
  382.          i : integer;
  383.       begin
  384.          i := intexpr;
  385.          require(tokcomma);
  386.          gotoxy(i, intexpr);
  387.       end;
  388.    procedure cmdon;
  389.       var
  390.          i : integer;
  391.          l : loopptr;
  392.       begin
  393.          i := intexpr;
  394.          if (t <> nil) and (t^.kind = tokgosub) then
  395.             begin
  396.                new(l);
  397.                l^.next := loopbase;
  398.                loopbase := l;
  399.                l^.kind := gosubloop;
  400.                l^.homeline := stmtline;
  401.                l^.hometok := t;
  402.                t := t^.next;
  403.             end
  404.          else
  405.             require(tokgoto);
  406.          if i < 1 then
  407.             skiptoeos
  408.          else
  409.             begin
  410.                while (i > 1) and not iseos do
  411.                   begin
  412.                      require(toknum);
  413.                      if not iseos then
  414.                         require(tokcomma);
  415.                      i := i - 1;
  416.                   end;
  417.                if not iseos then
  418.                   cmdgoto;
  419.             end;
  420.       end;
  421.    procedure cmddim;
  422.       var
  423.          i, j, k : integer;
  424.          v : varptr;
  425.          done : boolean;
  426.       begin
  427.          repeat
  428.             if (t = nil) or (t^.kind <> tokvar) then snerr;
  429.             v := t^.vp;
  430.             t := t^.next;
  431.             with v^ do
  432.                begin
  433.                   if numdims <> 0 then
  434.                      errormsg('Array already dimensioned');
  435.                   j := 1;
  436.                   i := 0;
  437.                   require(toklp);
  438.                   repeat
  439.                      k := intexpr + 1;
  440.                      if k < 1 then badsubscr;
  441.                      if i >= maxdims then badsubscr;
  442.                      i := i + 1;
  443.                      dims[i] := k;
  444.                      j := j * k;
  445.                      done := (t <> nil) and (t^.kind = tokrp);
  446.                      if not done then
  447.                         require(tokcomma);
  448.                   until done;
  449.                   t := t^.next;
  450.                   numdims := i;
  451.                   if stringvar then
  452.                      begin
  453.                         hpm_new(sarr, j*4);
  454.                         for i := 0 to j-1 do
  455.                            sarr^[i] := nil;
  456.                      end
  457.                   else
  458.                      begin
  459.                         hpm_new(arr, j*8);
  460.                         for i := 0 to j-1 do
  461.                            arr^[i] := 0;
  462.                      end;
  463.                end;
  464.             if not iseos then
  465.                require(tokcomma);
  466.          until iseos;
  467.       end;
  468.    procedure cmdpoke;
  469.       var
  470.          trick :
  471.             record
  472.                case boolean of
  473.                   true : (i : integer);
  474.                   false : (c : ^char);
  475.             end;
  476.       begin
  477.          $range off$
  478.          trick.i := intexpr;
  479.          require(tokcomma);
  480.          trick.c^ := chr(intexpr);
  481.          $if checking$ $range on$ $end$
  482.       end;
  483.    begin {exec}
  484.       try
  485.          repeat
  486.             repeat
  487.                gotoflag := false;
  488.                elseflag := false;
  489.                while (stmttok <> nil) and (stmttok^.kind = tokcolon) do
  490.                   stmttok := stmttok^.next;
  491.                t := stmttok;
  492.                if t <> nil then
  493.                   begin
  494.                      t := t^.next;
  495.                      case stmttok^.kind of
  496.                         tokrem     : ;
  497.                         toklist    : cmdlist;
  498.                         tokrun     : cmdrun;
  499.                         toknew     : cmdnew;
  500.                         tokload    : cmdload(false, stringexpr);
  501.                         tokmerge   : cmdload(true, stringexpr);
  502.                         toksave    : cmdsave;
  503.                         tokbye     : cmdbye;
  504.                         tokdel     : cmddel;
  505.                         tokrenum   : cmdrenum;
  506.                         toklet     : cmdlet(false);
  507.                         tokvar     : cmdlet(true);
  508.                         tokprint   : cmdprint;
  509.                         tokinput   : cmdinput;
  510.                         tokgoto    : cmdgoto;
  511.                         tokif      : cmdif;
  512.                         tokelse    : cmdelse;
  513.                         tokend     : cmdend;
  514.                         tokstop    : escape(-20);
  515.                         tokfor     : cmdfor;
  516.                         toknext    : cmdnext;
  517.                         tokwhile   : cmdwhile;
  518.                         tokwend    : cmdwend;
  519.                         tokgosub   : cmdgosub;
  520.                         tokreturn  : cmdreturn;
  521.                         tokread    : cmdread;
  522.                         tokdata    : cmddata;
  523.                         tokrestore : cmdrestore;
  524.                         tokgotoxy  : cmdgotoxy;
  525.                         tokon      : cmdon;
  526.                         tokdim     : cmddim;
  527.                         tokpoke    : cmdpoke;
  528.                      otherwise
  529.                         errormsg('Illegal command');
  530.                      end;
  531.                   end;
  532.                if not elseflag and not iseos then
  533.                   checkextra;
  534.                stmttok := t;
  535.             until t = nil;
  536.             if stmtline <> nil then
  537.                begin
  538.                   if not gotoflag then
  539.                      stmtline := stmtline^.next;
  540.                   if stmtline <> nil then
  541.                      stmttok := stmtline^.txt;
  542.                end;
  543.          until stmtline = nil;
  544.       recover
  545.          begin
  546.             if escapecode = -20 then
  547.                begin
  548.                   write('Break');
  549.                end
  550.             else if escapecode = 42 then
  551.                begin end
  552.             else
  553.                case escapecode of
  554.                   -4 : write(#7'Integer overflow');
  555.                   -5 : write(#7'Divide by zero');
  556.                   -6 : write(#7'Real math overflow');
  557.                   -7 : write(#7'Real math underflow');
  558.                   -8, -19..-15 : write(#7'Value range error');
  559.                   -10 :
  560.                      begin
  561.                         new(ioerrmsg);
  562.                         misc_getioerrmsg(ioerrmsg^, ioresult);
  563.                         write(#7, ioerrmsg^);
  564.                         dispose(ioerrmsg);
  565.                      end;
  566.                   otherwise
  567.                      begin
  568.                         if excp_line <> -1 then
  569.                            writeln(excp_line);
  570.                         escape(escapecode);
  571.                      end;
  572.                end;
  573.             if stmtline <> nil then
  574.                write(' in ', stmtline^.num:1);
  575.             writeln;
  576.          end;
  577.    end; {exec}
  578. begin {main}
  579.    new(inbuf);
  580.    linebase := nil;
  581.    varbase := nil;
  582.    loopbase := nil;
  583.    writeln('Chipmunk BASIC 1.0');
  584.    writeln;
  585.    exitflag := false;
  586.    repeat
  587.       try
  588.          repeat
  589.             write('>');
  590.             readln(inbuf^);
  591.             parseinput(buf);
  592.             if curline = 0 then
  593.                begin
  594.                   stmtline := nil;
  595.                   stmttok := buf;
  596.                   if stmttok <> nil then
  597.                      exec;
  598.                   disposetokens(buf);
  599.                end;
  600.          until exitflag or eof(input);
  601.       recover
  602.          if escapecode <> -20 then
  603.             misc_printerror(escapecode, ioresult)
  604.          else
  605.             writeln;
  606.    until exitflag or eof(input);
  607. end.