azok számára, akik most csatlakoztak hozzánk, az elmúlt néhány hónapban a “Java in Depth” oszlopban megvitattam, hogyan lehet egy tolmácsot építeni Java-ban. Az első tolmács oszlopban a tolmács néhány kívánatos tulajdonságát tárgyaltuk; a második oszlopban mind az értelmező, mind az osztálycsomag elrendezését tárgyaltuk a tolmács megvalósításához. Ebben az oszlopban megvizsgáljuk az interpreter futtatását, valamint az ehhez szükséges támogató osztályokat. Végül itt összefoglalom a sorozatot azzal a vitával, hogy egy tolmács hogyan kapcsolható be más Java osztályokba, ezáltal javítva képességeiket.
a vonatkozó bitek áttekintése
hadd kezdjem azzal, hogy felvázolom, mit fedtünk le eddig, és rámutatok a tervezés azon részeire, amelyek fontosabbá válnak, amikor a végrehajtási módot tárgyaljuk. Ezen osztályok részletesebb leírását lásd az előző oszlopokban vagy a forráskód hivatkozásokban, amelyek az alábbi
erőforrások szakaszban találhatók.
.
a tolmács megvalósításában három alaposztály létezik: Program
, Statement
és Expression
. Az alábbiakban bemutatjuk, hogy a három hogyan kapcsolódik egymáshoz:
Program
ez a
Program
osztály összeragasztja az elemző elemző és végrehajtó összetevőit. Ez az osztály két fő módszert határoz meg,load
ésrun
. Aload
metódus beolvassa az utasításokat egy bemeneti adatfolyamból, és egy utasításgyűjteménybe értelmezi őket, arun
metódus iterálja a gyűjteményt, és végrehajtja az egyes utasításokat. AProgram
osztály a változók gyűjteményét is biztosítja a program számára, valamint egy verem az adatok tárolására.
utasítás
a
Statement
osztály egyetlen elemzett utasítást tartalmaz. Ez az osztály valójában alosztályozódik egy adott típusú utasításba (PRINT, GOTO, IF stb.), de minden utasítás tartalmazza aexecute
metódust, amelyet az utasítás végrehajtására hívnak meg egyProgram
osztálypéldány összefüggésében.
Expression
a
Expression
osztály egy kifejezés elemzési fáját tartalmazza. A végrehajtás során avalue
metódust használjuk a kifejezés kiértékelésére és értékének visszaadására. AStatement
– hez hasonlóan aExpression
osztályt is elsősorban arra tervezték, hogy meghatározott típusú kifejezések alosztályozzák.
ezek az osztályok együttesen alkotják a tolmács alapját. A Program
osztály egyidejűleg magába foglalja az elemzési műveletet és a végrehajtási műveletet, míg a Statement
és Expression
osztályok az általunk megvalósított nyelv tényleges számítási koncepcióit. A tolmácsok építéséről szóló három cikk esetében a példanyelv alapvető volt.
számítástechnikai eszközök
a tolmácsban két végrehajtható osztály található,
Statement
és
Expression
. Először vessünk egy pillantást
Expression
a Expression
példányai a expression
módszerrel jönnek létre a ParseExpression
osztályban. A ParseExpression
osztály az értelmező kifejezést valósítja meg ebben az értelmezőben. Ez az osztály a ParseStatement
osztály peer-je, amely a statement
metódust használja az alapvető utasítások elemzésére. A Expression
példányoknak van egy belső type
, amely azonosítja a példány által képviselt operátort, és két módszer, a value
és a stringValue
, amelyek visszaadják a kifejezés számított értékét. Továbbá, amikor egy Kifejezéspéldány létrejön, névlegesen két paramétert kap, amelyek a kifejezés működésének bal és jobb oldalát képviselik. Forrás formában látható, a kifejezés első része a következő:
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
mint a fenti kódban látható, vannak a példányváltozók, az oper nevű operátor típus és a művelet két fele arg1 és arg2, majd néhány konstans a különböző típusok meghatározásához. Ezenkívül két konstruktor van, amelyeket a kifejezés elemző használ; ezek két kifejezésből új kifejezést hoznak létre. Forrásuk az alábbiakban látható:
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); }
az első konstruktor tetszőleges kifejezési objektumot épít, a második pedig egy “unary” kifejezési objektumot-például unary mínusz. Egy dolgot meg kell jegyezni, hogy ha csak egy argumentum van, akkor az arg2 értéket tárolja.
a Expression
osztályban leggyakrabban használt módszer a value
, amelyet a következőképpen határozunk meg:
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. ...
láthatja, hogy minden kifejezésobjektum egy operátorból és egy vagy két argumentumból álló tuple-t képvisel. A kifejezésvégrehajtó motor ilyen módon történő megtervezésének szórakoztató része az, hogy amikor ezt a kifejezéssorozatot a Expression
objektum alapján állítja össze, akkor a kifejezés értékét egyszerűen a value
metódus meghívásával számíthatja ki. A value
metódus rekurzív módon meghívja a kifejezést alkotó két argumentum value
metódusát, alkalmazza a műveletet rájuk, és visszaadja az eredményt. Ezt a kialakítást úgy használták, hogy a kifejezések könnyen érthetők legyenek.
az osztályszerkezet tisztán tartása érdekében az összes számítási egység-az állandóktól a trigonometrikus függvényekig-a Expression
alosztályai. Ez az ötlet, amelyet szégyentelenül loptak el a Lisp-től, teljesen magában foglalja az értékelés “okozásának” fogalmát, az értékelés “hogyan” tényleges megvalósításától kezdve. Annak bemutatásához, hogy ezt az elvet hogyan alkalmazzák, csak a Expression
néhány speciális alosztályát kell megvizsgálnunk.
a COCOA nevű Basic verzióm Konstansait a ConstantExpression
osztály képviseli, amely a Expression
alosztályba sorolja, és egyszerűen tárolja a numerikus értéket egy tagértékben. A forráskód ConstantExpression
fogalmilag az alábbiakban látható. Azért mondom, hogy “koncepcionálisan”, mert úgy döntöttem, hogy a StringConstantExpression
és a NumericConstantExpression
egy osztályba sorolom. Tehát a valós osztály tartalmaz egy konstruktort, amely konstansot hoz létre egy string argumentummal, és annak értékét karakterláncként adja vissza. A következő kód megmutatja, hogy a ConstantExpression
osztály hogyan kezeli a numerikus állandókat.
class ConstantExpression extends Expression { private double v; ConstantExpression(double a) { super(); v = a; } double value(Program pgm) throws BASICRuntimeError { return v; }}
a fenti kód A Expression
bonyolultabb konstruktorait egy példányváltozó egyszerű tárolásával helyettesíti; a value
metódust egyszerűen a tárolt érték visszatérésével helyettesítjük.
igaz, hogy kódolhatja a Expression
osztályt, hogy elfogadja a konstruktoraiban egy állandót, amely megmentene egy osztályt. A Expression
megtervezésének egyik előnye azonban az, hogy a Expression
kód maximálisan általános marad. Úgy találom, hogy ez a kódolási stílus segít kiküszöbölni a speciális esetek összetettségét, így amikor “végeztem” a Expression
kóddal, továbbléphetek a kifejezések más aspektusaira anélkül, hogy újra és újra megvizsgálnám az alaposztályt. Az előny világosabbá válik, ha belemerülünk a Expression
egy másik alosztályába, amelynek neve FunctionExpression
.
a FunctionExpression
osztályban két tervezési követelmény volt, amelyeket úgy éreztem, hogy teljesíteni kell a tolmács rugalmassága érdekében. Az első a szabványos alapfunkciók megvalósítása volt; a másik az volt, hogy a függvények argumentumainak elemzését ugyanabba az osztályba foglalja, amely ezeket a funkciókat megvalósította. A második követelményt, az elemzést az a vágy motiválta, hogy ezt az alapvető bővíthetőséget további függvénykönyvtárak létrehozásával tegye lehetővé, amelyeket a FunctionExpression
alosztályaként lehet átadni az elemzőnek. Ezenkívül az átadott osztályokat az elemző felhasználhatja a felhasználó programja számára elérhető funkciók számának növelésére.
a FunctionExpression
osztály csak mérsékelten bonyolultabb, mint a ConstantExpression
, és az alábbiakban tömörített formában jelenik meg:
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 }
a fenti forrás bemutatja a value
módszer megvalósítását. Az oper változót újra felhasználják a függvényazonosság megőrzésére,és az arg1 és arg2 által hivatkozott Kifejezésobjektumokat maguknak a függvényeknek az argumentumaként használják. Végül van egy nagy kapcsolónyilatkozat, amely elküldi a kérést. Az egyik érdekes szempont, hogy a value
módszer elkapja a lehetséges aritmetikai kivételeket, és átalakítja őket BASICRuntimeError
példányokká. A FunctionExpression
elemzési kód az alábbiakban látható, ismét tömörítve a helytakarékosság érdekében. (Ne feledje, hogy az összes forráskód elérhető az erőforrások szakasz linkjeivel.)
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 }
vegye figyelembe, hogy ez a kód kihasználja azt a tényt, hogy a ParseStatement
kifejezéselemző már rájött, hogy egy kifejezést néz, és átadta a kifejezés azonosságát az as paraméterben ty. Ehhez az elemzőnek csak meg kell találnia a nyitó zárójelet és a záró zárójelet, amelyek tartalmazzák az argumentumokat. De nézd meg alaposan: a #9-től #18-ig terjedő sorokban az elemző lehetővé teszi, hogy egyes függvényeknek ne legyen argumentuma (ebben az esetben RND és FRE). Ez bizonyítja azt a rugalmasságot, amelyet a függvény Alosztályának ebbe az osztályba történő beépítése biztosít, ahelyett, hogy az összes függvényt arra kényszerítené, hogy megfeleljen valamilyen előre meghatározott sablonnak. Adott függvénytípus a paraméterben ty, a switch utasítás kiválaszt egy ágat, amely elemezheti az adott függvényhez szükséges argumentumokat, legyenek azok húrok, számok, egyéb kifejezések stb.
egyéb szempontok: húrok és tömbök
a BASIC nyelv két másik részét a COCOA tolmács valósítja meg: húrok és tömbök. Először nézzük meg a húrok végrehajtását.
a karakterláncok változóként történő megvalósításához a Expression
osztályt úgy módosították, hogy tartalmazza a “karakterlánc” kifejezések fogalmát. Ez a módosítás két kiegészítés formájában történt: isString
és stringValue
. E két új módszer forrása az alábbiakban látható.
String stringValue(Program pgm) throws BASICRuntimeError { throw new BASICRuntimeError("No String representation for this."); } boolean isString() { return false; }
nyilvánvaló, hogy egy BASIC program számára nem túl hasznos az alapkifejezés karakterlánc-értékének megszerzése (amely mindig numerikus vagy logikai kifejezés). A hasznosság hiányából arra lehet következtetni, hogy ezek a módszerek akkor nem tartoztak a Expression
– be, hanem a Expression
alosztályába tartoztak. Ha azonban ezt a két módszert az alaposztályba helyezzük, az összes Expression
objektum tesztelhető, hogy valóban húrok-e.
egy másik tervezési megközelítés az, hogy a numerikus értékeket karakterláncként adja vissza egy StringBuffer
objektum segítségével érték létrehozásához. Így például ugyanazt a kódot lehet átírni, mint:
String stringValue(Program pgm) throws BASICRuntimeError { StringBuffer sb = new StringBuffer(); sb.append(this.value(pgm)); return sb.toString(); }
Ha pedig a fenti kódot használjuk, akkor kizárhatjuk a isString
használatát, mert minden kifejezés karakterlánc értéket adhat vissza. Ezenkívül módosíthatja a value
metódust, hogy megpróbáljon visszaadni egy számot, ha a kifejezés egy karakterláncra értékel, a valueOf
java.lang.Double
metódusán keresztül futtatva. Sok nyelven, mint például a Perl, TCL és REXX, ez a fajta amorf gépelés használják nagy előnye. Mindkét megközelítés érvényes, és a tolmács tervezése alapján kell választania. A Basicben a tolmácsnak hibát kell visszaadnia, amikor egy karakterláncot rendelnek egy numerikus változóhoz, ezért az első megközelítést választottam (hiba visszaadása).
ami a tömböket illeti, különböző módon tervezheti meg a nyelvét, hogy értelmezze őket. C a tömbelemek körüli szögletes zárójeleket használja, hogy megkülönböztesse a tömb indexhivatkozásait azoktól a függvényhivatkozásoktól, amelyek zárójelekkel rendelkeznek az argumentumaik körül. A basic nyelvtervezői azonban úgy döntöttek, hogy zárójeleket használnak mind a függvényekhez, mind a tömbökhöz, így amikor a NAME(V1, V2)
szöveget látja az elemző, ez lehet függvényhívás vagy tömbhivatkozás.
a lexikális elemző különbséget tesz a zárójelben szereplő tokenek között, először feltételezve, hogy függvények, és teszteli azokat. Ezután megnézi, hogy kulcsszavak vagy változók-e. Ez a döntés megakadályozza, hogy a program meghatározza a “SIN” nevű változót.”Minden olyan változót, amelynek neve egy függvénynévnek felel meg, a lexikai elemző függvény tokenként adja vissza. A második trükk, amelyet a lexikai elemző használ, annak ellenőrzése, hogy a változó nevét azonnal követi-e `(‘. Ha igen, akkor az analizátor feltételezi, hogy tömbhivatkozás. Ha ezt elemezzük a lexikális analizátorban, akkor a `MYARRAY ( 2 )
‘ karakterláncot nem értelmezzük érvényes tömbként (jegyezzük meg a változó neve és a nyitott zárójel közötti helyet).
a tömbök megvalósításának utolsó trükkje a Variable
osztály. Ezt az osztályt egy változó példányához használjuk, és amint azt a múlt havi oszlopban tárgyaltam, ez egy Token
alosztály. Ugyanakkor van néhány gépe is a tömbök támogatására, és ezt mutatom be alább:
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;
a fenti kód a változóhoz társított példányváltozókat mutatja, mint a ConstantExpression
osztályban. Az egyik, hogy a választás az osztályok számát kell használni, szemben a komplexitás egy osztály. Az egyik tervezési lehetőség lehet egy Variable
osztály felépítése, amely csak skaláris változókat tartalmaz, majd hozzáad egy ArrayVariable
alosztályt a tömbök bonyodalmainak kezeléséhez. Úgy döntöttem, hogy összekapcsolom őket, a skaláris változókat lényegében 1 hosszúságú tömbökké alakítva.
ha elolvassa a fenti kódot, tömbindexeket és szorzókat fog látni. Ezek azért vannak itt, mert a BASIC többdimenziós tömbjeit egyetlen lineáris Java tömb segítségével valósítják meg. A lineáris index a Java tömbbe manuálisan kerül kiszámításra a multiplikátor tömb elemeinek felhasználásával. Az alapprogramban használt indexek érvényességét úgy ellenőrizzük, hogy összehasonlítjuk őket az indexek ndx tömbjének maximális jogi indexével.
például egy 10, 10 és 8 dimenziójú ALAPTÖMB esetében a 10, 10 és 8 értékek az ndx-ben vannak tárolva. Ez lehetővé teszi az expresszióértékelő számára, hogy teszteljen egy “index határon kívüli” feltételt az ALAPPROGRAMBAN használt szám összehasonlításával az ndx-ben tárolt maximális jogi számmal. A példánkban szereplő szorzó tömb az 1, 10 és 100 értékeket tartalmazza. Ezek az állandók azokat a számokat képviselik, amelyeket egy többdimenziós tömbindex specifikációból lineáris tömbindex specifikációvá történő leképezéshez használnak. A tényleges egyenlet:
Java Index = Index1 + Index2 * az Index1 + Index3 maximális mérete * (az Index1 * MaxSizeIndex 2 maximális mérete)
a Variable
osztály következő Java tömbje az alábbiakban látható.
Expression expns;
az expns tömb a “A(10*B, i)
néven írt tömbök kezelésére szolgál.”Ebben az esetben az indexek valójában kifejezések, nem pedig állandók, ezért a hivatkozásnak mutatókat kell tartalmaznia azokra a kifejezésekre, amelyeket futás közben értékelnek. Végül van ez a meglehetősen csúnya kinézetű kóddarab, amely kiszámítja az indexet attól függően, hogy mit adtak át a programban. Ez a privát módszer az alábbiakban látható.
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; }
a fenti kódot tekintve megjegyezzük, hogy a kód először ellenőrzi, hogy a tömb hivatkozásakor a megfelelő számú indexet használták-e, majd hogy minden index az adott index törvényes tartományán belül volt. Ha hibát észlel, kivételt dob a tolmács. A numValue
és stringValue
metódusok a változó értékét számként vagy karakterláncként adják vissza. Ez a két módszer az alábbiakban látható.
double numValue(int ii) throws BASICRuntimeError { return nArrayValues; } String stringValue(int ii) throws BASICRuntimeError { if (subType == NUMBER_ARRAY) return ""+nArrayValues; return sArrayValues; }
vannak további módszerek a változó értékének beállítására, amelyek itt nem jelennek meg.
az egyes darabok megvalósításának összetettségének nagy részét elrejtve, amikor végre eljön az ideje az alapprogram végrehajtásának, a Java kód meglehetősen egyszerű.
a kód futtatása
az alapvető utasítások értelmezésére és végrehajtására szolgáló kódot a
run
módszer
Program
osztály. Ennek a módszernek a kódja az alábbiakban látható, és átmegyek rajta, hogy rámutatjak az érdekes részekre.
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 }
a fenti kód azt mutatja, hogy a run
módszer egy InputStream
és egy OutputStream
– et használ a végrehajtó program “konzoljaként”. A 3. sorban az e felsorolási objektum az stmts nevű gyűjtemény utasításkészletére van állítva. Ehhez a gyűjteményhez egy bináris keresési fa variációját használtam, amelyet “vörös-fekete” fának hívtak. (A bináris keresési fákkal kapcsolatos további információkért lásd az előző oszlopomat az Általános gyűjtemények felépítéséről.) Ezt követően két további gyűjtemény jön létre-az egyik a Stack
, a másik pedig a Vector
használatával. A verem ugyanúgy használható, mint a verem bármely számítógépen, de a vektort kifejezetten az alapprogram adatnyilatkozataihoz használják. A végső gyűjtemény egy másik vörös-fekete fa, amely az alapprogram által meghatározott változók referenciáit tartalmazza. Ez a fa az a szimbólumtábla, amelyet a program futása közben használ.
az inicializálás után a bemeneti és kimeneti adatfolyamok be vannak állítva, és ha e Nem null, akkor a deklarált adatok gyűjtésével kezdjük. Ez a következő kód szerint történik.
/* 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); } }
a fenti ciklus egyszerűen megvizsgálja az összes utasítást, és minden talált ADATUTASÍTÁST végrehajtanak. Az egyes ADATUTASÍTÁSOK végrehajtása beszúrja az adott utasítás által deklarált értékeket az adattár vektorába. Ezután végrehajtjuk a megfelelő programot, amelyet a következő kóddarab segítségével hajtunk végre:
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); }
amint az a fenti kódból látható, az első lépés az e. a következő lépés az első utasítás beolvasása az s változóba, majd a végrehajtási ciklus beírása. Van néhány kód, amely ellenőrzi a bemeneti adatfolyam függőben lévő bemenetét, hogy lehetővé tegye a program előrehaladásának megszakítását a program beírásával, majd a hurok ellenőrzi, hogy a végrehajtandó utasítás ADATNYILATKOZAT lenne-e. Ha igen, akkor a hurok kihagyja az utasítást, ahogy már végrehajtották. Az összes adatutasítás végrehajtásának meglehetősen bonyolult technikájára azért van szükség, mert a BASIC lehetővé teszi, hogy a READ utasításnak megfelelő ADATUTASÍTÁSOK bárhol megjelenjenek a forráskódban. Végül, ha a nyomkövetés engedélyezve van, a rendszer kinyomtat egy nyomkövetési rekordot, és meghívja a s = s.execute(this, in, pout);
nagyon nem nyomó utasítást. A szépség az, hogy az alapfogalmak könnyen érthető osztályokba történő beágyazásának minden erőfeszítése triviálissá teszi a végső kódot. Ha ez nem triviális, akkor talán van egy nyom, hogy lehet, hogy egy másik módja annak, hogy szét a design.
becsomagolás és további gondolatok
a tolmácsot úgy tervezték, hogy szálként futhasson, így egyszerre több COCOA tolmács szál is futhat a programterében. Továbbá a funkcióbővítés használatával olyan eszközt tudunk biztosítani, amellyel ezek a szálak kölcsönhatásba léphetnek egymással. Volt EGY program az Apple II-hez, majd később a PC-hez és a Unix-hoz, C-robots néven, amely interakciós” robot ” entitások rendszere volt, amelyeket egy egyszerű alapvető származékos nyelv segítségével programoztak be. A játék sok órányi szórakozást nyújtott nekem és másoknak, de kiváló módja volt a számítás alapelveinek bemutatására a fiatalabb diákok számára (akik tévesen azt hitték, hogy csak játszanak, és nem tanulnak). A Java alapú tolmács alrendszerek sokkal erősebbek, mint a Java előtti társaik, mert azonnal elérhetők bármely Java platformon. COCOA futott Unix rendszerek és Macintoshes ugyanazon a napon kaptam dolgozik egy Windows 95 alapú PC. Míg a Java – t a szál vagy az ablak eszközkészlet implementációinak inkompatibilitása veri fel, ezt gyakran figyelmen kívül hagyják: sok kód “csak működik.”
Chuck McManis jelenleg a Freegate Corp. rendszerszoftverének igazgatója, amely egy vállalkozás által finanszírozott induló vállalkozás, amely az internetes piac lehetőségeit vizsgálja. Mielőtt csatlakozott a FreeGate-hez, Chuck a Java csoport tagja volt. Csatlakozott a Java csoporthoz közvetlenül a FirstPerson Inc. megalakulása után. a portable OS csoport tagja volt (a Java operációs rendszerért felelős csoport). Később, amikor a FirstPerson feloszlott, ő maradta csoporttal a Java platform alpha and betaversions fejlesztésén keresztül. Ő hozta létre az első” All Java ” honlapot az interneten, amikor 1995 májusában elvégezte a Sun javaversion kezdőlapjának programozását. Emellett kifejlesztette az acryptographic library-t a Java-hoz és a Java classloader verzióit, amelyek digitális aláírások alapján képesek szűrni az osztályokat.Mielőtt csatlakozott a Firstpersonhez, Chuck az operációs rendszerekben dolgozotta SunSoft területe, hálózati alkalmazások fejlesztése, ahol tettea NIS + kezdeti tervezése. Is, nézd meg a kezdőlapot. : END_BIO
Tudjon meg többet erről a témáról
- itt találhatók a fent hivatkozott forrásfájlokra mutató linkek:
- ConstantExpression.java
- FunctionExpression.java
- Program.java
- utasítás.java
- StringExpression.java
- változó.java
- VariableExpression.java
- és itt van egy .A forrásfájlok ZIP fájlja:
mélység.zip - “Uncommon Lisp” – Java nyelven írt Lisp tolmács
http://user03.blue.aol.com/thingtone/workshop/lisp.htm - Mike Cowlishaw Java nyelven írt NetREXX tolmácsa
http://www2.hursley.ibm.com/netrexx/ - a USENET BASIC GYIK egy régi példánya (még mindig hasznos információkkal rendelkezik benne.)
http://whitworth.me.ic.ac.uk/people/students/djbur/qbasic.htm - kakaó, Java-ban írt alapvető tolmács
http://www.mcmanis.com/~cmcmanis/java/javaworld/examples/BASIC.html - Chuck Java források oldala
http://www.mcmanis.com/~cmcmanis/java/javaworld/ - Tcl tolmács Java nyelven
http://www.cs.cornell.edu/home/ioi/Jacl/
- :
- “Hogyan építsünk tolmácsot Java – ban, 2.résza szerkezet”
a trükk az alaposztályok összeállításához egy egyszerű tolmács számára. - “Hogyan építsünk egy tolmácsot a Java-ban, 1.részaz alapok”
a szkriptnyelvet igénylő összetett alkalmazásokhoz a Java használható a tolmács megvalósítására, szkriptkészítési képességek hozzáadásával bármely Java alkalmazáshoz. - “lexikális elemzés, 2.Részalkalmazás létrehozása”
a StreamTokenizer objektum használata interaktív számológép megvalósításához. - ” Lexical analysis and JavaPart 1″
Ismerje meg, hogyan konvertálhat ember által olvasható szöveget géppel olvasható adatokká a StringTokenizer és StreamTokenizer osztályok segítségével. - “Kód újrafelhasználás és objektum-orientált rendszerek”
segítő osztályt használ a dinamikus viselkedés kikényszerítésére. - ” konténer támogatás objektumok Java 1.0.2″
szervező objektumok egyszerű, ha őket konténerekbe. Ez a cikk végigvezeti Önt egy konténer tervezésén és megvalósításán. - ” a Java class loaders alapjai”
a Java architektúra ezen kulcsfontosságú összetevőjének alapjai. - ” nem használja a szemétgyűjtést”
minimalizálja a kupacverést a Java programokban. - “Threads and applet and visual controls”
a sorozat utolsó része több adatcsatorna olvasását vizsgálja. - “kommunikációs csatornák használata kisalkalmazásokban, 3.rész”
Visual Basic stílusú technikák fejlesztése az kisalkalmazások tervezéséhez-és a hőmérsékletek konvertálása a folyamat során. - ” Synchronizing threads in Java, Part II”
Ismerje meg, hogyan írhat adatcsatorna osztályt, majd hozzon létre egy egyszerű példaalkalmazást, amely szemlélteti az osztály valós megvalósítását. - ” Synchronizing threads in Java”
Chuck McManis, a Java csapat korábbi fejlesztője végigvezeti Önt egy egyszerű példán, amely bemutatja, hogyan kell szinkronizálni a szálakat a megbízható és kiszámítható applet viselkedés biztosítása érdekében.