annotate roundup/cgi/TAL/TALGenerator.py @ 2119:cc4667ef3f12

Added the ability to toggle where error messages go. They either go to the user (default, for backwards compatibility), the dispatcher, or both. These are able to be toggled via settings in config.py. Please refer to upgrading.txt for more details. (And Richard, let me know if I've done anything wrong with this checkin. :))
author Eddie Parker <eparker@users.sourceforge.net>
date Thu, 25 Mar 2004 19:27:15 +0000
parents fc52d57c6c3e
children 8c2402a78bb0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
1 ##############################################################################
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
2 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
4 # All Rights Reserved.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
5 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
6 # This software is subject to the provisions of the Zope Public License,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
7 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
11 # FOR A PARTICULAR PURPOSE
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
12 #
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
13 ##############################################################################
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1244
diff changeset
14 """Code generator for TALInterpreter intermediate code.
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
15 """
2005
fc52d57c6c3e documentation cleanup
Richard Jones <richard@users.sourceforge.net>
parents: 1244
diff changeset
16 __docformat__ = 'restructuredtext'
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
17
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18 import string
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19 import re
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20 import cgi
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22 from TALDefs import *
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
23
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
24 class TALGenerator:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
25
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26 inMacroUse = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
27 inMacroDef = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28 source_file = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
29
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30 def __init__(self, expressionCompiler=None, xml=1, source_file=None):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31 if not expressionCompiler:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 from DummyEngine import DummyEngine
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 expressionCompiler = DummyEngine()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 self.expressionCompiler = expressionCompiler
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35 self.CompilerError = expressionCompiler.getCompilerError()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 self.program = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 self.stack = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 self.todoStack = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 self.macros = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 self.slots = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 self.slotStack = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 self.xml = xml
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 self.emit("version", TAL_VERSION)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44 self.emit("mode", xml and "xml" or "html")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 if source_file is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 self.source_file = source_file
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 self.emit("setSourceFile", source_file)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 def getCode(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 assert not self.stack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 assert not self.todoStack
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 return self.optimize(self.program), self.macros
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54 def optimize(self, program):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 output = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56 collect = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57 rawseen = cursor = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58 if self.xml:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 endsep = "/>"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 endsep = " />"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62 for cursor in xrange(len(program)+1):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64 item = program[cursor]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65 except IndexError:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66 item = (None, None)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 opcode = item[0]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 if opcode == "rawtext":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 collect.append(item[1])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 if opcode == "endTag":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72 collect.append("</%s>" % item[1])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 if opcode == "startTag":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 if self.optimizeStartTag(collect, item[1], item[2], ">"):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 if opcode == "startEndTag":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 if self.optimizeStartTag(collect, item[1], item[2], endsep):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80 if opcode in ("beginScope", "endScope"):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 # Push *Scope instructions in front of any text instructions;
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 # this allows text instructions separated only by *Scope
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 # instructions to be joined together.
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 output.append(self.optimizeArgsList(item))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 text = string.join(collect, "")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 if text:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 i = string.rfind(text, "\n")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 if i >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 i = len(text) - (i + 1)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 output.append(("rawtextColumn", (text, i)))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 output.append(("rawtextOffset", (text, len(text))))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 if opcode != None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 output.append(self.optimizeArgsList(item))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 rawseen = cursor+1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 collect = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 return self.optimizeCommonTriple(output)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100 def optimizeArgsList(self, item):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101 if len(item) == 2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 return item
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 return item[0], tuple(item[1:])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 actionIndex = {"replace":0, "insert":1, "metal":2, "tal":3, "xmlns":4,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 0: 0, 1: 1, 2: 2, 3: 3, 4: 4}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 def optimizeStartTag(self, collect, name, attrlist, end):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109 if not attrlist:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 collect.append("<%s%s" % (name, end))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 return 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 opt = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 new = ["<" + name]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 for i in range(len(attrlist)):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 item = attrlist[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 if len(item) > 2:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 opt = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 name, value, action = item[:3]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 action = self.actionIndex[action]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 attrlist[i] = (name, value, action) + item[3:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 if item[1] is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 s = item[0]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125 s = "%s=%s" % (item[0], quote(item[1]))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126 attrlist[i] = item[0], s
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127 if item[1] is None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 new.append(" " + item[0])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 new.append(" %s=%s" % (item[0], quote(item[1])))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 if opt:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 new.append(end)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 collect.extend(new)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 return opt
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 def optimizeCommonTriple(self, program):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 if len(program) < 3:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 return program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 output = program[:2]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 prev2, prev1 = output
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141 for item in program[2:]:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 if ( item[0] == "beginScope"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 and prev1[0] == "setPosition"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144 and prev2[0] == "rawtextColumn"):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 position = output.pop()[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 text, column = output.pop()[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 prev1 = None, None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 closeprev = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 if output and output[-1][0] == "endScope":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
150 closeprev = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
151 output.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
152 item = ("rawtextBeginScope",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
153 (text, column, position, closeprev, item[1]))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
154 output.append(item)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
155 prev2 = prev1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
156 prev1 = item
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
157 return output
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
158
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
159 def todoPush(self, todo):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
160 self.todoStack.append(todo)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
161
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
162 def todoPop(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
163 return self.todoStack.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
164
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
165 def compileExpression(self, expr):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
166 try:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
167 return self.expressionCompiler.compile(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
168 except self.CompilerError, err:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
169 raise TALError('%s in expression %s' % (err.args[0], `expr`),
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
170 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
171
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
172 def pushProgram(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
173 self.stack.append(self.program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
174 self.program = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
175
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
176 def popProgram(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
177 program = self.program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
178 self.program = self.stack.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
179 return self.optimize(program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
180
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
181 def pushSlots(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
182 self.slotStack.append(self.slots)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
183 self.slots = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
184
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
185 def popSlots(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
186 slots = self.slots
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
187 self.slots = self.slotStack.pop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
188 return slots
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
189
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
190 def emit(self, *instruction):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
191 self.program.append(instruction)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
192
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
193 def emitStartTag(self, name, attrlist, isend=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
194 if isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
195 opcode = "startEndTag"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
196 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
197 opcode = "startTag"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
198 self.emit(opcode, name, attrlist)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
199
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
200 def emitEndTag(self, name):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
201 if self.xml and self.program and self.program[-1][0] == "startTag":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
202 # Minimize empty element
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
203 self.program[-1] = ("startEndTag",) + self.program[-1][1:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
204 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
205 self.emit("endTag", name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
206
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
207 def emitOptTag(self, name, optTag, isend):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
208 program = self.popProgram() #block
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
209 start = self.popProgram() #start tag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
210 if (isend or not program) and self.xml:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
211 # Minimize empty element
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
212 start[-1] = ("startEndTag",) + start[-1][1:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
213 isend = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
214 cexpr = optTag[0]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
215 if cexpr:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
216 cexpr = self.compileExpression(optTag[0])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
217 self.emit("optTag", name, cexpr, optTag[1], isend, start, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
218
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
219 def emitRawText(self, text):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
220 self.emit("rawtext", text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
221
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
222 def emitText(self, text):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
223 self.emitRawText(cgi.escape(text))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
224
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
225 def emitDefines(self, defines):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
226 for part in splitParts(defines):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
227 m = re.match(
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
228 r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
229 if not m:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
230 raise TALError("invalid define syntax: " + `part`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
231 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
232 scope, name, expr = m.group(1, 2, 3)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
233 scope = scope or "local"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
234 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
235 if scope == "local":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
236 self.emit("setLocal", name, cexpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
237 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
238 self.emit("setGlobal", name, cexpr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
239
1244
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
240 def emitOnError(self, name, onError, TALtag, isend):
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
241 block = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
242 key, expr = parseSubstitution(onError)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
243 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
244 if key == "text":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
245 self.emit("insertText", cexpr, [])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
246 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
247 assert key == "structure"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
248 self.emit("insertStructure", cexpr, {}, [])
1244
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
249 if TALtag:
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
250 self.emitOptTag(name, (None, 1), isend)
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
251 else:
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
252 self.emitEndTag(name)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
253 handler = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
254 self.emit("onError", block, handler)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
255
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
256 def emitCondition(self, expr):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
257 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
258 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
259 self.emit("condition", cexpr, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
260
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
261 def emitRepeat(self, arg):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
262 m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
263 if not m:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
264 raise TALError("invalid repeat syntax: " + `arg`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
265 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
266 name, expr = m.group(1, 2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
267 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
268 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
269 self.emit("loop", name, cexpr, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
270
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
271 def emitSubstitution(self, arg, attrDict={}):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
272 key, expr = parseSubstitution(arg)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
273 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
274 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
275 if key == "text":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
276 self.emit("insertText", cexpr, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
277 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
278 assert key == "structure"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
279 self.emit("insertStructure", cexpr, attrDict, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
280
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
281 def emitDefineMacro(self, macroName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
282 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
283 macroName = string.strip(macroName)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
284 if self.macros.has_key(macroName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
285 raise METALError("duplicate macro definition: %s" % `macroName`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
286 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
287 if not re.match('%s$' % NAME_RE, macroName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
288 raise METALError("invalid macro name: %s" % `macroName`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
289 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
290 self.macros[macroName] = program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
291 self.inMacroDef = self.inMacroDef - 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
292 self.emit("defineMacro", macroName, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
293
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
294 def emitUseMacro(self, expr):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
295 cexpr = self.compileExpression(expr)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
296 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
297 self.inMacroUse = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
298 self.emit("useMacro", expr, cexpr, self.popSlots(), program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
299
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
300 def emitDefineSlot(self, slotName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
301 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
302 slotName = string.strip(slotName)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
303 if not re.match('%s$' % NAME_RE, slotName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
304 raise METALError("invalid slot name: %s" % `slotName`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
305 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
306 self.emit("defineSlot", slotName, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
307
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
308 def emitFillSlot(self, slotName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
309 program = self.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
310 slotName = string.strip(slotName)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
311 if self.slots.has_key(slotName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
312 raise METALError("duplicate fill-slot name: %s" % `slotName`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
313 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
314 if not re.match('%s$' % NAME_RE, slotName):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
315 raise METALError("invalid slot name: %s" % `slotName`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
316 self.position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
317 self.slots[slotName] = program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
318 self.inMacroUse = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
319 self.emit("fillSlot", slotName, program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
320
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
321 def unEmitWhitespace(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
322 collect = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
323 i = len(self.program) - 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
324 while i >= 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
325 item = self.program[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
326 if item[0] != "rawtext":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
327 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
328 text = item[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
329 if not re.match(r"\A\s*\Z", text):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
330 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
331 collect.append(text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
332 i = i-1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
333 del self.program[i+1:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
334 if i >= 0 and self.program[i][0] == "rawtext":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
335 text = self.program[i][1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
336 m = re.search(r"\s+\Z", text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
337 if m:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
338 self.program[i] = ("rawtext", text[:m.start()])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
339 collect.append(m.group())
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
340 collect.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
341 return string.join(collect, "")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
342
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
343 def unEmitNewlineWhitespace(self):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
344 collect = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
345 i = len(self.program)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
346 while i > 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
347 i = i-1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
348 item = self.program[i]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
349 if item[0] != "rawtext":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
350 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
351 text = item[1]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
352 if re.match(r"\A[ \t]*\Z", text):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
353 collect.append(text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
354 continue
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
355 m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
356 if not m:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
357 break
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
358 text, rest = m.group(1, 2)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
359 collect.reverse()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
360 rest = rest + string.join(collect, "")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
361 del self.program[i:]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
362 if text:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
363 self.emit("rawtext", text)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
364 return rest
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
365 return None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
366
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
367 def replaceAttrs(self, attrlist, repldict):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
368 if not repldict:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
369 return attrlist
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
370 newlist = []
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
371 for item in attrlist:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
372 key = item[0]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
373 if repldict.has_key(key):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
374 item = item[:2] + ("replace", repldict[key])
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
375 del repldict[key]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
376 newlist.append(item)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
377 for key, value in repldict.items(): # Add dynamic-only attributes
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
378 item = (key, None, "insert", value)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
379 newlist.append(item)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
380 return newlist
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
381
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
382 def emitStartElement(self, name, attrlist, taldict, metaldict,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
383 position=(None, None), isend=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
384 if not taldict and not metaldict:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
385 # Handle the simple, common case
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
386 self.emitStartTag(name, attrlist, isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
387 self.todoPush({})
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
388 if isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
389 self.emitEndElement(name, isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
390 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
391
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
392 self.position = position
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
393 for key, value in taldict.items():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
394 if key not in KNOWN_TAL_ATTRIBUTES:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
395 raise TALError("bad TAL attribute: " + `key`, position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
396 if not (value or key == 'omit-tag'):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
397 raise TALError("missing value for TAL attribute: " +
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
398 `key`, position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
399 for key, value in metaldict.items():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
400 if key not in KNOWN_METAL_ATTRIBUTES:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
401 raise METALError("bad METAL attribute: " + `key`,
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
402 position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
403 if not value:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
404 raise TALError("missing value for METAL attribute: " +
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
405 `key`, position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
406 todo = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
407 defineMacro = metaldict.get("define-macro")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
408 useMacro = metaldict.get("use-macro")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
409 defineSlot = metaldict.get("define-slot")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
410 fillSlot = metaldict.get("fill-slot")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
411 define = taldict.get("define")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
412 condition = taldict.get("condition")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
413 repeat = taldict.get("repeat")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
414 content = taldict.get("content")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
415 replace = taldict.get("replace")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
416 attrsubst = taldict.get("attributes")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
417 onError = taldict.get("on-error")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
418 omitTag = taldict.get("omit-tag")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
419 TALtag = taldict.get("tal tag")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
420 if len(metaldict) > 1 and (defineMacro or useMacro):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
421 raise METALError("define-macro and use-macro cannot be used "
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
422 "together or with define-slot or fill-slot",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
423 position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
424 if content and replace:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
425 raise TALError("content and replace are mutually exclusive",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
426 position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
427
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
428 repeatWhitespace = None
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
429 if repeat:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
430 # Hack to include preceding whitespace in the loop program
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
431 repeatWhitespace = self.unEmitNewlineWhitespace()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
432 if position != (None, None):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
433 # XXX at some point we should insist on a non-trivial position
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
434 self.emit("setPosition", position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
435 if self.inMacroUse:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
436 if fillSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
437 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
438 if self.source_file is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
439 self.emit("setSourceFile", self.source_file)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
440 todo["fillSlot"] = fillSlot
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
441 self.inMacroUse = 0
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
442 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
443 if fillSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
444 raise METALError, ("fill-slot must be within a use-macro",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
445 position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
446 if not self.inMacroUse:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
447 if defineMacro:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
448 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
449 self.emit("version", TAL_VERSION)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
450 self.emit("mode", self.xml and "xml" or "html")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
451 if self.source_file is not None:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
452 self.emit("setSourceFile", self.source_file)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
453 todo["defineMacro"] = defineMacro
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
454 self.inMacroDef = self.inMacroDef + 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
455 if useMacro:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
456 self.pushSlots()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
457 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
458 todo["useMacro"] = useMacro
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
459 self.inMacroUse = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
460 if defineSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
461 if not self.inMacroDef:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
462 raise METALError, (
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
463 "define-slot must be within a define-macro",
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
464 position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
465 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
466 todo["defineSlot"] = defineSlot
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
467
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
468 if taldict:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
469 dict = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
470 for item in attrlist:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
471 key, value = item[:2]
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
472 dict[key] = value
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
473 self.emit("beginScope", dict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
474 todo["scope"] = 1
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
475 if onError:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
476 self.pushProgram() # handler
1244
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
477 if TALtag:
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
478 self.pushProgram() # start
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
479 self.emitStartTag(name, list(attrlist)) # Must copy attrlist!
1244
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
480 if TALtag:
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
481 self.pushProgram() # start
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
482 self.pushProgram() # block
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
483 todo["onError"] = onError
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
484 if define:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
485 self.emitDefines(define)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
486 todo["define"] = define
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
487 if condition:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
488 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
489 todo["condition"] = condition
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
490 if repeat:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
491 todo["repeat"] = repeat
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
492 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
493 if repeatWhitespace:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
494 self.emitText(repeatWhitespace)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
495 if content:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
496 todo["content"] = content
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
497 if replace:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
498 todo["replace"] = replace
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
499 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
500 optTag = omitTag is not None or TALtag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
501 if optTag:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
502 todo["optional tag"] = omitTag, TALtag
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
503 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
504 if attrsubst:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
505 repldict = parseAttributeReplacements(attrsubst)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
506 for key, value in repldict.items():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
507 repldict[key] = self.compileExpression(value)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
508 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
509 repldict = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
510 if replace:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
511 todo["repldict"] = repldict
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
512 repldict = {}
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
513 self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
514 if optTag:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
515 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
516 if content:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
517 self.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
518 if todo and position != (None, None):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
519 todo["position"] = position
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
520 self.todoPush(todo)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
521 if isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
522 self.emitEndElement(name, isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
523
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
524 def emitEndElement(self, name, isend=0, implied=0):
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
525 todo = self.todoPop()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
526 if not todo:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
527 # Shortcut
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
528 if not isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
529 self.emitEndTag(name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
530 return
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
531
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
532 self.position = position = todo.get("position", (None, None))
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
533 defineMacro = todo.get("defineMacro")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
534 useMacro = todo.get("useMacro")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
535 defineSlot = todo.get("defineSlot")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
536 fillSlot = todo.get("fillSlot")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
537 repeat = todo.get("repeat")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
538 content = todo.get("content")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
539 replace = todo.get("replace")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
540 condition = todo.get("condition")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
541 onError = todo.get("onError")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
542 define = todo.get("define")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
543 repldict = todo.get("repldict", {})
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
544 scope = todo.get("scope")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
545 optTag = todo.get("optional tag")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
546
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
547 if implied > 0:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
548 if defineMacro or useMacro or defineSlot or fillSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
549 exc = METALError
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
550 what = "METAL"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
551 else:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
552 exc = TALError
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
553 what = "TAL"
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
554 raise exc("%s attributes on <%s> require explicit </%s>" %
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
555 (what, name, name), position)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
556
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
557 if content:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
558 self.emitSubstitution(content, {})
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
559 if optTag:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
560 self.emitOptTag(name, optTag, isend)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
561 elif not isend:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
562 self.emitEndTag(name)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
563 if replace:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
564 self.emitSubstitution(replace, repldict)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
565 if repeat:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
566 self.emitRepeat(repeat)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
567 if condition:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
568 self.emitCondition(condition)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
569 if onError:
1244
8dd4f736370b merge from maintenance branch
Richard Jones <richard@users.sourceforge.net>
parents: 1049
diff changeset
570 self.emitOnError(name, onError, optTag and optTag[1], isend)
1049
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
571 if scope:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
572 self.emit("endScope")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
573 if defineSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
574 self.emitDefineSlot(defineSlot)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
575 if fillSlot:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
576 self.emitFillSlot(fillSlot)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
577 if useMacro:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
578 self.emitUseMacro(useMacro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
579 if defineMacro:
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
580 self.emitDefineMacro(defineMacro)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
581
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
582 def test():
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
583 t = TALGenerator()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
584 t.pushProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
585 t.emit("bar")
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
586 p = t.popProgram()
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
587 t.emit("foo", p)
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
588
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
589 if __name__ == "__main__":
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
590 test()

Roundup Issue Tracker: http://roundup-tracker.org/