#!/usr/local/bin/python
# $Id: xml2lout.py,v 1.1 1997/05/22 19:40:11 connolly Exp $
# http://www.w3.org/pub/WWW/COPYRIGHT

import xml
import loutwr
from loutwr import BOL, INDENT, LB, RB

OFF='off'
ON='on'
ATTR='attr'
CHAR='char'
RESET='reset'
INC='inc'
VALUE='value'
CASE='case'

class T(xml.InferEndTags):
    def __init__(self, wr):
	xml.InferEndTags.__init__(self)
	self.wr = lw = loutwr.T(wr)
	s = xml.Scanner()
	self.scanner(s)

	self.skip = 0
	self.warned = []
	self.counters = {}
	self.rules = ()

    def convert(self, infp):
	self.p.feed(infp.read())
	self.p.next(self)


    def text(self, str):
	if self.skip: return
	self.wr.text(str)

    def startElement(self, elm):
	elm.loutEnd = ()
	for pat, start, stop in self.rules:
	    if self.match(pat):
		self.do(elm, start)
		elm.loutEnd = stop
		return

	names = ()
	for e in self.stack: names = names + (e.name,)
	if names in self.warned:
	    pass
        else:
	    warn("No rule for %s [line %d]\n" % (`names`, elm.line))
	    self.warned.append(names)

    def endElement(self, elm):
	self.do(elm, elm.loutEnd)

    def match(self, pat):
	stack = self.stack
	s = 0
	p = 0
	while s < len(stack):
	    name = stack[s].name
	    s = s + 1
	    if name == pat[p]:
		p = p + 1
		if p == len(pat):
		    if s == len(stack): return 1
		    else: break

	return 0

    def do(self, elm, items):
	for item in items:
	    if item is OFF:
		self.skip = self.skip - 1
		if self.skip == 0: warn("@@skip off at: %s\n" % (elm.name,))
	    elif item is ON:
		self.skip = self.skip + 1
		if self.skip == 1: warn("@@skip on at: %s\n" % (elm.name,))
	    elif type(item) is type(()):
		opcode = item[0]
		if not self.skip:
		    if opcode is ATTR:
			name = item[1]
			try:
			    text = elm.attrs[name]
			    self.wr.text(text)
			except KeyError:
			    pass
		    elif opcode is CHAR:
			self.wr.char(item[1])
		    elif opcode is RESET:
			cname, newval = item[1:3]
			c = self.counters[cname] = newval
		    elif opcode is INC:
			#@@ handle numeric, roman, ...
			cname = item[1]
			old = self.counters[cname]
			self.counters[cname] = chr(ord(old)+1)
		    elif opcode is VALUE:
			cname = item[1]
			val = self.counters[cname]
			self.wr.sym(val)
		    elif opcode is CASE:
			cname = item[1]
			val = self.counters[cname]
			cases = item[2:]
			for cand, items in cases:
			    if val == cand: self.do(elm, items)
		    else:
			raise ValueError, item
	    else:
		if not self.skip:
		    self.wr.do(item)

def warn(msg):
    import sys
    sys.stderr.write(msg)

if __name__ == '__main__':
    import sys
    x = T(sys.stdout)
    x.convert(sys.stdin)
