| Rozdział 2ZAPIS PROGRAMU W PAMIĘCIGdyby  program  zapisany  był  w  pamięci  komputera w taki
sposób,  jak to widać na ekranie, to zajmowałby stosunkowo duży
obszar tej pamięci. Ponadto wykonywanie tak zapisanego programu
byłoby   powolne   ze   względu  na  konieczność  każdorazowego
rozpoznawania  instrukcji,  operacji  i  zmiennych. Dlatego też
interpreter  tłumaczy  każdy  wprowadzony  wiersz  programu  na
zestaw specjalnych kodów zwanych tokenami, sprawdzając przy tym
jego    poprawność    składniową,    a   następnie   zakodowany
(stokenizowany) wiersz programu umieszcza w tablicy instrukcji.
 Podział  obszaru  zajmowanego przez program był już opisany
we   wprowadzeniu.   Kolejne  wiersze  właściwego  programu  są
umieszczane  w pamięci według kolejności ich numerów, przy czym
wiersze wprowadzone w trybie bezpośrednim otrzymują numer 32768
($8000) i są zapisywane na końcu tablicy instrukcji.
 
 W  dalszej  części  tego  rozdziału  zostanie przedstawiona
lista  tokenów  i  sposób  ich  zapisu w pamięci komputera oraz
proces   tokenizacji.   Proces   ten   jest   jednakże   bardzo
skomplikowany   ze  względu  na  jednoczesną  kontrolę  składni
instrukcji  i  jego zrozumienie wymaga bardzo dobrej znajomości
języka  maszynowego.  Z  tego  powodu  kontrola  składni będzie
przedstawiona   tylko   w   sposób   przybliżony,   a  bardziej
zainteresowani   tym   tematem  Czytelnicy  muszą  samodzielnie
dokonać dokładnej analizy.
 
 2.1. Tokeny Atari BasicPodczas   tokenizacji   wprowadzony  wiersz  programu  jest
zamieniany  na  ciąg kodów. Rządzą tym oczywiście pewne reguły,
które  teraz  zostaną podane. Jako przykład wykorzystamy krótki
wiersz programu następującej postaci:
 
          10 DIM NAZWA$(20):NAZWA$="ATARI":PRINT ALFA+5
Pierwsze   dwa   tokeny   reprezentują   numer   wiersza  w
standardowej  postaci  -  młodszy bajt, starszy bajt - a więc w
naszym  przypadku $0A, $00. Trzeci bajt określa długość wiersza
(tu  $28),  a czwarty długość instrukcji. Przez długość wiersza
należy  rozumieć  kolejny  numer  tokena symbolizującego koniec
wiersza  (znak RETURN - token $16). Podobnie długość instrukcji
jest  przedstawiona  jako  numer tokena oznaczającego dwukropek
pomiędzy  instrukcjami  (token  $14)  lub koniec wiersza. Gdy w
jednym  wierszu  znajduje się kilka instrukcji, to każda z nich
rozpoczyna   się   od   tokena  określającego  jej  długość  (w
przykładzie  są  to  kolejno  $10, $1C i $28). Pozostałe tokeny
zawierają właściwą treść wiersza programu.
 Stałe   liczbowe   są   przedstawione   w   postaci  liczby
zmiennoprzecinkowej   poprzedzonej   kodem  określającym  stałą
liczbową  (razem siedem bajtów). Zapis stałych tekstowych także
zaczyna  się  od  kodu stałej tekstowej, po którym znajduje się
liczba  znaków  stałej,  a  następnie  stała  zapisana  znakami
ATASCII.  Zmienne  są  zapisywane  przy  pomocy  ich  numerów w
tablicy nazw zmiennych. Numery te mają ustawiony najstarszy bit
(są zwiększone o $80).
 
 Każda   instrukcja   programu   zaczyna   się   od   tokena
oznaczającego komendę języka Basic. Dalej umieszczone są tokeny
stałych i zmiennych oraz tokeny operatorów i funkcji. Znaczenie
tych   tokenów   jest   przedstawione  w  poniższych  tabelach.
Numeracja   wszystkich   tokenów   odpowiada  ich  położeniu  w
tablicach  nazw  instrukcji  STNAME  i  operatorów  OPFN oraz w
tablicach wektorów instrukcji STVTAB i operatorów OPVTAB.
 
 
    Tabela 1. Tokeny instrukcji Atari Basic
      token HEX i DEC   instrukcja
      ----------------------------
            $00     0     REM
            $01     1     DATA
            $02     2     INPUT
            $03     3     COLOR
            $04     4     LIST
            $05     5     ENTER
            $06     6     LET
            $07     7     IF
            $08     8     FOR
            $09     9     NEXT
            $0A    10     GOTO
            $0B    11     GO TO
            $0C    12     GOSUB
            $0D    13     TRAP
            $0E    14     BYE
            $0F    15     CONT
            $10    16     COM
            $11    17     CLOSE
            $12    18     CLR
            $13    19     DEG
            $14    20     DIM
            $15    21     END
            $16    22     NEW
            $17    23     OPEN
            $18    24     LOAD
            $19    25     SAVE
            $1A    26     STATUS
            $1B    27     NOTE
            $1C    28     POINT
            $1D    29     XIO
            $1E    30     ON
            $1F    31     POKE
            $20    32     PRINT
            $21    33     RAD
            $22    34     READ
            $23    35     RESTORE
            $24    36     RETURN
            $25    37     RUN
            $26    38     STOP
            $27    39     POP
            $28    40     ?
            $29    41     GET
            $2A    42     PUT
            $2B    43     GRAPHICS
            $2C    44     PLOT
            $2D    45     POSITION
            $2E    46     DOS
            $2F    47     DRAWTO
            $30    48     SETCOLOR
            $31    49     LOCATE
            $32    50     SOUND
            $33    51     LPRINT
            $34    52     CSAVE
            $35    53     CLOAD
            $36    54     opuszczone LET
            $37    55     błąd składni
Wyjaśnienia   wymagają   dwa  ostatnie  tokeny.  Jeśli  nie
zostanie rozpoznana prawidłowa komenda, to interpreter zakłada,
że   jest   to   nazwa  zmiennej  i  wpisuje  token  instrukcji
przypisania  z  opuszczonym  słowem LET. W przypadku napotkania
błędu  składniowego  w  tokenizowanym  wierszu na jego początku
zapisywany jest token błędu składniowego (STNTAX ERROR), a cały
wiersz jest przepisywany do tablicy instrukcji bez tokenizacji.
 Pierwszą  instrukcją  naszego  przykładu  jest  DIM, której
odpowiada  token  $14.  Taka właśnie liczba jest piątym tokenem
wiersza.   Kolejna  instrukcja  jest  podstawieniem,  w  którym
opuszczone zostało słowo LET - odpowiada jej token $36 (pozycja
18). Ostatnią instrukcją jest PRINT - token $20 na pozycji 30.
 
 Po  każdej  z  wymienionych  instrukcji  następuje zmienna.
Pierwsza  zmienna  (NAZWA$)  o numerze 0 jest oznaczona tokenem
$80  (pozycje  6  i 19), zaś druga zmienna (ALFA) o numerze 1 -
tokenem  $81 (pozycja 31). Ponadto w przykładzie występują dwie
stałe  liczbowe:  20  (pozycje  8-14)  i 5 (pozycje 33-39) oraz
stała tekstowa "ATARI" (pozycje 21-27).
 
 Na  tym  przykładzie  wyraźnie  widać  oszczędność  pamięci
