Anotácie, generátor jazykových procesorov YAJCo

Ciele
  1. Oboznámiť sa s anotáciami.
  2. Oboznámiť sa s generátorom jazykových procesorov YAJCo.
  3. Oboznámiť sa so spôsobom použitia anotácií potrebných pre definovanie konkrétnej syntaxe jazyka entít priamo v kóde metamodelu.
  4. Oboznámiť sa so spôsobom konfigurácie projektu pre použitie nástroja YAJCo.
Úvod
    Tento modul bližšie opisuje tento generátor jazykových procesorov a anotácie, ktoré sa používajú na zadefinovanie konkrétnej syntaxe generovaného jazyka.
Postup
  1. Generátor jazykových procesorov (angl. parser generator) je nástroj, ktorý generuje jazykový procesor na základe formálnej špecifikácie tohto procesora (resp. jazyka). Najznámejší príklad generátora jazykových procesorov je YACC. Vstupom generátora je zvyčajne bezkontextová gramatika zapísaná v požadovanom formáte a výstupom je zdrojový kód jazykového procesora. Pre generovania jazykového procesora je odporúčané použiť generátor YAJCo (Yet Another Java Compiler Compiler). Generátor YAJCo umožňuje generovať jazykový procesor priamo z modelu jazyka, ktorý je zapísaný vo forme anotovaných tried jazyka Java. Anotácie slúžia na označovanie jazykových elementov (balík, trieda, metóda, premenná) v programe v podobe štruktúrovaných poznámok. Anotácie nesú informácie, ktoré je možné interpretovať v kontexte anotovaných jazykových elementov. Okrem vstavaných anotačných typov je možné definovať vlastné anotačné typy. Viac informácii o anotáciách v jazyku Java je možné nájsť na nasledujúcich stránkach: Generátor YAJCo je detailnejšie opísaný v publikácii ako súčasť výskumu na Katedre počítačov a informatiky FEI TU Košice.
  2. Konkrétna syntax jazyka je definovaná pre tento generátor prostredníctvom anotovaných konštruktorov tried. Nasledujúci text stručne opisuje anotácie a uvádza ich použitie na príkladoch.
    • @Optional anotácia určuje, že sa pojem v konštrukcii nemusí vyskytnúť. Používa sa na označenie parametra konštruktora.
    • @Range anotácia sa používa pre definovanie minimálneho alebo maximálneho počtu výskytov pojmov v konštrukcii. Anotácia @Range je použiteľná len na označenie parametra konštruktora typu pole. V prípade, že anotácia nie je uvedená pri poli, generátor interpretuje rozsah ako 0 až nekonečno.
    • Anotácia @Before určuje lexikálne symboly, ktoré budú predchádzať označenej konštrukcii. Je ňou možné označiť parameter konštruktora alebo konštruktor.
    • Anotácia @After vymenováva lexikálne symboly, ktoré budú nasledovať za označenou konštrukciou. Je ňou možné označiť parameter konštruktora alebo konštruktor.
    • Anotácia @Separator sa používa na určenie oddeľovača postupnosti pojmov toho istého typu prostredníctvom lexikálneho symbolu. je použiteľná len na označenie parametra konštruktora typu pole.
    • Anotácia @Token sa používa na špecifikáciu lexikálneho symbolu, ktorý je podstatný pre abstraktnú syntax a sémantiku z pohľadu jeho výskytu a zápisu (napr. číslo, identifikátor). Je ňou možné označiť parameter konštruktora.
    • Anotácia @Exclude sa používa na vylúčenie triedy respektíve konštruktora zo spracovania generátorom. Anotáciu je možné použiť na označenie triedy respektíve konštruktora.
    V textovej forme jazyka sú vzhľadom na lineárny charakter tejto formy používané identifikátory. Výskytom pojmov vo vete (napr. premenné, funkcie) sú priradené mená (identifikátory), prostredníctvom ktorých je možné na inom mieste vo vete definovať odkaz na výskyt tohto pojmu. Referencie a identifikátory umožňujú zdieľanie výskytov pojmov vo vete. Identifikátor musí jednoznačne identifikovať daný výskyt pojmu. To ale neznamená, že rôzne výskyty aj tých istých pojmov musia mať rôzne identifikátory. Príkladom môže byť rovnaké meno rôznych premenných v dvoch rôznych procedúrach. Výskyt je teda identifikovaný nielen svojim menom ale aj kontextom, v ktorom sa vyskytuje. Pre potreby definovania identifikátorov a referencií generátor YAJCo obsahuje dva anotačné typy.
    • @Identifier anotácia je určená na označenie jednoznačného identifikátora výskytu pojmu vo vete. Zároveň umožňuje definovať kontext, v ktorom má byť identifikátor jedinečný prostredníctvom hodnoty atribútu unique. Tento atribút je reťazec obsahujúci štandardný XPath výraz. Nasledujúce príklady sú ukážkami použitia anotácie @Identifier. Ako identifikátor pojmu je v oboch prípadoch zvolená premenná name.
    • @References anotácia umožňuje špecifikovať referencie na výskyty pojmov. Generátor YAJCo na základe reflexie vyhľadáva určené objekty prostredníctvom anotácie @References. Identifikátory vo vyhľadaných objektoch musia byť označené prostredníctvom anotácie @Identifier. Nájdené referencie na výskyty špecifikovaných pojmov sú následne uložené prostredníctvom injektáže do objektu (set metóda). Povinný atribút value anotácie @References definuje cieľový pojem. Nasledujúce príklady sú ukážkami použitia anotácie @References. Atribút field anotácie @References, umožňuje odlíšiť premennú na uloženie referencie. Bez uvedenie mena premennej je uložená referencia na základe typu pojmu.
  3. Uvedieme niekoľko príkladov použitia anotácií generátora YAJCo.
    
    public class Condition implements Statement {
        public Condition(
                Expression expression,
                Statement trueStatement,
                @Optional Statement falseStatement) { ... }
        ...
    }
    
    Vo vyjadrení prostredníctvom EBNF zápisu Entity ::= 'entity' <NAME> '{' Property+ '}' zodpovedá nasledujuci konštruktor:
    
    public class Entity implements Named {  
        @Identifier
        private final String name;
    
        @Before("entity")
        public Entity(String name,
                @Before("{") @After("}") @Range(minOccurs = 1) Property[] properties) {
            ...
        }
    }
    
    Zápisu Property ::= <NAME> ':' Type (Constraint (',' Constraint)*)? zodpovedá:
        
    public class Property implements Named {
    
        @Identifier(unique = "../sk.tuke.magsa.tools.metamodel.Property")
        private final String name;
    
        public Property(String name,
                @Before(":") Type type,
                @Separator(",") Constraint[] constraints) {
            ...
        }
    
        @Exclude
        public Property(String name, Type type) {
          ...
        }
    }
    
    Zápisu Length ::= 'length' <INT_VALUE> <INT_VALUE> zodpovedá:
     
    public class Length extends Constraint {
        @Before("length")
        public Length(@Token("INT_VALUE") int minLength, @Token("INT_VALUE") int maxLength) {
            ...
    }
    
    Zápis Reference ::= 'reference' <NAME> <NAME> je vyjadrený nasledovne:
     
    @Before("reference")
    public Reference(
            @References(value = Entity.class, field = "from") @Token("NAME") String from,
            @References(value = Entity.class, field = "to") @Token("NAME") String to) {
    }
    
    Poznámka: Anotácie @Identifier a @References vyplývajú z kontextu použitia, nie zo samotnej syntaxe jazyka.
  4. Okrem uvedených anotácii pre definovanie konkrétnej syntaxe je pre generátor nutné špecifikovať ďalšie údaje. Anotácia @Parser sa používa pre označenie balíka v jazyku Java s modelom jazyka a umiestňuje sa v zmysle špecifikácie jazyka Java do súboru package-info.java. Na základe tejto anotácie získava generátor hlavnú (koreňovú) triedu v doménovom modeli a následne spracováva celý model počnúc touto triedou. Táto anotácia taktiež určuje meno hlavnej triedy vygenerovaného jazykového procesora a definuje lexikálne symboly a biele znaky. Zapísanú anotáciu @Parser pre model jazyka entít je možné nájsť v súbore parser1.zip.
    Poznámka: Generátor YAJCo generuje výstupné súbory pre JavaCC. Viac o JavaCC je možné zistiť na https://javacc.java.net/. Lexikálne jednotky pre YAJCo sa zapisujú vo forme regulárnych výrazov jazyka Java.
    Poznámka: Mimo vývojového prostredia je možné použiť procesor YAJCo nasledovne.
    
    javac -s src -proc:only -cp lib\yajco.jar;lib\javacc.jar;lib\velocity-1.6.1-dep.jar 
    src\sk\tuke\magsa\metamodel\*.java src\sk\tuke\magsa\metamodel\constraints\*.java 
    src\sk\tuke\magsa\metamodel\ui\*.java
    
    Uvedený príkaz príkazového riadku predpokladá existenciu adresára lib so súbormi yajco.jar, javacc.jar a velocity-1.6.1-dep.jar a adresára src so zdrojovými textami.
Zdroje
  1. Anotácie:
  2. Viac o generátoroch jazykových procesorov
  3. Zdrojové kódy:
    • parser1.zip - konfiguračný súbor pre balík jazykového procesora
  4. Knižnice:
    • yajco.jar - knižnica generátora jazykových procesororv YAJCo
    • javacc.jar - knižnica generátora jazykových procesorov javacc
comments powered by Disqus