blob: 33f3852886bf1f063a010c2d30a8bb39582cbe84 [file] [log] [blame]
# tclrivetparser.tcl -- parse Rivet files in pure Tcl.
# Copyright 2003-2004 The Apache Software Foundation
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# $Id$
package provide tclrivetparser 0.1
namespace eval tclrivetparser {
set starttag <?
set endtag ?>
set outputcmd {puts -nonewline}
namespace export parserivetdata
}
# tclrivetparser::setoutputcmd --
#
# Set the output command used. In regular Rivet scripts, we use
# puts, but that might not be ideal if you want to parse Rivet
# pages in a Tcl script.
#
# Arguments:
# newcmd - if empty, return the current command, if not, set the
# command.
#
# Side Effects:
# May set the output command used.
#
# Results:
# The current output command.
proc tclrivetparser::setoutputcmd { {newcmd ""} } {
variable outputcmd
if { $outputcmd == "" } {
return $outputcmd
}
set outputcmd $newcmd
}
# tclrivetparser::parse --
#
# Parse a buffer, transforming <? and ?> into the appropriate
# Tcl strings. Note that initial 'puts "' is not performed
# here.
#
# Arguments:
# data - data to scan.
# outbufvar - name of the output buffer.
#
# Side Effects:
# None.
#
# Results:
# Returns the $inside variable - 1 if we are inside a <? ?>
# section, 0 if we outside.
proc tclrivetparser::parse { data outbufvar } {
variable outputcmd
variable starttag
variable endtag
set inside 0
set shorthand 0
upvar $outbufvar outbuf
set i 0
set p 0
set len [expr {[string length $data] + 1}]
set next [string index $data 0]
while {$i < $len} {
incr i
set cur $next
set next [string index $data $i]
if { $inside == 0 } {
# Outside the delimiting tags.
if { $cur == [string index $starttag $p] } {
incr p
if { $p == [string length $starttag] } {
if {$next == "="} {
# puts stderr "shorthand begin detected"
append outbuf "\"\n $outputcmd "
set shorthand 1
incr i
set next [string index $data $i]
} else {
append outbuf "\"\n"
}
set inside 1
set p 0
continue
}
} else {
if { $p > 0 } {
append outbuf [string range $starttag 0 [expr {$p - 1}]]
set p 0
}
switch -exact -- $cur {
"\{" {
append outbuf \ $cur
}
"\}" {
append outbuf \ $cur
}
"\$" {
append outbuf "\\$"
}
"\[" {
append outbuf "\\["
}
"\]" {
append outbuf "\\]"
}
"\"" {
append outbuf "\\\""
}
"\\" {
append outbuf "\\\\"
}
default {
append outbuf $cur
}
}
continue
}
} else {
# Inside the delimiting tags.
if { $cur == [string index $endtag $p] } {
incr p
if { $p == [string length $endtag] } {
if {$shorthand} {
# puts stderr "shorthand end detected"
set shorthand 0
}
append outbuf "\n$outputcmd \""
set inside 0
set p 0
}
} else {
if { $p > 0 } {
append outbuf [string range $endtag 0 $p]
set p 0
}
append outbuf $cur
}
}
}
return $inside
}
# tclrivetparser::parserivetdata --
#
# Parse a rivet script, and add the relavant opening and closing
# bits.
#
# Arguments:
# data - data to parse.
#
# Side Effects:
# None.
#
# Results:
# Returns the parsed script.
proc tclrivetparser::parserivetdata { data } {
variable outputcmd
set outbuf {}
append outbuf "$outputcmd \""
if { [parse $data outbuf] == 0 } {
append outbuf "\"\n"
}
return $outbuf
}