#!/bin/tclsh # # Run this TCL script to generate syntax bubble diagrams from # text descriptions. # # This version generates a pure HTML table based version with # no graphics, all in one file named "all-text.html". It may # be useful to people wanting text search or screen reader # support. source [file join [file dirname [info script]] bubble-generator-data.tcl] # used for curves set rad "4px" set rad1 "5px" # used for bubble text (<= (2 x rad)+2) set font1 "9px" # used for arrows (~ 3 x rad) set font2 "12px" # used for everything else (~ font1+5) set font3 "14px" # | set c9474 "
" # -| set c9488 "
" # |- set c9484 "
" # |_ set c9492 "
" # _| set c9496 "
" #-(- top left set c9581 "
" #-)- top right set c9582 "
" #-|- set c9516 "
" #( bot left set c9584 "
" # ) bot right set c9583 "
" # |- set c9500 "
" # -| set c9508 "
" #-> set rarr "
>
" # <- set larr "
<
" # --- set hr "
" # Draw a bubble containing $txt. # proc draw_bubble {txt} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr if {$txt=="nil"} { return [list 1 "
$hr
"] } elseif {$txt=="bullet"} { return [list 1 "
"] } if {[regexp {^/[a-z]} $txt]} { set txt [string range $txt 1 end] set istoken 1 } elseif {[regexp {^[a-z]} $txt]} { set istoken 0 } else { set istoken 1 } set href " $txt " set txt " $txt " if {$istoken} { return [list 1 "
$txt
"] } else { return [list 1 "
$href
"] } return [list 0 ""] } # Draw a sequence of terms from left to write. Each element of $lx # descripts a single term. # proc draw_line {lx} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set n [llength $lx] set h 1 set content "" set i 0 foreach term $lx { incr i set rc [draw_diagram $term] set th [lindex $rc 0] set tcontent [lindex $rc 1] if { $th > $h } { set h $th } if {$i != $n} { set content "$content$tcontent$rarr" } else { set content "$content$tcontent" } } set content "$content
" return [list $h $content] } # Draw a sequence of terms from right to left. # proc draw_backwards_line {lx} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set n [llength $lx] set h 1 if {$n < 1} { set content "$hr" } { set content "" set i 0 foreach term $lx { incr i set rc [draw_diagram $term 1] set th [lindex $rc 0] set tcontent [lindex $rc 1] if { $th > $h } { set h $th } if {$i != $n} { set content "$larr$tcontent$content" } else { set content "$tcontent$content" } } } set content "$content
$hr
" return [list $h $content] } # Draw a sequence of terms from top to bottom. # proc draw_stack {indent lx} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set n [llength $lx] set h 0 set content "" set i 0 foreach term $lx { set rc [draw_diagram $term 1] set th [lindex $rc 0] set tcontent [lindex $rc 1] set h [ expr { $h + $th } ] set v [ expr { $th - 1 } ] set vert [string repeat "" $v] incr i if {$i == 1} { set down "
$c9474
$vert
$c9488
" set up "$vert
$c9484
" set content "$content$hr$hr$tcontent$rarr$down$up" } elseif {$i == $n} { set content "$content$c9492$rarr$tcontent$hr$rarr$c9496" } else { set down "$vert
$c9488
" set up "$vert
$c9474
" set content "$content$c9492$rarr$tcontent$rarr$down$up" } if {$i != $n} { incr h set content "$content$c9484$larr$hr$larr$c9496$c9474" } } set content "$content" return [list $h $content] } proc draw_loop {forward back} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set h 0 set content "" set rc [draw_diagram $forward 1] set th [lindex $rc 0] set tcontent [lindex $rc 1] set v [ expr { $th - 1 } ] set vert [string repeat "" $v] set up "$c9581" set down "$c9582" if { $v > 0 } { set up "
$c9474
$vert
$up
" set down "$vert
$down
" } set h [ expr { $h + $th } ] set content "$content$up$rarr$tcontent$rarr$down" set rc [draw_backwards_line $back] set th [lindex $rc 0] set tcontent [lindex $rc 1] set h [ expr { $h + $th } ] set content "$content$c9584$larr$tcontent$larr$c9583" set content "$content" return [list $h $content] } proc draw_toploop {forward back} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set h 0 set content "" set rc [draw_diagram $forward 1] set th [lindex $rc 0] set tcontent [lindex $rc 1] set v [ expr { $th - 1 } ] set vert [string repeat "" $v] set up "$c9581" set down "$c9582" if { $v > 0 } { set up "
$c9474
$vert
$up
" set down "$vert
$down
" } set h [ expr { $h + $th } ] set content "$content$up$rarr$tcontent$rarr$down" set rc [draw_backwards_line $back] set th [lindex $rc 0] set tcontent [lindex $rc 1] set h [ expr { $h + $th } ] set content "$content$c9584$larr$tcontent$larr$c9583" set content "$content" return [list $h $content] } proc draw_or {lx} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set n [llength $lx] set h 0 if {$n < 1} { set content "$hr" } else { set content "" set i 0 foreach term $lx { set rc [draw_diagram $term 1] set th [lindex $rc 0] set tcontent [lindex $rc 1] set v [ expr { $th - 1 } ] set vert [string repeat "$c9474" $v] incr i if {$i == 1} { set beg "$c9582" set end "$c9581" } elseif {$i == $n} { set beg "$c9584" set end "$c9583" set vert "" } else { set beg "$c9500" set end "$c9508" } set h [ expr { $h + $th } ] set content "$content$beg$vert
$rarr$tcontent$rarr$end$vert
" } } set content "$content
" return [list $h $content] } proc draw_diagram {spec {draw_hr 0}} { global c9474 c9488 c9484 c9492 c9496 c9581 c9582 c9516 c9584 c9583 c9500 c9508 rarr larr hr set n [llength $spec] set cmd [lindex $spec 0] if {$n==1} { set rc [draw_bubble $spec] } elseif {$n==0} { set rc [draw_bubble nil] } elseif {$cmd=="line"} { set rc [draw_line [lrange $spec 1 end]] } elseif {$cmd=="stack"} { set rc [draw_stack 0 [lrange $spec 1 end]] } elseif {$cmd=="indentstack"} { set rc [draw_stack $::HSEP [lrange $spec 1 end]] } elseif {$cmd=="loop"} { set rc [draw_loop [lindex $spec 1] [lindex $spec 2]] } elseif {$cmd=="toploop"} { set rc [draw_toploop [lindex $spec 1] [lindex $spec 2]] } elseif {$cmd=="or"} { set rc [draw_or [lrange $spec 1 end]] } elseif {$cmd=="opt"} { set args [lrange $spec 1 end] if {[llength $args]==1} { set rc [draw_or [list nil [lindex $args 0]]] } else { set rc [draw_or [list nil "line $args"]] } } elseif {$cmd=="optx"} { set args [lrange $spec 1 end] if {[llength $args]==1} { set rc [draw_or [list [lindex $args 0] nil]] } else { set rc [draw_or [list "line $args" nil]] } } elseif {$cmd=="tailbranch"} { # set rc [draw_tail_branch [lrange $spec 1 end]] set rc [draw_or [lrange $spec 1 end]] } else { error "unknown operator: $cmd" } set h [lindex $rc 0] set content [lindex $rc 1] if {$draw_hr} { set content "
$content$hr
" } { set content "
$content
" } return [list $h $content] } proc draw_graph {name spec} { set rc [ draw_diagram "line bullet [list $spec] bullet"] set h [lindex $rc 0] set content [lindex $rc 1] return [list $h $content] } set f [open all-text.html w] puts $f "" puts $f "" puts $f "" puts $f "" puts $f "" puts $f "" foreach {name graph} $all_graphs { if {$name == "sql-stmt-list" || 1} { puts $f "

$name:

" set rc [draw_graph $name $graph] set h [lindex $rc 0] set content [lindex $rc 1] puts $f "$content" } } puts $f "" puts $f "" close $f