Leksika korrektsust kontrolliv programm

Eelmises peatükis esitatud Pisi-Algoli leksika grammatika põhjal on lihtne kirjutada programmi (programmeerimiskeele Ada95 süntaksis), mis kontrollib sisestatud programmiteksti leksilist korrektsust, s.t. et lähtetekst vastab Pisi-Algoli leksika kirjeldusele, nagu see oli grammatika abil defineeritud. Väljundtegevuste lisamisega on saab sellest hiljem Pisi-Algol-i leksika analüüsi teostav programm - skanner.

Defineerime algul kõik tarvisminevad andmetüübid; predikaadi in abil võimaldavad need hiljem lihtsalt kontrollida, millise lähteteksti lekseemi FIRST või FOLLOW hulka sümbol kuulubs.t. milline lekseem järgmisena tuleb. Loetlustüübi definitsioon koosneb lihtsalt sellise tüübiga muutuja kõigi lubatud väärtuste loetelust; alamtüübi definitsioonis näitatakse baastüübi (loetlustüüp) esimene ja viimane element; märkide -- järel (kuni realõpuni) on kommentaar.

Andmetüüpide defineerimisel on aluseks keele leksika kirjeldus. Tüüp SYMBOL kirjeldab kõik sümbolid, mis üldse programmi tekstis võivad esineda, s.t. keele tähestiku, alamtüübid TÄHT, NUMBER ja MÄRK kirjeldavad hulki FIRST(SÕNA), FIRST(ARV) ja FIRST(ERALDAJA).

type SYMBOL is ( 'A','B',...,'Z','0','1',...,'9','+','-','*','/','=','>','<','(',')',';',' ');
subtype TÄHT is SYMBOL range 'A'..'Z';
subtype NUMBER is SYMBOL range '0'..'9';
subtype MÄRK is SYMBOL range '+'..' ';

Et sisendtekstis esinevaid vigu paigaldada, on tarvis andmetüüpi, mis võimaldab kirjeldada sisendteksti sümbolite asukohta:

type textposition is record
LINENUMBER: 1..99999; -- s.t. PISI-ALGOLI programmis ei või olla rohkem ridu! CHARPOSITION: 0..80 -- s.t. programmireas ei või olla rohkem märke! end record;

Vea leidmisel salvestatakse veakood ja selle esinemiskoht

type ERROR is record
ERRORCODE: INTEGER; ERRORPOSITION: TEXTPOSITION; end record;

Vead salvestatakse ja teatatakse kasutajale alles kogu analüüsi lõppedes (s.t. programm püüab sisendtekstis vea leidmisel tööd jätkata):

ERRORLIST: array 1..ERRORMAX of ERROR
-- ERRORMAX on maksimaalne lubatud vigade arv sisendtekstis

Protseduur READ annab globaalse SYMBOL- tüüpi muutuja CH väärtuseks sisendteksti järgmise sümboli ja muutuja POSITION väärtuseks saab selle asukoht lähtetekstis; protseduuri READ ehitus (keha tekst) meid siin ei huvita:

procedure READ(
CH: out SYMBOL; POSITION: out TEXTPOSITION);

Kasutades alamprotseduure SÕNA, ARV, ERALDAJA (need vastavad alamautomaatidele, mis eelmises peatükis kirjeldasid vastavalt sõnu, arve ja eraldajaid) võib kogu leksikat tunnistava (kontrolliva) programmi kirjutada täpses vastavuses leksikat defineeriva grammatika struktuuriga. PeaprotseduuriSCAN struktuur (loogika) vastab leksika struktuuri kirjeldavale regulaarse avaldise (ERALDAJA | SÕNA ERALDAJA | ARV ERALDAJA )+ struktuurile:

procedure SCAN(SISEND: in FILE) is
begin READ; -- CH väärtuseks saab sisendi esimene sümbol while CH in SYMBOL loop -- PROGRAMM (ERALDAJA | IDENT ERALDAJA | CONST ERALDAJA )*
case CH is when TÄHT SÕNA;ERALDAJA; when NUMBER ARV;ERALDAJA; when MÄRK ERALDAJA; end case; end loop;
if CH='#' then ACCEPT else RECORD_ERROR(0,POSITION) -- # - sisendteksti lõpusümbol
-- veakood 0: lubamatu sümbol
end SCAN;

Ka alamprotseduuride SÕNA struktuur vastab regulaarse avaldise TÄHT(TÄHT|NUMBER)* struktuurile, kuid selle käivitamisel on loetava sõna esimene täht juba loetud, s.t. see on muutuja CH väärtuseks:

procedure SÕNA is
begin while CH in TÄHT or CH in NUMBER loop READ; end loop; end while; end WORD;

Ka protseduuri ARV struktuuri määrab täisarve kirjeldav regulaarne avaldis (NUMBER)+:

procedure ARV is
begin while CH in DIGIT loop READ; end loop; end while; end NUMBER;

Protseduuri ERALDAJA loogika määrab samuti leksika kirjeldus - eraldajad on OP | ( | ) | := | ; |' '|, kuid kahest sümbolist koosneva lekseemi := jaoks tuleb lisada teise sümboli korrektsuse kontroll:

procedure ERALDAJA is
begin case CH is when '+'|'-'|'*'|'/'|'=' | > | < |';'|'('|')' READ; when ':' READ; if CH = '=' then READ else RECORD_ERROR(1,POSITION); end if; -- veakood 1: oodati sümbolit '=' end case; end ERALDAJA;


Ülesandeid:
1. Koosta ülalesitatud näite põhjal leksika tunnistaja (kasutades Ada95 süntaksit) programmeerimiskeelele C, C++, Java !.
2. Teisenda ülalesitatud näited programmeerimiskeelde C!

Küsimused, probleemid: ©2004-2013 Jaak Henno