Programavimas

Kaip susikurti vertėją „Java“, 1 dalis: PAGRINDINIAI

Kai pasakiau draugui, kad parašiau „Java“ vertėją BASIC, jis taip nusijuokė, kad vos neišpylė sodos, kurią laikė ant savo drabužių. "Kodėl pasaulyje jūs statytumėte BASIC vertėją„ Java “? buvo pirmas nuspėjamas klausimas iš jo burnos. Atsakymas yra paprastas ir sudėtingas. Paprastas atsakymas yra tas, kad buvo įdomu rašyti vertėją „Java“ kalba, o jei ketinčiau rašyti vertėją, galėčiau parašyti ir tokį, apie kurį nuo ankstyvųjų asmeninio skaičiavimo dienų prisimenu malonius prisiminimus. Kalbant apie sudėtingą pusę, pastebėjau, kad daugelis žmonių, naudojančių „Java“, šiandien jau praėjo kurti „Duke“ programėles ir pereiti prie rimtų programų. Dažnai kurdami programą norėtumėte, kad ją būtų galima konfigūruoti. Perkonfigūravimo pasirinkimo mechanizmas yra tam tikras dinaminio vykdymo variklis.

Dinaminis vykdymas, žinomas kaip makrokomandos arba konfigūravimo kalbos, leidžia vartotojui „užprogramuoti“ programą. Dinamiško vykdymo variklio pranašumas yra tas, kad įrankius ir programas galima pritaikyti atlikti sudėtingas užduotis nepakeičiant įrankio. „Java“ platforma siūlo daugybę dinaminių vykdymo variklių variantų.

„HotJava“ ir kiti populiarūs variantai

Trumpai panagrinėkime kai kurias galimas dinaminio vykdymo variklio parinktis ir nuodugniai pažvelkime į mano vertėjo įgyvendinimą. Dinaminis vykdymo variklis yra įterptasis vertėjas. Vertėjui dirbti reikia trijų patalpų:

  1. Priemonė pakrauti su instrukcijomis
  2. Modulio formatas, skirtas vykdytinoms instrukcijoms saugoti
  3. Modelis arba aplinka sąveikai su pagrindine programa

„HotJava“

Garsiausias įterptasis vertėjas turi būti „HotJava“ „programėlių“ aplinka, kuri visiškai pakeitė žmonių požiūrį į interneto naršykles.

„HotJava“ „programėlės“ modelis buvo paremtas nuostata, kad „Java“ programa gali sukurti bendrą bazinę klasę su žinoma sąsaja ir tada dinamiškai įkelti tos klasės poklasius ir vykdyti juos vykdymo metu. Šios programėlės suteikė naujų galimybių ir, nepaisant pagrindinės klasės, suteikė dinamišką vykdymą. Ši dinaminio vykdymo galimybė yra pagrindinė „Java“ aplinkos dalis ir vienas iš dalykų, dėl kurių ji yra tokia ypatinga. Šią konkrečią aplinką nuodugniai apžvelgsime vėlesniame stulpelyje.

GNU EMACS

Iki „HotJava“ atėjimo turbūt sėkmingiausia programa su dinamišku vykdymu buvo „GNU EMACS“. Šio redaktoriaus LISP tipo makro kalba tapo daugelio programuotojų pagrindine dalimi. Trumpai tariant, EMACS LISP aplinką sudaro LISP vertėjas ir daugelis redagavimo tipo funkcijų, kurias galima naudoti sudarant sudėtingiausias makrokomandas. Nereikia laikyti nuostabos, kad EMACS redaktorius iš pradžių buvo parašytas makrokomandose, skirtose redaktoriui, vadinamam TECO. Taigi galimybė naudotis turtinga (jei neįskaitoma) makrokomanda TECO leido sukurti visiškai naują redaktorių. Šiandien GNU EMACS yra pagrindinis redaktorius, o visi žaidimai buvo parašyti tik EMACS LISP kodu, vadinamu el-code. Dėl šios konfigūravimo galimybės GNU EMACS tapo pagrindiniu redaktoriumi, o VT-100 terminalai, kuriais jis buvo sukurtas, tapo tiesiog rašytojo skilties išnašomis.

REXX

