Bygg en tolk I Java-Implementer utførelsesmotoren

for de av dere som bare blir med oss, i min» Java In Depth » – kolonne de siste par månedene, har jeg diskutert hvordan man kan gå om å bygge en tolk I Java. I den første tolk-kolonnen dekket vi noen av de ønskelige egenskapene til en tolk; i den andre kolonnen diskuterte vi både parsing og utformingen av en klassepakke for implementering av tolken. I denne kolonnen ser vi på å kjøre tolken, og støtteklassene som er nødvendige for å oppnå det. Til slutt vil jeg pakke opp serien her med en diskusjon om hvordan en tolk kan bli hekta i Andre Java-klasser, og dermed forbedre sine evner.

Gjennomgå relevante biter

La meg begynne med å skissere hva vi har dekket så langt, og påpeke de delene av designet som blir viktigere når vi diskuterer utførelsesmodus. Hvis du vil ha en mer detaljert beskrivelse av disse klassene, kan du se mine tidligere kolonner eller kildekodelenkene som er i Delen

Ressurser

nedenfor.

det er tre grunnklasser i gjennomføringen av tolken, Program, Statement og Expression. Følgende viser hvordan de tre er relatert:

Program

denne Program klassen limer sammen parsing og kjøring av komponentene i parseren. Denne klassen definerer to hovedmetoder, load og run. Metoden load leser setninger fra en inngangsstrøm og analyserer dem i en samling av setninger, metoden run itererer over samlingen og utfører hver av setningene. Klassen Program gir også en samling av variabler for programmet å bruke, samt en stabel for lagring av data.

Setning

klassen Statement inneholder en enkelt analysert setning. Denne klassen er faktisk underklasse i en bestemt type setning (PRINT, GOTO, IF, OG så videre), men alle setninger inneholder metoden execute som kalles for å utføre setningen i sammenheng med en Program klasseforekomst.

Uttrykk

klassen Expression inneholder analysetreet til et uttrykk. Under kjøring brukes metoden value til å evaluere uttrykket og returnere verdien. Som Statement er klassen Expression primært designet for å bli underklasset av bestemte typer uttrykk.

alle disse klassene arbeider sammen for å danne grunnlaget for en tolk. Klassen Program innkapsler samtidig analyseoperasjonen og utførelsesoperasjonen, mens klassene Statement og Expression innkapsler de faktiske beregningsbegrepene til språket vi har implementert. For disse tre artiklene om å bygge tolker har eksempelspråket vært GRUNNLEGGENDE.

fasiliteter for beregning

det er to kjørbare klasser i tolken,

Statement

og

Expression

. Først la oss ta en titt på

Expression

forekomstene av Expression opprettes ved metoden expression i klassen ParseExpression. Klassen ParseExpression implementerer uttrykksparseren i denne tolken. Denne klassen er en peer av klassen ParseStatement, som bruker metoden statement til å analysere GRUNNLEGGENDE setninger. Forekomster av Expression har en intern type som identifiserer hvilken operator forekomsten representerer, og to metoder, value og stringValue, som returnerer den beregnede verdien av uttrykket. I tillegg, når Et Uttrykk forekomst er opprettet, er det nominelt gitt to parametere som representerer venstre og høyre side av uttrykkets operasjon. Vist i kildeform, er Den første delen av Uttrykket som følger:

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

som du kan se i koden ovenfor, er det forekomstvariablene, en operatype kalt oper, og to halvdeler av operasjonen i arg1 og arg2, og deretter noen konstanter for å definere de ulike typene. Det er også to konstruktører som brukes av uttrykksparseren; disse oppretter et nytt uttrykk fra to uttrykk. Deres kilde er vist nedenfor:

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); }

den første konstruktøren bygger et vilkårlig uttrykksobjekt, og den andre bygger et» unary » uttrykksobjekt-for eksempel unary minus. En ting å merke seg er at hvis det bare er ett argument, brukes arg2 til å lagre verdien.

metoden som brukes oftest i klassen Expression er value, som er definert som følger:

 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. ...

