Wynikiem ostatnich postów (i odpowiadającej im implementacji) jest to, że potrafię już przetłumaczyć tekst na tokeny. A jak te tokeny mają się do bytów z dziedziny wykonywania wyrażeń? Dzisiejszy post traktuje właśnie o tym, a jednocześnie podsumowuje moje dotychczasowe osiągnięcia w temacie kompilacji DSLa.
Do tej pory opisywałem tokeny osobno – pokazałem ich klasy i odpowiadające im parsery. Czas poskładać informacje do kupy. Zróbmy to na przykładzie zapisu, który przewijał się w poprzednich postach:
log('Calculating...') sub(add('1' '2') '3')
Wspominałem już, że wynikiem parsowania całego zapisu jest drzewo tokenów. Zamiast obrazowo to opisywać, lepiej opisać to obrazem. Dla powyższego zestawu instrukcji drzewo wygląda tak:
Jak z takiego drzewa uzyskać strukturę gotową do wykonania, czyli zrozumiałą dla DSLExecutora, czyli drzewo wyrażeń? Koncepcyjnie – bardzo prosto. Zauważmy, że każdy token reprezentuje wyrażenie:
- TokenTree to BatchExpression,
- FunctionCall to FunctionExpression,
- Literal to ConstantExpression.
Wystarczy więc przekształcić każdy token w odpowiadające mu wyrażenie. W wyniku takiego przekształcenia dostaniemy drzewo wyrażeń, które pojawiło się już w jednym z postów:
Jak widać, koncepcja jest prosta. W kolejnych postach będę ją wprowadzał w życie, pokazując implementację przekształceń poszczególnych tokenów – zapraszam!