$ // Whether to do DAG(tree) or not $ param type = 'simple' $ ecmascript function check (tree, name) { var t = '_' + tree + '_'; return t.indexOf('_' + name + '_') == -1; } var da = new Array(); function not_done(name) { if ( da[name] ) return false; da[name] = true; return true; } $ end ecmascript $ // This is a recursive template applied on productions $ template tree(prod = '') $prod [shape=diamond,label="@name"] $ foreach {alt} $ set alt = {concat($prod,'_alt_',@ename)} $alt [shape=box,label="${../@name}.@name"] $prod -> $alt $ foreach enode in {elem} $ set elem = {concat($alt,'_',@ename)} $ if {@is_token} $alt -> $elem [label="@name@modifier"] $elem [shape=ellipse,label="@type"] $ else $ if {sablecc:check(string($prod), string(@etype))} $ foreach {//production[@ename=$enode/@etype]} $ set subtree = {concat($elem,'_',@ename)} $alt -> $subtree [label="@name@modifier"] $ call tree(prod = $subtree) $ end $ else $alt -> $elem [label="@name@modifier"] $elem [shape=triangle,label="@type"] $ end if $ end if $ end foreach $ end foreach $ end template $ template simple(prod = '') $prod [shape=diamond,label="@name"] $ foreach {alt} $ set alt = {concat($prod,'_alt_',@ename)} $alt [shape=box,label="${../@name}.@name"] $prod -> $alt $ foreach enode in {elem} $ set elem = {concat($alt,'_',@ename)} $ if {@is_token} $alt -> $elem [label="@name@modifier"] $elem [shape=ellipse,label="@type"] $ else $ if {sablecc:not_done(string(@etype))} $ set subtree = {concat($elem,'_',@ename)} $alt -> $subtree [label="@name@modifier"] $ foreach {//production[@ename=$enode/@etype]} $ call simple(prod = $subtree) $ end $ else $alt -> $elem [label="@name@modifier"] $elem [shape=triangle,label="@type"] $ end if $ end if $ end foreach $ end foreach $ end template digraph mygraph { $ choose $ when {$type='simple'} $ foreach {//production[position()=1]} $ call simple(prod = @ename) $ end foreach $ end when $ when {$type='tree'} $ foreach {//production[position()=1]} $ call tree(prod = @ename) $ end foreach $ end when $ when {$type='graph'} $ foreach {//production} @ename [shape=diamond,label="@name"] $ foreach {alt} @ename [shape=box,label="${../@name}.@name"] ${../@ename} -> @ename $ foreach {elem} ${../@ename} -> @etype [label="@name@modifier"] $ if {@is_token} @etype [shape=ellipse,label="@type"] $ end if $ end foreach $ end foreach $ end foreach $ end when $ end choose }