Viena iš mano mėgstamiausių kalbų, kuri niekada nepadarė nusipelniusio purslų, buvo „REXX“, sukurta Mike'o Cowlishawo iš IBM. Bendrovei reikėjo kalbos, kad būtų galima valdyti didelių didžiųjų kompiuterių, kuriuose veikia VM operacinė sistema, programas. „REXX“ atradau „Amiga“, kur jis buvo glaudžiai sujungtas su įvairiausiomis programomis per „REXX prievadus“. Šie prievadai leido programas valdyti nuotoliniu būdu per REXX vertėją. Šis vertėjo ir programos sujungimas sukūrė daug galingesnę sistemą, nei buvo įmanoma su jos komponentais. Laimei, kalba gyvuoja NETREXX - Mike'o parašytoje versijoje, kuri buvo sukompiliuota į Java kodą.

Kai žiūrėjau į NETREXX ir daug ankstesnę kalbą („Java“ LISP), man pasirodė, kad šios kalbos sudaro svarbias „Java“ programų istorijos dalis. Kaip geriau papasakoti šią istorijos dalį, nei čia nuveikti ką nors linksmo - pavyzdžiui, prikelti BASIC-80? Dar svarbiau, kad būtų naudinga parodyti vieną būdą, kaip scenarijų kalbas galima rašyti „Java“, ir, integruojant jas su „Java“, parodyti, kaip jos gali pagerinti jūsų „Java“ programų galimybes.

PAGRINDINIAI „Java“ programų tobulinimo reikalavimai

BASIC yra, paprasčiausiai, pagrindinė kalba. Yra dvi minčių mokyklos, kaip būtų galima rašyti tam vertėją. Vienas iš būdų yra parašyti programavimo kilpą, kurioje vertėjo programa nuskaito vieną teksto eilutę iš interpretuojamos programos, ją išanalizuoja ir paskui iškviečia paprogramę jai vykdyti. Skaitymo, analizavimo ir vykdymo seka kartojama tol, kol vienas iš interpretuojamos programos teiginių liepia vertėjui sustoti.

Antras ir daug įdomesnis būdas įgyvendinti projektą yra analizuoti kalbą į analizės medį ir tada atlikti analizės medį „vietoje“. Štai kaip veikia vertėjai žodžiu ir kaip aš nusprendžiau tęsti. Žetonų žymėjimas taip pat yra greitesnis, nes jiems nereikia pakartotinai nuskaityti įvesties kiekvieną kartą, kai jie atlieka pareiškimą.

Kaip jau minėjau aukščiau, trys komponentai, būtini norint pasiekti dinamišką vykdymą, yra pakrovimo būdas, modulio formatas ir vykdymo aplinka.

Pirmąjį komponentą - įkrovimo priemonę - tvarkys „Java“ „InputStream“. Kadangi įvesties srautai yra pagrindiniai „Java“ įvesties / išvesties architektūroje, sistema yra sukurta skaityti programoje iš „ „InputStream“ ir paversti ją vykdoma forma. Tai yra labai lankstus būdas įvesti kodą į sistemą. Žinoma, duomenų, einančių per įvesties srautą, protokolas bus PAGRINDINIS šaltinio kodas. Svarbu pažymėti, kad galima vartoti bet kurią kalbą; nesuklyskite manydami, kad ši technika negali būti taikoma jūsų programai.

Įvedus interpretuojamos programos šaltinio kodą į sistemą, sistema konvertuoja šaltinio kodą į vidinį vaizdą. Pasirinkau šio projekto vidinio atvaizdavimo formatą naudoti analizės medį. Sukūrus analizės medį, juo galima manipuliuoti arba vykdyti.

Trečiasis komponentas yra vykdymo aplinka. Kaip matysime, šio komponento reikalavimai yra gana paprasti, tačiau įgyvendinimas turi keletą įdomių posūkių.

Labai greita „BASIC“ kelionė

Tiems iš jūsų, kurie galbūt niekada nebuvo girdėję apie BASIC, trumpai apžvelgsiu kalbą, kad galėtumėte suprasti laukiančius analizavimo ir vykdymo iššūkius. Norėdami gauti daugiau informacijos apie BASIC, labai rekomenduoju šio stulpelio pabaigoje esančius išteklius.

