grammar-inference-engine/experiments/gbnf_eval.py

70 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Run pipeline + GBNF conversion on a codebase. Output results to JSON."""
import sys
import json
import time
from pathlib import Path
from bex.tag_preprocessor.analyze import analyze_directory
from bex.gbnf import to_gbnf
from bex.grammar import Empty
def run(codebase_name, dir_path):
print(f"\n{'='*60}")
print(f" {codebase_name}: {dir_path}")
print(f"{'='*60}")
t0 = time.time()
results = analyze_directory(
dir_path, slice='package', method='langsize',
min_coverage=0.05, min_methods=3,
)
elapsed = time.time() - t0
output = []
gbnf_ok = 0
gbnf_fail = 0
total_pkgs = 0
for ext, pkgs in results.items():
for pkg, info in sorted(pkgs.items()):
grammar_str = info.get('grammar', '')
if grammar_str:
total_pkgs += 1
entry = {'package': pkg, 'ext': ext, 'grammar': grammar_str, 'methods': info.get('methods', 0)}
try:
gbnf = to_gbnf(grammar_str)
entry['gbnf'] = gbnf
gbnf_ok += 1
except Exception as e:
entry['gbnf_error'] = str(e)
gbnf_fail += 1
output.append(entry)
print(f"\nTime: {elapsed:.1f}s")
print(f"Packages with grammar: {total_pkgs}")
print(f"GBNF OK: {gbnf_ok}, FAIL: {gbnf_fail}")
# Print all conversions
print(f"\n{''*60}")
for e in output:
if 'gbnf' in e:
print(f" {e['package']}")
print(f" Grammar: {e['grammar']}")
print(f" GBNF: {e['gbnf']}")
elif 'gbnf_error' in e:
print(f" {e['package']}")
print(f" Grammar: {e['grammar']}")
print(f" ERR: {e['gbnf_error']}")
# Save to file
out_path = Path(f"/tmp/gbnf_{codebase_name.lower().replace(' ','_')}.json")
with open(out_path, 'w') as f:
json.dump(output, f, indent=2)
print(f"\nSaved to {out_path}")
return output
if __name__ == '__main__':
name = sys.argv[1]
path = sys.argv[2]
run(name, path)