Du kan se at hvert uttrykksobjekt representerer en tuple som består av en operator og ett eller to argumenter. Den morsomme delen av å designe uttrykksutføringsmotoren på denne måten er at når du konstruerer dette settet med uttrykkstupler basert på Expression – objektet, kan du beregne verdien av uttrykket ved å bare påkalle value – metoden. Metoden value kaller rekursivt metoden value for de to argumentene som utgjør dette uttrykket, bruker operasjonen på dem og returnerer resultatet. Denne utformingen ble brukt slik at uttrykk ville være lett å forstå.

for å holde klassestrukturen ren, er alle beregningsenheter-fra konstanter til trigonometriske funksjoner-underklasser av Expression. Denne ideen, stjålet skamløst Fra Lisp, innkapsler helt tanken om å «forårsake» en evaluering som skal skje, fra den faktiske implementeringen av «hvordan» den evalueringen skjer. For å demonstrere hvordan dette prinsippet brukes, trenger vi bare å se på noen av de spesialiserte underklassene Expression.

Konstanter i MIN VERSJON AV BASIC, som jeg kalte COCOA, er representert av klassen ConstantExpression, som underklasser Expression og bare lagrer den numeriske verdien i en medlemsverdi. Kildekoden til ConstantExpression er vist konseptuelt nedenfor. Jeg sier «konseptuelt» fordi jeg valgte å pakke hva som ville vært StringConstantExpression og NumericConstantExpression i en enkelt klasse. Så den virkelige klassen inkluderer en konstruktør for å skape en konstant med et strengargument og for å returnere verdien som en streng. Følgende kode viser hvordan klassen ConstantExpression håndterer numeriske konstanter.

class ConstantExpression extends Expression { private double v; ConstantExpression(double a) { super(); v = a; } double value(Program pgm) throws BASICRuntimeError { return v; }}

koden ovenfor erstatter de mer kompliserte konstruktørene av Expression med en enkel butikk av en forekomstvariabel; value – metoden erstattes ganske enkelt med en retur av den lagrede verdien.

det er sant at du kan kode Expression – klassen for å akseptere i konstruktørene en konstant som vil spare deg for en klasse. En fordel med å designe Expression slik jeg har, er imidlertid at koden i Expression forblir maksimalt generisk. Jeg finner denne kodestilen hjelper meg med å eliminere kompleksiteten til spesielle tilfeller, og når jeg er «ferdig» med Expression – koden, kan jeg gå videre til andre aspekter av uttrykk uten å revidere grunnklassen igjen og igjen. Fordelen blir tydeligere når vi dykker inn i en annen underklasse av Expression kalt FunctionExpression.

i klassen FunctionExpression var det to designkrav jeg følte skulle oppfylles for å holde tolken fleksibel. Den første var å implementere standard GRUNNLEGGENDE funksjoner; den andre var å innkapsle analysen av funksjonsargumentene i samme klasse som implementerte disse funksjonene. Det andre kravet, parsing, var motivert av et ønske om å gjøre DETTE GRUNNLEGGENDE utvidbart ved å opprette flere funksjonsbiblioteker som kunne sendes til parseren som underklasser av FunctionExpression. Videre kan de bestått i klasser brukes av parser for å øke antall funksjoner som er tilgjengelige for brukerens program.

klassen FunctionExpression er bare moderat mer komplisert enn en ConstantExpression og vises i kondensert form under:

 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 }

ovennevnte kilde viser hvordan value metoden er implementert. Oper-variabelen gjenbrukes til å holde funksjonsidentiteten, Og Uttrykksobjektene referert til av arg1 og arg2 brukes som argumenter for selve funksjonene. Til slutt er det en stor brytererklæring som sender forespørselen. Et interessant aspekt er at value – metoden fanger de potensielle aritmetiske unntakene og konverterer dem til forekomster av BASICRuntimeError. Analysekoden i FunctionExpression er vist nedenfor, igjen kondensert for å spare plass. (Husk at all kildekoden er tilgjengelig ved hjelp av lenker I Resources-delen.)

 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 }

