Commit 45bc66e3 authored by 's avatar

Start adding start-tag column + lineno info in error msgs.

Repaired test for ""at most one of content, replace, repeat" TAL error
and improved the msg.
parent 83ee138f
...@@ -90,7 +90,7 @@ import sys ...@@ -90,7 +90,7 @@ import sys
import string import string
from TALGenerator import TALGenerator from TALGenerator import TALGenerator
from TALDefs import ZOPE_METAL_NS, ZOPE_TAL_NS from TALDefs import ZOPE_METAL_NS, ZOPE_TAL_NS, METALError, TALError
from nsgmllib import SGMLParser from nsgmllib import SGMLParser
BOOLEAN_HTML_ATTRS = [ BOOLEAN_HTML_ATTRS = [
...@@ -209,7 +209,8 @@ class HTMLTALParser(SGMLParser): ...@@ -209,7 +209,8 @@ class HTMLTALParser(SGMLParser):
else: else:
self.tagstack.append(tag) self.tagstack.append(tag)
attrlist, taldict, metaldict = self.extract_attrs(attrs) attrlist, taldict, metaldict = self.extract_attrs(attrs)
self.gen.emitStartElement(tag, attrlist, taldict, metaldict) self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
self.getpos())
def finish_endtag(self, tag, implied=0): def finish_endtag(self, tag, implied=0):
if tag in EMPTY_HTML_TAGS: if tag in EMPTY_HTML_TAGS:
...@@ -284,11 +285,17 @@ class HTMLTALParser(SGMLParser): ...@@ -284,11 +285,17 @@ class HTMLTALParser(SGMLParser):
prefix, suffix = string.split(key, ':', 1) prefix, suffix = string.split(key, ':', 1)
nsuri = self.nsdict.get(prefix) nsuri = self.nsdict.get(prefix)
if nsuri == ZOPE_METAL_NS: if nsuri == ZOPE_METAL_NS:
if metaldict.has_key(suffix):
raise METALError("duplicate METAL attribute " +
`suffix`, self.getpos())
item = (key, value) item = (key, value)
metaldict[suffix] = value metaldict[suffix] = value
if suffix == "define-macro": if suffix == "define-macro":
item = (key,value,"macroHack") item = (key,value,"macroHack")
elif nsuri == ZOPE_TAL_NS: elif nsuri == ZOPE_TAL_NS:
if taldict.has_key(suffix):
raise TALError("duplicate TAL attribute " +
`suffix`, self.getpos())
item = (key, value) item = (key, value)
taldict[suffix] = value taldict[suffix] = value
attrlist.append(item) attrlist.append(item)
......
...@@ -111,7 +111,17 @@ KNOWN_TAL_ATTRIBUTES = [ ...@@ -111,7 +111,17 @@ KNOWN_TAL_ATTRIBUTES = [
] ]
class TALError(Exception): class TALError(Exception):
pass def __init__(self, msg, position=None):
self.msg = msg
self.position = position # (line, offset) pair
def __str__(self):
if self.position:
result = "%s, at line %d, column %d" % (
self.msg, self.position[0], self.position[1]+1)
else:
result = self.msg
return result
class METALError(TALError): class METALError(TALError):
pass pass
......
...@@ -202,12 +202,13 @@ class TALGenerator: ...@@ -202,12 +202,13 @@ class TALGenerator:
def emitText(self, text): def emitText(self, text):
self.emitRawText(cgi.escape(text)) self.emitRawText(cgi.escape(text))
def emitDefines(self, defines): def emitDefines(self, defines, position):
for part in splitParts(defines): for part in splitParts(defines):
m = re.match( m = re.match(
r"\s*(?:(global|local)\s+)?(%s)\s+(.*)" % NAME_RE, part) r"\s*(?:(global|local)\s+)?(%s)\s+(.*)" % NAME_RE, part)
if not m: if not m:
raise TALError("invalid define syntax: " + `part`) raise TALError("invalid define syntax: " + `part`,
position)
scope, name, expr = m.group(1, 2, 3) scope, name, expr = m.group(1, 2, 3)
scope = scope or "local" scope = scope or "local"
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
...@@ -304,13 +305,14 @@ class TALGenerator: ...@@ -304,13 +305,14 @@ class TALGenerator:
newlist.append(item) newlist.append(item)
return newlist return newlist
def emitStartElement(self, name, attrlist, taldict, metaldict): def emitStartElement(self, name, attrlist, taldict, metaldict,
position):
for key in taldict.keys(): for key in taldict.keys():
if key not in KNOWN_TAL_ATTRIBUTES: if key not in KNOWN_TAL_ATTRIBUTES:
raise TALError("bad TAL attribute: " + `key`) raise TALError("bad TAL attribute: " + `key`, position)
for key in metaldict.keys(): for key in metaldict.keys():
if key not in KNOWN_METAL_ATTRIBUTES: if key not in KNOWN_METAL_ATTRIBUTES:
raise METALError("bad METAL attribute: " + `key`) raise METALError("bad METAL attribute: " + `key`, position)
todo = {} todo = {}
defineMacro = metaldict.get("define-macro") defineMacro = metaldict.get("define-macro")
useMacro = metaldict.get("use-macro") useMacro = metaldict.get("use-macro")
...@@ -328,13 +330,15 @@ class TALGenerator: ...@@ -328,13 +330,15 @@ class TALGenerator:
if fillSlot: n = n+1 if fillSlot: n = n+1
if defineSlot: n = n+1 if defineSlot: n = n+1
if n > 1: if n > 1:
raise METALError("only one METAL attribute per element") raise METALError("only one METAL attribute per element",
position)
n = 0 n = 0
if content: n = n+1 if content: n = n+1
if replace: n + n+1 if replace: n = n+1
if repeat: n = n+1 if repeat: n = n+1
if n > 1: if n > 1:
raise TALError("can't use content, replace, repeat together") raise TALError("at most one of content, replace, repeat",
position)
repeatWhitespace = None repeatWhitespace = None
if repeat: if repeat:
# Hack to include preceding whitespace in the loop program # Hack to include preceding whitespace in the loop program
...@@ -354,7 +358,7 @@ class TALGenerator: ...@@ -354,7 +358,7 @@ class TALGenerator:
todo["fillSlot"] = fillSlot todo["fillSlot"] = fillSlot
if defines: if defines:
self.emit("beginScope") self.emit("beginScope")
self.emitDefines(defines) self.emitDefines(defines, position)
todo["define"] = defines todo["define"] = defines
if condition: if condition:
self.pushProgram() self.pushProgram()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment