Version 2 of Syntax highlighting in tG2

Updated 2014-10-15 16:13:28 by SeS

SeS Having scrolled through -I guess- most examples regarding syntax highlighting in this wiki, I was not able to get out definitive solution for implementing a procedure for syntax checks in tG²...the most satisfying way. Also, I needed to know the mechanics of syntax checks in depth, best way for me is to work the bottom-up way, I figured.

What I did understand so far is the most basic checks that are required as a minimum, are related with braces, such as {}, and (). While some solutions also dive into checking quote balancing as well. What I also learned is the existance of command "info complete {}". So, I relied upon my previous knowledge of finding balanced braces for regular (c)text highlighting and figured out a way to combine it with "info complete {}" to provide a first generation basic syntax lighlighting procedure for tG². With time, I hope to get better insight and improve the algorithm. Satisfied with the intermediate results though.

How it works: I simply scan each line for each category of brace types and manage a counter for the occurance of opening/closing braces (i & j). While this method will also register braces inside comments, which it ideally should not... This is where "info complete {}" comes in handy. So long as this latter command does not fail, I will simply not report eventual inbalances found. If the command fails on the other hand, I can provide the first line (z) where the inbalance starts. I noticed it is effective in 50~75% of cases, which is better than nothing in tG²'s current version v1.07.01 - beta6. With some additional code to the check4syntax procedure, tG² is lately able to jump to the line in the source editor and highlight it for further analyses by the user.

Current script does not perform a run-time like syntax check either, so most inbalances within procedure bodies will be discovered by wishrun.exe only...BUT...the tG² release that I am working on as of this writing @ 15th Oct 2014, is able to detect background error states of the tool being run and pinppoint the line of concern in the source code! Thanks to a simple handshaking mechanism between tG² and the tool. So, this is partially covered at the moment. Feature is optional btw, if we prefer the good old Tk-dialog to view the bgerror and wonder where to go now, we still have the choice...

Further things to be improved:

        - not able to accurately pinpoint the exact position/character causing the syntax error
        - Success rate of accurately pinpointing the probable line causing the error is ~50..75%
        - no checks for quote balancing...yet
        - braces inside comments are registered as well, ideally should not...

I think I got myself a nice simple piece of 1st generation code to chew on for the coming months...anyway, here it is:

proc openFile {file} {
  set f [open $file]
  set content [read $f]
  close $f
  return $content
}

proc check4syntax {files} {
  set allFiles $files
  foreach file $allFiles {
    set data [openFile $file]
    if {![info complete $data]} {set found([file tail $file]) " : unknown"} {set found([file tail $file]) ""}
    set data [split $data \n]
    foreach pats {"\\\{ \\\}" "\\\( \\\)" "\\\[ \\\]"} {
      set i 0 ;# index for starting brace
      set j 0 ;# index for ending brace
      set z 0 ;# line counter
      set synt($pats) 0
      foreach line $data {
        set pat "[lindex $pats 0]"; set s 0
        while {[string first $pat $line $s]>=0} {incr i; set s [expr [string first $pat $line $s]+1]}
        set pat "\\[lindex $pats 0]"; set s 0
        while {[string first $pat $line $s]>=0} {incr i -1; set s [expr [string first $pat $line $s]+1]}
  
        set pat "[lindex $pats 1]"; set s 0
        while {[string first $pat $line $s]>=0} {incr j; set s [expr [string first $pat $line $s]+1]}
        set pat "\\[lindex $pats 1]"; set s 0
            while {[string first $pat $line $s]>=0} {incr j -1; set s [expr [string first $pat $line $s]+1]}
              
            incr z
            if {($i>$j) && ($synt($pats)==0)} {set synt($pats) $z} {
              if {($i<=$j) && ($synt($pats)!=0)} {set synt($pats) 0}
            }
      }
      if {$j!=$i} {set found([file tail $file]) "$found([file tail $file]) : $pats @ line $synt($pats)"; break}
    }
  }
  
  set ret ""
  foreach file $allFiles {
    if {($found([file tail $file])!="") && ([lindex $found([file tail $file]) 1]=="unknown")} {
          set msg "Syntax check FAILED inside [file tail $file], for the following category $found([file tail $file])"
          set ret "${ret}[file tail $file] "
    } {
            set msg "Syntax check OK for [file tail $file]"
    }
    puts $msg
  }
  if {$ret!=""} {puts "Syntax check FAILED for 1 or more files, see logging for more info..." 1; return 1}
  return 0
}