Merk at denne koden utnytter det faktum at uttrykksparseren i ParseStatement allerede har funnet ut at den ser på et uttrykk og har passert uttrykkets identitet i som parameter ty. Denne parseren trenger da bare å finne åpningsparentesen og lukkeparentesen som inneholder argumentet(e). Men se nøye: i linjene # 9 til #18 lar parseren noen funksjoner ikke ha noen argumenter(I dette tilfellet RND og FRE). Dette demonstrerer fleksibiliteten som gis ved å ha funksjonsdelparseren innebygd i denne klassen, i stedet for å tvinge alle funksjoner til å samsvare med noen forhåndsdefinerte mal. Gitt en funksjonstype i parameteren ty, velger switch-setningen en gren som kan analysere argumentene som kreves for den funksjonen, det være seg strenger, tall, andre uttrykk og så videre.

Andre aspekter: Strenger og matriser

TO andre deler AV GRUNNSPRÅKET implementeres av COCOA tolk: strenger og matriser. La oss se på implementeringen av strenger først.

for å implementere strenger som variabler, ble klassen Expression endret for å inkludere begrepet «streng» uttrykk. Denne modifikasjonen tok form av to tillegg: isString og stringValue. Kilden for disse to nye metodene er vist nedenfor.

 String stringValue(Program pgm) throws BASICRuntimeError { throw new BASICRuntimeError("No String representation for this."); } boolean isString() { return false; }

Det Er Klart at det Ikke er så nyttig for ET GRUNNLEGGENDE program å få strengverdien til et baseuttrykk (som alltid er enten numerisk eller boolsk uttrykk). Du kan konkludere fra mangelen på nytte at disse metodene da ikke tilhørte Expression og tilhørte i en underklasse av Expression i stedet. Men ved å sette disse to metodene i grunnklassen, kan alle Expression objekter testes for å se om de faktisk er strenger.

en annen utforming tilnærming er å returnere de numeriske verdiene som strenger ved hjelp av et StringBuffer objekt for å generere en verdi. Så, for eksempel, kan den samme koden omskrives som:

 String stringValue(Program pgm) throws BASICRuntimeError { StringBuffer sb = new StringBuffer(); sb.append(this.value(pgm)); return sb.toString(); }

og hvis koden ovenfor brukes, kan du eliminere bruken av isString fordi hvert uttrykk kan returnere en strengverdi. Videre kan du endre metoden value for å prøve å returnere et tall hvis uttrykket evalueres til en streng ved å kjøre den gjennom metoden valueOfjava.lang.Double. På Mange språk som Perl, TCL og REXX brukes denne typen amorf skriving til stor fordel. Begge tilnærmingene er gyldige, og du bør gjøre ditt valg basert på utformingen av tolken din. I BASIC må tolken returnere en feil når en streng er tilordnet en numerisk variabel, så jeg valgte den første tilnærmingen (returnerer en feil).

når det gjelder arrays, er det forskjellige måter du kan designe språket ditt for å tolke dem på. C bruker hakeparentesene rundt matriseelementer for å skille matrisens indeksreferanser fra funksjonsreferanser som har parenteser rundt argumentene. Imidlertid valgte språkdesignerne FOR BASIC å bruke parenteser for både funksjoner og matriser, slik at når teksten NAME(V1, V2) ses av parseren, kan det være enten et funksjonskall eller en matrisereferanse.

