niille teistä, jotka juuri liityitte seuraamme, olen parin viime kuukauden aikana keskustellut ”Java in Depth” – palstallani siitä, miten tulkkia voitaisiin rakentaa Javalla. Ensimmäisellä tulkki-palstalla Käsittelimme joitakin tulkin toivottavia ominaisuuksia, toisella palstalla käsittelimme sekä tulkin jäsentämistä että luokkapaketin asettelua tulkin toteuttamiseksi. Tällä palstalla tarkastelemme tulkin pyörittämistä ja siihen tarvittavia tukiluokkia. Lopuksi lopetan sarjan tähän keskusteluun siitä, miten tulkki voidaan kytkeä muihin Java-luokkiin, mikä parantaa heidän kykyjään.
relevanttien bittien tarkistaminen
sallikaa minun aloittaa hahmottelemalla, mitä olemme tähän mennessä käsitelleet, ja tuoda esiin ne suunnittelun osat, jotka tulevat tärkeämmiksi, kun keskustelemme toteutustavasta. Tarkempi kuvaus näistä luokista löytyy aiemmista sarakkeistani tai lähdekoodin linkeistä, jotka ovat
resurssit-osiossa
alla.
tulkin toteutuksessa on kolme perustusluokkaa, Program
, Statement
ja Expression
. Seuraava osoittaa, miten nämä kolme liittyvät toisiinsa:
ohjelma
tämä
Program
Luokka liimaa yhteen jäsentimen jäsennys-ja suorituskomponentit. Tässä luokassa määritellään kaksi pääasiallista menetelmää,load
jarun
.load
– menetelmä lukee lauseet tulovirrasta ja jäsentää ne lauseiden kokoelmaksi,run
– menetelmä iteroi kokoelman yli ja toteuttaa jokaisen lausuman.Program
– luokka tarjoaa myös kokoelman muuttujia ohjelman käytettäväksi sekä pinon tietojen tallentamiseen.
lausuma
Statement
luokka sisältää yhden jäsennellyn lausuman. Tämä luokka on itse asiassa aliluokitettu tietyntyyppiseksi lausekkeeksi (PRINT, GOTO, IF ja niin edelleen), mutta kaikki lausekkeet sisältävät menetelmänexecute
, jota kutsutaan lausuman toteuttamiseksiProgram
Luokka-instanssin yhteydessä.
lauseke
Expression
luokka sisältää lausekkeen jäsenpuun. Suorituksen aikana käytetäänvalue
– menetelmää lausekkeen arvioimiseksi ja sen arvon palauttamiseksi. KutenStatement
, myösExpression
– luokka on suunniteltu ensisijaisesti tietyntyyppisten lausekkeiden alaryhmäksi.
kaikki nämä luokat toimivat yhdessä tulkin pohjana. Program
Luokka kapseloi samanaikaisesti jäsennysoperaation ja suoritusoperaation, kun taas Statement
ja Expression
luokat kapseloivat toteuttamamme kielen varsinaiset laskennalliset käsitteet. Näissä kolmessa rakennustulkkeja käsittelevässä kirjoituksessa esimerkkikieli on ollut perus.
laskennan tilat
tulkissa on kaksi suoritettavaa luokkaa,
Statement
ja
Expression
. Katsotaan ensin
Expression
esiintymät Expression
luodaan menetelmällä expression
luokassa ParseExpression
. ParseExpression
– luokka toteuttaa ilmaisun jäsennin tässä tulkinnassa. Tämä luokka on ParseStatement
– luokan vertainen, joka käyttää statement
– menetelmää PERUSLAUSEIDEN jäsentämiseen. Esiintymillä Expression
on sisäinen type
, joka tunnistaa, mitä operaattoria esiintymä edustaa, ja kaksi menetelmää, value
ja stringValue
, jotka palauttavat lausekkeen laskennallisen arvon. Lisäksi, kun lauseke instanssi luodaan, sille annetaan nimellisesti kaksi parametria, jotka edustavat lausekkeen toiminnan vasenta ja oikeaa puolta. Esitetty lähdemuodossa, lausekkeen alkuosa on seuraava:
class Expression { Expression arg1, arg2; int oper; final static int OP_ADD = 1; // Addition '+' final static int OP_SUB = 2; // Subtraction '-' final static int OP_MUL = 3; // Multiplication '*' final static int OP_DIV = 4; // Division '/' final static int OP_BNOT = 19; // Boolean negation '.NOT.' final static int OP_NEG = 20; // Unary minus
kuten yllä olevasta koodista näkyy, on olemassa instanssimuuttujat, operaattorityyppi nimeltä oper, sekä operaation kaksi puoliskoa arg1: ssä ja arg2: ssa ja sitten joitakin vakioita, joilla määritellään eri tyypit. Lisäksi on olemassa kaksi konstruktiota, joita käytetään lausekkeessa jäsennin; nämä luovat uuden lausekkeen kahdesta lausekkeesta. Niiden lähde näkyy alla:
protected Expression(int op, Expression a, Expression b) throws BASICSyntaxError { arg1 = a; arg2 = b; oper = op; /* * If the operator is a boolean, both arguments must be boolean. */ if (op > OP_GE) { if ( (! (arg1 instanceof BooleanExpression)) || (! (arg2 instanceof BooleanExpression)) ) throw new BASICSyntaxError(typeError); } else { if ((arg1 instanceof BooleanExpression) || (arg2 instanceof BooleanExpression)) throw new BASICSyntaxError(typeError); } } protected Expression(int op, Expression a) throws BASICSyntaxError { arg2 = a; oper = op; if ((oper == OP_BNOT) && (! (arg2 instanceof BooleanExpression))) throw new BASICSyntaxError(typeError); }
ensimmäinen konstruktori rakentaa mielivaltaisen lauseke-objektin, ja toinen rakentaa ”unary” lauseke-objektin-kuten unary minus. On huomattava, että jos on vain yksi argumentti, arg2: ta käytetään sen arvon tallentamiseen.
Expression
luokassa useimmin käytetty menetelmä on value
, joka määritellään seuraavasti:
double value(Program pgm) throws BASICRuntimeError { switch (oper) { case OP_ADD : return arg1.value(pgm) + arg2.value(pgm); case OP_SUB : return arg1.value(pgm) - arg2.value(pgm); ... etc for all of the other operator types. ...
voit nähdä, että jokainen lauseke objekti edustaa monikkoa, joka koostuu operaattorista ja yhdestä tai kahdesta argumentista. Hauskinta lausekkeen toteutusmoottorin suunnittelussa tällä tavalla on se, että kun rakennat tämän lausekkeiden joukon Expression
objektin pohjalta, voit laskea lausekkeen arvon yksinkertaisesti vetoamalla value
– menetelmään. value
– menetelmä vetoaa rekursiivisesti tämän lausekkeen muodostavien kahden argumentin value
– menetelmään, soveltaa operaatiota niihin ja palauttaa tuloksen. Tätä muotoilua käytettiin, jotta ilmaisut olisivat helposti ymmärrettäviä.
luokkarakenteen puhtaana pitämiseksi kaikki laskennalliset yksiköt — vakioista trigonometrisiin funktioihin — ovat alaluokkia Expression
. Tämä Lispiltä häpeämättömästi varastettu ajatus kiteyttää täysin käsitteen” aiheuttaa ”arvioinnin tapahtuvan, siitä tosiasiallisesta toteutuksesta” miten ” arviointi tapahtuu. Osoittaaksemme, miten tätä periaatetta sovelletaan, meidän tarvitsee vain tarkastella joitakin erikoistuneita alaluokkia Expression
.
vakioita omassa basic-versiossani, jonka nimesin KAAKAOKSI, edustaa luokka ConstantExpression
, joka alaluokittaa Expression
ja yksinkertaisesti tallentaa numeerisen arvon johonkin jäsenarvoon. ConstantExpression
: n lähdekoodi on esitetty käsitteellisesti alla. Sanon ”käsitteellisesti”, koska valitsin niputtaa sen, mikä olisi ollut StringConstantExpression
ja NumericConstantExpression
yhdeksi luokaksi. Reaaliluokkaan kuuluu siis konstruktori, jolla luodaan vakio merkkijonoargumentilla ja palautetaan sen arvo merkkijonona. Seuraava koodi näyttää, miten ConstantExpression
– Luokka käsittelee numeerisia vakioita.
class ConstantExpression extends Expression { private double v; ConstantExpression(double a) { super(); v = a; } double value(Program pgm) throws BASICRuntimeError { return v; }}
edellä esitetty koodi korvaa Expression
monimutkaisemmat konstruktiot yksinkertaisella instanssimuuttujan varastolla; value
– menetelmä korvataan yksinkertaisesti tallennetun arvon palauttamisella.
on totta, että Expression
luokan saattoi koodata hyväksymään konstruktioissaan vakion, joka säästäisi luokan. Yksi etu Expression
: n muotoilussa on kuitenkin se, että Expression
: n koodi pysyy maksimaalisesti yleisenä. Koen, että tämä koodaustyyli auttaa minua poistamaan erikoistapausten monimutkaisuuden ja näin Kun olen ”valmis” Expression
– koodin kanssa, voin siirtyä ilmaisujen muihin näkökohtiin käymättä perusluokkaa uudelleen ja uudelleen. Etu kirkastuu, kun kaivaudutaan toiseen Expression
– alaluokkaan nimeltä FunctionExpression
.
luokassa FunctionExpression
oli kaksi suunnitteluvaatimusta, jotka minun mielestäni piti täyttää, jotta tulkki pysyisi joustavana. Ensimmäinen oli toteuttaa standardin perustoiminnot; toinen oli kapseloida jäsentämällä funktioiden argumentit samaan luokkaan, joka toteutti nämä funktiot. Toisen vaatimuksen, jäsentämisen, taustalla oli halu tehdä tämä PERUSJATKETTAVA luomalla ylimääräisiä funktiokirjastoja, jotka voitiin siirtää jäsentäjälle alaluokiksi FunctionExpression
. Edelleen, nämä läpäistyt luokat voitaisiin käyttää jäsennin lisätä toimintojen määrää käyttäjän ohjelman.
FunctionExpression
– luokka on vain kohtalaisen monimutkaisempi kuin a ConstantExpression
ja se on esitetty tiivistettynä alla:
1 class FunctionExpression extends Expression { 2 3 double value(Program p) throws BASICRuntimeError { 4 try { 5 switch (oper) { 6 case RND : 7 if (r == null) 8 r = p.getRandom(); 9 return (r.nextDouble() * arg2.value(p));10 case INT :11 return Math.floor(arg2.value(p));12 case SIN :13 return Math.sin(arg2.value(p));14 15 default :16 throw new BASICRuntimeError("Unknown or non-numeric function.");17 }18 } catch (Exception e) {19 if (e instanceof BASICRuntimeError)20 throw (BASICRuntimeError) e;21 else22 throw new BASICRuntimeError("Arithmetic Exception.");23 }24 }
yllä oleva lähde kertoo, miten value
– menetelmä on toteutettu. Oper-muuttujaa käytetään uudelleen funktion identiteetin pitämiseksi, ja arg1: n ja arg2: n viittaamia lausekkeita käytetään argumentteina itse funktioille. Lopuksi on suuri kytkinlausunto, joka lähettää pyynnön. Yksi mielenkiintoinen seikka on se, että value
– menetelmä ottaa huomioon mahdolliset aritmeettiset poikkeukset ja muuntaa ne esiintymiksi BASICRuntimeError
. Jäsennyskoodi FunctionExpression
näkyy alla, jälleen tiivistettynä tilan säästämiseksi. (Muista, että kaikki lähdekoodi on saatavilla linkkien avulla resurssit-osiossa.)
1 static FunctionExpression parse(int ty, LexicalTokenizer lt) throws BASICSyntaxError { 2 FunctionExpression result; 3 Expression a; 4 Expression b; 5 Expression se; 6 Token t; 7 8 t = lt.nextToken(); 9 if (! t.isSymbol('(')) {10 if (ty == RND) {11 lt.unGetToken();12 return new FunctionExpression(ty, new ConstantExpression(1));13 } else if (ty == FRE) {14 lt.unGetToken();15 return new FunctionExpression(ty, new ConstantExpression(0));16 }17 throw new BASICSyntaxError("Missing argument for function.");18 }19 switch (ty) {20 case RND:21 case INT:22 case SIN:23 case COS:24 case TAN:25 case ATN:26 case SQR:27 case ABS:28 case CHR:29 case VAL:30 case STR:31 case SPC:32 case TAB:33 case LOG:34 a = ParseExpression.expression(lt);35 if (a instanceof BooleanExpression) {36 throw new BASICSyntaxError(functions.toUpperCase()+" function cannot accept boolean expression.");37 }38 if ((ty == VAL) && (! a.isString()))39 throw new BASICSyntaxError(functions.toUpperCase()+" requires a string valued argument.");40 result = new FunctionExpression(ty, a);41 break; 42 default:43 throw new BASICSyntaxError("Unknown function on input.");4445 }46 t = lt.nextToken();47 if (! t.isSymbol(')')) {48 throw new BASICSyntaxError("Missing closing parenthesis for function.");49 }50 return result;51 }
huomaa, että tämä koodi hyödyntää sitä, että lausekkeen jäsennin ParseStatement
on jo tajunnut tarkastelevansa lauseketta ja ohittanut lausekkeen identiteetin as-parametrissa ty. Tämä jäsennin sitten tarvitsee vain paikantaa avaaminen suluissa ja sulkeminen suluissa, jotka sisältävät argumentti(s). Mutta katso huolellisesti: riveillä #9 kautta #18 jäsennin sallii joidenkin funktioiden ei ole argumentteja (tässä tapauksessa RND ja FRE). Tämä osoittaa joustavuutta, jonka tarjoaa ottaa funktion subparser rakennettu tähän luokkaan, sen sijaan pakottaa kaikki toiminnot mukautua jonkin ennalta mallin. Koska parametrissa ty on funktion tyyppi, kytkinlauseke valitsee haaran, joka voi jäsentää kyseisen funktion vaatimia argumentteja, olivatpa ne merkkijonoja, numeroita, muita lausekkeita ja niin edelleen.
muut näkökohdat: jouset ja taulukot
kaksi muuta peruskielen osaa on kaakaon tulkin toteuttamia: jouset ja taulukot. Katsotaanpa täytäntöönpanoa Jouset ensin.
merkkijonojen toteuttamiseksi muuttujina Expression
luokkaa muutettiin siten, että siihen sisällytettiin käsite ”merkkijono” – lausekkeet. Tämä muutos tehtiin kahtena lisäyksenä: isString
ja stringValue
. Näiden kahden uuden menetelmän lähde on esitetty alla.
String stringValue(Program pgm) throws BASICRuntimeError { throw new BASICRuntimeError("No String representation for this."); } boolean isString() { return false; }
on selvää, että PERUSOHJELMALLE ei ole kovin hyödyllistä saada kantalausekkeen merkkijonoarvoa (joka on aina joko numeerinen tai Boolen lauseke). Hyödyllisyyden puutteesta voisi päätellä, että nämä menetelmät eivät silloin kuuluneet Expression
vaan kuuluivat sen sijaan alaluokkaan Expression
. Asettamalla nämä kaksi menetelmää perusluokkaan kaikki Expression
oliot voidaan kuitenkin testata, ovatko ne todellisuudessa merkkijonoja.
toinen suunnittelutapa on palauttaa numeeriset arvot merkkijonoina käyttäen StringBuffer
– objektia arvon luomiseksi. Niinpä esimerkiksi sama koodi voitaisiin kirjoittaa uudelleen:
String stringValue(Program pgm) throws BASICRuntimeError { StringBuffer sb = new StringBuffer(); sb.append(this.value(pgm)); return sb.toString(); }
ja jos yllä olevaa koodia käytetään, voit poistaa isString
käytön, koska jokainen lauseke voi palauttaa merkkijonon arvon. Lisäksi value
– menetelmää voi muokata niin, että yrittää palauttaa luvun, jos lauseke arvioi merkkijonon ajamalla sen valueOf
– menetelmällä java.lang.Double
. Monissa kielissä, kuten Perl, TCL ja REXX, tällaista amorfista kirjoitusta käytetään suureksi hyödyksi. Molemmat lähestymistavat ovat päteviä, ja sinun tulisi tehdä valintasi tulkin suunnittelun perusteella. BASIC-järjestelmässä tulkin on palautettava virhe, kun merkkijono on annettu numeeriselle muuttujalle, joten valitsin ensimmäisen lähestymistavan (palauttamalla virheen).
kuten taulukoissa, on olemassa erilaisia tapoja, joilla voit suunnitella oman kielesi tulkitsemaan niitä. C käyttää hakasulkeita array-elementtien ympärillä erottaakseen array: n indeksiviitteet funktioviitteistä, joiden argumenttien ympärillä on sulkeita. Basic-kielen suunnittelijat päättivät kuitenkin käyttää sulkeita sekä funktioissa että matriiseissa, joten kun teksti NAME(V1, V2)
on jäsentäjän näkemä, se voi olla joko funktiokutsu tai matriisiviite.
leksikaalinen analysaattori erottaa toisistaan tokeneita, joita seuraavat sulut, olettaen ensin, että ne ovat funktioita ja testaamalla sitä. Sitten se menee nähdä, jos ne ovat avainsanoja tai muuttujia. Tämä päätös estää ohjelmaasi määrittelemästä muuttujaa nimeltä ” SIN.”Jokainen muuttuja, jonka nimi vastasi funktion nimeä, palautettaisiin leksikaalisella analysaattorilla funktiotunnuksena sen sijaan. Toinen temppu, jota lexical analyzer käyttää, on tarkistaa, onko muuttujan nimen perässä välittömästi” (”. Jos se on, analysaattori olettaa, että se on array viittaus. Jäsentämällä tätä leksikaalisessa analysaattorissa poistamme merkkijonon ”MYARRAY ( 2 )
” tulkitsemasta kelvolliseksi rivistöksi (huomaa muuttujan nimen ja avoimen sulun välinen tila).
viimeinen juju toteutuksessa on Variable
– luokassa. Tätä luokkaa käytetään muuttujan ilmentymänä, ja kuten viime kuun palstalla käsittelin, se on alaluokka Token
. Kuitenkin, se on myös joitakin koneita tukemaan taulukoita ja se on mitä näytän alla:
class Variable extends Token { // Legal variable sub types final static int NUMBER = 0; final static int STRING = 1; final static int NUMBER_ARRAY = 2; final static int STRING_ARRAY = 4; String name; int subType; /* * If the variable is in the symbol table these values are * initialized. */ int ndx; // array indices. int mult; // array multipliers double nArrayValues; String sArrayValues;
yllä oleva koodi esittää muuttujaan liittyvät instanssimuuttujat, kuten ConstantExpression
– luokassa. On tehtävä valinta käytettävien luokkien määrästä ja luokan monimutkaisuudesta. Yksi suunnitteluvalinta voisi olla rakentaa Variable
– luokka, johon mahtuu vain skalaarimuuttujia, ja lisätä sitten ArrayVariable
– alaluokka käsittelemään matriisien koukeroita. Päätin yhdistää ne, kääntämällä skalaarimuuttujat olennaisesti matriisit Pituus 1.
jos luet yllä olevaa koodia, näet array-indeksit ja-kertoimet. Nämä ovat tässä, koska Basicin moniulotteiset matriisit on toteutettu yhden lineaarisen Java-matriisin avulla. Lineaarinen indeksi Java-matriisiin lasketaan manuaalisesti käyttäen kertojajoukon elementtejä. PERUSOHJELMASSA käytettyjen indeksien pätevyys tarkistetaan vertaamalla niitä indeksien ndx-matriisin enimmäisindeksiin.
esimerkiksi perusjoukolla, jonka kolme ulottuvuutta ovat 10, 10 ja 8, olisi ndx: ään tallennetut arvot 10, 10 ja 8. Tämän avulla lausekkeen arvioija voi testata” indeksin out of bounds ” ehdon vertaamalla PERUSOHJELMASSA käytettyä lukua ndx: ään tallennettuun lakimääräiseen maksimilukuun. Kerroinrivistö esimerkissämme sisältäisi arvot 1, 10 ja 100. Nämä vakiot edustavat lukuja, joita käytetään kartoittamaan moniulotteisesta matriisiindeksimäärityksestä lineaariseksi matriisiindeksimääritykseksi. Todellinen yhtälö on:
Java Index = Index1 + Index2 * maksimikoko Index1 + Index3 * (maksimikoko Index1 * MaxSizeIndex 2)
seuraava Java-array Variable
– luokassa on esitetty alla.
Expression expns;
expns-taulukkoa käytetään käsittelemään taulukoita, jotka kirjoitetaan ”A(10*B, i)
.”Tällöin indeksit ovat itse asiassa lausekkeita vakioiden sijaan, joten viittauksen on sisällettävä osoittimia niihin lausekkeisiin, jotka arvioidaan suorituksen aikana. Lopuksi on tämä melko rumannäköinen koodinpätkä, joka laskee indeksin sen mukaan, mitä ohjelmassa läpäistiin. Tämä yksityinen menetelmä on esitetty alla.
private int computeIndex(int ii) throws BASICRuntimeError { int offset = 0; if ((ndx == null) || (ii.length != ndx.length)) throw new BASICRuntimeError("Wrong number of indices."); for (int i = 0; i < ndx.length; i++) { if ((ii < 1) || (ii > ndx)) throw new BASICRuntimeError("Index out of range."); offset = offset + (ii-1) * mult; } return offset; }
kun katsoo yllä olevaa koodia, huomaa, että koodi tarkistaa ensin, että taulukkoon viitattaessa käytettiin oikeaa määrää indeksejä, ja sitten, että kukin indeksi oli kyseisen indeksin lainmukaisen vaihteluvälin sisällä. Jos virhe havaitaan, tulkille heitetään poikkeus. Menetelmät numValue
ja stringValue
palauttavat muuttujan arvon vastaavasti numerona tai jonona. Nämä kaksi menetelmää on esitetty alla.
double numValue(int ii) throws BASICRuntimeError { return nArrayValues; } String stringValue(int ii) throws BASICRuntimeError { if (subType == NUMBER_ARRAY) return ""+nArrayValues; return sArrayValues; }
muuttujan arvon asettamiseen on muitakin menetelmiä, joita ei ole esitetty tässä.
piilottamalla suuren osan kunkin kappaleen toteutustavan monimutkaisuudesta, kun lopulta tulee aika suorittaa perusohjelma, Java-koodi on melko suoraviivainen.
juokseva koodi
koodi PERUSLAUSEIDEN tulkitsemiseen ja toteuttamiseen sisältyy
run
menetelmä
Program
Luokka. Koodi tämä menetelmä on esitetty alla, ja minä askel sen kautta huomauttaa mielenkiintoisia osia.
1 public void run(InputStream in, OutputStream out) throws BASICRuntimeError { 2 PrintStream pout; 3 Enumeration e = stmts.elements(); 4 stmtStack = new Stack(); // assume no stacked statements ... 5 dataStore = new Vector(); // ... and no data to be read. 6 dataPtr = 0; 7 Statement s; 8 9 vars = new RedBlackTree();1011 // if the program isn't yet valid.12 if (! e.hasMoreElements())13 return;1415 if (out instanceof PrintStream) {16 pout = (PrintStream) out;17 } else {18 pout = new PrintStream(out);19 }
yllä oleva koodi osoittaa, että run
menetelmä vaatii InputStream
ja OutputStream
käytettäväksi suoritusohjelman ”konsolina”. Rivillä 3 arvojoukko objekti e asetetaan kokoelman lausekkeiden joukkoon nimeltä stmts. Tässä kokoelmassa käytin muunnelmaa binäärisestä hakupuusta nimeltä ”punamusta” puu. (Lisätietoja binäärihakupuista on edellisessä kolumnissani geneeristen kokoelmien rakentamisesta.) Tämän jälkeen luodaan kaksi lisäkokoelmaa — toinen käyttäen a Stack
ja toinen käyttäen a Vector
. Pinoa käytetään kuten pinoa missä tahansa tietokoneessa, mutta vektoria käytetään nimenomaan perusohjelman DATALAUSEISSA. Loppukokoelma on toinen punamusta puu, jossa on viitteet perusohjelman määrittelemille muuttujille. Tämä puu on symboli taulukko, jota ohjelma käyttää, kun se suoritetaan.
alustuksen jälkeen Tulo-ja ulostulovirrat asetetaan, ja jos e ei ole nolla, aloitetaan keräämällä kaikki ilmoitetut tiedot. Tämä tehdään kuten seuraavassa koodissa.
/* First we load all of the data statements */ while (e.hasMoreElements()) { s = (Statement) e.nextElement(); if (s.keyword == Statement.DATA) { s.execute(this, in, pout); } }
yllä oleva silmukka tarkastelee yksinkertaisesti kaikkia väittämiä, minkä jälkeen kaikki sen löytämät DATALAUSEET suoritetaan. Kunkin TIETOLAUSEKKEEN suoritus lisää kyseisessä lausekkeessa ilmoitetut arvot dataStore-vektoriin. Seuraavaksi suoritamme ohjelman oikein, joka tehdään käyttämällä tätä seuraavaa koodinpätkää:
e = stmts.elements(); s = (Statement) e.nextElement(); do { int yyy; /* While running we skip Data statements. */ try { yyy = in.available(); } catch (IOException ez) { yyy = 0; } if (yyy != 0) { pout.println("Stopped at :"+s); push(s); break; } if (s.keyword != Statement.DATA) { if (traceState) { s.trace(this, (traceFile != null) ? traceFile : pout); } s = s.execute(this, in, pout); } else s = nextStatement(s); } while (s != null); }
kuten yllä olevasta koodista näkyy, ensimmäinen vaihe on käynnistää e uudelleen. seuraava vaihe on hakea ensimmäinen lauseke muuttujaan s ja syöttää sen jälkeen suoritussilmukka. On olemassa joitakin koodia tarkistaa vireillä syöte tulovirrassa, jotta ohjelman eteneminen voidaan keskeyttää kirjoittamalla ohjelma, ja sitten silmukka tarkistaa, jos suoritettava lauseke olisi tietojen lauseke. Jos näin on, silmukka ohittaa lausunnon sellaisena kuin se on jo suoritettu. Melko mutkikas tekniikka suorittaa kaikki tiedot lausekkeet ensin tarvitaan, koska BASIC mahdollistaa tiedon lausekkeet, jotka täyttävät lukea lauseke näkyvät missä tahansa lähdekoodissa. Lopuksi, jos jäljitys on käytössä, tulostetaan jäljitystietue ja vedotaan erittäin epäuskottavaan lausumaan s = s.execute(this, in, pout);
. Kauneus on siinä, että kaikki pyrkimys kapseloida peruskäsitteet helppotajuisiksi luokiksi tekee lopullisesta koodista triviaalin. Jos se ei ole triviaali sitten ehkä sinulla on vihje, että voisi olla toinen tapa jakaa suunnittelu.
paketointi ja lisäajatukset
tulkki on suunniteltu siten, että se voisi toimia lankana, jolloin ohjelmatilassasi voi olla samanaikaisesti useita COCOA interpreter-kierteitä. Lisäksi funktion laajentamisen avulla voimme tarjota keinon, jolla nämä kierteet voivat olla vuorovaikutuksessa keskenään. Apple II: lle ja myöhemmin PC: lle ja Unixille oli olemassa ohjelma nimeltä C-robots, joka oli vuorovaikuttavien ”robottien” kokonaisuuksien järjestelmä, joka ohjelmoitiin yksinkertaisella perusjohdannaisella. Peli tarjosi minulle ja muille monta tuntia viihdettä, mutta oli myös erinomainen tapa esitellä laskennan perusperiaatteet nuoremmille opiskelijoille (jotka virheellisesti uskoivat, että he vain pelasivat eivätkä oppineet). Java – pohjainen tulkki alijärjestelmät ovat paljon tehokkaampia kuin niiden ennen Java kollegansa, koska ne ovat heti saatavilla millä tahansa Java-alustalla. COCOA juoksi Unix-järjestelmissä ja Macintoshes samana päivänä sain työskennellä Windows 95-pohjainen PC. Vaikka Java saa Hakataan yhteensopimattomuudet kierre tai ikkuna toolkit toteutukset, mitä usein unohdetaan on tämä: paljon koodia ”vain toimii.”
Chuck McManis on tällä hetkellä FreeGate Corp.-nimisen, riskirahoitteisen start-up-yrityksen johtaja, joka tutkii mahdollisuuksia Internetin markkinoilla. Ennen Freegateen liittymistä Chuck oli Java-yhtyeen jäsen. Hän liittyi Java-konserniin heti FirstPerson Inc: n perustamisen jälkeen. ja oli jäsenenä portable OS group (Ryhmä vastuussa Osportti Java). Myöhemmin, kun FirstPerson lakkautettiin, hän pysyi ryhmän mukana kehittämällä Java-alustan alpha-ja betaversions-versioita. Hän loi ensimmäisen ”all Java” – kotisivun Internetiin, kun hän teki ohjelmoinnin Sun-kotisivun Javaversion-sivulle toukokuussa 1995. Hän kehitti myös Javalle akryptografisen kirjaston ja Java classloaderin versiot, joilla pystyi seulomaan luokkia digitaalisten allekirjoitusten perusteella.Ennen firstpersoniin liittymistään Chuck työskenteli Sunsoftin käyttöjärjestelmäalueella kehittäen verkostoitumissovelluksia, joissa hän teki NIS+: n alkuperäisen suunnittelun. Katso myös hänen kotisivunsa. : END_BIO
lisätietoja aiheesta
- tässä linkit yllä mainittuihin lähdetiedostoihin:
- jatkuva ilme.java
- Funktioekspressio.java
- ohjelma.java
- Statement.java
- Stringekspressio.java
- muuttuja.java
- variable Expression.Jaava
- ja tässä on .Lähdetiedostojen ZIP-tiedosto:
syvällinen.zip - ”Uncommon Lisp” — Javalla kirjoitettu Lisp-tulkki
http://user03.blue.aol.com/thingtone/workshop/lisp.htm - Mike Cowlishaw ’ n NetREXX tulkki kirjoitettu Java
http://www2.hursley.ibm.com/netrexx/ - vanha kopio USENET BASIC FAQ (se on edelleen hyödyllistä tietoa siinä.)
http://whitworth.me.ic.ac.uk/people/students/djbur/qbasic.htm - COCOA, perus tulkki kirjoitettu Java
http://www.mcmanis.com/~cmcmanis/java/javaworld/examples/BASIC.html - Chuckin Java resources-sivu
http://www.mcmanis.com/~cmcmanis/java/javaworld/ - TCL tulkki kirjoitettu Java
http://www.cs.cornell.edu/home/ioi/Jacl/
- :
- ”How to build an interpreter in Java, Part 2rakenne”
the trick to assembling the foundation classes for a simple interpreter. - ”How to build an interpreter in Java, Part 1The BASICs”
monimutkaisissa ohjelmissa, jotka vaativat komentosarjakieltä, Javaa voidaan käyttää tulkin toteuttamiseen lisäämällä skriptauskykyjä mihin tahansa Java-sovellukseen. - ”Lexical analysis, Part 2Build an application”
kuinka StreamTokenizer-objektia käytetään interaktiivisen laskimen toteuttamiseen. - ” Lexical analysis and JavaPart 1″
Opi muuntamaan ihmisen luettava teksti koneellisesti luettavaksi tiedoksi StringTokenizer-ja StreamTokenizer-luokkien avulla. - ”Code reuse and object-oriented systems”
käytä apuluokkaa dynaamisen käyttäytymisen toteuttamiseen. - ” konttien tuki kohteille Javassa 1.0.2″
esineiden järjestäminen on helppoa, kun ne laittaa konttiin. Tämä artikkeli opastaa suunnittelussa ja toteutuksessa säiliön. - ”the basics of Java class loaders”
the fundamentals of this key component of the Java architecture. - ”ei käytä roskien keruuta”
minimoi kasojen rymistely Java-ohjelmissasi. - ”Threads and applets and visual controls”
tämä sarjan päätösosa tutkii useiden datakanavien lukemista. - ”Using communication channels in applets, Part 3”
Develop Visual Basic-tyylisiä tekniikoita applet design — and convert temperatures in the process. - ” synkronoivat kierteet Java, osa II”
Opettele kirjoittamaan datakanavaluokka ja luo sitten yksinkertainen esimerkkisovellus, joka havainnollistaa luokan reaalimaailman toteutusta. - ” Synchronizing threads in Java”
entinen Java-tiimin Kehittäjä Chuck McManis opastaa yksinkertaisen esimerkin, joka havainnollistaa, miten säikeitä synkronoidaan luotettavan ja ennustettavan sovelmien käyttäytymisen varmistamiseksi.