My program is import json
import re
import sys

token_patterns = [
(r’#[^\n]‘, None),
(r’\s+‘, None),
(r’[‘, ‘LBRACKET’),
(r’]‘, ‘RBRACKET’),
(r’{‘, ‘LBRACE’),
(r’}‘, ‘RBRACE’),
(r’%{‘, ‘LMAPBRACE’),
(r’=>‘, ‘ARROW’),
(r’,‘, ‘COMMA’),
(r’(true|false)‘, ‘BOOLEAN’),
(r’(0|[1-9][0-9_])‘, ‘INTEGER’),
(r’:[A-Za-z_]\w*‘, ‘ATOM’),
(r’[A-Za-z_]\w*‘, ‘KEY’),
(r’:‘, ‘COLON’),
]

regex_parts = [f’(?P<{name}>{pattern})’ if name else f’(?:{pattern})’ for pattern, name in token_patterns]
token_regex = ‘|’.join(regex_parts)
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]!r} at index {pos}‘)
pos = match.end()
if match.lastgroup:
yield match.lastgroup, match.group(match.lastgroup)

def make_hashable(value):
“”“Recursively converts JSON-like objects to an immutable and hashable type.”“”
if isinstance(value, list):
return tuple(make_hashable(x) for x in value)
elif isinstance(value, dict):
return tuple((make_hashable(k), make_hashable(v)) for k, v in value.items())
else:
return value # Integers, strings, booleans, and None are already hashable


class Node:
def init(self, kind, value):
self.kind = kind
self.value = value

def to_json(self):
if self.kind == “map”:
# Corrected conditional to account for empty maps
if not self.value: # self.value is empty
return {“%k”: self.kind, “%v”: {}} # Return an empty dictionary instead of an empty list
return {“%k”: self.kind, “%v”: {k.to_json()[“%v”]: v.to_json() for k, v in self.value}}
elif self.kind == “list”:
return {“%k”: self.kind, “%v”: [item.to_json() for item in self.value]}
else:
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:
node = self.parse_data_literal()
nodes.append(node)
if self.current_token and self.current_token[0] in {‘COMMA’, ‘COLON’, ‘ARROW’}:
self.next_token()
return nodes

def parse_data_literal(self):
# Parse the correct type based on the current token
if not self.current_token:
raise ParserException(“Unexpected end of input”)

token_type, token_value = self.current_token

if token_type == ‘LBRACKET’:
return self.parse_list()
elif token_type == ‘LBRACE’:
return self.parse_tuple()
elif token_type == ‘LMAPBRACE’:
return self.parse_map()
elif token_type == ‘INTEGER’:
self.next_token() # Move to the next token after parsing
return Node(‘int’, int(token_value)) # Convert string to integer
elif token_type == ‘ATOM’:
self.next_token()
return Node(‘atom’, token_value)
elif token_type == ‘BOOLEAN’:
self.next_token()
# Convert string ‘true’ or ‘false’ to a boolean
return Node(‘bool’, token_value == ‘true’)
elif token_type == ‘KEY’:
self.next_token()
return Node(‘key’, token_value)
else:
raise ParserException(f"Unexpected token type {token_type}“)

def parse_list(self):
self.next_token()
items = []
while self.current_token and self.current_token[0] != ‘RBRACKET’:
item = self.parse_data_literal()
items.append(item)
if self.current_token and self.current_token[0] == ‘COMMA’:
self.next_token()

if not self.current_token or self.current_token[0] != ‘RBRACKET’:
raise ParserException(‘List not properly terminated with ]’)

self.next_token() # Consume ‘RBRACKET’
return Node(‘list’, items)

def parse_tuple(self):
items = []
self.next_token()
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()
if self.current_token is None or self.current_token[0] != ‘RBRACE’:
raise ParserException(‘Tuple not properly terminated with }’)
self.next_token()
return Node(‘tuple’, [item.to_json() for item in items])


def parse_map(self):
self.next_token() # Skip ‘LMAPBRACE’
map_items = []

while self.current_token and self.current_token[0] != ‘RBRACE’:
key = self.parse_data_literal()

if self.current_token[0] not in [‘ARROW’, ‘COLON’]:
raise ParserException(f"Expected ‘=>’ or ‘:’, found {self.current_token} instead”)

self.next_token() # Skip ‘ARROW’ or ‘COLON’
value = self.parse_data_literal()

# Serialize your key to a format that can be used in a JSON dictionary
# This can be a string representation or a nested structure

map_items[str(key)] = value

if self.current_token and self.current_token[0] == ‘COMMA’:
self.next_token()

if not self.current_token or self.current_token[0] != ‘RBRACE’:
raise ParserException(‘Map not properly terminated with “}”’)

self.next_token() # Skip ‘RBRACE’
return Node(‘map’, map_items)

def main():
try:
text = sys.stdin.read()

tokens = list(tokenize(text))

if not tokens:
print(json.dumps([]))
else:
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’)
except ParserException as e:
sys.stderr.write(str(e) + ‘\n’)


if name == ‘main’:
main()
which is failing many test cases and the ideal program that passes all the test cases is #!/usr/bin/env python3

import re
import sys
from collections import namedtuple
import json

