import json
import re
import sys

# Define regular expressions for the tokens
token_patterns = [
    (r'#[^\n]', None),  # comments (ignored; match till end of line)
    (r'\s+', None),      # whitespace (ignored)
    (r'[', 'LBRACKET'),
    (r']', 'RBRACKET'),
    (r'{', 'LBRACE'),
    (r'}', 'RBRACE'),
    (r'%{', 'LMAPBRACE'),
    (r'=>', 'ARROW'),
    (r':', 'COLON'),    # A standalone colon
    (r',', 'COMMA'),
    (r'(true|false)', 'BOOLEAN'),
    (r'(0|[1-9]\d)', 'INTEGER'),
    (r':[A-Za-z_]\w*', 'ATOM'),  # For :atom syntax
    (r'[A-Za-z_]\w*', 'KEY'),    # For keys in key-value pairs
]

# Compile the regular expressions and make a lookup table
token_regex = '|'.join('(?:%s)' % pattern if name is None else '(?P<%s>%s)' % (name, pattern) for pattern, name in token_patterns)
token_re = re.compile(token_regex)
class TokenizerException(Exception): pass
class ParserException(Exception): pass

def tokenize(text):
    pos = 0
    while pos < len(text):
        match = token_re.match(text, pos)
        if not match:
            raise TokenizerException(f'Illegal character {text[pos]} at index {pos}')
        pos = match.end()
        groupdict = match.groupdict()
        for name, value in groupdict.items():
            if value is not None:
                tok_type = name
                tok_value = value
                yield tok_type, tok_value
                break

# Define a node structure to represent the parse tree
class Node:
    def __init__(self, kind, value):
        self.kind = kind
        self.value = value

    def to_json(self):
        return { "%k": self.kind, "%v": self.value }

class Parser:
    def __init__(self, tokens):
        self.tokens = iter(tokens)
        self.current_token = None
        self.next_token()

    def next_token(self):
        try:
            self.current_token = next(self.tokens)
        except StopIteration:
            self.current_token = None

    def parse(self):
        result = self.parse_sentence()
        if self.current_token is not None:
            raise ParserException('Unexpected token at the end')
        return result

    def parse_sentence(self):
        nodes = []
        while self.current_token is not None and self.current_token[0] not in {'RBRACE', 'RBRACKET'}:
            node = self.parse_data_literal()
            nodes.append(node)
            if self.current_token and self.current_token[0] == 'COMMA':
                self.next_token()  # Skip commas
        return nodes

    def parse_data_literal(self):
        if self.current_token[0] == 'LBRACKET':
            return self.parse_list()
        elif self.current_token[0] == 'LBRACE':
            return self.parse_tuple()
        elif self.current_token[0] == 'LMAPBRACE':
            return self.parse_map()
        elif self.current_token[0] == 'INTEGER':
            value = int(self.current_token[1].replace('_', ''))
            self.next_token()
            return Node('int', value)
        elif self.current_token[0] == 'ATOM':
            value = self.current_token[1]
            self.next_token()
            return Node('atom', value)
        elif self.current_token[0] == 'BOOLEAN':
            value = self.current_token[1] == 'true'
            self.next_token()
            return Node('bool', value)
        elif self.current_token[0] == 'KEY':
            value = ':' + self.current_token[1][:-1]
            self.next_token()
            return Node('atom', value)
        else:
            raise ParserException(f'Unexpected token {self.current_token[1]}')

    def parse_list(self):
        items = []
        self.next_token()  # Skip '['
        while self.current_token is not None and self.current_token[0] != 'RBRACKET':
            items.append(self.parse_data_literal())
            if self.current_token and self.current_token[0] == 'COMMA':
                self.next_token()  # Skip commas
        if self.current_token is None or self.current_token[0] != 'RBRACKET':
            raise ParserException('List not properly terminated with ]')
        self.next_token()  # Skip ']'
        return Node('list', [item.to_json() for item in items])

    def parse_tuple(self):
        items = []
        self.next_token()  # Skip '{'
        while self.current_token is not None and self.current_token[0] != 'RBRACE':
            items.append(self.parse_data_literal())
            if self.current_token and self.current_token[0] == 'COMMA':
                self.next_token()  # Skip commas
        if self.current_token is None or self.current_token[0] != 'RBRACE':
            raise ParserException('Tuple not properly terminated with }')
        self.next_token()  # Skip '}'
        return Node('tuple', [item.to_json() for item in items])

    def parse_map(self):
        items = []
        self.next_token()  # Skip '%{'
        while self.current_token is not None and self.current_token[0] != 'RBRACE':
            key = self.parse_data_literal()
            if self.current_token and self.current_token[0] == 'COLON':
                self.next_token()  # Skip ':'
                value = self.parse_data_literal()
                items.append([key.to_json(), value.to_json()])
            elif self.current_token and self.current_token[0] == 'ARROW':
                self.next_token()  # Skip '=>'
                value = self.parse_data_literal()
                items.append([key.to_json(), value.to_json()])
            else:
                raise ParserException('Invalid map entry format, expected ":" or "=>"')
        if self.current_token is None or self.current_token[0] != 'RBRACE':
            raise ParserException('Map not properly terminated with }')
        self.next_token()  # Skip '}'
        return Node('map', items)

def main():
    try:
        # Prompt for input
        text = input("Enter your input: ")
        tokens = tokenize(text)
        parser = Parser(tokens)
        result = parser.parse()
        json_output = json.dumps([node.to_json() for node in result], separators=(',', ':'))
        print(json_output)
    except TokenizerException as e:
        sys.stderr.write(str(e) + '\n')
        raise
    except ParserException as e:
        sys.stderr.write(str(e) + '\n')
        raise

if __name__ == '__main__':
    main()
Modify the program such that it can give correct outputs of totally-empty test, empty-with-comment test, empty-multi-comment test, single-atom test, single-int. test, extended-ints test, multi-bool test, true-false test, multi-primitives test, empty-lists test, simple-lists test, empty-tuples test, simple-tuples test, empty-maps test, simple-maps test, compound-data test, miss-delim error, miss-delim2 error, truefalse error, extra-comma error, extra-close-delim error, bad-int error