pythonlisttcl

Translate Tcl List to Python List


I try to translate Tcl list to python list.

There are two problems:

Python 3 code:

import tkinter


class TclInterpreter(object):
    def __init__(self):
        self._tcl = tkinter.Tcl()

    def eval(self, tcl_cmd):
        return self._tcl.eval(tcl_cmd)


class TclPyListTranslator(object):
    def __init__(self, tcl):
        self._tcl = tcl

    def to_py(self, tcl_list, dtype=str):
        # convert a Tcl List to python list, also convert elements of each leaf
        # node to dtype
        self._tcl.eval("set tcl_list %s" % tcl_list)
        numItems = int(self._tcl.eval("llength $tcl_list"))
        if numItems > 1:
            result = [self._tcl.eval("lindex $tcl_list %d" % i) for i in range(
                numItems)]
            for i in range(numItems):
                result[i] = self.to_py("{" + result[i] + "}", dtype)
        else:
            result = dtype(self._tcl.eval("lindex $tcl_list %d" % 0))
        return result


inter = TclInterpreter()
translator = TclPyListTranslator(inter)
tcl_list = "{12 {{12 34}} {56 {78 {11 12} 10}}}"

# prints ['12', '12 34', ['56', ['78', ['11', '12'], '10']]]
# The '12 34' is incorrect
print(translator.to_py(tcl_list))

# does not run
print(translator.to_py(tcl_list, int))

Solution

  • Python parser:

    def add_element(cache, element):
        if element != '':
            cache[-1].append(element)
        return ''
    
    def parse(tcl_list):
        """ Parse TCL list to Python list """    
        out = []
        cache = [out]
        element = ''
        escape = False
        for char in tcl_list:
            if escape:
                element += char
                escape = False
            elif char == "\\":
                escape = True
            elif char in [" ", "\t", "\r", "\n"]:
                element = add_element(cache, element)
            elif char == "{":
                a = []
                cache[-1].append(a)
                cache.append(a)
            elif char == "}":
                element = add_element(cache, element)
                cache.pop()
            else:
                element += char
        return out[0]
    import pprint
    pprint.pprint(
        parse("{ 12 apple {100} {} {{12 34}} \n {56\n { \\{78 {11 12 11} 10}}}"))
    

    output:

    ['12',
     'apple',
     ['100'],
     [],
     [['12', '34']],
     ['56', ['{78', ['11', '12', '11'], '10']]]