„BASIC“ reiškia „Pradedančiųjų universalusis simbolinis instrukcijų kodas“. Jis buvo sukurtas Dartmuto universitete mokyti skaičiavimo koncepcijų bakalauro studentams. Nuo savo vystymosi BASIC virto įvairiomis tarmėmis. Paprasčiausios iš šių tarmių yra naudojamos kaip pramoninių procesų valdiklių valdymo kalbos; sudėtingiausios tarmės yra struktūrizuotos kalbos, kurios apima kai kuriuos objektinio programavimo aspektus. Savo projektui pasirinkau aštuntojo dešimtmečio pabaigoje CP / M operacinėje sistemoje populiarią tarmę, vadinamą BASIC-80. Ši tarmė yra tik vidutiniškai sudėtingesnė už paprasčiausias tarmes.

Teiginių sintaksė

Visos teiginio eilutės yra tokios formos

[ : [ : ... ] ]

kur „Linija“ yra sakinio eilutės numeris, „Raktinis žodis“ yra PAGRINDINIS teiginio raktinis žodis, o „Parametrai“ yra parametrų rinkinys, susietas su tuo raktiniu žodžiu.

Eilutės numeris turi du tikslus: jis naudojamas kaip etikečių teiginiams, kurie valdo vykdymo srautą, pavyzdžiui, a eiti į sakinį, ir jis tarnauja kaip į programą įterptų teiginių rūšiavimo žyma. Kaip rūšiavimo žyma, eilutės numeris palengvina eilutės redagavimo aplinką, kurioje redagavimas ir komandų apdorojimas yra sumaišomi per vieną interaktyvų seansą. Beje, to reikėjo, kai viskas, ką turėjai, buvo teletipas. :-)

Nors linijų numeriai nėra labai elegantiški, vertėjo aplinkai suteikiama galimybė atnaujinti programą po vieną. Šis sugebėjimas kyla iš to, kad teiginys yra vienas išanalizuotas objektas ir duomenų struktūroje gali būti susietas su eilutės numeriais. Be eilutės numerių, dažnai reikia iš naujo išanalizuoti visą programą, kai linija keičiasi.

Raktinis žodis identifikuoja BASIC sakinį. Šiame pavyzdyje mūsų vertėjas palaikys šiek tiek išplėstą BASIC raktinių žodžių rinkinį, įskaitant eiti į, gosub, grįžti, spausdinti, jei, galas, duomenis, atkurti, skaityti, ant, rem, dėl, Kitas, leisti, įvestis, sustabdyti, neryškus, atsitiktinai, tronir trofas. Akivaizdu, kad visa tai neperžiūrėsime šiame straipsnyje, tačiau kitą mėnesį mano „Java gilumoje“ bus keletas dokumentų, kuriuos galėsite ištirti.

Kiekvienas raktinis žodis turi teisėtų raktinių žodžių parametrų rinkinį, kuris gali jį sekti. Pavyzdžiui, eiti į po raktinio žodžio turi būti eilutės numeris jei po sakinio turi būti sąlyginė išraiška ir raktinis žodis tada -- ir taip toliau. Parametrai būdingi kiekvienam raktiniam žodžiui. Keletą šių parametrų sąrašų išsamiai apžvelgsiu kiek vėliau.

Išraiškos ir operatoriai

Dažnai teiginyje nurodytas parametras yra išraiška. Čia naudojama BASIC versija palaiko visas standartines matematines operacijas, logines operacijas, eksponavimą ir paprastą funkcijų biblioteką. Svarbiausias išraiškos gramatikos komponentas yra gebėjimas iškviesti funkcijas. Pačios išraiškos yra gana standartinės ir panašios į tas, kurias analizuoja mano ankstesnio „StreamTokenizer“ stulpelio pavyzdys.

Kintamieji ir duomenų tipai

Dalis priežasčių, kodėl BASIC yra tokia paprasta kalba, yra ta, kad joje yra tik du duomenų tipai: skaičiai ir eilutės. Kai kurios scenarijų kalbos, pvz., REXX ir PERL, net neskiria duomenų tipų, kol jie nėra naudojami. Bet naudojant „BASIC“ duomenų tipams nustatyti naudojama paprasta sintaksė.

