1#!/usr/bin/env python2 2 3from __future__ import absolute_import, division, print_function 4import argparse 5import datetime 6import os.path as path 7 8 9def print_tests(tests): 10 print('\n'.join([test_tostr(t) for t in tests])) 11 12 13def read_tests(f): 14 basename, _ = path.splitext(path.basename(f)) 15 tests = [] 16 for lineno, line in enumerate(open(f), 1): 17 fields = filter(None, map(str.strip, line.split('\t'))) 18 if not (4 <= len(fields) <= 5) \ 19 or 'E' not in fields[0] or fields[0][0] == '#': 20 continue 21 22 opts, pat, text, sgroups = fields[0:4] 23 groups = [] # groups as integer ranges 24 if sgroups == 'NOMATCH': 25 groups = [None] 26 elif ',' in sgroups: 27 noparen = map(lambda s: s.strip('()'), sgroups.split(')(')) 28 for g in noparen: 29 s, e = map(str.strip, g.split(',')) 30 if s == '?' and e == '?': 31 groups.append(None) 32 else: 33 groups.append((int(s), int(e))) 34 else: 35 # This skips tests that should result in an error. 36 # There aren't many, so I think we can just capture those 37 # manually. Possibly fix this in future. 38 continue 39 40 if pat == 'SAME': 41 pat = tests[-1][1] 42 if '$' in opts: 43 pat = pat.decode('string_escape') 44 text = text.decode('string_escape') 45 if 'i' in opts: 46 pat = '(?i)%s' % pat 47 48 name = '%s_%d' % (basename, lineno) 49 tests.append((name, pat, text, groups)) 50 return tests 51 52 53def test_tostr(t): 54 lineno, pat, text, groups = t 55 options = map(group_tostr, groups) 56 return 'mat!(match_%s, r"%s", r"%s", %s);' \ 57 % (lineno, pat, '' if text == "NULL" else text, ', '.join(options)) 58 59 60def group_tostr(g): 61 if g is None: 62 return 'None' 63 else: 64 return 'Some((%d, %d))' % (g[0], g[1]) 65 66 67if __name__ == '__main__': 68 parser = argparse.ArgumentParser( 69 description='Generate match tests from an AT&T POSIX test file.') 70 aa = parser.add_argument 71 aa('files', nargs='+', 72 help='A list of dat AT&T POSIX test files. See src/testdata') 73 args = parser.parse_args() 74 75 tests = [] 76 for f in args.files: 77 tests += read_tests(f) 78 79 tpl = ''' 80// DO NOT EDIT. Automatically generated by 'scripts/regex-match-tests.py' 81// on {date}. 82'''.lstrip() 83 print(tpl.format(date=str(datetime.datetime.now()))) 84 85 for f in args.files: 86 print('// Tests from %s' % path.basename(f)) 87 print_tests(read_tests(f)) 88 print('') 89