Az Anvil a C-hez hasonlító nyelvek osztályba tartozik, de sok tulajdonságot vett át a Java, a Python nyelvekből, és egy keveset pedig a Perl-ből.
A nyelvtan nem mondható jól formáltnak. Megpróbáltak jól olvasható nyelvtant alkotni. Néhány szabály ismételve lett a könnyebb érthetőség kedvéért. Rövid magyarázat a szintaxishoz:
A
A egy szabály AN
A szabály és N az informális
név a szabályhoz A B ..
jelentése szekvencia. ( A B ..)
jelentése szekvencia. ( A | B | .. | C )
jelentése az, hogy válassz egyet.[ A ]
jelentése, hogy A opcionális A ?
jelentése, hogy A opcionális A * jelentése, hogy
A-t megismételhetjük 0..N alkalommal
A +
jelentése, hogy A-t legalább 1 szer szerepeltetni kell.
module := "module" [
symbol
module := module-decls
module-decls =(
import |
constant |
variable |
function |
namespace |
class |
interface ) *
import := "import"
import-source [ import-as ] ";"
import := "import"
import-source ":" import-list ";"
import-name :=
symbol
( "."
symbol
)*
import-source := (
string-literal
import-as := "as"
symbol
import-list := "*"
import-list := import-entity ( ","
import-entity )*
import-entity := import-name ["." "*"] [
import-as ]
constant := "const"
constant-decl ( "," constant-decl )* ";"
constant-decl :=
symbol
variable := "var"
variable-decl ( "," variable-decl )* ";"
variable-decl :=
symbol
namespace := "namespace" namespace-name
"{" (
import |
constant |
variable |
function |
namespace |
class ) * "}"
namespace-name :=
symbol
( "."
symbol
)*
entity
:= ( "module" "."
symbol
| symbol
) ( "."
symbol
) *
class :=
"class"
symbol
[ "extends"
entity
[ "implements"
entity
"{"
(
import
|
constant
|
variable
|
function
| "static"
variable
| "static"
function
|
class
)*
"}"
entity
:= ( "module" "."
symbol
| symbol
) ( "."
symbol
) *
interface :=
"interface"
symbol
"extends" [
entity
"{"
(
import
|
constant
|
variable
| "static"
function
|
interface-method
|
interface
)*
"}"
arguments := [
argument ( "," argument )* ] [ ".."
symbol
argument :=
symbol
interface-method := "function"
symbol
arguments := [ argument ( "," argument )* ] [
".."
symbol
argument :=
symbol
function :=
["synchronized"] "function"
symbol
"{"
(
function
|
import
|
statement )
*
"}"
arguments := [
argument ( "," argument )* ] [ ".."
symbol
argument :=
symbol
inline-function := "{" "|" arguments "|"
statement
* "}"
inline-function := "{" "||"
statement *
"}"
statement
:= (
assert
|
break |
catch
|
continue |
empty
|
exit |
expr-stmt
|
finally |
if
|
print |
return
|
synchronized |
throw
|
try |
yield
| [
label ]
block
| [
label ]
do
| [
label ]
for
| [
label ]
foreach | [
label ]
switch | [
label ]
while
)
assert
:= "assert"
expr
break
:= "break" [
symbol
continue := "continue" [
symbol
continue := "continue" [
symbol
continue := "continue" [
symbol
empty
:= ";"
exit := "exit" [
expr-list
expr-stmt :=
expr-start
[
stmt-modifier ] ";"
print
:= ("print" | "println" | "printbr" ) [
print-expr-list
print-expr-list :=
expr-start
( ( "," )+
expr-start
) *
return
:= "return" [
expr-list
throw
:= "throw"
expr-list
yield
:= "yield"
expr-list
stmt-modifier := ( "if"
expr
label :=
symbol
block
:= "{"
statement * "}"
catch
:= "catch" "("
assignable-expr
catch
:= "catch" "("
assignable-expr
catch
:= "catch" "("
assignable-expr
do := "do"
statement
"while" "("
expr-start
finally := "finally"
statement
for
:= "for" "(" exprs ")"
statement
for-exprs := [ for-expr-list
for-expr-list :=
expr-start
( ","
expr-start ) *
foreach := "foreach" "(" [[[[
foreach-expr-list
[ foreach-expr-list
foreach-expr-list :=
assignable-expr
if := "if" "("
expr-start
switch :=
"switch" "("
expr-start
"{"
( "case"
expr
| "default" ":"
statement *
) *
"}"
synchronized := "synchronized" "("
expr-start
try
:= "try"
statement (
catch
)* [
finally ]
while
:= "while" "("
expr-start
expr-start
:= assignment |
expr
expr-list :=
expr (
"," expr
)*
assignable-expr := ["&"]
identifier accessor
assign-target :=
assignable-expr
assign-targets := assign-target (","
assign-target ) *
assignment := assign-targets
"="
expr-list
assignment := assign-targets
"+="
expr-list
assignment := assign-targets
"-="
expr-list
assignment := assign-targets
"*="
expr-list
assignment := assign-targets
"/="
expr-list
assignment := assign-targets
"%="
expr-list
assignment := assign-targets
"&="
expr-list
assignment := assign-targets
"?="
expr-list
expr
:=
foreach-expr |
pipe-expr
|
map-expr |
cond-expr |
range-expr
|
or-expr |
xor-expr
|
and-expr |
eq-expr
|
rel-expr |
in-expr
|
add-expr |
mul-expr
|
match-expr |
unary-expr
|
cast-expr |
augment-expr |
is-expr
| has-expr
| lazy-expr
|
primary
foreach-expr :=
expr "foreach"
inline-function
pipe-expr :=
expr
map-expr :=
expr
cond-expr :=
expr
cond-expr :=
expr
cond-expr :=
expr
range-expr :=
expr
range-expr :=
expr
range-expr := ".."
expr
range-expr := ".."
or-expr :=
expr
"||" expr
xor-expr :=
expr
"^^" expr
and-expr :=
expr
"&&" expr
eq-expr
:= expr
"==" expr
eq-expr
:= expr
"!=" expr
eq-expr
:= expr
"==="
expr
eq-expr
:= expr
"!=="
expr
eq-expr
:= expr
"<=>"
expr
eq-expr
:= expr
"<==>"
expr
rel-expr :=
expr ">"
expr
rel-expr :=
expr
">=" expr
rel-expr :=
expr "<"
expr
rel-expr :=
expr
"<=" expr
in-expr
:= expr
in-expr
:= expr
add-expr :=
expr "+"
expr
add-expr :=
expr "-"
expr
add-expr :=
expr "&"
expr
mul-expr :=
expr "*"
expr
mul-expr :=
expr "/"
expr
mul-expr :=
expr "%"
expr
match-expr :=
expr
match-expr :=
expr
unary-expr := "!"
expr
unary-expr := "+"
expr
unary-expr := "-"
expr
unary-expr := "*"
expr
unary-expr := "copyof"
expr
unary-expr := "cloneof"
expr
unary-expr := "sizeof"
expr
unary-expr := "classof"
expr
cast-expr := "(" "boolean" ")"
expr
cast-expr := "(" "int" ")"
expr
cast-expr := "(" "float" ")"
expr
cast-expr := "(" "string" ")"
expr
augment-expr := "++"
assignable-expr
augment-expr := "--"
assignable-expr
augment-expr :=
assignable-expr "++"
augment-expr :=
assignable-expr "--"
is-expr :=
expr
"is" ["!"] "defined"
is-expr :=
expr
"is" ["!"] "undefined"
is-expr :=
expr
"is" ["!"] "null"
is-expr :=
expr
"is" ["!"] "boolean"
is-expr :=
expr
"is" ["!"] "int"
is-expr :=
expr
"is" ["!"] "float"
is-expr :=
expr
"is" ["!"] "string"
is-expr :=
expr
"is" ["!"] "&"
is-expr :=
expr
"is" ["!"] ".."
is-expr :=
expr
"is" ["!"] "=>"
is-expr :=
expr
"is" ["!"] "(" ")"
is-expr :=
expr
"is" ["!"] "{" "}"
is-expr :=
expr
"is" ["!"] "[" "]"
is-expr :=
expr
"is" ["!"] "class"
is-expr :=
expr
"is" ["!"]
entity
has-expr :=
expr
"has" ["!"]
symbol
has-expr :=
expr
"has" ["!"] "("
expr ")"
lazy-expr := "^"
primary
primary := (
parenthesized |
literal |
import-expr |
defined-expr |
delete-expr |
list-expr |
tuple-expr |
array-expr |
type-expr |
new-expr |
inline-function |
call-expr |
ref-expr
|
identifier )
accessor *
parenthesized := "("
expr ")"
import-expr :=
import "("
expr
defined-expr := "defined"
identifier
defined-expr := "defined" "("
identifier ")"
delete-expr := "delete"
identifier
delete-expr := "delete" "("
identifier ")"
tuple-expr := "(" ")"
tuple-expr := "("
expr ","
")"
tuple-expr := "("
expr-list
[","] ")"
list-expr := "\{"
expr-list
[","] "}"
list-ctor := "\{" comprehension-foreach "}"
comprehension-foreach := "foreach" "(" ...
")" comprehension
comprehension-if ::= "if" "("
expr ")"
comprehension
comprehension := comprehension-foreach |
comprehension-if |
expr
array-expr := "["
array-mapping (","
array-mapping )* [","] "]"
array-expr := "[" comprehension-foreach "]"
array-mapping :=
expr
comprehension-foreach := "foreach" "(" ...
")" comprehension
comprehension-if ::= "if" "("
expr ")"
comprehension
comprehension := comprehension-foreach |
comprehension-if |
expr
type-expr := ( "boolean" | "int" | "float" | "string"
)
new-expr := "new"
identifier
new-expr := "new"
identifier
param := [
symbol
parameters := param ( "," param )*
identifier := [ "var" ]
[ symbol
| "module" | "class" | "static" | "this" | "super"
] ( "." (
symbol
| "this" ) ) *
[ "." ( "class"
| "sizeof" | "copyof"
| "cloneof" ) ]
call-expr :=
identifier
call-expr :=
identifier
parameters := param ( "," param )*
param := [
symbol
ref-expr := "&"
identifier
accessor :=
acc-call |
acc-closure-call |
acc-invoke |
acc-attribute |
acc-reference
acc-call := "(" parameters ")"
parameters := param ( "," param )*
param := [
symbol
acc-closure-call :=
inline-function
acc-invoke := "."
symbol
acc-invoke := "." "("
expr ")"
"(" parameters ")"
acc-invoke := "."
symbol
acc-invoke := "." "("
expr ")"
inline-function
parameters := param ( "," param )*
param := [ "@" ]
expr
acc-attribute := "."
symbol
acc-reference := "["
expr-list
"]"
acc-reference := "[" "]"
literal :=
int-literal |
float-literal |
string-literal |
pattern-literal | "inf" | "false"
| "true" | "undefined"
Az Anvil programot egy elő-feldolgozó komponens olvassa el.. Az elő-feldolgozó a tokenek listáját a lexikális elemzőtől kapja.
A lexikális elemző az ISO-8859-1 karakter készletet használja.
Ebben vannak Megjegyzések, Azonosítók, kulcsszavak és Literálok.
Megjegyzések:
A megjegyzések törölve lesznek, nem lesz belőlük token. Négy fajta megjegyzés van:.
1. Egyszerű sor megjegyzés, ami egy hash karakterrel (#
) kezdődik
és a sor végéig tart.
# # $Id: index.nvl,v 1.38 2002/01/31 14:35:18 jkl Exp $ #
2. Egyszerű sor megjegyzés, ami 2 per karakterrel (//
) kezdődik
és a sor végéig tart.
// FIXME: Quick hack
3. Több soros megjegyzés, ami egy /*
kezdődik és */
végződik.
/* * Comment example */
4. Dokumentációs megjegyzés, ami /** kezdődik
és */
végződik. Nézd meg az
Anvil dokumentációt
részletekért..
/** * Sets the name of blarg. * @param name New name */ function setName(name) { ... }
Azonosítók és Kulcsszavak:
Az azonosítók alfa-numerikus karakterek szekvenciájából állnak, és
tartalmazhatják az aláhúzást (_
). Minden ISO-Latin betű
használható. Habár az azonosítók nem kezdődhetnek számmal. Az azonosítók
kis-nagybetű érzékenyek, de nincs korlátozás a hosszukra vonatkozólag.
Néhány azonosítót foglalt szónak nevezünk, amik speciális jelentéssel bírnak. A kulcsszavak:
as assert boolean break case catch class classof const copyof cloneof continue default defined delete do else extends exit false finally float foreach for function if implements import in inf interface int is has module namespace new null println printbr print return sizeof string static super switch synchronized this throw true try typeof undefined var while yield
Habár a kulcsszavak nem használhatók általános azonosítóként, azért ez
elkerülhető a dollár jellel. ($
). Ellentétben más nyelvekkel a
dollár jel nem jelez előre egy változót; csupán ez is használható eszköz.
Példák:
$if = 1; $for = 10;
Néhány kulcsszó konstansokat jelöl, akárcsak más nyelvi konstrukciókban. Ezek:
true false null undefined inf
Néhány az anvil.lang-ben található típusokat jelöli. Ezek:
string int float
Literálok:
A literálok konstans értékeket jelölnek, amelyek valamilyen típus szerint épülnek fel.
A literálok lehetnek: Sztringliterálok, Egész literálok, Lebegő pontos literálok, Reguláris kifejezések és Operátorok és határoló jelek.
Sztring literálok:
Ezeknek van néhány különleges tulajdonságuk. A sztringeknek van kezdő és bezáró jelük, amely vagy egyszerű felső aposztróf ('), vagy macskaköröm ("), vagy ferde aposztróf (`). Nem lehet benne sortörés, vagy kivételes karakterek, mint backslash.
A hosszú sztringek tripla macskakörömmel kezdődnek és végződnek. ("""). Ezek lehetnek több sorban is.
A Backslash sztring egy backslash-el (\) kezdődik rögtön követve a szimbólummal.
Az alábbiak beágyazott kifejezések lehetnek a sztringen belül:
Jel | Jelentése |
---|---|
\\ | Backslash |
\' | Egyszerű aposztróf |
\" | Macskaköröm |
\` | Ferde Aposztróf |
\b | Csengő |
\f | Formázott |
\n | Sortörés |
\r | Kocsi visszatér |
\t | Horizontális tabulátor |
\xNN | 8-bites unicode karakter hexadecimálisan NN |
\xNNN | 8-bit unicode karakter oktálisan NNN |
\uNNNN | 16-bit unicode karakter hexadecimálisan NNNN |
Több sztringet lehetőségünk van eggyé konkatenálni. A megkötés csupán annyi, hogy egyik sztring sem tartalmazhat megjegyzéseket vagy white spaceket.
Példák:
str = "hello\nworld\n"; str = 'hello\n' `world\n`; // same as above str = 'hello\n' `world\n`; // same as above str = \Hello \World; // "HelloWorld" greeting = """Hello! Time is now ${anvil.time.getTime()}. Wuzzup?"""; name = \anvil;
A legfelsőbb szintű kifejezések (expr-start) tartalmazhatnak felsorolási vagy érték kifejezésére szánt típusokat. Illetve a kifejezéseket használhatjuk mint egy feltétel kifejezéseként, utasításban, vagy akár állhat önállóan egymagában.
expr := foreach-expr | pipe-expr | map-expr | cond-expr | range-expr | or-expr | xor-expr | and-expr | eq-expr | rel-expr | in-expr | add-expr | mul-expr | match-expr | unary-expr | cast-expr | augment-expr | is-expr | has-expr | lazy-expr | primary
Az utasítások végrehajtása az elkerülhetetlen útja annak, hogy csináljunk is
valamit.
A Definíciós utasításokat a nyelvi konstrukciók bevezetésére használjuk. Ide azok az eszközök tartoznak amelyekkel a kifejezések és más utasítások dolgoznak.
A definíciós utasítások vagy entitásokat definiálnak vagy entitásokat importálnak. Ezek lehetnek:
Az Egyszerű utasítás az ami nem tartalmaz másik utasítást. Ennek három típusa:
Utasítások, amelyek a végrehajtás folyamatáért felelősek: Assert, Break, Continue, Exit, Return, Throw, Yield
Nyomtatási utasítás: Print
Üres utasítás: Empty utasítás
A Kifejezés
utasítás tartalmaz kifejezést:
expr-stmt := expr-start [ stmt-modifier ] ";"
Az Összetett utasítások tartalmazhatnak más utasításokat, és ők tipikusan arra használandók, hogy átvegyék a vezérlést.
statement := ( assert | break | catch | continue | empty | exit | expr-stmt | finally | if | print | return | synchronized | throw | try | yield | [ label ] block | [ label ] do | [ label ] for | [ label ] foreach | [ label ] switch | [ label ] while )
Mint már említettem az Anvilen belül minden Objektum. Még az egészek és lebegőpontos kifejezések is. Az objektum valahol az osztály és instancia között helyezkedik el.
Amikor egy objektum létrejön, akkor egy identitást kap. Ez jelenthet egy rögzített pozíciót a memóriában. Az addressOf() függvény segítségével a címe le is kérdezhető.
Egy objektum típusa lekérdezhető a classof obj
vagy a meta attribútumok obj.class segítségével
.
Mindkét kifejezés egy objektum típussal tér vissza, amely megtalálható az
anvil.runtime.Type-ban.
Néhány Objektum lehet megváltoztathatatlan, ami azt jelenti, hogy a létrejötte után a tartalma nem megváltoztatható. Az ilyen objektum tartalmaz egészeket, lebegőpontos típust, sztringet, sablonokat.
A legtöbb objektum tartalma megváltoztatható. A felhasználó által definiált osztályokkal erre jó példákat lehet adni.
Amikor egy objektum létrejött az sohase szűnik meg explicit módon. Habár a Java virtuális gép miatt előfordulhat, hogy többé nem lesz elérhető, aztán a szemétgyűjtő algoritmusnak köszönhetően az objektumok törlődnek, hogy a memória felszabadulhasson.
Minden osztály egy modulhoz tartozik. A modul egy osztály és függvény gyűjtemény. Egy modulhoz egy instancia tartozik.
Az osztályok és modulok három különböző fába csoportosíthatók. Mindegyikük elérése kissé különböző, de érthető.
anvil.lang.object
.
Itt található számos callbacks methodus amik aláhúzással kezdődnek.
anvil.lang.object
.
java.lang.Object
Az Anvil használ statikus beágyazást. A beágyazáskor neveket vagy
ponttal szeparált neveket használunk (pl. com.acme.tool
)
amik az entitáshoz kapcsolódnak. Amikor a statikus beágyazás nem alkalmazható,
akkor használjuk a dinamikus beágyazást, ami futás időben történik.
Instanciáknál akkor történik, amikor egy objektumra a
data.toString()
metódust meghívja .
Az entitások az alábbiak lehetnek:
Az entitások hatókörökben vannak definiálva. Hatókörök, amelyek a szkriptben deklarálhatók:
Amikor beágyazáskor egy névre keresünk, akkor a keresés mindig az eredeti hatókörtől kezdődik és folytatódik lefelé egészen addig amíg egy entitást nem talál. Ha minden más hatókór érvénytelen , akkor az utolsó kipróbált hatókör mindig az anvil.lang modul és hiba generálódik, ha nem talált egyezést.
Az anvil verem alapú engedély ellenőrzést használ annak a megvizsgálására, hogy jogosult vagy e egy akció végrehajtására.
Alapértelmezés szerint az ellenőrzés ki van kapcsolva, és egyébként is az ellenőrzés engedélyezéséhez szükség van legalább egy vezérlési elv (policy) beállítására. A vezérlési elvek domainonként állíthatók.
Az elvek tartalmaznak egy jogosultság gyűjteményt, amelyek a jogosultságokkal együttesen alkotják a finom-hangolt biztonsági elvet. Futási időben megszerezhetsz jogosultsági köröket, de ha ez egyszer ez már megtörtént, akkor futás időben már nem vehető vissza.
A Citizens és a tribes is tartalmazhatnak jogosultságokat..
Amikor egy jogosultsághoz kötött akció (mint fájl olvasás, írás vagy socket létrehozás) végrehajtódna, akkor előbb konzultál a biztonsági elvel:
anvil.lang.AccessDenied
kivétel. Mint ahogyan azt korábban említettem az Anvil egy szerver oldali alkalmazás, amely a Java nyelvre épülő szkript nyelvből és egy template nyelvből áll. Szóval az Anvil igazából két nyelvet tömörít magába. Az alábbiakban a template nyelvről lesz szó.
Az Anvil sablonok nagyon egyszerű szkriptek. A kódolás alapja ugyanaz, de a funkciók korlátozva vannak.
A sablonokat felosztja számítási utasításokra, címkékre, adatokra és megjegyzésekre az anvil.parser.Parser, amely rugalmas, de alapvetően címke utasítás orientált előfeldolgozó. Érdekessége, hogy sohasem generál hibát. Az előfeldolgozó funkciói az anvil.xml.parse()-en kersztűl használhatóak..
A sablon nyelvtan áttekintése itt található.
A <module>, <namespace>, <class>, <function>, <var> és <const> címkék a nyelv deklarálásának konstruktív eszközei.
A legtöbb sablon utasítás címke funkciója megfelel a hasonló szkript utasítás funkciójának.
További információkat a karakter adatok kezeléséről itt olvashatsz.
Saját címkék természetesen definiálhatók.
Az Anvil szkript és sablon nyelv a java-stílusú megjegyzéseket használja.
A szkripten belüli megjegyzés szintaxisa a következő:
/** * Sets the name of user. * @synopsis void setUser(User user) * @param user User object * @author zorg */ function setUser(user) { ... }
A sablonon belüli megjegyzés szintaxisa a következő:
<!--/** * Shows the user's information. * @param user User object * ... */--> <function name=showUser param=user>...</function>
A megjegyzések csatolhatók modulokhoz, névterekhez, osztályokhoz, iterfészekhez, fügvényekhez, konstansokhoz és változókhoz.
A következő címkék jelenhetnek meg a szkriptben, sablonokban és Java könyvtárakban:
@attribute identifier text
- Ez a címke nem állhat önállóan, hanem ez egy osztály dokumentáció része lehet. Ezt különböző attribútum elérések megjelölésére használják általában.
@author text
- A szerző feltüntetésére szolgál.
@category text
1- Specifikálja a logikai "kategóriáját" a cél entitásnak.
@default text
- Megjegyzés az alapértelmezett érték feltüntetésére. Csak a
@param
címkével használatos.
@exclude
1- Jelzi, hogy ezt az entitást nem kell megmutatni a dokumentum megjelenítőben.
@operator identifier text
- Ez a címke nem állhat egyedül. Általában egy osztály dokumentáció része. Annak a jelzésére szolgál, hogy a különféle operátorokat mikor használhatja egy instancia vagy egy osztály szintű kérés.
@param identifier text
- Paraméter hozzáadása a "Paraméterek" részhez.
@reference identifier text
- Ez a címke nem állhat egyedül. Általában egy osztály dokumentáció része. A különböző referencia elérések (
self[expr]
) jelzésére szolgál, amelyek egy instancia vagy osztály szintű kéréshez tartoznak.
@return text
- A "Visszatérési" részhez adandó leíró szöveg. Ez lehet egy visszatérési típus, vagy egy érték tartomány is.
@see text
- Egy linket ad a dokumentáció kapcsolódó részeihez.
@since text
- Kiírja a verziót, amely óta ez a rész elérhető.
@throws identifier text
- Jelzi, hogy ezek a kivételek váltódhatnak ki kritikus esetkben.
@type text
- Jelzi a paraméter típusát. Ez a címke csakis a
@param címkével együtt használható.
@version text
- Az API verziójának jelzésére szolgál.
@define identifier text
- Paraméter hozzáadása egy függvényhez vagy metódushoz.
1: Címkéket nem használ a dokumentáció megjelentő.
Ha a címkének van azonosítója, akkor ez opcionálisan mellékelhető egy macskakörömmel ("), ami lehetőséget ad arra, hogy whitespaceket legyenek egy azonosítóban. A következő címkék megjelennek az alap java könyvtárakban, ahol ők szükségesek a dokumentáció szövegkörnyezetének megállapításához:
@class identifier text
@const identifier text
@constructor identifier text
@function identifier text
@interface identifier text
@member identifier text
@method identifier text
@module identifier text
@namespace identifier text
@var identifier text