Kintamieji pavadinimai šioje BASIC versijoje yra raidžių ir skaičių eilutės, kurios visada prasideda raide. Kintamieji neskiria didžiųjų ir mažųjų raidžių. Taigi visi A, B, FOO ir FOO2 yra galiojantys kintamųjų pavadinimai. Be to, BASIC kintamasis FOOBAR yra lygiavertis FooBar. Norėdami identifikuoti stygas, prie kintamojo pavadinimo pridedamas dolerio ženklas ($); taigi kintamasis FOO $ yra kintamasis, kuriame yra eilutė.

Galiausiai ši kalbos versija palaiko masyvus, naudojančius neryškus raktinį žodį ir kintamą formos NAME sintaksę (index1, index2, ...) iki keturių indeksų.

Programos struktūra

Programos, esančios BASIC, pagal numatytuosius nustatymus pradedamos skaičiuoti nuo mažiausios eilutės ir tęsiamos tol, kol nebeliks nei eilučių, nei apdoroti sustabdyti arba galas raktiniai žodžiai vykdomi. Žemiau parodyta labai paprasta BASIC programa:

100 REM Tai tikriausiai yra kanoninis BASIC 110 REM programos pavyzdys. Atkreipkite dėmesį, kad REM sakiniai nepaisomi. 120 SPAUSDINTI "Tai bandomoji programa". 130 PRINT "Sumuojant vertes nuo 1 iki 100" 140 LET total = 0 150 FOR I = 1 iki 100 160 LET total = total + i 170 NEXT I 180 PRINT "Visų skaitmenų tarp 1 ir 100 yra" iš viso 190 END 

Aukščiau esantys eilučių numeriai nurodo sakinių leksinę tvarką. Kai jie vykdomi, 120 ir 130 eilutės spausdina pranešimus į išvestį, 140 eilutė inicializuoja kintamąjį, o linija 150 - 170 atnaujina to kintamojo vertę. Galiausiai rezultatai atspausdinami. Kaip matote, BASIC yra labai paprasta programavimo kalba, todėl ideali kandidatė mokyti skaičiavimo koncepcijų.

Organizuoti požiūrį

Paprastai scenarijų kalboms BASIC apima programą, susidedančią iš daugybės teiginių, kurie veikia tam tikroje aplinkoje. Projektavimo iššūkis yra sukurti objektus, kad tokia sistema būtų naudinga.

Kai aš pažvelgiau į problemą, man tiesmukai iššoko tiesioginė duomenų struktūra. Ši struktūra yra tokia:

Viešąją sąsają su scenarijų kalba sudaro:

  • Gamyklinis metodas, kuris ima šaltinio kodą ir grąžina programą reprezentuojantį objektą.
  • Aplinka, suteikianti pagrindą, kuriame programa vykdoma, įskaitant „įvesties / išvesties“ įrenginius teksto įvedimui ir išvedimui.
  • Standartinis to objekto modifikavimo būdas, galbūt sąsajos forma, leidžiantis derinti programą ir aplinką, kad būtų pasiekti naudingi rezultatai.

Vertėjo žodžiu struktūra buvo kiek sudėtingesnė. Iškilo klausimas, kaip būtų galima suskirstyti du scenarijų kalbos aspektus - analizavimą ir vykdymą? Rezultatas buvo trys klasių grupės - viena skirta analizuoti, viena - struktūrinei struktūrai, kurioje pateikiamos analizuojamos ir vykdomos programos, ir viena, kuri sudarė pagrindinę aplinkos klasę vykdymui.

Analizavimo grupėje reikalingi šie objektai:

  • Leksinė analizė kodui apdoroti kaip tekstui
  • Išraiškos analizavimas, norint sukonstruoti išraiškų medžius
  • Pareiškimų analizavimas, norint sukonstruoti pačių teiginių analizės medžius
  • Klaidų klasės pranešant apie klaidas analizuojant

Pagrindų grupę sudaro objektai, kuriuose yra išanalizuoti medžiai ir kintamieji. Jie apima:

  • Pareiškimo objektas, turintis daug specializuotų poklasių, kad būtų parodyti išanalizuoti teiginiai
  • Išraiškos objektas, reiškiantis išraiškas vertinimui
  • Kintamas objektas, turintis daug specializuotų poklasių, vaizduojančių atominius duomenų egzempliorius