Я пишу компилятор для университетского проекта, и я хотел бы преобразовать свое абстрактное синтаксическое дерево в граф потока управления (CFG).
Я думаю, что узлы (V
) в CFG должныбыть узлами из АСТ.Я алгоритмически знаю, как построить набор ребер (G=(V,E)
), но мне трудно написать процесс более формально
Я создал это сопоставление с шаблоном стиля scala (Pseudo):
def edges(n:Node)(nestedin_next: Node) : List[(Node,Node)] =
n match {
case (c_1 :: c_2::tl) => (c1,c2) :: edges(c2::tl)(nestedin_next)++
edges(c_1)(c_2)//recurse
case c_1 :: Nil => (c_1,nestedin_next)::Nil
case i@ IF(_,c1,c2) => (i,c1)::(i,c2)::edges(c1)(nestedin_next)++
edges(c2)(nestedin_next)
case _ => Nil
}
Который должен соответствовать структуре AST, например:
( IF(1,
ASSIGN(x,1), // ia1
ASSIGN(x,2) // ia2
) :: // i1
ASSIGN(y,2) :: // a1
ASSIGN(z,ADD(x,y)) :: //a2
IF(z,
RET(z), //i2r1
assign(z,0):: // i2a1
ret(z) // i2r2
) :://i2
Nil
)
и обеспечивать набор ребер, например:
{ i1 -> ia1,
i1 -> ia2,
ia1 -> a1,
ia2 -> a1,
a1 -> a2,
a2 -> i2,
i2 -> i2r1
i2-> i2a1
i2a1 -> i2r2
i2r2 -> _|_
i2r1 -> _|_
}
DotSrc
Кто-нибудь получил какие-либо подсказки о том, как сделать это немного более формально, чем scala "псевдокод"?
Я думаю, что-то индуктивное, как:
e[[ IF(_,b1,b2) ]] = (if -> b1) + (if -> b2) \cup e[[ b1 ]] \cup e[[ b2 ]]
e[[ b1, b2 ]] = e[[b1]] \cup e[[b2]]
(приведенное выше даст толькодерево, а не график. Нет ребра от края тогдашней ветви до следующего оператора, например)
РЕДАКТИРОВАТЬ:
Я читал о Киама и потоки данных для scala, и мне нравится «succ» и «следующий» подход, который они используют.Тем не менее, мне тяжело свести это к более формальному описанию, в основном из-за изящных childAttr
, s.next
, которые скрывают некоторые детали, которые становятся некрасивыми, когда я пытаюсь определить это формально.
EDIT2:
Я прошел через Книгу Дракона и "Реализацию современного компилятора в ML", а также некоторые другие материалы из Учимся писать компилятор и некоторые /большинство упоминает поток данных и поток управления, но никогда особо не касается того, КАК создавать CFG каким-либо формальным способом.
EDIT3:
Через Kiama автор, Доцент д-р Тони Слоун Я получил дополнительных ссылок на книги для поиска .
Насколько я понимаю, «способ сделать это» согласно этим книгам основанна «на утверждение» программы больше, чем на AST и основывается на базовых блоках.Тем не менее, отличный вклад!