SupyML: change the variable lifetime (and make it work), and the <while> managment (not tested)

master
Valentin Lorentz 2010-11-14 09:22:49 +01:00
parent dfca8e3a34
commit a486749808
3 changed files with 65 additions and 31 deletions

View File

@ -32,10 +32,8 @@ numerics, but it is their own problems.
Variable lifetime
-----------------
When setting a new variable, the variable is readable and writable in the
node where it is created, and in the child nodes.
If a child node write a variable defined in a parent node, the new value of
the variable will be available in the parent node.
When creating/setting/editing a variable or its value, the changes are
available everywhere in the source code.
About the names
---------------

View File

@ -30,9 +30,10 @@
import re
import copy
import time
import Queue
import supybot.world as world
from xml.dom import minidom
import supybot.world as world
import supybot.utils as utils
from supybot.commands import *
from supybot.irclib import IrcMsgQueue
@ -50,10 +51,20 @@ except:
_ = lambda x:x
internationalizeDocstring = lambda x:x
class ParseError(Exception):
pass
class LoopError(Exception):
pass
class LoopTypeIsMissing(Exception):
pass
class FakeIrc():
def __init__(self, irc):
self._irc = irc
self._message = ''
self._data = ''
def error(self, message):
message = message
self._data = message
@ -74,29 +85,34 @@ class SupyMLParser:
self._msg = msg
self._code = code
self.warnings = []
self._parse()
self._parse(code)
def _run(self, code, proxify):
"""Runs the command using Supybot engine"""
tokens = callbacks.tokenize(str(code))
if proxify:
fakeIrc = FakeIrc(self._irc)
# TODO : add nested level
else:
fakeIrc = self._irc
self._plugin.Proxy(fakeIrc, self._msg, tokens)
if proxify:
# TODO : don't wait if the plugin is not threaded
time.sleep(0.1)
return fakeIrc._data
def _parse(self):
"""Returns a dom object from self._code."""
dom = minidom.parseString(self._code)
return self._processDocument(dom)
def _parse(self, code, variables={}, proxify=False):
"""Returns a dom object from the code."""
dom = minidom.parseString(code)
output = self._processDocument(dom, variables, proxify)
return output
def _processDocument(self, dom):
def _processDocument(self, dom, variables={}, proxify=False):
"""Handles the root node and call child nodes"""
for childNode in dom.childNodes:
if isinstance(childNode, minidom.Element):
self._processNode(childNode, {}, False)
output = self._processNode(childNode, variables, proxify)
return output
def _processNode(self, node, variables, proxifyIrc=True):
"""Returns the value of an internapreted node.
@ -107,23 +123,19 @@ class SupyMLParser:
if isinstance(node, minidom.Text):
return node.data
output = node.nodeName + ' '
newVariables = copy.deepcopy(variables)
for childNode in node.childNodes:
if not repr(node) == repr(childNode.parentNode):
print "CONTINUING"
continue
if childNode.nodeName == 'loop':
output += self._processLoop(childNode, newVariables)
output += self._processLoop(childNode, variables)
elif childNode.nodeName == 'if':
output += self._processId(childNode, newVariables)
output += self._processId(childNode, variables)
elif childNode.nodeName == 'var':
output += self._processVar(childNode, newVariables)
output += self._processVar(childNode, variables)
elif childNode.nodeName == 'set':
output += self._processSet(childNode, newVariables)
output += self._processSet(childNode, variables)
else:
output += self._processNode(childNode, newVariables) or ''
for key in variables:
variables[key] = newVariables[key]
output += self._processNode(childNode, variables) or ''
value = self._run(output, proxifyIrc)
return value
@ -149,7 +161,28 @@ class SupyMLParser:
def _processLoop(self, node, variables):
"""Handles the <loop> tag"""
return '<NOT IMPLEMENTED>'
loopType = None
loopCond = 'false'
loopContent = ''
output = ''
for childNode in node.childNodes:
if loopType is None and childNode.nodeName not in ('while'):
raise LoopTypeIsMissing(node.toxml())
elif loopType is None:
loopType = childNode.nodeName
loopCond = childNode.toxml()[len('<while>'):-len('</while>')]
else:
loopContent += childNode.toxml()
if loopType == 'while':
try:
while utils.str.toBool(self._parse(loopCond, variables, True)):
output += self._parse(loopContent)
except AttributeError: # toBool() failed
pass
except ValueError: # toBool() failed
pass
return output
def _checkVariableName(self, variableName):
if len(variableName) == 0:

View File

@ -55,6 +55,8 @@ class SupyMLTestCase(ChannelPluginTestCase):
answer = ircmsgs.IrcMsg(prefix="", command="PRIVMSG",
args=('ProgVal', 'test wants me to tell you: foo'))
self.failIf(self._getIfAnswerIsEqual(answer) == False)
self.assertResponse('SupyML eval <nne>4 5</nne>', 'true')
self.assertResponse('SupyML eval <echo><nne>4 5</nne></echo>', 'true')
def testNoMoreThanOneAnswer(self):
self.assertResponse('SupyML eval '
@ -95,24 +97,25 @@ class SupyMLTestCase(ChannelPluginTestCase):
'<var name="foo" />'
'</echo>'
'</echo>',
'bar')
'barbar')
def testWhile(self):
self.assertResponse('SupyML eval '
'<echo>'
'<set name="foo">bar</set>'
'<set name="foo">4</set>'
'<loop>'
'<while>'
'<nne>'
'<var name="foo" /> 5'
'</nne>'
'</while>'
'<set name="foo">5</set>'
'<echo>'
'bar'
'</echo>'
'</loop>'
'</echo>',
'bar'*5)
'barbar')
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: