import re
src = open('App/sims/klima/game-2d.html', 'r', encoding='utf-8').read()
scripts = list(re.finditer(r'', src, re.DOTALL))
print('scripts:', len(scripts))
# Only 1 script
m = scripts[0]
start_char = m.start(1)
js = m.group(1)
# Determine line offset in source
prefix = src[:start_char]
base_line = prefix.count('\n') + 1
print('base line:', base_line)
js = re.sub(r'/\*.*?\*/', '', js, flags=re.DOTALL)
BACKSLASH = chr(92)
out = []
line_map = [] # map cleaned-index -> line
i = 0
n = len(js)
lineno = 0
while i < n:
c = js[i]
if c == '/' and i + 1 < n and js[i+1] == '/':
while i < n and js[i] != '\n':
i += 1
continue
if c in ('"', "'", '`'):
quote = c
i += 1
while i < n:
if js[i] == BACKSLASH:
i += 2
continue
if js[i] == '\n':
lineno += 1
if js[i] == quote:
i += 1
break
i += 1
continue
if c == '\n':
lineno += 1
out.append(c)
line_map.append(lineno)
i += 1
code = ''.join(out)
# Track brace pairs; identify orphan `{` at the end (scope gain > loss by 1)
stack = [] # each entry: (line_in_script, idx)
for idx, ch in enumerate(code):
ln = line_map[idx]
if ch == '{':
stack.append((ln, idx))
elif ch == '}':
if stack:
stack.pop()
else:
print('Unmatched } at script line', ln, '= file line', base_line + ln)
if stack:
# orphan open braces
for (ln, idx) in stack[-5:]:
file_line = base_line + ln
ctx = code[max(0,idx-60):idx+60]
print('Orphan {{ at script line', ln, '= file line', file_line)
print(' ctx:', repr(ctx))