den leksikalske analysatoren diskriminerer mellom tokens som følges av parenteser ved først å anta at de er funksjoner og testing for det. Deretter fortsetter det å se om de er søkeord eller variabler. Det er denne beslutningen som forhindrer programmet i å definere en variabel som heter » SIN.»Enhver variabel hvis navn samsvarer med et funksjonsnavn, vil bli returnert av den leksikalske analysatoren som et funksjonstoken i stedet. Det andre trikset den leksikalske analysatoren bruker, er å sjekke om variabelnavnet umiddelbart etterfølges av’ (‘. Hvis det er, antar analysatoren at det er en matrisereferanse. Ved å analysere dette i den leksikalske analysatoren eliminerer vi strengen ‘MYARRAY ( 2 ) ‘ fra å bli tolket som en gyldig matrise (merk mellomrommet mellom variabelnavnet og den åpne parentesen).

det siste trikset for å implementere arrays er i klassen Variable. Denne klassen brukes til en forekomst av en variabel, og som jeg diskuterte i forrige måneds kolonne, er det en underklasse av Token. Det har imidlertid også noen maskiner for å støtte arrays, og det er det jeg vil vise nedenfor:

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;

koden ovenfor viser forekomstvariablene knyttet til en variabel, som i klassen ConstantExpression. Man må gjøre et valg om antall klasser som skal brukes versus kompleksiteten i en klasse. Et designvalg kan være å bygge en Variable klasse som bare inneholder skalarvariabler og deretter legge til en ArrayVariable underklasse for å håndtere vanskelighetene i arrays. Jeg valgte å kombinere dem, snu skalarvariabler i hovedsak i arrays med lengde 1.

hvis du leser koden ovenfor, vil du se matriseindekser og multiplikatorer. Disse er her fordi flerdimensjonale arrays I BASIC er implementert ved hjelp av en enkelt lineær Java array. Den lineære indeksen I Java array beregnes manuelt ved hjelp av elementene i multiplikator array. Indeksene som brukes I GRUNNPROGRAMMET, kontrolleres for gyldighet ved å sammenligne dem med den maksimale juridiske indeksen i indeksens ndx-array.

FOR EKSEMPEL vil EN GRUNNLEGGENDE matrise med tre dimensjoner på 10, 10 og 8 ha verdiene 10, 10 og 8 lagret i ndx. Dette gjør at uttrykksevaluatoren kan teste for en» index out of bounds » – tilstand ved å sammenligne tallet som brukes I BASIC-programmet, med det maksimale juridiske nummeret som nå er lagret i ndx. Multiplikator array i vårt eksempel vil inneholde verdiene 1, 10 og 100. Disse konstantene representerer tallene man bruker til å kartlegge fra en flerdimensjonal matriseindeksspesifikasjon til en lineær matriseindeksspesifikasjon. Den faktiske ligningen er:

Java Index = Index1 + Index2 * Maks Størrelse På Index1 + Index3 * (Maks Størrelse På Index1 * MaxSizeIndex 2)

den neste Java-matrisen i Variable – klassen er vist nedenfor.

 Expression expns;

expns-matrisen brukes til å håndtere matriser som er skrevet som » A(10*B, i).»I så fall er indeksene faktisk uttrykk i stedet for konstanter, så referansen må inneholde pekere til de uttrykkene som evalueres ved kjøretid. Endelig er det denne ganske stygg utseende stykke kode som beregner indeksen avhengig av hva som ble vedtatt i programmet. Denne private metoden er vist nedenfor.

 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; }

når du ser på koden ovenfor, vil du merke at koden først sjekker for å se at riktig antall indekser ble brukt når du refererte til matrisen, og deretter at hver indeks var innenfor det juridiske området for den indeksen. Hvis det oppdages en feil, blir et unntak kastet til tolken. Metodene numValue og stringValue returnerer en verdi fra variabelen som henholdsvis et tall eller en streng. Disse to metodene er vist nedenfor.

 double numValue(int ii) throws BASICRuntimeError { return nArrayValues; } String stringValue(int ii) throws BASICRuntimeError { if (subType == NUMBER_ARRAY) return ""+nArrayValues; return sArrayValues; }

det finnes flere metoder for å angi verdien av en variabel som ikke vises her.

Ved å skjule mye av kompleksiteten i hvordan hver brikke er implementert, Når det endelig kommer tid til å kjøre GRUNNLEGGENDE program, Er Java-koden ganske grei.

Kjører koden

koden for å tolke DE GRUNNLEGGENDE setningene og utføre dem finnes i

run

metode for

Program

klasse. Koden for denne metoden er vist nedenfor, og jeg går gjennom den for å påpeke de interessante delene.

 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 }

