Institute of Computer Science
  1. Courses
  2. 2017/18 spring
  3. Automata, Languages and Compilers (LTAT.03.006)
ET
Log in

Automata, Languages and Compilers 2017/18 spring

  • Üldinfo
  1. Õppekorraldus
  2. Eksam
  3. Reeglid
  4. Töövahendid
  5. Projekt
  • Kava
  1. Soojendus
  2. Regulaaravaldised
  3. Olekumasinad
  4. Lõplikud automaadid
  5. Avaldise struktuur
    1. Struktuur
    2. RegexAnalyzer
    3. Puu harjutused
    4. Kodutöö
    5. Java AST analüüs*
  6. Grammatikad ja lekser
  7. Käsitsi parsimine
  8. ANTLR intro
  9. AST loomine
  10. Interpretaator
  11. Semantiline analüüs
  12. Kompilaator
  • Moodle
  • Bitbucket
  • Fleep!

Regulaaravaldise struktuuri esitamine ja uurimine

Mõtteharjutus

Kuidas oleks hea esitada regulaaravaldist arvutiprogrammis, kui me tahaksime küsida selle kohta midagi taolist:

  • Kas regulaaravaldise poolt esitatud keel on lõplik? Kui jah, siis mitu sõna kuulub keelde?
  • Kas tühi sõna kuulub keelde?
  • Kas sõna "kalamari" kuulub keelde?
  • Kas avaldist saab lihtsustada? Kuidas?

Arutage paarilisega ja formuleerige oma ettepanek.

Analoogiline näide

Teeme nüüd läbi selline harjutus, kus esitame mõistlikul kujul aritmeetilist avaldist. Proovige defineerida eval meetod, mis väärtustab avaldist.

    public static void main(String[] args) {
        Expression expr1 = div(add(num(5), add(num(3), neg(num(2)))), num(2));
        Expression expr2 = div(div(num(8), num(2)), num(2));
        Expression expr3 = div(num(8), div(num(2), num(2)));

        System.out.println(expr1.eval()); // tulemus: 3
    }

Puu väline analüüs: ExprAnalyzer

Kuna meie süntaksipuu klassid genereeritakse automaatselt ANTLRi poolt, siis ei ole väga mõistlik hakkata neid redigeerima. Mõnikord on ka mugavam, kui kogu funktsiooni loogika on ühes kohas. Seetõttu defineerime siin ka eval meetod väliselt. Klassis ExprAnalyzer on samuti eval meetod, mis võiks arvutada sama tulemus ehk võiks kehtida expr.eval() == ExprAnalyzer.eval(expr).

(Optional) Objektorienteeritud lähenemine

Kui oled väga palju OO propagandat ära söönud, siis instanceof kasutamine võib üsna häiriv olla. Siin on siis kaks objekt-orienteeritud lähenemist ka lisatud, mida võib tulevikus kasutada. Sellel praktikumil aga taame, et selline basic funktsionaalne lähenemine oleks kõigil selge.

  • Listener. Eriti soblik, kui tahame süntakspuu elementidele lihtsalt reageerida. Oletame, et taheme kõik avaldises esinevad täisarvud ühte hulka kokku koguda. Seda on väga mugav listeneriga teha. Tulemuse tagastamise asemel peab ise seisundit jälgima, mistõttu avaldiste väärtustamine ei ole sellega kõige mugavam.
  • Visitor. Laseb meil puud läbida ja väärtust tagastada. Põhimõtteliselt hoolitseb siis lihtsalt nende cast'ide eest ja meil jääb ainult loogikat defineerida. Sellega on ideaalne eval implementeerida.

Listener

Listener idee on see, et läbitakse puu tippe selliselt, et külastatakse kõik lapsi vasakult-paremale, aga selle liidese kasutaja võib teatud külastussündmustele reageerida. Sündmused toimuvad enne ja pärast tipu külastamist, aga muidugi ei pea kõikidele sündmustele reageerima. Näiteks liitmise tipu külastamisel kutsutakse järgmised meetodid:

                enterAdd(node); // <-- võime seda implementeerida
                visit(node.getLeft());
                visit(node.getRight());
                exitAdd(node);  // <-- või siis seda... (või mõlemad)

Repositooriumis on näide, kuidas kokku koguda kõik avaldises esinevad väärtused. Selleks peab ainult exitNum juures väärtus meie hulka lisada. Me saame ka väärtustamist implementeerida, aga selleks peame ise argumente magasini peal arvutama.

Visitor

Visitor on üsna kuulus disainimuster ja sellel on väga palju erinevad variante. Mõnikord fikseerib raamistik tipude läbimise strateegia, aga kasutame selline üldine visitor, mis sisuliselt ainult lahendab seda tüübiteisenduste süntaksit. Me kutsume ise välja visit meetod. Me saame (aga ei pea) siseklassidena implementeerida oma visitorid:

    public static int eval(ExprNode expr) {
        ExprVisitor<Integer> visitor = new ExprVisitor<Integer>() {
            public Integer visitAdd(Add node) {
                return visit(node.getLeft()) + visit(node.getRight());
            }
            public Integer visitNum(Num node) {
                return node.getValue();
            }
            // jne...
        };
        return expr.accept(visitor);
    }

Kõikide nende erinevate enter/exit ja visit meetoditel, mis erinevad ainult sisendtüübi järgi, võib kasutada sama nimi. Kui tahad kasutada eksamil Listener/Visitor, siis ole selleks valmis, et erinevatel AST klasside generaatoritel on natuke erinevad nimetamise konventsioonid.

  • Institute of Computer Science
  • Faculty of Science and Technology
  • University of Tartu
In case of technical problems or questions write to:

Contact the course organizers with the organizational and course content questions.
The proprietary copyrights of educational materials belong to the University of Tartu. The use of educational materials is permitted for the purposes and under the conditions provided for in the copyright law for the free use of a work. When using educational materials, the user is obligated to give credit to the author of the educational materials.
The use of educational materials for other purposes is allowed only with the prior written consent of the University of Tartu.
Terms of use for the Courses environment