Version 1 of Syntax highlighting in tG2

Updated 2014-10-15 16:12:53 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 tG2. 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, tG2 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
}