Updated 2015-09-01 13:43:24 by pooryorick

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 {}, g 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 occurrence 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]) ne {}) && ([lindex $found([file tail $file]) 1] eq {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 ne {}} {puts "Syntax check FAILED for 1 or more files, see logging for more info..." 1; return 1}
    return 0