koden ovenfor viser at metoden run tar en InputStream og en OutputStream for bruk som «konsoll» for det utførende programmet. I linje 3 er opplistingsobjektet e satt til settet med setninger fra samlingen som heter stmts. For denne samlingen brukte jeg en variant av et binært søketre kalt et» rød-svart » tre. (For ytterligere informasjon om binære søketrær, se min forrige kolonne om å bygge generiske samlinger.) Etter det blir to ekstra samlinger opprettet – en med en Stack og en med en Vector. Stakken brukes som stabelen i en hvilken som helst datamaskin, men vektoren brukes uttrykkelig for datasetningene i GRUNNPROGRAMMET. Den endelige samlingen er et annet rød-svart tre som inneholder referansene for variablene definert av GRUNNPROGRAMMET. Dette treet er symboltabellen som brukes av programmet mens det utføres.

Etter initialiseringen er inngangs-og utgangsstrømmene satt opp, og hvis e ikke er null, starter vi med å samle inn data som er deklarert. Det er gjort som vist i følgende kode.

 /* 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); } }

ovennevnte sløyfe ser bare på alle setningene, og EVENTUELLE data setninger den finner blir deretter utført. Utførelsen av HVER datasetning setter inn verdiene deklarert av denne setningen i dataStore-vektoren. Neste vi kjøre programmet riktig, som er gjort ved hjelp av denne neste stykke kode:

 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); }

Som du kan se i koden ovenfor, det første trinnet er å initialisere e. det neste trinnet er å hente den første setningen i variabelen s og deretter gå inn i utførelsesløkken. Det er noen kode for å se etter ventende inngang på inngangsstrømmen for å tillate fremdriften av programmet å bli avbrutt ved å skrive på programmet, og deretter sløyfen sjekker for å se om setningen som skal utføres, ville være EN dataerklæring. Hvis det er, hopper sløyfen setningen som den allerede var utført. Den heller convoluted teknikken for å utføre alle data setninger først er nødvendig fordi BASIC tillater data setninger som tilfredsstiller EN LESE setning å vises hvor som helst i kildekoden. Til slutt, hvis sporing er aktivert, skrives en sporingspost ut og den svært uninpressive setningen s = s.execute(this, in, pout); startes. Skjønnheten er at all innsats for å innkapsle grunnkonseptene i enkle å forstå klasser gjør den endelige koden triviell. Hvis det ikke er trivielt, har du kanskje en anelse om at det kan være en annen måte å dele designet på.

Innpakning og videre tanker

tolken ble utformet slik at den kunne kjøre som en tråd, slik at det kan være flere COCOA tolk tråder som kjører samtidig i programrommet samtidig. Videre, ved bruk av funksjonsutvidelse kan vi gi et middel hvorved disse trådene kan samhandle med hverandre. Det var et Program For Apple II og Senere FOR PC og Unix kalt C-roboter som var et system av samspill «robot» enheter som ble programmert ved hjelp av en enkel GRUNNLEGGENDE derivat språk. Spillet ga meg og andre mange timer med underholdning, men var også en utmerket måte å introdusere de grunnleggende prinsippene for beregning til yngre studenter (som feilaktig trodde de bare spilte og ikke lærte). Java basert tolk delsystemer er mye kraftigere enn sine pre-Java kolleger fordi de er umiddelbart tilgjengelig på Alle Java-plattform. COCOA kjørte På Unix-systemer og Macintoshes samme dag jeg jobbet på En Windows 95 – BASERT PC. Mens Java blir slått opp av inkompatibiliteter i tråd-eller window toolkit-implementeringene, er det som ofte overses dette :mye kode » virker bare.»

Chuck McManis er for tiden direktør for systemprogramvare Hos FreeGate Corp., en venture-finansiert oppstart som utforsker muligheter i internettmarkedet. Før han ble Med FreeGate, Var Chuck medlem Av Java-Gruppen. Han sluttet Seg Til Java-Gruppen like etter dannelsen Av FirstPerson Inc. og varet medlem av den bærbare OS-gruppen (gruppen som er ansvarlig For OSportion Av Java). Senere, da FirstPerson ble oppløst, ble hanmed gruppen gjennom utviklingen av alpha og betaversions Av Java-plattformen. Han opprettet den første» All Java » – hjemmesiden på Internett da han gjorde programmeringen For Javaversion Of The Sun home page I Mai 1995. Han utviklet også acryptographic library For Java og versjoner Av Java classloader som kunne skjerm klasser basert på digitale signaturer.Før Han kom Til FirstPerson, Jobbet Chuck i operativsystemeneområde Av SunSoft, utvikle nettverksapplikasjoner, hvor han gjorde detden første utformingen AV NIS+. Også, sjekk ut hans hjemmeside. : END_BIO

Lær mer om dette emnet

  • her er lenker til kildefilene referert ovenfor:
    • Konstantuttrykk.java
    • Funksjonuttrykk.java
    • Program.java
    • Uttalelse.java
    • StringExpression.java
    • Variabel.java
    • Variableuttrykk.java
  • Og her er en .ZIP-fil av kildefilene:
    indepth.zip
  • «Uvanlig Lisp» – En Lisp tolk skrevet I Java
    http://user03.blue.aol.com/thingtone/workshop/lisp.htm
  • Mike Cowlishaws NetREXX tolk skrevet I Java
    http://www2.hursley.ibm.com/netrexx/
  • en gammel kopi AV USENET BASIC FAQ (DEN har fortsatt nyttig informasjon i den.)
    http://whitworth.me.ic.ac.uk/people/students/djbur/qbasic.htm
  • COCOA, EN grunnleggende tolk skrevet I Java
    http://www.mcmanis.com/~cmcmanis/java/javaworld/examples/BASIC.html
  • Chuck ‘ S Java resources page
    http://www.mcmanis.com/~cmcmanis/java/javaworld/
  • TCL Tolk skrevet I Java
    http://www.cs.cornell.edu/home/ioi/Jacl/
  • :
  • «Hvordan bygge en tolk I Java, Del 2strukturen»
    trikset for å montere grunnklassen for en enkel tolk.
  • » hvordan bygge en tolk I Java, Del 1grunnleggende »
    For komplekse applikasjoner som krever et skriptspråk, Kan Java brukes Til å implementere tolken, og legge til skriptevner til Hvilken Som Helst Java-app.
  • «Leksikalsk analyse, Del 2bygg et program»
    slik bruker Du StreamTokenizer-objektet til å implementere en interaktiv kalkulator.
  • «Leksikalsk analyse Og JavaPart 1»
    Lær hvordan du konverterer lesbar tekst til maskinlesbare data ved Hjelp Av StringTokenizer-og StreamTokenizer-klassene.
  • «Gjenbruk Av Kode og objektorienterte systemer»
    Bruk en hjelpeklasse til å håndheve dynamisk oppførsel.
  • «Beholderstøtte for objekter I Java 1.0.2»
    Det Er enkelt Å Organisere objekter når du legger dem i beholdere. Denne artikkelen leder deg gjennom design og implementering av en container.
  • «grunnleggende Om Java – klasselastere»
    grunnleggende om denne nøkkelkomponenten I Java-arkitekturen.
  • «Bruker ikke søppelsamling»
    Minimere heap juling I Java-programmer.
  • «Tråder og applets og visuelle kontroller»
    denne siste delen av serien utforsker å lese flere datakanaler.
  • «Bruke kommunikasjonskanaler I applets, Del 3»
    Utvikle Visual Basic-stil teknikker for å applet design-og konvertere temperaturer i prosessen.
  • «Synkronisere tråder I Java, Del II»
    Lær hvordan du skriver en datakanalklasse, og opprett deretter et enkelt eksempelprogram som illustrerer en virkelig implementering av klassen.
  • «Synkronisere tråder I Java»
    Tidligere Java team developer Chuck McManis leder deg gjennom et enkelt eksempel som illustrerer hvordan du synkroniserer tråder for å sikre pålitelig og forutsigbar appletadferd.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.