’‘’
dataItems
: dataItem*
;
dataItem
: list
| tuple
| map
| primitive
;
primitive
: INT
| ATOM
| BOOL
;
list
: ‘[’ dataItem (‘,’ dataItem)* ‘]’
| ‘[’ ‘]’
;
tuple
: ‘{’ dataItem (‘,’ dataItem)* ‘}’
| ‘{’ ‘}’
;
map
: ‘%{’ keyPair (‘,’ keyPair)* ‘}’
| ‘%{’ ‘}’
;
keyPair
: dataItem ‘=>’ dataItem
| KEY dataItem
;
‘’‘

################################# Parser ################################


def parse(text):
toks = tokenize(text)
toksIndex = 0
tok = toks[toksIndex]
toksIndex += 1

def peek(kind):
nonlocal tok
return tok.kind == kind

def consume(kind):
nonlocal tok, toks, toksIndex
if (peek(kind)):
tok = toks[toksIndex]
toksIndex += 1
else:
error(kind, text)

def error(kind, text):
nonlocal tok
pos = tok.pos
if pos >= len(text) or text[pos] == ‘\n’: pos -= 1
lineBegin = text.rfind(’\n’, 0, pos)
if lineBegin < 0: lineBegin = 0
lineEnd = text.find(‘\n’, pos)
if lineEnd < 0: lineEnd = len(text)
line = text[lineBegin:lineEnd]
print(f"error: expecting ‘{kind}’ but got ‘{tok.kind}’",
file=sys.stderr)
print(line, file=sys.stderr)
nSpace = pos - lineBegin if pos >= lineBegin else 0
print(‘^’.rjust(nSpace+1), file=sys.stderr)
sys.exit(1)

def data_items():
items = [];
while is_item_start():
items.append(data_item());
return items

def data_item():
if peek(‘[’):
return list();
elif peek(‘{’):
return tuple();
elif peek(‘%{’):
return map();
else:
return primitive();

def list():
items = []
consume(‘[’)
if is_item_start():
items.append(data_item());
while peek(‘,’):
consume(‘,’)
items.append(data_item())
consume(‘]’);
return { ‘%k’: ‘list’, ‘%v’: items };

def tuple():
items = []
consume(‘{’)
if is_item_start():
items.append(data_item());
while peek(‘,’):
consume(‘,’)
items.append(data_item())
consume(‘}’);
return { ‘%k’: ‘tuple’, ‘%v’: items };

def map():
pairs = []
consume(‘%{’)
if is_item_start() or peek(‘KEY’):
pairs.append(keyValue());
while peek(‘,’):
consume(‘,’)
pairs.append(keyValue())
consume(‘}’);
return { ‘%k’: ‘map’, ‘%v’: pairs };

def primitive():
if peek(‘INT’):
v = int(tok.lexeme.replace(‘_’, ‘’));
consume(‘INT’);
return { ‘%k’: ‘int’, ‘%v’: v };
elif peek(‘ATOM’):
v = tok.lexeme;
consume(‘ATOM’);
return { ‘%k’: ‘atom’, ‘%v’: v };
else:
v = tok.lexeme == ‘true’;
consume(‘BOOL’);
return { ‘%k’: ‘bool’, ‘%v’: v };

def keyValue():
key = ‘’;
if peek(‘KEY’):
atom = ‘:’ + tok.lexeme[0:-1];
consume(‘KEY’);
key = { ‘%k’: ‘atom’, ‘%v’: atom };
else:
key = data_item();
consume(‘=>’);
value = data_item();
return [ key, value ];

def is_item_start():
return peek(‘ATOM’) or peek(‘INT’) or peek(‘BOOL’) or <br/> peek(‘[’) or peek(‘{’) or peek(‘%{’);


items = data_items()
if tok.kind != ‘EOF’: error(‘EOF’, text)
return items


################################# Lexer #################################

SKIP_RE = re.compile(r’(\s+|#.)+‘)
INT_RE = re.compile(r’\d(_?\d+)‘)
ATOM_RE = re.compile(r’:[_a-zA-Z]\w*‘)
KEY_RE = re.compile(r’[_a-zA-Z]\w*:‘)
BOOL_RE = re.compile(r’\b(true|false)\b’)
ARROW_RE = re.compile(r’=&gt;‘)
FANCY_LBRACE_RE = re.compile(r’%{‘)

Token = namedtuple(‘Token’, ‘kind lexeme pos’)

def tokenize(text, pos=0):
toks = []
while pos < len(text):
m = SKIP_RE.match(text, pos)
if m:
pos += len(m.group())
if pos >= len(text): break
if m := INT_RE.match(text, pos):
tok = Token(‘INT’, m.group(), pos)
elif m := ATOM_RE.match(text, pos):
tok = Token(‘ATOM’, m.group(), pos)
elif m := KEY_RE.match(text, pos):
tok = Token(‘KEY’, m.group(), pos)
elif m := BOOL_RE.match(text, pos):
tok = Token(‘BOOL’, m.group(), pos)
elif m := ARROW_RE.match(text, pos):
tok = Token(’=>‘, m.group(), pos)
elif m := FANCY_LBRACE_RE.match(text, pos):
tok = Token(’%{‘, m.group(), pos)
else:
tok = Token(text[pos], text[pos], pos)
pos += len(tok.lexeme)
toks.append(tok)
toks.append(Token(‘EOF’, ‘<EOF>’, pos))
return toks


################################## Main #################################

def main():
text = sys.stdin.read()
#print(tokenize(text))
result = parse(text)
print(json.dumps(result, separators=(’,', ‘:’))) #no whitespace

if name == “main”:
main() Make changes to my program so that it can also pass the test cases. take the reference from the ideal program and make necessary changes to my program.
rewrite the new program