MokkaScript - ein Interpreter für "simplified Javascript"Seit der dritten Version von ActionScript verzichtet Adobe
ganz auf die "eval"-Funktion, die eigentlich zum Sprachumfang von
Javascript gehört. Mitunter ist es aber ganz praktisch, eine solche
Funktion zur Hand zu haben. Auf dieser Seite wird deshalb mit
"MokkaScript", einem Interpreter für "simplified Javascript", ein
Ersatz für die "eval"-Funktion vorgestellt. ThemenübersichtFolgende Themen stehen derzeit zur Verfügung - klicken Sie
einfach auf einen Beitrag Ihrer Wahl:
Actionscript und "eval" -
Auslöser der MokkaScript-Entwicklung
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| whitespace |
:= |
space | tab | eol |
line-comment | block-comment |
| line-comment |
:= |
"//" ... eol |
| block-comment |
:= |
"/*" ... "*/" |
| boolean |
:= |
"true" | "false" |
| number |
:= |
mantissa [exponent] |
hexadecimal-number | "NaN" | "Infinity" |
| mantissa |
:= |
integer ["."
{digit}] |
| exponent |
:= |
("e" | "E")
["+" | "-"]
integer |
| integer |
:= |
"0" | (("1"..."9")
{digit}) |
| digit |
:= |
"0"..."9" |
| octal-number |
:= |
"0" octal-digit
{octal-digit} |
| octal-digit |
:= |
"0"..."7" |
| hexadecimal-number |
:= |
"0x" hex-digit
{hex-digit} |
| hex-digit |
:= |
"0"..."9"
| "a"..."f" |
"A"..."F" |
| string |
:= |
double-quote ...
double-quote | single-quote ... single-quote |
| escape-sequence |
:= |
"\"" | "\'"
| "\\" | "\/"
| "\b" | "\f" | "\n" | "\r" | "\t"
| "\u" hex-digit hex-digit hex-digit hex-digit |
Im Gegensatz zur lexikalischen Grammatik wird "Weißraum" in
der syntaktischen Grammatik nicht explizit erwähnt, sondern darf
zwischen allen genannten Symbolen in beliebiger Menge auftreten.
| program |
:= |
[statements] eof |
| statements |
:= |
statement {";" statement} |
| statement |
:= | var-statement | expression-statement |
function-statement | if-statement | switch-statement | for-statement | do-statement | while-statement | try-statement | disruptive-statement |
| var-statement |
:= | "var" var-declaration {"," var-declaration} |
| var-declaration | := | identifier ["=" expression] |
| expression-statement | := |
"delete" expression qualification | qualified-name "="} [qualified-name in-situ-operator] expression | qualified-name invocation |
| qualified-name |
:= | identifier [{invocation | qualification}
qualification] |
| function-statement |
:= |
"function" identifier "("
[parameter-list] ")" block |
| if-statement |
:= | "if" "(" expression ")"
block ["else"
block] |
| switch-statement |
:= | [label] "switch" "("
expression ")" "{" {case-clause} [default-clause] {case-clause} "}" |
| case-clause |
:= | "case" expression ":"
[switch-chunk] |
| default-clause | := | "default" ":"
[switch-chunk] |
| switch-chunk |
:= |
[statements ";"]
disruptive-statement ";" |
| for-statement |
:= | [label] for-next-statement |
for-in-statement |
| for-next-statement |
:= | "for" "("
[for-initializer] ";"
[expression] ";" for-incrementor ")" [block] |
| for-initializer |
:= | comma-statement {"," comma-statement} |
| for-incrementor |
:= | comma-statement {"," comma-statement} |
| comma-statement |
:= |
"var" var-declaration |
expression-statement |
| for-in-statement |
:= | "for" "(" ["var"]
identifier "in" expression ")"
block |
| do-statement |
:= | [label] "do" block "while"
"(" expression
")" |
| while-statement |
:= | [label] "while" "("
expression ")" block |
| disruptive-statement |
:= | break-statement | continue-statement | return-statement | throw-statement |
| break-statement | := | "break" [identifier] |
| continue-statement | := | "continue" [identifier] |
| return-statement | := | "return" [expression] |
| throw-statement | := | "throw" expression |
| try-statement |
:= | "try" block ["catch" "("
identifier ")" block]
["finally" block] |
| block |
:= | "{" [statements] "}" |
| expression-statement |
:= | assignment | object-invocation |
object-deletion |
| expression |
:= | literal | identifier | "("
expression ")"
| prefix-operator expression | expression infix-operator expression | expression "?" expression ":" expression | expression invocation | expression qualification | "new" expression invocation | "delete" expression qualification |
| literal |
:= | boolean | number | string | regexp-literal
| object-literal | array-literal | function-literal | "null" | "undefined" |
| object-literal |
:= | "{" object-entry {","
object-entry} "}" |
| object-entry |
:= | (identifier | string) ":"
expression |
| array-literal |
:= | "[" [expression {","
expression}] "]" |
| function-literal |
:= | "function" [identifier]
parameter-list
block |
| parameter-list |
:= | "(" identifier {","
identifier} ")" |
| identifier | := | (letter | "_" | "$")
{letter | digit | "_"
| "$"} |
| prefix-operator |
:= | "+" | "-" | "!"
| “typeof" |
| infix-operator |
:= | "*" | "/" | "%"
| "+" | "-" | "instanceof" | "in" | "<" | "<=" | ">=" | ">" | "===" | "!==" | "||" | "&&" |
| in-situ-operator |
:= | "+=" | "-=" | "*="
| "/=" | "%=" |
| object-creation |
:= | "new" object-invocation |
| object-deletion |
:= | "delete" expression {qualification} |
| object-invocation |
:= | name {qualification} {invocation} |
| invocation |
:= | "(" [expression {","
expression}] ")" |
| qualification |
:= | "." identifier | "["
expression "]" |
| label |
:= |
identifier ":" |
Als
Ersatz für "eval" wurde MokkaScript so konstruiert, daß
es sich möglichst nahtlos in eine bestehende Flash- oder Flex-Umgebung
einpaßt. So kann man beispielsweise von einem MokkaScript-Makro aus
problemlos auf die Objekte und Funktionen der Umgebung zugreifen -
MokkaScript nutzt dasselbe (Paket-spezifische) "Global"-Objekt und
dieselben in Javascript
eingebauten Prototypen wie jedes andere Javascript-Programm auch.
Desweiteren können die innerhalb eines MokkaScript-Makros
erstellten Funktionen unmittelbar als Event-Handler eingesetzt werden -
der Aufruf von MokkaScript-Funktionen unterscheidet sich in nichts vom
Aufruf anderer Funktionen (und Methoden).
Leider sorgt genau dieser Komfort jedoch auch dafür, daß sich
MokkaScript derzeit eher weniger für die Implementierung von Plugins
oder
ähnlichen Komponenten eignet, die innerhalb einer möglichst hermetisch
geschlossenen "Sandbox" ablaufen sollen. Hier ist derzeit noch Vorsicht
geboten - in einer späteren Version soll MokkaScript auch eine
entsprechende Sandbox mitbringen.
Vorbemerkung: die folgende Beschreibung geht davon aus, daß Sie "MokkaScript" innerhalb des "Flex Builder" [6] von Adobe einsetzen. Falls Sie für Ihre Entwicklungen eine andere Umgebung verwenden, müssen Sie die Anleitungen entsprechend anpassen.
Grundsätzlich gibt es drei verschiedene Verfahren für die "MokkaScript"-Integration in eigene "Flex Builder"-Projekte: Sie können
Das erstgenannte Verfahren lohnt sich nur, falls Sie vorhaben, den "MokkaScript"-Interpreter speziell für Ihr vorliegendes Projekt zu modifizieren. Die zweitgenannte Methode ist die einfachste und bietet sich an, wenn Sie sich weder für den Quelltext von "MokkaScript" interessieren noch vorhaben, diesen jemals zu verändern. Falls Sie die Klasse jedoch an eigene Bedürfnisse anpassen und anschließend mehrfach in Ihren Projekten einsetzen möchten, empfiehlt sich die letztgenannte Vorgehensweise.
Im folgenden werden zunächst die Methoden 2 und 3 genauer
beschrieben. Anschließend erfahren Sie, wie Sie "MokkaScript" von Ihrem
Programm aus aufrufen können.
Das Einbinden der fertig übersetzten Klasse in ein eigenes Projekt ist denkbar einfach:
Nach einem Klick auf "Ok" und dem Verlassen des Dialoges steht Ihnen "MokkaScript" zur Verfügung.
Das Einbinden des "MokkaScript"-Interpreter über einen Verweis auf das zugehörige Projekt ist ebenfalls äußerst einfach:
Nach einem Klick auf "Ok" und dem Verlassen des Dialoges steht
Ihnen "MokkaScript" zur Verfügung.
Die zentrale Funktion für die Auswertung eines Ausdruckes lautet:
MokkaScript.ValueOf(SourceCode,GlobalObject)
Darin stehen
Vor der Ausführung des Quelltextes schreibt MokkaScript alle
von Javascript standardmäßig bereitgestellten globalen Werte, Objekte
und Funktionen in das "GlobalObject", so daß beim Aufruf problemlos
auch ein leeres Objekt übergeben werden kann. Eine kleine Anmerkung am
Rande: MokkaScript stellt selbst eine "eval"-Funktion zur Verfügung -
bei Bedarf kann der Interpreter also seinerseits Javascript-Quelltext
interpretieren.
Vom Javascript-Programm nicht behandelte Ausnahmen werden an das aufrufende Programm durchgereicht. Innerhalb des "MokkaScriptDemonstrator" wird der Aufruf von "ValueOf" deshalb in eine "try"-Anweisung eingebettet:
try {
ResultView.text = "";
var Result:* = MokkaScript.ValueOf(CodeEntry.text,GlobalObject);
} catch (Signal:*) {
ResultView.text += String(Signal);
};
Folgende Dateien können von hier aus auf den eigenen Rechner
heruntergeladen werden:
Dies ist die erste, noch nicht ganz vollständige Version des
MokkaScript-Interpreters. Folgende Einschränkungen sollten Sie beachten:
| [1] |
ECMAscript (siehe http://www.ecmascript.org/) ECMAscript ist die standardisierte Form der ursprünglich von Brendan Eich entwickelten Sprache "Javascript". Derzeit dürften sich die meisten Implementierungen noch an der dritten Fassung des Standards orientieren - soeben (d.h. im Dezember 2009) ist jedoch die fünfte Fassung (eine vierte gibt es nicht!) erschienen. |
| [2] |
Brendan Eich mozilla/js/narcissus (siehe http://mxr.mozilla.org/mozilla/source/js/narcissus/) Narcissus ist ein von Brendan Eich höchstselbst entwickelter, quell-offener Interpreter für Javascript, der ebenfalls in Javascript geschrieben ist. |
| [3] |
RIA One The D.eval API (siehe http://www.riaone.com/products/deval/index.html) D.eval ist ebenfalls ein in ActionScript geschriebener, kostenloser Javascript-Interpreter, der als Ersatz für die fehlende "eval"-Funktion in AS3 dienen kann. |
| [4] |
Metal Hurlant AS3 Eval Library (siehe http://eval.hurlant.com/) Die AS3 Eval Library ist ein auf dem Tamarin Compiler aufsetzender Javascript-Interpreter für ActionScript. |
| [5] |
Douglas Crockford Javascript: The Good Parts O'Reilly Media, December 2008 In seinem (auch auf Deutsch erschienenen) Buch
analysiert Douglas Crockford (Entwickler des JSON-Dateiformates und
Mitglied des Standardisierungsgremiums für ECMAscript 5) Syntax und
Semantik der Sprache Javascript/ECMAscript (noch in der dritten Fassung)
und erläutert, welche Eigenschaften der Sprache nützlich sind und
welche man tunlichst meiden sollte. |
| [6] |
Adobe
Flex Builder (siehe http://www.adobe.com/de/products/flex/) Der "Flex Builder" ist eine auf Eclipse aufsetzende Entwicklungsumgebung für Flex- (und Flash-)Anwendungen von Adobe. Obwohl nicht kostenlos, ist der "Flex Builder" (vor allem für Adobe-Verhältnisse) erstaunlich preisgünstig. |
|
|
|
| http://www.Rozek.de/MokkaScript/index_de.html | Stand: 23.12.2009 |