uzyskiwaną  przez zastosowanie zmiennych zamiast stałych. Każda
zmienna  zajmuje  miejsce  w tablicy nazw (zwykle 2-3 bajty), w
tablicy  wartości  zmiennych  (8 bajtów) i tyle miejsc,ile razy
wystąpi w programie, przy czym raz musi mieć nadaną wartość (12
bajtów).  Jeśli  stała  występuje  w  programie cztery razy, to 
zajmie  4*7=28  bajtów.  Po  zastąpieniu  jej  przez stałą mamy
2+8+12+4*1=26   bajtów.   Warto   więc   każdą  stałą  liczbową
występującą  w  programie  ponad  trzy razy zastępować zmienną.
Podobnie  jest  ze stałymi tekstowymi, lecz opłacalność takiego
zabiegu zależy od długości stałej.
 
 
    Tabela 2. Tokeny operatorów i funkcji Atari Basic
      token HEX i DEC     operator lub funkcja
      ----------------------------------------
            $0E    14     stała liczbowa
            $0F    15     stała tekstowa
            $10    16     niewykorzystany
            $11    17     niewykorzystany
            $12    18     , -przecinek
            $13    19     $ -znak dolara
            $14    20     : -koniec instrukcji
            $15    21     ; -średnik
            $16    22     EOL -znak RETURN
            $17    23     GOTO -w ON
            $18    24     GOSUB -w ON
            $19    25     TO -w FOR
            $1A    26     STEP -w FOR
            $1B    27     THEN -w IF
            $1C    28     # -znak "numer"
            $1D    29     <=  -+
            $1E    30     <>   |
            $1F    31     >=   | porównanie
            $20    32     <    |   liczb
            $21    33     >    |
            $22    34     =   -+
            $23    35     ^ -potęgowanie
            $24    36     * -mnożenie
            $25    37     + -dodawanie
            $26    38     - -odejmowanie
            $27    39     / -dzielenie
            $28    40     NOT
            $29    41     OR
            $2A    42     AND
            $2B    43     ( -wyr. arytmet.
            $2C    44     ) -kończący
            $2D    45     = -LET liczbowe
            $2E    46     = -LET tekstowe
            $2F    47     <=  -+
            $30    48     <>   |
            $31    49     >=   | porównanie
            $32    50     <    |  tekstów
            $33    51     >    |
            $34    52     =   -+
            $35    53     + -znak liczby
            $36    54     - -znak liczby
            $37    55     ( -zm. tekstowa
            $38    56     ( -zm. tablicowa
            $39    57     ( -wymiar zm. tabl.
            $3A    58     ( -funkcja
            $3B    59     ( -wymiar zm. tekst.
            $3C    60     , -w zmiennej tablic.
            $3D    61     STR$
            $3E    62     CHR$
            $3F    63     USR
            $40    64     ASC
            $41    65     VAL
            $42    66     LEN
            $43    67     ADR
            $44    68     ATN
            $45    69     COS
            $46    70     PEEK
            $47    71     SIN
            $48    72     RND
            $49    73     FRE
            $4A    74     EXP
            $4B    75     LOG
            $4C    76     CLOG
            $4D    77     SQR
            $4E    78     SGN
            $4F    79     ABS
            $50    80     INT
            $51    81     PADDLE
            $52    82     STICK
            $53    83     PTRIG
            $54    84     STRIG
W  tabeli  tokenów  operatorów  zwraca  uwagę  duża  liczba
różnych  tokenów  dla  nawiasów  oraz  oddzielenie identycznych
operatorów wyrażeń tekstowych i liczbowych. Pomimo identycznego
wyglądu  wykonywane  przez  nie  funkcje  różnią się znacznie i
zróżnicowanie tokenów powoduje następnie wybór różnych procedur
wykonawczych przy realizacji programu.
 Wygląd  stokenizowanego przykładowego wiersza programu jest
przedstawiony na następnej stronie.
 
 
            pozycja   token   znaczenie
            --------------------------------------
                1      $0A    ; numer wiersza
                2      $00    ;  $000A = 10
                3      $28    długość wiersza (40)
                4      $10    dł. instrukcji (16)
                5      $14    instrukcja DIM
                6      $80    zmienna numer 0
                7      $3B    ( -nawias wymiaru
                8      $0E    stała liczbowa
                9      $40    |
               10      $20    |
               11      $00    | liczba 20
               12      $00    | w kodzie BCD
               13      $00    |
               14      $00    |
               15      $2C    ) -nawias kończący
               16      $14    : -koniec instrukcji
               17      $1C    dł. instrukcji (28)
               18      $36    opuszczone LET
               19      $80    zmienna numer 0
               20      $2E    = -LET tekstowe
               21      $0F    stała tekstowa
               22      $05    długość stałej
               23      $41    A  |
               24      $54    T  |
               25      $41    A  | kody ATASCII
               26      $52    R  |
               27      $49    I  |
               28      $14    : -koniec instrukcji
               29      $28    dł. instrukcji (40)
               30      $20    instrukcja PRINT
               31      $81    zmienna numer 1
               32      $25    + -dodawanie
               33      $0E    stała liczbowa
               34      $40    |
               35      $05    |
               36      $00    | liczba 5
               37      $00    | w kodzie BCD
               38      $00    |
               39      $00    |
               40      $16    EOL - koniec wiersza
 2.2. Proces tokenizacjiTokenizacja  wiersza  programu jest nieodłącznie związana z
procesem  kontroli  jego  składni.  Czynności  te są wykonywane
przez   procedurę  SYNTAX,  która  jest  największym  elementem
interpretera.
 
               < SYNTAX >
                   |
          +------------------+
          | pobranie rekordu |<----------------+
          +------------------+                 |
                   |                           |
                   v                           |
        /---------------------\ tak  +-------------------+
       < tylko numer wiersza ? >---->| usunięcie wiersza |
        \---------------------/      +-------------------+
                   | nie
                   v
       +------------------------+
       | rozpoznanie instrukcji |
    +->|   i kontrola składni   |
    |  +------------------------+
    |              |
    |              v
    |         /----------\ nie  +---------------------+
    |        < poprawna ? >---->| przepisanie wiersza |
    |         \----------/      +---------------------+
    |              | tak                   |
    |              v                       |
    |  nie /----------------\              |
    +<----< koniec wiersza ? ><------------+
           \----------------/
                   | tak
                   v
      +-------------------------+
      | zapis wiersza w pamięci |
      +-------------------------+
                   |
                   v
                /------\ tak  +----------------------+
               < błąd ? >---->| wyświetlenie wiersza |
                \------/      +----------------------+
                   | nie                  |
                   v                      |
          /------------------\ nie        v
         < tryb bezpośredni ? >---->----->+
          \------------------/            |
                   | tak                  |
                   v                      v
        +----------------------+      < SYNTAX >
        | wykonanie instrukcji |
        +----------------------+
          Rys.2. Struktura procedury SYNTAX
 
0100 ;check SYNTAX            0660     STA COX
0110 ;                        0670     STA SXFLG
0120 AUXBR = $AF              0680     STA TMPIX
0130 BHLD1 = $B0              0690     STA BHLD1
0140 BHLD2 = $B1              0700     STA BHLD2
0150 BUFIX = $9F              0710     LDA VNTD
0160 CDST =  $A000            0720     STA MAXLN
0170 CIX =   $F2              0730     LDA VNTD+1
0180 COX =   $94              0740     STA MAXLN+1
0190 CSTAD = $97              0750     JSR INBSS
0200 DELEL = $A8F7            0760     JSR PLINEN
0210 FNDCST = $A9A2           0770     JSR SAVTKN
0220 FR0 =   $D4              0780     LDA FR0+1
0230 GETREC = $BDED           0790     BPL DCD
0240 GIRQST = $A9F2           0800     STA SXFLG
0250 GLNLEN = $A9DC           0810 DCD JSR INBSS
0260 INBSS = $DBA1            0820     LDY CIX
0270 INBUFP = $F3             0830     STY INIX
0280 INIX =  $A8              0840     LDA (INBUFP),Y
0290 INSEL = $A87A            0850     CMP #$9B
0300 LOADFLG = $CA            0860     BNE DCDSTM
0310 LOMEM = $80              0870     BIT SXFLG
0320 LSTPLN = $B58E           0880     BMI SYNTAX
0330 MAXLN = $AD              0890     JMP DELPLN
0340 NXTSTM = $A9D0           0900 ;
0350 OUTIX = $A7              0910 DeCoDe STateMent
0360 PLINEN = $A19A           0920 ;
0370 PRCSTM = $A95E           0930 DCDSTM LDA COX
0380 PROMPT = $C2             0940     STA OUTIX
0390 PRTPLN = $B5AA           0950     JSR SAVTKN
0400 RECNAM = $A454           0960     JSR INBSS
0410 SAVTKN = $A2C4           0970     LDA # >STNAME
0420 STBV =  $DA51            0980     LDY # <STNAME
0430 STMCUR = $8A             0990     LDX #$02
0440 STMSX = $A1BE            1000     JSR RECNAM
0450 STMTAB = $88             1010     STX CIX
0460 STNAME = $A49F           1020     LDA AUXBR
0470 SXFLG = $A6              1030     JSR SAVTKN
0480 TMPIX = $B3              1040     JSR INBSS
0490 VNTD =  $84              1050     JSR STMSX
0500 ;                        1060     BCC SAVL
0510     *=  $A060            1070     LDY BUFIX
0520 ;                        1080     LDA (INBUFP),Y
0530 SYNTAX LDA LOADFLG       1090     CMP #$9B
0540     BNE CDST             1100     BNE MCH
0550     LDX #$FF             1110     INY
0560     TXS                  1120     STA (INBUFP),Y
0570     JSR STBV             1130     DEY
0580     LDA #$5D             1140     LDA #$20
0590     STA PROMPT           1150 MCH ORA #$80
0600     JSR GETREC           1160     STA (INBUFP),Y
0610     JSR GIRQST           1170     LDA #$40
0620     BEQ SYNTAX           1180     ORA SXFLG
0630     LDA #$00             1190     STA SXFLG
0640     STA CIX              1200     LDY INIX
0650     STA BUFIX            1210     STY CIX
1220     LDX #$03             1670     JSR NXTSTM
1230     STX OUTIX            1680     LDX #STMCUR
1240     INX                  1690     JSR DELEL+1
1250     STX COX              1700 STORE LDY COX
1260     LDA #$37             1710 LP2 DEY
1270 LP1 JSR SAVTKN           1720     LDA (LOMEM),Y
1280 ;                        1730     STA (STMCUR),Y
1290 ;MOVe ToKeNs             1740     TYA
1300 ;                        1750     BNE LP2
1310 MOVTKN LDY CIX           1760     BIT SXFLG
1320     LDA (INBUFP),Y       1770     BVC EXIT
1330     INC CIX              1780     LDA BHLD2
1340     CMP #$9B             1790     ASL A
1350     BNE LP1              1800     ASL A
1360     JSR SAVTKN           1810     ASL A
1370 SAVL LDA COX             1820     LDX #STMTAB
1380     LDY OUTIX            1830     JSR DELEL
1390     STA (LOMEM),Y        1840     SEC
1400     LDY CIX              1850     LDA VNTD
1410     DEY                  1860     SBC MAXLN
1420     LDA (INBUFP),Y       1870     TAY
1430     CMP #$9B             1880     LDA VNTD+1
1440     BNE DCDSTM           1890     SBC MAXLN+1
1450     LDY #$02             1900     LDX #VNTD
1460     LDA COX              1910     JSR DELEL+3
1470     STA (LOMEM),Y        1920     BIT SXFLG
1480     JSR FNDCST           1930     BPL LIST
1490     LDA #$00             1940     JSR PRTPLN
1500     BCS LEN              1950     JMP SYNTAX
1510     JSR GLNLEN           1960 LIST JSR LSTPLN
1520 LEN SEC                  1970 LOOP JMP SYNTAX
1530     SBC COX              1980 EXIT BPL LOOP
1540     BEQ STORE            1990     JMP PRCSTM
1550     BCS SML              2000 ;
1560     EOR #$FF             2010 ;DELete Program LiNe
1570     TAY                  2020 ;
1580     INY                  2030 DELPLN JSR FNDCST
1590     LDX #STMCUR          2040     BCS LOOP
1600     JSR INSEL            2050     JSR GLNLEN
1610     LDA CSTAD            2060     TAY
1620     STA STMCUR           2070     JSR NXTSTM
1630     LDA CSTAD+1          2080     LDX #STMCUR
1640     STA STMCUR+1         2090     JSR DELEL+1
1650     BNE STORE            2100     JMP SYNTAX
1660 SML TAY
SYNTAX  rozpoczyna  się  od  wywołania procedury STBV (zob.
"Mapa   pamięci   Atari  XL/XE.  Podstawowe  procedury  systemu
operacyjnego"),  która wpisuje adres bufora LBUFF (Line BUFFer)
do  rejestru  INBUFF  (INput  BUFfer  Pointer). Następnie przez
wywołanie  procedury  GETREC  (jest  ona  częścią PUTRET - zob.
rozdział  6.6.10)  odczytywany  jest z edytora wiersz programu.
Przed  przystąpieniem  do  jego analizy wywoływana jest jeszcze
procedura   GIRQST.   Służy  ona  do  sprawdzenia,  czy  został
naciśnięty  klawisz  BREAK.  Jeżeli  tak,  to następuje skok do
początku  procedury  SYNTAX, a w przeciwnym wypadku zerowane są
niezbędne  rejestry  (CIX,  COX,  BUFIX,  TMPIX, SXFLG, BHLD1 i
BHLD2),  a  wektor  VNTD jest przepisywany do MAXLN. Dopiero po
tym  wstępie  rozpoczyna  się  kontrola  składni  wprowadzonego
wiersza i jego tokenizacja. 
 
            0100 ;Get IRQ STatus
            0110 ;
            0120 IRQSTAT = $11
            0130 ;
            0140     *=  $A9F2
            0150 ;
            0160     LDY IRQSTAT
            0170     BNE END
            0180     DEC IRQSTAT
            0190     TYA
            0200 END RTS
Podczas  tych operacji często są wywoływane procedury INBSS
i  SAVTKN.  Pierwsza  z  nich  znajduje się w pakiecie procedur
zmiennoprzecinkowych  i  ustawia  licznik  bufora  CIX (Current
Input  indeX)  na  następnym  znaku  innym  niż  spacja.  Druga
zapisuje  przekazany  jej  w akumulatorze token na odpowiedniej
pozycji  bufora  tokenizacji.  Pozycja ta jest wskazywana przez
licznik  COX  (Current  Output indeX), a przekroczenie wartości
równej  $FF  powoduje  sygnalizację nadmiernej długości wiersza
(błąd   Line   Too   LonG   ERror).   Warto  zauważyć,  że  dla
zaoszczędzenia  bajtu  pamięci  SAVTKN  korzysta  z rozkazu RTS
umieszczonego w poprzedzającej ją procedurze.
 
            0100 ;SAVe ToKeN
            0110 ;
            0120 COX =   $94
            0130 LOMEM = $80
            0140 LTLGER = $B918
            0150 ;
            0160     *=  $A2C4
            0170 ;
            0180     LDY COX
            0190     STA (LOMEM),Y
            0200     INC COX
            0210     BNE $A2C3   ;RTS
            0220     JMP LTLGER
Jako   pierwszy   rozpoznawany   jest  numer  wprowadzonego
wiersza.  Wykonuje  to  procedura PLINEN. Wywołuje ona najpierw
procedurę  AFP (pakiet FP), która zamienia ciąg znaków ASCII na
liczbę.  Jeśli jest to niemożliwe (znaki ASCII nie są cyframi),
to  licznik  CIX jest zerowany, a wiersz otrzymuje numer $8000,
co  oznacza  tryb bezpośredni. Po rozpoznaniu liczby wywoływana
jest  krótka  procedura  GETINT zamieniająca otrzymany wynik na
dwubajtową  liczbę całkowitą. Gdy wartość tej liczby przekracza
$8000,  to  także  jest redukowana do tej wartości. Otrzymany w
rezultacie  numer  wiersza  jest  umieszczany  w rejestrze CLNN
(Current  LiNe  Number)  oraz  przez dwukrotne wywołanie SAVTKN
przepisywany do bufora tokenizacji.
 
            0100 ;Program LINE Number
            0110 ;
            0120 AFP =   $D800
            0130 CIX =   $F2
            0140 CLNN =  $A0
            0150 FR0 =   $D4
            0160 GETINT = $AD41
            0170 SAVTKN = $A2C4
            0180 ;
            0190     *=  $A19A
            0200 ;
            0210     JSR AFP
            0220     BCC LIN
            0230 DIR LDA #$00
            0240     STA CIX
            0250     LDY #$80
            0260     BMI STR
            0270 LIN JSR GETINT
            0280     LDY FR0+1
            0290     BMI DIR
            0300     LDA FR0
            0310 STR STY CLNN+1
            0320     STA CLNN
            0330     JSR SAVTKN
            0340     LDA CLNN+1
            0350     STA FR0+1
            0360     JMP SAVTKN
Wspomniana  wcześniej procedura GETINT została wprowadzona,
aby   umożliwić   właściwą  sygnalizację  błędu.  Wywołuje  ona
procedurę FPI z pakietu FP i, w przypadku niepoprawnego wyniku,
sygnalizuje  błędną  wartość  przez  skok  do BVALER (Bad VALue
ERror).
 
            0100 ;GET INTeger value
            0110 ;
            0120 BVALER = $B92E
            0130 FPI =   $D9D2
            0140 ;
            0150     *=  $AD41
            0160 ;
            0170     JSR FPI
            0180     BCS ERR
            0190     RTS
            0200 ERR JSR BVALER
Kolejne  wywołanie  procedury SAVTKN ma na celu zwiększenie
licznika  COX,  aby  pozostawić  miejsce  na  token określający
długość  wprowadzonego  wiersza. Jeśli wiersz ten jest w trybie
bezpośrednim, to znacznik SXFLG (SyntaX FLaG) otrzymuje wartość
$80.  Teraz sprawdzany jest kod następnego znaku. Jeśli jest to
koniec  wiersza  ($9B)  i wiersz jest w trybie bezpośrednim, to
następuje  powrót  do  początku  procedury  SYNTAX.  Gdy wiersz
zawiera  tylko  poprawny  numer,  następuje  skok  do  etykiety
DELPLN,  gdzie  wykonywane  jest  usunięcie  wiersza  o podanym
numerze z tablicy instrukcji (zob. 2.2.1. Usuwanie wiersza).
 W przypadku nierozpoznania końca wiersza aktualna zawartość
licznika COX jest przepisywana do rejestru OUTIX (OUTput IndeX)
i  przez  wywołanie  SAVTKN  rezerwowane  jest miejsce na token
długości   instrukcji.   Kolejnym  etapem  jest  przeszukiwanie
tablicy  nazw  instrukcji  przez procedurę RECNAM. Tablica nazw
STNAME  -  oprócz  samych  nazw  -  zawiera  wektory wskazujące
położenie  w  tablicy  składni  danych  określających  wymaganą
składnię instrukcji.
 
 
0100 ;STatement NAME table    0570     .CBYTE "LET"
0110 ;                        0580     .WORD SIF-1
0120 SBYE =  $A6B9            0590     .CBYTE "IF"
0130 SCOLOR = $A6B8           0600     .WORD SFOR-1
0140 SCLOSE = $A71B           0610     .CBYTE "FOR"
0150 SDATA = $A7C6            0620     .WORD SNEXT-1
0160 SDIM =  $A75A            0630     .CBYTE "NEXT"
0170 SENTER = $A71E           0640     .WORD SCOLOR-1
0180 SFOR =  $A6CD            0650     .CBYTE "GOTO"
0190 SGET =  $A6E3            0660     .WORD SCOLOR-1
0200 SIF =   $A78F            0670     .CBYTE "GO TO"
0210 SINPUT = $A6EF           0680     .WORD SCOLOR-1
0220 SLET =  $A6BB            0690     .CBYTE "GOSUB"
0230 SLIST = $A72D            0700     .WORD SCOLOR-1
0240 SLOCAT = $A6DD           0710     .CBYTE "TRAP"
0250 SLPRNT = $A6FB           0720     .WORD SBYE-1
0260 SNEXT = $A6E5            0730     .CBYTE "BYE"
0270 SNOTE = $A744            0740     .WORD SBYE-1
0280 SON =   $A75D            0750     .CBYTE "CONT"
0290 SOPEN = $A714            0760     .WORD SDIM-1
0300 SPOKE = $A757            0770     .CBYTE "COM"
0310 SPRINT = $A6F7           0780     .WORD SCLOSE-1
0320 SPUT =  $A6B5            0790     .CBYTE "CLOSE"
0330 SREAD = $A6F0            0800     .WORD SBYE-1
0340 SREM =  $A7C3            0810     .CBYTE "CLR"
0350 SRSTR = $A6EA            0820     .WORD SBYE-1
0360 SRUN =  $A721            0830     .CBYTE "DEG"
0370 SSETC = $A755            0840     .WORD SDIM-1
0380 SSOUND = $A753           0850     .CBYTE "DIM"
0390 SSTAT = $A73B            0860     .WORD SBYE-1
0400 SXIO =  $A712            0870     .CBYTE "END"
0410 ;                        0880     .WORD SBYE-1
0420     *=  $A49F            0890     .CBYTE "NEW"
0430 ;                        0900     .WORD SOPEN-1
0440     .WORD SREM-1         0910     .CBYTE "OPEN"
0450     .CBYTE "REM"         0920     .WORD SENTER-1
0460     .WORD SDATA-1        0930     .CBYTE "LOAD"
0470     .CBYTE "DATA"        0940     .WORD SENTER-1
0480     .WORD SINPUT-1       0950     .CBYTE "SAVE"
0490     .CBYTE "INPUT"       0960     .WORD SSTAT-1
0500     .WORD SCOLOR-1       0970     .CBYTE "STATUS"
0510     .CBYTE "COLOR"       0980     .WORD SNOTE-1
0520     .WORD SLIST-1        0990     .CBYTE "NOTE"
0530     .CBYTE "LIST"        1000     .WORD SNOTE-1
0540     .WORD SENTER-1       1010     .CBYTE "POINT"
0550     .CBYTE "ENTER"       1020     .WORD SXIO-1
0560     .WORD SLET-1         1030     .CBYTE "XIO"
1040     .WORD SON-1          1300     .WORD SCOLOR-1
1050     .CBYTE "ON"          1310     .CBYTE "GRAPHICS"
1060     .WORD SPOKE-1        1320     .WORD SPOKE-1
1070     .CBYTE "POKE"        1330     .CBYTE "PLOT"
1080     .WORD SPRINT-1       1340     .WORD SPOKE-1
1090     .CBYTE "PRINT"       1350     .CBYTE "POSITION"
1100     .WORD SBYE-1         1360     .WORD SBYE-1
1110     .CBYTE "RAD"         1370     .CBYTE "DOS"
1120     .WORD SREAD-1        1380     .WORD SPOKE-1
1130     .CBYTE "READ"        1390     .CBYTE "DRAWTO"
1140     .WORD SRSTR-1        1400     .WORD SSETC-1
1150     .CBYTE "RESTORE"     1410     .CBYTE "SETCOLOR"
1160     .WORD SBYE-1         1420     .WORD SLOCAT-1
1170     .CBYTE "RETURN"      1430     .CBYTE "LOCATE"
1180     .WORD SRUN-1         1440     .WORD SSOUND-1
1190     .CBYTE "RUN"         1450     .CBYTE "SOUND"
1200     .WORD SBYE-1         1460     .WORD SLPRNT-1
1210     .CBYTE "STOP"        1470     .CBYTE "LPRINT"
1220     .WORD SBYE-1         1480     .WORD SBYE-1
1230     .CBYTE "POP"         1490     .CBYTE "CSAVE"
1240     .WORD SPRINT-1       1500     .WORD SBYE-1
1250     .CBYTE "?"           1510     .CBYTE "CLOAD"
1260     .WORD SGET-1         1520     .WORD SLET-1
1270     .CBYTE "GET"         1530     .CBYTE $00,$00
1280     .WORD SPUT-1         1540     .WORD $2A00
1290     .CBYTE "PUT"         1550 ERMSG .CBYTE "ERROR-  "
Przed   wywołaniem   procedury   RECNAM  w  akumulatorze  i
rejestrze  Y  umieszczany  jest  adres  przeszukiwanej tablicy.
Rejestr  X  zawiera  natomiast  indeks  określający, od którego
znaku  należy  porównywać  nazwę. Zwykle jest to zero, lecz dla
tablicy  nazw instrukcji indeks jest równy 2, gdyż dwa pierwsze
bajty  są  wektorem  do  tablicy  składni.  Przed  rozpoczęciem
przeszukiwania   indeks  z  rejestru  X  jest  przepisywany  do
rejestru STPTR (STack PoinTeR). 
 Procedura  RECNAM  działa  w  pętli. Najpierw adres tablicy
jest  zapisywany  do  rejestru POKADR (POKe ADdRess), a kolejny
numer  sprawdzanej  nazwy  (licząc  od  zera) do rejestru AUXBR
(AUXiliary  Basic  Register). Z tablicy odczytywany jest bajt i
jeśli  jest  równy  zero  (koniec  tablicy),  to  procedura się
kończy,  a  ustawiony  bit  Carry  sygnalizuje niepowodzenie. W
przeciwnym  wypadku  kolejne  znaki  są  odczytywane  z  bufora
wejściowego  i  porównywane  z  zawartością  tablicy.  Rezultat
porównania  jest  zapisywany na stosie. Przerwanie porównywania
znaków  następuje  po  osiągnięciu  końca  nazwy w tablicy, a w
przypadku  instrukcji  także  po  odczytaniu  z  bufora kropki.
Koniec  nazwy  jest  zawsze  oznaczony  w  tablicy  ustawieniem
najstarszego bitu w ostatnim znaku nazwy.
 
 Teraz  wynik porównania jest odczytywany ze stosu. Gdy jest
on  negatywny, pętla się powtarza. Odnalezienie nazwy w tablicy
jest   sygnalizowane  przez  skasowanie  bitu  Carry.  W  takim
przypadku po zakończeniu procedury RECNAM rejestr AUXBR zawiera
numer  kolejny  rozpoznanej nazwy, a w rejestrze X znajduje się
indeks  następnego  znaku w buforze wejściowym i po powrocie do
miejsca  wywołania  licznik  CIX  jest  uaktualniany według tej
wartości.  Przy  przeszukiwaniu  tablicy  STNAME trzeba zwrócić
uwagę  na  fakt, że jeśli nie została rozpoznana poprawna nazwa
instrukcji,  to  rejestr AUXBR zawiera wartość $36, czyli token
instrukcji  przypisania  z opuszczonym słowem LET. Każda nazwa,
inna  niż  umieszczona  w  tablicy STNAME, jest więc traktowana
jako nazwa zmiennej.
 
 
            0100 ;RECognize NAMe
            0110 ;
            0120 AUXBR = $AF
            0130 CIX =   $F2
            0140 LBUFF = $0580
            0150 POKADR = $95
            0160 STPTR = $AA
            0170 ;
            0180     *=  $A454
            0190 ;
            0200 RECNAM STX STPTR
            0210     LDX #$FF
            0220     STX AUXBR
            0230 SAV STA POKADR+1
            0240     STY POKADR
            0250     INC AUXBR
            0260     LDX CIX
            0270     LDY STRPTR
            0280     LDA (POKADR),Y
            0290     BEQ END
            0300     LDA #$00
            0310     PHP
            0320 RDC LDA LBUFF,X
            0330     AND #$7F
            0340     CMP #
            0350     BEQ CST
            0360 CHK EOR (POKADR),Y
            0370     ASL A
            0380     BEQ NXT
            0390     PLA
            0400     PHP
            0410 NXT INY
            0420     INX
            0430     BCC RDC
            0440     PLP
            0450     BEQ $A452   ;CLC,RTS
            0460 ;
            0470 ;NeXT NAMe
            0480 ;
            0490 NXTNAM CLC
            0500     TYA
            0510     ADC POKADR
            0520     TAY
            0530     LDA POKADR+1
            0540     ADC #$00
            0550     BNE SAV
            0560 END SEC
            0570     RTS
            0580 CST LDA #$02
            0590     CMP STPTR
            0600     BNE CHK
            0610 CHR LDA (POKADR),Y
            0620     BMI LST
            0630     INY
            0640     BNE CHR
            0650 LST SEC
            0660     BCS NXT
Rozkaz  AND #$7F  w  procedurze  RECNAM (wiersz 330) kasuje
najstarszy  bit  znaku  pobranego  z bufora wejściowego. Dzięki
temu  -  wbrew  rozpowszechnionym  opiniom  - interpreter Atari
Basic  rozpoznaje  wszystkie  instrukcje,  funkcje  i operatory
zapisane   w  negatywie  (inverse  video)!  Sygnalizację  błędu
powoduje  jedynie  wpisanie w negatywie stałych liczbowych oraz
nazw  zmiennych.  Przykład  ten  świadczy  o  tym,  jak  często
negatywne  opinie  o  Atari są powtarzane bez sprawdzenia stanu
faktycznego.
 Odczytany  token instrukcji jest teraz zapisywany do bufora
tokenizacji  i  wywoływana jest procedura STMSX, która sprawdza
poprawność  składniową  tej  instrukcji.  Procedura  STMSX jest
przedstawiona w rozdziale 2.2.2.
 
 Jeśli  został  stwierdzony  błąd  składni,  to miejsce jego
wystąpienia   jest  zaznaczane  ustawieniem  najstarszego  bitu
znaku,  a  jako  piąty token wiersza wpisywana jest wartość $37
(SYNTAX  ERROR).  Następnie  cała  zawartość bufora wejściowego
jest  przepisywana do bufora tokenizacji. Dodatkowo w rejestrze
SXFLG ustawiany jest bit 6, co umożliwia późniejsze rozpoznanie
błędnego wiersza.
 
 Po  stokenizowaniu  całej instrukcji aktualny stan licznika
COX   jest  zapisywany  w  miejscu  wskazanym  przez  zawartość
rejestru  OUTIX,  czyli  na  początku  instrukcji. W ten sposób
otrzymujemy   token   określający   długość  instrukcji.  Jeśli
ostatnim  odczytanym  znakiem nie był znak końca wiersza (EOL),
to  procedura  się  powtarza  od  rozpoznania  nazwy  następnej
instrukcji w wierszu. W przeciwnym razie stan licznika COX jest
wpisywany jako trzeci token, a więc jako długość wiersza.
 
 Teraz   stokenizowany   wiersz   musi   być  umieszczony  w
odpowiednim miejscu tablicy instrukcji. Odszukanie tego miejsca
jest  zadaniem  procedury  FNDCST. Przeszukuje ona całą tablicę
instrukcji,  aż do napotkania wiersza o takim samym lub wyższym
numerze.  Sygnalizuje  przy  tym  rezultat  poszukiwania  przez
ustawienie   bitu   Carry,   gdy  numery  są  różne,  lub  jego
skasowanie,  gdy  są  równe. Odpowiednio do tego w akumulatorze
jest  umieszczana  wartość  zero  lub długość wiersza odczytana
przez ponowne wywołanie procedury GLNLEN.
 
 
            0100 ;FiND Current STatement
            0110 ;
            0120 CLNN =  $A0
            0130 GLNLEN = $A9DC
            0140 NXTSTM = $A9D0
            0150 SAVCUR = $BE
            0160 STMCUR = $8A
            0170 STMTAB = $88
            0180 ;
            0190     *=  $A9A2
            0200 ;
            0210     LDA STMCUR
            0220     STA SAVCUR
            0230     LDA STMCUR+1
            0240     STA SAVCUR+1
            0250     LDA STMTAB+1
            0260     LDY STMTAB
            0270     STA STMCUR+1
            0280     STY STMCUR
            0290 LOOP LDY #$01
            0300     LDA (STMCUR),Y
            0310     CMP CLNN+1
            0320     BCC NXT
            0330     BNE END
            0340     DEY
            0350     LDA (STMCUR),Y
            0360     CMP CLNN
            0370     BCC NXT
            0380     BNE END
            0390     CLC
            0400 END RTS
            0410 NXT JSR GLNLEN
            0420     JSR NXTSTM
            0430     JMP LOOP
Przy   przeszukiwaniu   zawartości  tablicy  instrukcji  są
wykorzystywane dwie krótkie procedury GLNLEN i NXTSTM. Pierwsza
z   nich   odczytuje   token   określający   długość  aktualnie
sprawdzanego wiersza. Druga dodaje tą długość do adresu wiersza
dając w wyniku adres następnego wiersza programu.
 
            0100 ;Get LiNe LENgth
            0110 ;
            0120 STMCUR = $8A
            0130 ;
            0140     *=  $A9DC
            0150 ;
            0160     LDY #$02
            0170     LDA (STMCUR),Y
            0180     RTS
            0100 ;NeXT STateMent
            0110 ;
            0120 STMCUR = $8A
            0130 ;
            0140     *=  $A9D0
            0150 ;
            0160     CLC
            0170     ADC STMCUR
            0180     STA STMCUR
            0190     LDA STMCUR+1
            0200     ADC #$00
            0210     STA STMCUR+1
            0220     RTS
Znajdująca   się   w   akumulatorze  długość  wiersza  jest
porównywana  z  długością  nowego  wiersza określoną przez stan
licznika  COX.  Zależnie  od  różnicy długości starego i nowego
wiersza   programu   wykonywana   jest   odpowiednia  sekwencja
instrukcji.  Jeśli  nowy  wiersz  jest  dłuższy, to miejsce dla
niego  tworzone  jest  przez  wywołanie  procedury INSEL, a gdy
krótszy,  to  nadmiar  miejsca  kasuje  procedura  DELEL.  Przy
równych  długościach starego i nowego wiersza ten fragment jest
pomijany.   Po   przygotowaniu   miejsca  stokenizowany  wiersz
programu  jest  przepisywany  do  tablicy  instrukcji  z bufora
tokenizacji.
 Pozostaje   jeszcze  zakończyć  procedurę  SYNTAX.  W  celu
wybrania  odpowiedniego  wariantu  zakończenia  testowany  jest
rejestr  SXFLG.  Gdy  ma  on  ustawiony  bit  6, to oznacza, że
wpisany  wiersz  jest  niepoprawny.  W  takim  przypadku  przez
dwukrotne  wywołanie procedury DELEL usuwane są z tablic nazw i
wartości   zmiennych   informacje   wprowadzone   tam   podczas
tokenizacji   tego   wiersza.   Następnie  błędny  wiersz  jest
wyświetlany  na ekranie przez procedurę LSTPLN (wiersz w trybie
programowym) lub PRTPLN (wiersz w trybie bezpośrednim), po czym
wykonywany jest skok do początku procedury SYNTAX.
 
 Powyższa    informacja   przeczy   obiegowej   opinii,   że
interpreter  Atari  Basic  gromadzi w tablicach nazw i wartości
zmiennych  śmieci  powstałe  na  skutek  błędów przy wpisywaniu
programu.   Opinia   ta   jest   prawdziwa  TYLKO  w  przypadku
poprzedniej wersji interpretera (Revision B).
 
 Jeżeli   wiersz   jest   poprawny,  to  w  przypadku  trybu
programowego  także  następuje powrót do początku SYNTAX, zaś w
trybie  bezpośrednim  wykonywany jest skok do procedury PRCSTM,
która  powoduje  wykonanie wprowadzonego wiersza (zob. rozdział
2.2.3).
 
 2.2.1. Usuwanie wierszaUsuwanie  wiersza  z  programu  jest wykonywane przez część
procedury  SYNTAX oznaczoną etykietą DELPLN. Jej działanie jest
bardzo   proste.  Najpierw  przez  wywołanie  procedury  FNDCST
odszukiwany  jest  w  pamięci wiersz do usunięcia. Jeśli go nie
ma, to procedura jest przerywana skokiem do początku SYNTAX. Po
odnalezieniu  wiersza  odczytywana  jest  jego  długość  (przez
GLNLEN),  a następnie obliczany jest adres początkowy kolejnego
wiersza  (przez NXTSTM). Teraz wywoływana jest procedura DELEL,
która  przesuwa  znajdującą się wyżej zawartość pamięci i w ten
sposób  kasuje  wskazany  element  programu.  Procedura  DELPLN
kończy się skokiem do początku procedury SYNTAX.
 Wielokrotnie    już   wymieniana   procedura   DELEL   jest
odwrotnością   procedury   INSEL.   Przemieszcza  ona  podobnie
zawartość   obszaru   pamięci,   lecz  w  przeciwnym  kierunku.
Stosowane  są trzy sposoby wywołania procedury DELEL: od DELEL,
DELEL+1  i  DELEL+3.  W  pierwszym i drugim przypadku następuje
przemieszczenie  na  odległość nie przekraczającą jednej strony
pamięci,  gdyż  starszy bajt wielkości przemieszczenia ma wtedy
wartość  zero.  Młodszy  bajt  jest przekazywany do procedury w
akumulatorze  (przy wywołaniu od DELEL) lub w rejestrze Y (przy
wywołaniu  od  DELEL+1).  Przemieszczenie  obszaru  pamięci  na
odległość przekraczającą jedną stronę (256 bajtów) następuje po
wywołaniu  od  DELEL+3.  Akumulator musi wtedy zawierać starszy
bajt wielkości przemieszczenia, a rejestr Y młodszy bajt.
 
 
            0100 ;DELete program ELement
            0110 ;
            0120 APPMHI = $0E
            0130 BMEMHI = $90
            0140 LENPEL = $A4
            0150 MEOLFLG = $92
            0160 MRANGE = $A2
            0170 NEWMHI = $9B
            0180 OLDMHI = $99
            0190 ;
            0200     *=  $A8F7
            0210 ;
            0220     TAY
            0230     LDA #$00
            0240     STY LENPEL
            0250     STA LENPEL+1
            0260     SEC
            0270     LDA BMEMHI
            0280     SBC $00,X
            0290     EOR #$FF
            0300     TAY
            0310     INY
            0320     STY MRANGE
            0330     LDA BMEMHI+1
            0340     SBC $01,X
            0350     STA MRANGE+1
            0360     LDA $00,X
            0370     SBC MRANGE
            0380     STA OLDMHI
            0390     LDA $01,X
            0400     SBC #$00
            0410     STA OLDMHI+1
            0420     STX NEWMHI
            0430 LOOP SEC
            0440     LDA $00,X
            0450     SBC LENPEL
            0460     STA $00,X
            0470     LDA $01,X
            0480     SBC LENPEL+1
            0490     STA $01,X
            0500     INX
            0510     INX
            0520     CPX #MEOLFLG
            0530     BCC LOOP
            0540     STA APPMHI+1
            0550     LDA BMEMHI
            0560     STA APPMHI
            0570     LDX NEWMHI
            0580     LDA $00,X
            0590     SBC MRANGE
            0600     STA NEWMHI
            0610     LDA $01,X
            0620     SBC #$00
            0630     STA NEWMHI+1
            0640 ;
            0650 ;MOVe MEMory
            0660 ;
            0670 MOVMEM LDX MRANGE+1
            0680     INX
            0690     LDY MRANGE
            0700     BNE MOVE
            0710     DEX
            0720     BNE MOVE
            0730     RTS
            0740 NEXT INC OLDMHI+1
            0750     INC NEWMHI+1
            0760 MOVE LDA (OLDMHI),Y
            0770     STA (NEWMHI),Y
            0780     INY
            0790     BNE MOVE
            0800     DEX
            0810     BNE NEXT
            0820     RTS
Szczegółowy  opis  działania  procedury  DELEL jest zbędny,
gdyż  stanowi  ona  odwrotność  INSEL  i  zasada  działania obu
procedur   jest  jednakowa.  Trzeba  jednak  zwrócić  uwagę  na
etykietę  MOVMEM. Wywołanie procedury od tego miejsca umożliwia
przemieszczenie  dowolnego  obszaru  pamięci  w stronę niższych
adresów,  a  jeśli  stary  i  nowy obszar nie pokrywają się, to
także  w  stronę  wyższych  adresów. Zamiast wymyślać do swoich
programów  nowe  procedury przemieszczeń warto więc wykorzystać
już istniejący fragment interpretera.
 2.2.2. Kontrola składniPo  rozpoznaniu instrukcji wywoływana jest procedura STMSX,
która  dokonuje  kontroli składni tej instrukcji i jednocześnie
przeprowadza  jej  tokenizację.  Przed  przystąpieniem  do  tej
czynności  wektor  umieszczony  w  tabeli  STNAME  przed  nazwą
instrukcji   jest  przepisywany  do  rejestrów  PCNTC  (Program
CouNTer  Current  register)  i  BPRCNT (Basic PRogram CouNTer).
Przepisywane  są  także  stany  liczników: COX do BOUTIX (Basic
OUTput IndeX) oraz CIX do BINIX (Basic INput IndeX).
 
0100 ;STateMent SyntaX        0550     LDX #$FF
0110 ;                        0560 ADPC CLC
0120 BINIX = $0480            0570     ADC PCNTC
0130 BOUTIX = $0481           0580     PHA
0140 BPRCNT = $0482           0590     TXA
0150 BUFIX = $9F              0600     ADC PCNTC+1
0160 CIX =   $F2              0610     PHA
0170 COX =   $94              0620     JMP SAVCPM
0180 GTCCHR = $A293           0630 ;
0190 INCPRC = $A28C           0640 ;PusH ADdRess
0200 LTLGER = $B918           0650 ;
0210 PCNTC = $9D              0660 PHADR JSR STCCHR
0220 POKADR = $95             0670     PHA
0230 STIX =  $A9              0680     JSR GTCCHR
0240 VALUE = $A29B            0690     PHA
0250 ;                        0700     BCC SAVCPM
0260     *=  $A1BE            0710     PLA
0270 ;                        0720     TAY
0280 STMSX LDY #$01           0730     PLA
0290     LDA (POKADR),Y       0740     TAX
0300     STA PCNTC+1          0750     TYA
0310     STA BPRCNT+1         0760     PHA
0320     DEY                  0770     TXA
0330     LDA (POKADR),Y       0780     PHA
0340     STA PCNTC            0790 EXIT RTS
0350     STA BPRCNT           0800 ;
0360     STY STIX             0810 ;SAVe Current ParaMeters
0370     LDA COX              0820 ;
0380     STA BOUTIX           0830 SAVCPM LDX STIX
0390     LDA CIX              0840     INX
0400     STA BINIX            0850     INX
0410 CHAR JSR GTCCHR          0860     INX
0420     BMI NEG              0870     INX
0430     CMP #$01             0880     BEQ ERR
0440     BCC PHADR            0890     STX STIX
0450     BNE CVL              0900     LDA CIX
0460     JSR PHADR            0910     STA BINIX,X
0470     JMP RSM              0920     LDA COX
0480 CVL CMP #$05             0930     STA BOUTIX,X
0490     BCC GPC              0940     LDA PCNTC
0500     JSR VALUE            0950     STA BPRCNT,X
0510     JMP RSM              0960     LDA PCNTC+1
0520 NEG SEC                  0970     STA BPRCNT+1,X
0530     SBC #$C1             0980     PLA
0540     BCS ADPC             0990     STA PCNTC+1
1000     PLA                  1190     CMP #$02
1010     STA PCNTC            1200     BCS NVL
1020     JMP CHAR             1210     JSR INCPRC
1030 ERR JMP LTLGER           1220     JSR INCPRC
1040 GPC LDX STIX             1230     BNE NXT
1050     BEQ EXIT             1240 NVL CMP #$03
1060     LDA BPRCNT,X         1250     BEQ GPC
1070     STA PCNTC            1260     BCS NXT
1080     LDA BPRCNT+1,X       1270     LDA CIX
1090     STA PCNTC+1          1280     CMP BUFIX
1100     DEX                  1290     BCC GTIX
1110     DEX                  1300     STA BUFIX
1120     DEX                  1310 GTIX LDX STIX
1130     DEX                  1320     LDA BINIX,X
1140     STX STIX             1330     STA CIX
1150 RSM BCS NXT              1340     LDA BOUTIX,X
1160     JMP CHAR             1350     STA COX
1170 NXT JSR GTCCHR           1360     JMP CHAR
1180     BMI NXT
Podczas   kontroli  składni  z  tablicy  składni  SXTAB  są
odczytywane kolejne liczby, które oznaczają elementy składniowe
instrukcji.  Odczyt ten jest wykonywany przez procedurę GTCCHR.
Najpierw  zwiększa  ona  stan  licznika  PCNTC  przez wywołanie
procedury INCPRC, a następnie odczytuje wskazany przezeń kod. 
 
            0100 ;GeT Current CHaRacter
            0110 ;
            0120 INCPRC = $A28C
            0130 PCNTC = $9D
            0140 ;
            0150     *=  $A293
            0160 ;
            0170     JSR INCPRC
            0180     LDX #$00
            0190     LDA (PCNTC,X)
            0200     RTS
Procedura INCPRC jest bardzo prosta, gdyż jej zadaniem jest
jedynie  zwiększenie  stanu  dwubajtowego  licznika PCNTC. Opis
działania jest tu całkowicie zbędny.
 
            0100 ;INCrease PRogram Counter
            0110 ;
            0120 PCNTC = $9D
            0130 ;
            0140     *=  $A28C
            0150 ;
            0160     INC PCNTC
            0170     BNE END
            0180     INC PCNTC+1
            0190 END RTS
Kontrola   składni   instrukcji   jest  bardzo  złożonym  i
skomplikowanym  procesem.  Postępowanie  interpretera zależy od
kodu  odczytanego  z tabeli składni. Dla ułatwienia analizy tej
tablicy  podam  znaczenie poszczególnych kodów. Kod $00 oznacza
przepisanie  dwóch  kolejnych  bajtów  na  stos, a następnie do
licznika  PCNTC,  a więc skok w inne miejsce tablicy (w wydruku
oznaczony  jako  jsr).  Kod  $01  oznacza  wykonanie  skoku  do
procedury  o adresie zawartym w dwóch następnych bajtach (jmp).
Możliwe  odmiany składni są rozdzielone kodem $02 (or). Kod $03
sygnalizuje   koniec  fragmentu  składniowego  (end).  Kod  $0D
powoduje  opuszczenie następnego znaku z bufora (skip). Kod $0E
wskazuje,  że  w  tym miejscu wymagana jest wartość - stała lub
zmienna  (value).  Kod $0F nakazuje przepisanie następnego kodu
jako  tokena  do wprowadzanego wiersza (token). Kody większe od
$80  powodują  skoki o wartość wyrażenia kod-$C1 (adresy skoków
są  oznaczone  przez  Qnn).  Pozostałe  kody są kodami tokenów.
A oto cała tablica składni:
 
       0100 ;SyntaX TABle
       0110 ;
       0120 MOVLIN = $A2DB
       0130 NUMCNS = $A3F5
       0140 NUMVAR = $A320
       0150 SCDSTM = $A2CF
       0160 STRCNS = $A41C
       0170 STRVAR = $A324
       0180 ;
       0190     *=  $A605
       0200 ;
       0210 Q01 .BYTE $CD,$C4,$02,$C2    ; Q03 Q02 or Q02
       0220     .BYTE $03                ; end
       0230 Q02 .BYTE $2B,$BA,$2C,$DB    ; ( Q01 ) Q05
       0240     .BYTE $02,$CD,$D8,$03    ; or Q04 Q05 end
       0250 Q03 .BYTE $25,$0F,$35,$02    ; + token + or
       0260     .BYTE $26,$0F,$36,$02    ; - token - or
       0270     .BYTE $28,$03            ; NOT end
       0280 Q04 .BYTE $FE,$02,$E8,$02    ; Q08 or L1 or
       0290     .BYTE $01                ; jmp
       0300     .WORD NUMCNS-1
       0310     .BYTE $02,$00            ; or jsr
       0320     .WORD L3-1
       0330     .BYTE $03                ; end
       0340 Q05 .BYTE $C4,$9C,$02,$03    ; Q06 Q01 or end
       0350 Q06 .BYTE $23,$02,$25,$02    ; ^ or + or
       0360     .BYTE $26,$02,$24,$02    ; - or * or
       0370     .BYTE $27,$02,$1D,$02    ; / or <= or
       0380     .BYTE $1F,$02,$1E,$02    ; >= or <> or
       0390     .BYTE $20,$02,$21,$02    ; < or > or
       0400     .BYTE $22,$02,$2A,$02    ; = or AND or
       0410     .BYTE $29,$03            ; OR end
       0420 L1  .BYTE $01                ; jmp
       0430     .WORD NUMVAR-1
       0440     .BYTE $C2,$03            ; Q07 end
       0450 Q07 .BYTE $0D,$2B,$0F,$38    ; skip ( token ixv
       0460     .BYTE $0E,$C4,$2C,$02    ; value L2 ) or
       0470     .BYTE $03                ; end
       0480 L2  .BYTE $12,$0F,$3C,$0E    ; , token , value
       0490     .BYTE $02,$03            ; or end
       0500 Q08 .BYTE $44,$D2,$02,$00    ; ATN Q10 or jsr
       0510     .WORD L7-1
       0520     .BYTE $D3,$02,$C2,$03    ; Q11 or Q09 end
       0530 Q09 .BYTE $3F,$2B,$0F,$3A    ; USR ( token (
       0540     .BYTE $00                ; jsr
       0550     .WORD L9-1
       0560     .BYTE $2C,$03            ; ) end
       0570 Q10 .BYTE $2B,$0F,$3A,$0E    ; ( token ( value
       0580     .BYTE $2C,$03            ; ) end
       0590 Q11 .BYTE $2B,$0F,$3A,$C7    ; ( token ( L4
       0600     .BYTE $2C,$03            ; ) end
       0610 L3  .BYTE $C4,$E3,$C2,$03    ; L4 Q16 L4 end
       0620 L4  .BYTE $C8,$02,$CB,$02    ; Q12 or Q13 or
       0630     .BYTE $01                ; jmp
       0640     .WORD STRCNS-1
       0650     .BYTE $03                ; end
       0660 Q12 .BYTE $00                ; jsr
       0670     .WORD L8-1
       0680     .BYTE $A5,$03            ; Q10 end
       0690 Q13 .BYTE $01                ; jmp
       0700     .WORD STRVAR-1
       0710     .BYTE $C2,$03            ; Q14 end
       0720 Q14 .BYTE $2B,$0F,$37,$0E    ; ( token ( value
       0730     .BYTE $C4,$2C,$02,$03    ; Q15 ) or end
       0740 Q15 .BYTE $12,$0F,$3C,$0E    ; , token , value
       0750     .BYTE $02,$03            ; or end
       0760 Q16 .BYTE $1D,$0F,$2F,$02    ; <= token <= or
       0770     .BYTE $1E,$0F,$30,$02    ; <> token <> or
       0780     .BYTE $1F,$0F,$31,$02    ; >= token >= or
       0790     .BYTE $20,$0F,$32,$02    ; < token < or
       0800     .BYTE $21,$0F,$33,$02    ; > token > or
       0810     .BYTE $22,$0F,$34,$03    ; = token = end
       0820 SPUT .BYTE $1C,$0E,$12       ; # value ,
       0830 SCOLOR .BYTE $0E             ; value
       0840 SBYE .BYTE $FA,$03           ; Q18 end
       0850 SLET .BYTE $00               ; jsr
       0860     .WORD L1-1
       0870     .BYTE $22,$0F,$2D,$0E    ; = token = value
       0880     .BYTE $F1,$02,$86,$22    ; Q18 or Q13 =
       0890     .BYTE $0F,$2E,$00        ; token = jsr
       0900     .WORD L4-1
       0910     .BYTE $E8,$03            ; Q18 end
       0920 SFOR .BYTE $01               ; jmp
       0930     .WORD NUMVAR-1
       0940     .BYTE $22,$0F,$2D,$0E    ; = token = value
       0950     .BYTE $19,$0E,$C3,$DC    ; TO value Q17 Q18
       0960     .BYTE $03                ; end
       0970 Q17 .BYTE $1A,$0E,$02,$03    ; STEP value or end
       0980 SLOCAT .BYTE $0E,$12,$0E     ; value , value
       0990     .BYTE $12,$C4,$03        ; , SNEXT end
       1000 SGET .BYTE $DD,$12           ; Q19 ,
       1010 SNEXT .BYTE $01              ; jmp
       1020     .WORD NUMVAR-1
       1030     .BYTE $CB,$03            ; Q18 end
       1040 SRSTR .BYTE $0E,$C8,$02,$C6  ; value Q18 or Q18
       1050     .BYTE $03                ; end
       1060 SINPUT .BYTE $F7             ; Q23
       1070 SREAD .BYTE $DB,$C2,$03      ; Q21 Q18 end
       1080 Q18 .BYTE $14,$02,$16,$03    ; : or EOL end
       1090 SPRINT .BYTE $C9,$BB,$02,$EC ; Q19 Q18 or Q23
       1100 SLPRNT .BYTE $00             ; jsr
       1110     .WORD L5-1
       1120     .BYTE $B5,$03            ; Q18 end
       1130 Q19 .BYTE $1C,$0E,$03        ; # value end
       1140 Q20 .BYTE $01                ; jmp
       1150     .WORD NUMVAR-1
       1160     .BYTE $02,$01            ; or jmp
       1170     .WORD STRVAR-1
       1180     .BYTE $03                ; end
       1190 Q21 .BYTE $B8,$C2,$03        ; Q20 Q22 end
       1200 Q22 .BYTE $12,$BC,$02,$03    ; , Q21 or end
       1210 SXIO .BYTE $0E,$12           ; value ,
       1220 SOPEN .BYTE $AC,$12,$F9,$12  ; Q19 , Q27 ,
       1230     .BYTE $F3,$9A,$03        ; Q26 Q18 end
       1240 SCLOSE .BYTE $A5,$97,$03     ; Q19 Q18 end
       1250 SENTER .BYTE $ED,$94,$03     ; Q26 Q18 end
       1260 SRUN .BYTE $EA,$91,$02,$8F   ; Q26 Q18 or Q18
       1270     .BYTE $03                ; end
       1280 Q23 .BYTE $9A,$12,$02,$97    ; Q19 , or Q19
       1290     .BYTE $15,$02,$03        ; ; or end
       1300 SLIST .BYTE $DE,$85,$02      ; Q26 Q18 or
       1310     .BYTE $DB,$12,$C4,$02    ; Q26 , Q24 or
       1320     .BYTE $C2,$03            ; Q24 end
       1330 Q24 .BYTE $00                ; jsr
       1340     .WORD L6-1
       1350     .BYTE $F4,$03            ; Q31 end
       1360 SSTAT .BYTE $C3,$F1,$03      ; Q25 Q31 end
       1370 Q25 .BYTE $82,$12,$00        ; Q19 , jsr
       1380     .WORD L1-1
       1390     .BYTE $03                ; end
       1400 SNOTE .BYTE $BA,$12,$00      ; Q25 , jsr
       1410     .WORD L1-1
       1420     .BYTE $E4,$03            ; Q31 end
       1430 Q26 .BYTE $00                ; jsr
       1440     .WORD L4-1
       1450     .BYTE $03                ; end
       1460 Q27 .BYTE $0E,$12,$0E,$03    ; value , value end
       1470 SSOUND .BYTE $0E,$12         ; value ,
       1480 SSETC .BYTE $0E,$12          ; value ,
       1490 SPOKE .BYTE $B8,$D5,$03      ; Q27 Q31 end
       1500 SDIM .BYTE $ED,$D2,$03       ; Q33 Q31 end
       1510 SON .BYTE $0E,$C4,$C7        ; value Q28 Q29
       1520     .BYTE $CD,$03            ; Q31 end
       1530 Q28 .BYTE $17,$02,$18,$03    ; GOTO or GOSUB end
       1540 Q29 .BYTE $0E,$C2,$03        ; value Q30 end
       1550 Q30 .BYTE $12,$BC,$02,$03    ; , Q29 or end
       1560 Q31 .BYTE $14,$02,$16,$03    ; : or EOL end
       1570 Q32 .BYTE $01                ; jmp
       1580     .WORD NUMVAR-1
       1590     .BYTE $0D,$2B,$0F,$39    ; skip ( token dixv
       1600     .BYTE $0E,$00            ; value jsr
       1610     .WORD L2-1
       1620     .BYTE $2C,$02,$01        ; ) or jmp
       1630     .WORD STRVAR-1
       1640     .BYTE $2B,$0F,$3B,$0E    ; ( token ( value
       1650     .BYTE $2C,$03            ; ) end
       1660 Q33 .BYTE $AA,$C3,$02,$03    ; Q32 Q34 or end
       1670 Q34 .BYTE $12,$BB,$02,$03    ; , Q33 or end
       1680 SIF .BYTE $0E,$1B,$C3,$9B    ; value THEN Q35 Q31
       1690     .BYTE $03                ; end
       1700 Q35 .BYTE $01                ; jmp
       1710     .WORD NUMCNS-1
       1720     .BYTE $02,$01            ; or jmp
       1730     .WORD SCDSTM-1
       1740 L5  .BYTE $C9,$02,$D4,$C3    ; Q37 or Q39 Q36
       1750     .BYTE $02,$03            ; or end
       1760 Q36 .BYTE $C3,$02,$03        ; Q37 or end
       1770 Q37 .BYTE $C3,$C8,$03        ; Q38 or end
       1780 Q38 .BYTE $0E,$02,$00        ; value or jsr
       1790     .WORD L4-1
       1800     .BYTE $03                ; end
       1810     .BYTE $C4,$B3,$02,$03    ; Q39 Q36 or end
       1820 Q39 .BYTE $C6,$C2,$03        ; Q41 Q40 end
       1830 Q40 .BYTE $BD,$02,$03        ; Q39 or end
       1840 Q41 .BYTE $12,$02,$15,$03    ; , or ; end
       1850 L6  .BYTE $0E                ; value
       1860     .BYTE $C3,$02,$03        ; Q42 or end
       1870 Q42 .BYTE $12,$0E,$02,$03    ; , value or end
       1880 SREM .BYTE $01               ; jmp
       1890     .WORD MOVLIN-1
       1900 SDATA .BYTE $01              ; jmp
       1910     .WORD MOVLIN-1
       1920 L7  .BYTE $40,$02,$41,$02    ; ASC or VAL or
       1930     .BYTE $43,$02,$42,$03    ; ADR or LEN end
       1940 L8  .BYTE $3D,$02,$3E,$03    ; STR$ or CHR$ end
       1950 L9  .BYTE $0E,$C2,$03        ; value Q43 end
       1960 Q43 .BYTE $12,$0F,$3C,$BA    ; , token , L9
       1970     .BYTE $02,$03            ; or end
W   trakcie   kontroli   składni  wywoływane  są  dodatkowe
procedury   pomagające   w   tokenizacji   elementów  programu.
Najprostszą   z  nich  jest  procedura  MOVLIN,  wywoływana  po
rozpoznaniu  tokenu  instrukcji  REM  lub  DATA.  Po ustawieniu
wszystkich  bitów statusu wykonuje ona skok do etykiety MOVTKN,
co powoduje przepisanie bez zmian pozostałej części wiersza.
 
            0100 ;MOVe LINe
            0110 ;
            0120 MOVTKN = $A0FB
            0130 ;
            0140     *=  $A2DB
            0150 ;
            0160     LDX #$FF
            0170     TXS
            0180     JMP MOVTKN
Równie  prosta  procedura  jest  wywoływana  po rozpoznaniu
instrukcji IF nie zakończonej numerem wiersza. Procedura SCDSTM
zapisuje  w  stokenizowanym  wierszu  długość  instrukcji IF, a
następnie  przechodzi  do  rozpoznawania  następnych instrukcji
znajdujących się w tym samym wierszu.
 
            0100 ;Start of ConDitional STateMent
            0110 ;
            0120 COX =   $94
            0130 DCDSTM = $A0B1
            0140 LOMEM = $80
            0150 OUTIX = $A7
            0160 ;
            0170     *=  $A2CF
            0180 ;
            0190     LDX #$FF
            0200     TXS
            0210     LDA COX
            0220     LDY OUTIX
            0230     STA (LOMEM),Y
            0240     JMP DCDSTM
Jeśli  spodziewana  jest stała liczbowa, to wywoływana jest
procedura  NUMCNS.  Najpierw zamienia ona przy pomocy procedury
AFP ciąg znaków ASCII na liczbę zmiennoprzecinkową. W przypadku
niepowodzenia  ustawiany jest bit Carry i procedura się kończy.
Poprawny  wynik  zamiany  powoduje  wpisanie  tokena $0E, który
oznacza stałą liczbową, oraz przepisanie sześciu bajtów liczby.
W  tym  przypadku  przed  opuszczeniem procedury bit Carry jest
kasowany.
 
            0100 ;NUMber CoNStant
            0110 ;
            0120 AFP =   $D800
            0130 CIX =   $F2
            0140 COX =   $94
            0150 FR0 =   $D4
            0160 INBSS = $DBA1
            0170 LOMEM = $80
            0180 SAVTKN = $A2C4
            0190 TIX =   $AC
            0200 ;
            0210     *=  $A3F5
            0220 ;
            0230     JSR INBSS
            0240     LDA CIX
            0250     STA TIX
            0260     JSR AFP
            0270     BCC SUCC
            0280     LDA TIX
            0290     STA CIX
            0300     RTS
            0310 SUCC LDA #$0E
            0320     JSR SAVTKN
            0330     INY
            0340     LDX #$00
            0350 LOOP LDA FR0,X
            0360     STA (LOMEM),Y
            0370     INY
            0380     INX
            0390     CPX #$06
            0400     BCC LOOP
            0410     STY COX
            0420     CLC
            0430     RTS
Zbliżone   jest   postępowanie   przy   tokenizacji  stałej
tekstowej.  Wykonuje  to  procedura STRCNS. Najpierw sprawdzany
jest  pierwszy  znak stałej, i jeśli nie jest to cudzysłów ("),
procedura   jest   przerywana   z  ustawionym  bitem  Carry.  W
przeciwnym  wypadku zapisywany jest token stałej tekstowej $0F,
po  czym  kolejne znaki z bufora wejściowego są przepisywane do
bufora  tokenizacji,  aż  do napotkania drugiego cudzysłowu lub
końca  wiersza.  Po  zapisaniu długości stałej procedura kończy
się ze skasowanym bitem Carry.
 
            0100 ;STRing CoNStant
            0110 ;
            0120 CIX =   $F2
            0130 COX =   $94
            0140 INBSS = $DBA1
            0150 INBUFP = $F3
            0160 LOMEM = $80
            0170 SAVTKN = $A2C4
            0180 TOX =   $AB
            0190 ;
            0200     *=  $A41C
            0210 ;
            0220     JSR INBSS
            0230     LDY CIX
            0240     LDA (INBUFP),Y
            0250     CMP #'"
            0260     BNE $A3F3   ;SEC,RTS
            0270     LDA #$0F
            0280     JSR SAVTKN
            0290     LDA COX
            0300     STA TOX
            0310     JSR SAVTKN
            0320 LOOP INC CIX
            0330     LDY CIX
            0340     LDA (INBUFP),Y
            0350     CMP #$9B
            0360     BEQ END
            0370     CMP #'"
            0380     BEQ NXT
            0390     JSR SAVTKN
            0400     JMP LOOP
            0410 NXT INC CIX
            0420 END CLC
            0430     LDA COX
            0440     SBC TOX
            0450     LDY TOX
            0460     STA (LOMEM),Y
            0470     CLC
            0480     RTS
Jeżeli  interpreter  oczekuje nazwy zmiennej, to wywoływana
jest  procedura  odpowiednia  do  typu  zmiennej.  Dla zmiennej
liczbowej  jest  to procedura NUMVAR, zaś dla tekstowej STRVAR.
Przebieg  obu  procedur  jest  wspólny  poza początkową fazą, w
której  zapisywany  jest  w  rejestrze VART (VARiable Type) typ
zmiennej ($00 - liczbowa, $80 - tekstowa).
 
            0100 ADBT =  $DBAF
            0110 AUXBR = $AF
            0120 BHLD1 = $B0
            0130 BHLD2 = $B1
            0140 CIX =   $F2
            0150 CMPLTR = $A3E8
            0160 CSTAD = $97
            0170 EXPSX = $A2E1
            0180 INBSS = $DBA1
            0190 INBUFP = $F3
            0200 INSEL = $A87A
            0210 LBUFF = $0580
            0220 NXTNAM = $A482
            0230 RECNAM = $A454
            0240 SAVTKN = $A2C4
            0250 STMNUM = $B2
            0260 STMTAB = $88
            0270 TIX =   $AC
            0280 TMVRER = $B92C
            0290 VARN =  $D3
            0300 VART =  $D2
            0310 VNTD =  $84
            0320 VNTP =  $82
            0330 ;
            0340     *=  $A320
            0350 ;
            0360 ;NUMber VARiable
            0370 ;
            0380 NUMVAR LDA #$00
            0390     BEQ EXE
            0400 ;
            0410 ;STRing VARiable
            0420 ;
            0430 STRVAR LDA #$80
            0440 EXE STA VART
            0450     JSR INBSS
            0460     LDA CIX
            0470     STA TIX
            0480     JSR CMPLTR
            0490     BCS BAD
            0500     JSR EXPSX
            0510     LDA BHLD1
            0520     BEQ CCR
            0530     LDY STMNUM
            0540     LDA (INBUFP),Y
            0550     CMP #'0
            0560     BCC BAD
            0570 CCR INC CIX
            0580     JSR CMPLTR
            0590     BCC CCR
            0600     JSR ADBT
            0610     BCC CCR
            0620     LDA (INBUFP),Y
            0630     CMP #'$
            0640     BEQ STR
            0650     BIT VART
            0660     BPL DIM
            0670 BAD SEC
            0680     RTS
            0690 STR BIT VART
            0700     BPL BAD
            0710     INY
            0720     BNE FND
            0730 DIM LDA (INBUFP),Y
            0740     CMP #'(
            0750     BNE FND
            0760     INY
            0770     LDA #$40
            0780     ORA VART
            0790     STA VART
            0800 FND LDA TIX
            0810     STA CIX
            0820     STY TIX
            0830     LDA VNTP+1
            0840     LDY VNTP
            0850     LDX #$00
            0860     JSR RECNAM
            0870 NXT BCS NEW
            0880     CPX TIX
            0890     BEQ SAV
            0900     JSR NXTNAM
            0910     JMP NXT
            0920 NEW SEC
            0930     LDA TIX
            0940     SBC CIX
            0950     STA CIX
            0960     TAY
            0970     LDX #VNTD
            0980     JSR INSEL
            0990     LDA AUXBR
            1000     STA VARN
            1010     LDY CIX
            1020     DEY
            1030     LDX TIX
            1040     DEX
            1050 PUT LDA LBUFF,X
            1060     STA (CSTAD),Y
            1070     DEX
            1080     DEY
            1090     BPL PUT
            1100     LDY CIX
            1110     DEY
            1120     LDA (CSTAD),Y
            1130     ORA #$80
            1140     STA (CSTAD),Y
            1150     LDY #$08
            1160     LDX #STMTAB
            1170     JSR INSEL
            1180     INC BHLD2
            1190     LDY #$02
            1200     LDA #$00
            1210 RST STA VART,Y
            1220     INY
            1230     CPY #$08
            1240     BCC RST
            1250     DEY
            1260 GET LDA VART,Y
            1270     STA (CSTAD),Y
            1280     DEY
            1290     BPL GET
            1300 SAV BIT VART
            1310     BVC BPS
            1320     DEC TIX
            1330 BPS LDA TIX
            1340     STA CIX
            1350     LDA AUXBR
            1360     BMI ERR
            1370     ORA #$80
            1380     CLC
            1390     JMP SAVTKN
            1400 ERR JMP TMVRER
Rozpoznawanie   zmiennej   rozpoczyna  się  od  sprawdzenia
poprawności  jej  zapisu.  Najpierw  pierwszy  znak  nazwy jest
kontrolowany  przy  pomocy  procedury CMPLTR. Jeśli nie jest on
literą,  to  sygnalizowany jest błąd. Następnie wywoływana jest
procedura  EXPSX,  która przeszukuje tablicę nazw funkcji OPFN.
Gdy  badana nazwa nie występuje w tej tablicy, to sprawdzane są
jej kolejne znaki, aż do napotkania znaku innego niż litera lub
cyfra.  Jeżeli znakiem tym jest dolar ($), to rejestr VART musi
zawierać wartość $80. Wystąpienie błędu podczas wyżej opisanych
czynności   jest   sygnalizowane   ustawieniem   bitu  Carry  i
przerwaniem procedury.
 Teraz  sprawdzany jest pierwszy znak następujący po nazwie.
Jeśli  jest  to  nawias,  ustawiany jest bit 6 w rejestrze VART
(wymiar  lub indeks zmiennej tablicowej). Ponieważ zmienna może
się  już znajdować w tablicy nazw zmiennych, to teraz procedura
RECNAM przeszukuje tą tablicę. W rezultacie tego przeszukania w
rejestrze  AUXBR  znajduje  się numer zmiennej (gdy zmienna nie
została  znaleziona,  jest  to liczba o jeden większa od numeru
ostatniej  zmiennej  w  tablicy).  Nowa  zmienna jest następnie
wpisywana  do  tablicy nazw i tablicy wartości. W tym celu jest
wykorzystywana opisana już procedura INSEL. Jeżeli zmienna jest
już w tablicy, to ten fragment jest pomijany.
 
 Na  samym  końcu  procedury kontrolowany jest jeszcze numer
zmiennej.   Gdy   jest  on  większy  od  $7F  (więcej  niż  128
zmiennych),   to   wykonywany   jest  skok  do  TMVRER  w  celu
zasygnalizowania  błędu  (Too  Many  VaRiables ERror). Poprawny
numer  zmiennej  jest zwiększany o $80 i przez wywołanie SAVTKN
zapisywany w buforze tokenizacji.
 
 Do  sprawdzenia  znaku pobranego z bufora wejściowego służy
procedura  CMPLTR.  Odczytuje  ona znak i sprawdza, czy jest on
literą  z zakresu A-Z. Przy wywołaniu tej procedury od etykiety
CHKLTR sprawdzeniu jest poddawany znak zawarty w akumulatorze.
 
 
            0100 ;CoMPare for LeTteR
            0110 ;
            0120 CIX =   $F2
            0130 INBUFP = $F3
            0140 ;
            0150     *=  $A3E8
            0160 ;
            0170 CMPLTR LDY CIX
            0180     LDA (INBUFP),Y
            0190 ;
            0200 ;CHecK for LeTteR
            0210 ;
            0220 CHKLTR CMP #'A
            0230     BCC ERR
            0240     CMP #'[
            0250     RTS
            0260 ERR SEC
            0270     RTS
Kolejną  procedurą  wykorzystywaną podczas kontroli składni
jest VALUE. Wywoływana jest ona po napotkaniu kodu większego od
$04  i  mniejszego  od $80. Jeżeli jest to kod $0F, to następny
znak  z tablicy składni jest przepisywany do bufora tokenizacji
i  procedura  się kończy. Gdy kodem tym jest $0E, to znajdujący
się  na  stosie  adres  jest  zastępowany  adresem  początkowym
tablicy  SXTAB.  W pozostałych przypadkach wykonywany jest skok
do  procedury  EXPSX,  przy  czym  kod  $0D powoduje pominięcie
jednego znaku z bufora wejściowego.
 
            0100 ;VALUE
            0110 ;
            0120 COX =   $94
            0130 EXPSX = $A2E1
            0140 INCPRC = $A28C
            0150 LOMEM = $80
            0160 PCNTC = $9D
            0170 SAVCPM = $A21B
            0180 SXTAB = $A605
            0190 ;
            0200     *=  $A29B
            0210 ;
            0220     CMP #$0F
            0230     BEQ SAV
            0240     BCS EXPSX
            0250     CMP #$0D
            0260     BNE CSX
            0270     JSR INCPRC
            0280     JMP EXPSX+3
            0290 CSX PLA
            0300     PLA
            0310     LDA # <SXTAB-1
            0320     PHA
            0330     LDA # >SXTAB-1
            0340     PHA
            0350     JMP SAVCPM
            0360 SAV JSR INCPRC
            0370     LDY #$00
            0380     LDA (PCNTC),Y
            0390     LDY COX
            0400     DEY
            0410     STA (LOMEM),Y
            0420     CLC
            0430     RTS
Nazwy wszystkich legalnych operatorów i funkcji Atari Basic
są  zapisane  w tablicy OPFN. Jest ona zbliżona do tablicy nazw
instrukcji,  lecz  nie  zawiera  wektorów  do  tablicy składni.
Niektóre  znajdujące  się  w niej operatory dotyczące zmiennych
różnych    typów   są   powtórzone.   Umożliwia   to   wybranie
odpowiedniego wariantu procedury przy realizacji programu.
 
            0100 ;OPerator & Function Names
            0110 ;
            0120     *=  $A7DE
            0130 ;
            0140     .CBYTE $02
            0150     .CBYTE $00
            0160     .CBYTE ","
            0170     .CBYTE "$"
            0180     .CBYTE ":"
            0190     .CBYTE ";"
            0200     .BYTE $9B      ;EOL
            0210     .CBYTE "GOTO"
            0220     .CBYTE "GOSUB"
            0230     .CBYTE "TO"
            0240     .CBYTE "STEP"
            0250     .CBYTE "THEN"
            0260     .CBYTE "#"
            0270     .CBYTE "<="    ;
            0280     .CBYTE "<>"    ;
            0290     .CBYTE ">="    ;operatory
            0300     .CBYTE "<"     ;liczbowe
            0310     .CBYTE ">"     ;
            0320     .CBYTE "="     ;
            0330     .CBYTE "^"
            0340     .CBYTE "*"
            0350     .CBYTE "+"
            0360     .CBYTE "-"
            0370     .CBYTE "/"
            0380     .CBYTE "NOT"
            0390     .CBYTE "OR"
            0400     .CBYTE "AND"
            0410     .CBYTE "("     ;nawiasy
            0420     .CBYTE ")"     ;zwykłe
            0430     .CBYTE "="     ;LET liczbowe
            0440     .CBYTE "="     ;LET tekstowe
            0450     .CBYTE "<="    ;
            0460     .CBYTE "<>"    ;
            0470     .CBYTE ">="    ;operatory
            0480     .CBYTE "<"     ;tekstowe
            0490     .CBYTE ">"     ;
            0500     .CBYTE "="     ;
            0510     .CBYTE "+"     ;znak
            0520     .CBYTE "-"     ;znak
            0530     .CBYTE "("     ;wyr. tekstowe
            0540     .CBYTE $00     ;zm. indeks.
            0550     .CBYTE $00     ;wym. zm. ind.
            0560     .CBYTE "("     ;wyr. funkc.
            0570     .CBYTE "("     ;wym. zm. tekst.
            0580     .CBYTE ","     ;w indeksie zm.
            0590     .CBYTE "STR$"
            0600     .CBYTE "CHR$"
            0610     .CBYTE "USR"
            0620     .CBYTE "ASC"
            0630     .CBYTE "VAL"
            0640     .CBYTE "LEN"
            0650     .CBYTE "ADR"
            0660     .CBYTE "ATN"
            0670     .CBYTE "COS"
            0680     .CBYTE "PEEK"
            0690     .CBYTE "SIN"
            0700     .CBYTE "RND"
            0710     .CBYTE "FRE"
            0720     .CBYTE "EXP"
            0730     .CBYTE "LOG"
            0740     .CBYTE "CLOG"
            0750     .CBYTE "SQR"
            0760     .CBYTE "SGN"
            0770     .CBYTE "ABS"
            0780     .CBYTE "INT"
            0790     .CBYTE "PADDLE"
            0800     .CBYTE "STICK"
            0810     .CBYTE "PTRIG"
            0820     .CBYTE "STRIG"
            0830     .BYTE $00
Powyższa  tablica jest przeszukiwana przez procedurę EXPSX,
która   służy   do  kontroli  składni  wyrażeń  arytmetycznych,
logicznych i tekstowych. Znaleziony numer operatora lub funkcji
zapisywany  jest  do  bufora  tokenizacji.  Poprawny  wynik tej
operacji jest sygnalizowany skasowaniem bitu Carry.
 
            0100 ;EXPression SyntaX
            0110 ;
            0120 AUXBR = $AF
            0130 BHLD1 = $B0
            0140 CIX =   $F2
            0150 INBSS = $DBA1
            0160 OPFN =  $A7DE
            0170 PCNTC = $9D
            0180 RECNAM = $A454
            0190 SAVTKN = $A2C4
            0200 STMNUM = $B2
            0210 TMPIX = $B3
            0220 ;
            0230     *=  $A2E1
            0240 ;
            0250     JSR INBSS
            0260     LDA CIX
            0270     CMP TMPIX
            0280     BEQ CHK
            0290     STA TMPIX
            0300     LDA # >OPFN
            0310     LDY # <OPFN
            0320     LDX #$00
            0330     JSR RECNAM
            0340     BCS NFD
            0350     STX STMNUM
            0360     LDA AUXBR
            0370     ADC #$10
            0380     STA BHLD1
            0390 CHK LDY #$00
            0400     LDA (PCNTC),Y
            0410     CMP BHLD1
            0420     BEQ SAV
            0430     CMP #$44
            0440     BNE ERR
            0450     LDA BHLD1
            0460     CMP #$44
            0470     BCC ERR
            0480 SAV JSR SAVTKN
            0490     LDX STMNUM
            0500     STX CIX
            0510     CLC
            0520     RTS
            0530 NFD LDA #$00
            0540     STA BHLD1
            0550 ERR SEC
            0560     RTS
2.2.3. Wykonanie instrukcjiJeżeli  wprowadzony  wiersz  jest w trybie bezpośrednim, to
procedura  SYNTAX  kończy  się  skokiem do PRCSTM. Jej zadaniem
jest   w   tym   wypadku   wykonanie  instrukcji  zawartych  we
wprowadzonym  wierszu. Procedura ta jest także wywoływana przez
XRUN  w  celu  wykonania  programu  znajdującego  się w pamięci
komputera.
 
            0100 ;PRoCeed STateMent
            0110 ;
            0120 BUFIX = $9F
            0130 EXESTM = $A97E
            0140 GHISTM = $A9E1
            0150 GIRQST = $A9F2
            0160 GSTMLN = $B819
            0170 INIX =  $A8
            0180 NXTSTM = $A9D0
            0190 OUTIX = $A7
            0200 STMCUR = $8A
            0210 WAITIN = $A05D
            0220 XEND =  $B78C
            0230 XSTOP = $B792
            0240 ;
            0250     *=  $A95E
            0260 ;
            0270 PRCSTM JSR GSTMLN
            0280 STAT JSR GIRQST
            0290     BEQ STOP
            0300     LDY OUTIX
            0310     CPY BUFIX
            0320     BCS NEXT
            0330     LDA (STMCUR),Y
            0340     STA OUTIX
            0350     TYA
            0360     INY
            0370     LDA (STMCUR),Y
            0380     INY
            0390     STY INIX
            0400     JSR EXESTM
            0410     NOP
            0420     JMP STAT
            0430 ;
            0440     *=  $A989
            0450 ;
            0460 NEXT LDY #$01
            0470     LDA (STMCUR),Y
            0480     BMI WAIT
            0490     LDA BUFIX
            0500     JSR NXTSTM
            0510     JSR GHISTM
            0520     BPL PRCSTM
            0530     JMP XEND
            0540 STOP JMP XSTOP
            0550 WAIT JMP WAITIN
Pierwszą  czynnością  jest odczytanie długości wykonywanego
wiersza.   Uzyskana   wartość  służy  do  zliczania  tokenów  i
umożliwia  zakończenie  realizacji  wiersza po osiągnięciu jego
końca.   Odczyt  długości  wiersza  następuje  przez  wywołanie
procedury GSTMLN. Przy pomocy wektora STMCUR (STateMent CURrent
address) trzeci token, którego wartość określa długość wiersza,
jest  pobierany  z  tabeli  instrukcji i zapisywany do licznika
BUFIX  (BUFfer IndeX). Indeks następnego tokena jest zapisywany
w liczniku OUTIX.
 
            0100 BUFIX = $9F
            0110 FNDCST = $A9A2
            0120 OUTIX = $A7
            0130 STMCUR = $8A
            0140 ;
            0150     *=  $B816
            0160 ;
            0170 ;Find STatement & Get LeNgth
            0180 ;
            0190 FSTGLN JSR FNDCST
            0200 ;
            0210 ;Get STateMent LeNgth
            0220 ;
            0230 GSTMLN LDY #$02
            0240     LDA (STMCUR),Y
            0250     STA BUFIX
            0260     INY
            0270     STY OUTIX
            0280     RTS
Następnie  sprawdzany  jest  przez procedurę GIRQST rejestr
statusu  przerwań.  Jeśli  sygnalizuje  on naciśnięcie klawisza
BREAK,  to  wykonywanie  wiersza  jest  przerywane  skokiem  do
procedury   XSTOP.   Naciśnięcie  BREAK  jest  więc  równoważne
umieszczeniu  w  wierszu  instrukcji STOP. Teraz porównywane są
zawartości  liczników  BUFIX  i  OUTIX.  Gdy  są  one różne, to
wykonywanie wiersza jest kontynuowane. Następny odczytany token
oznacza  długość  instrukcji, a właściwie indeks jej ostatniego
tokena.  Jest  on  zapisywany  do  licznika  OUTIX.  Z kolei do
akumulatora   pobierany   jest   token   instrukcji,  a  indeks
następnego  tokena do odczytu jest umieszczany w rejestrze INIX
(INput  IndeX).  Odpowiednia  procedura realizacyjna instrukcji
jest  wywoływana przez procedurę EXESTM i pętla się powtarza od
sprawdzenia klawisza BREAK.
 
 Zrównanie   zawartości  rejestrów  BUFIX  i  OUTIX  oznacza
zakończenie  wykonywania całego wiersza. Jeżeli był to wiersz w
trybie bezpośrednim, to wykonywany jest skok do etykiety WAITIN
i komputer oczekuje na następne polecenia. W trybie programowym
poprzez   wywołanie   procedury  NXTSTM  przepisywany  jest  do
rejestru  STMCUR  adres  kolejnego  wiersza.  Starszy bajt tego
wiersza  jest  odczytywany  przez procedurę GHISTM. Wartość $80
sygnalizuje,  że  następny wiersz jest w trybie bezpośrednim, a
więc  cały  program  został  już  wykonany.  W  takim przypadku
wykonywany  jest  skok  do  procedury  XEND, jeśli zaś następny
wiersz  programu znajduje się w pamięci, to ponownie wykonywana
jest procedura PRCSTM.
 
 
            0100 ;Get HIgh byte of STateMent
            0110 ;
            0120 STMCUR = $8A
            0130 ;
            0140     *=  $A9E1
            0150 ;
            0160 GHISTM LDY #$01
            0170     LDA (STMCUR),Y
            0180 ;
            0190 ;eXecute REM statement
            0200 ;
            0210 XREM RTS
Właściwe wywołanie procedury realizującej żądaną instrukcję
jest  przeprowadzane  przez  procedurę  EXESTM  według wartości
tokenu  przekazanej  w akumulatorze. Zastosowano tu popularny w
systemie  Atari  sposób:  adres  procedury  jest umieszczany na
stosie,  po czym wykonywany jest rozkaz RTS. Powrót z procedury
wykonawczej następuje do miejsca wywołania EXESTM.
 
            0100 ;EXEcute STateMent
            0110 ;
            0120 STVTAB = $A9FA
            0130 ;
            0140     *=  $A97E
            0150 ;
            0160     ASL A
            0170     TAX
            0180     LDA STVTAB,X
            0190     PHA
            0200     LDA STVTAB+1,X
            0210     PHA
            0220     RTS
Adres  procedury  wykonawczej  jest  odczytywany  z tablicy
wektorów  STVTAB  przy wykorzystaniu podwojonej wartości tokena
instrukcji  (adresy  są dwubajtowe). Tablica wektorów musi więc
zawierać  adresy  procedur  w kolejności zgodnej z tablicą nazw
instrukcji STNAME.
 
            0100 ;STatement Vectors TABle
            0110 ;
            0120 SNTXER = $B912
            0130 XBYE =  $A9E6
            0140 XCLR =  $B766
            0150 XCLOAD = $BB64
            0160 XCLOSE = $BC22
            0170 XCOLOR = $BA1F
            0180 XCONT = $B7B5
            0190 XCSAVE = $BBD1
            0200 XDEG =  $B28D
            0210 XDIM =  $B206
            0220 XDRAW = $BA27
            0230 XDOS =  $A9EC
            0240 XEND =  $B78C
            0250 XENTER = $BAC5
            0260 XFOR =  $B67D
            0270 XGET =  $BC85
            0280 XGOSUB = $B6D2
            0290 XGOTO = $B6D5
            0300 XGRAPH = $BA46
            0310 XIF =   $B778
            0320 XINPUT = $B33E
            0330 XLET =  $AADA
            0340 XLIST = $B4B5
            0350 XLOAD = $BAFB
            0360 XLOCAT = $BC9E
            0370 XLPRNT = $B496
            0380 XNEW =  $A00C
            0390 XNEXT = $B700
            0400 XNOTE = $BC3D
            0410 XON =   $B7E4
            0420 XOPEN = $BBF2
            0430 XPLOT = $BA6C
            0440 XPOINT = $BC54
            0450 XPOKE = $B278
            0460 XPOP =  $B83E
            0470 XPOS =  $BA0C
            0480 XPRINT = $B3DA
            0490 XPUT =  $BC78
            0500 XRAD =  $B291
            0510 XREAD = $B2AE
            0520 XREM =  $A9E5
            0530 XRSTR = $B296
            0540 XRTRN = $BDA8
            0550 XRUN =  $B74C
            0560 XSAVE = $BB6D
            0570 XSETC = $B9AD
            0580 XSOUND = $B9D3
            0590 XSTAT = $BC2F
            0600 XSTOP = $B792
            0610 XTRAP = $B7D8
            0620 XXIO =  $BBEC
            0630 ;
            0640     *=  $A9FA
            0650 ;
            0660     .DBYTE XREM-1    ;REM
            0670     .DBYTE XREM-1    ;DATA
            0680     .DBYTE XINPUT-1  ;INPUT
            0690     .DBYTE XCOLOR-1  ;COLOR
            0700     .DBYTE XLIST-1   ;LIST
            0710     .DBYTE XENTER-1  ;ENTER
            0720     .DBYTE XLET-1    ;LET
            0730     .DBYTE XIF-1     ;IF
            0740     .DBYTE XFOR-1    ;FOR
            0750     .DBYTE XNEXT-1   ;NEXT
            0760     .DBYTE XGOTO-1   ;GOTO
            0770     .DBYTE XGOTO-1   ;GO TO
            0780     .DBYTE XGOSUB-1  ;GOSUB
            0790     .DBYTE XTRAP-1   ;TRAP
            0800     .DBYTE XBYE-1    ;BYE
            0810     .DBYTE XCONT-1   ;CONT
            0820     .DBYTE XDIM-1    ;COM
            0830     .DBYTE XCLOSE-1  ;CLOSE
            0840     .DBYTE XCLR-1    ;CLR
            0850     .DBYTE XDEG-1    ;DEG
            0860     .DBYTE XDIM-1    ;DIM
            0870     .DBYTE XEND-1    ;END
            0880     .DBYTE XNEW-1    ;NEW
            0890     .DBYTE XOPEN-1   ;OPEN
            0900     .DBYTE XLOAD-1   ;LOAD
            0910     .DBYTE XSAVE-1   ;SAVE
            0920     .DBYTE XSTAT-1   ;STATUS
            0930     .DBYTE XNOTE-1   ;NOTE
            0940     .DBYTE XPOINT-1  ;POINT
            0950     .DBYTE XXIO-1    ;XIO
            0960     .DBYTE XON-1     ;ON
            0970     .DBYTE XPOKE-1   ;POKE
            0980     .DBYTE XPRINT-1  ;PRINT
            0990     .DBYTE XRAD-1    ;RAD
            1000     .DBYTE XREAD-1   ;READ
            1010     .DBYTE XRSTR-1   ;RESTORE
            1020     .DBYTE XRTRN-1   ;RETURN
            1030     .DBYTE XRUN-1    ;RUN
            1040     .DBYTE XSTOP-1   ;STOP
            1050     .DBYTE XPOP-1    ;POP
            1060     .DBYTE XPRINT-1  ;?
            1070     .DBYTE XGET-1    ;GET
            1080     .DBYTE XPUT-1    ;PUT
            1090     .DBYTE XGRAPH-1  ;GRAPHICS
            1100     .DBYTE XPLOT-1   ;PLOT
            1110     .DBYTE XPOS-1    ;POSITION
            1120     .DBYTE XDOS-1    ;DOS
            1130     .DBYTE XDRAW-1   ;DRAWTO
            1140     .DBYTE XSETC-1   ;SETCOLOR
            1150     .DBYTE XLOCAT-1  ;LOCATE
            1160     .DBYTE XSOUND-1  ;SOUND
            1170     .DBYTE XLPRNT-1  ;LPRINT
            1180     .DBYTE XCSAVE-1  ;CSAVE
            1190     .DBYTE XCLOAD-1  ;CLOSE
            1200     .DBYTE XLET-1    ;opuszczone LET
            1210     .DBYTE SNTXER-1  ;ERROR
 |