|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# Copyright 2026 Paolo Pastori |
| 4 | +# Distributed under the Boost Software License, Version 1.0. |
| 5 | +# (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) |
| 6 | + |
| 7 | +# List of tested regexps. Each tuple contains the pattern, |
| 8 | +# the value used for the test, and the expected result (do not use [] here). |
| 9 | +# Any test is processed by an instruction such as |
| 10 | +# |
| 11 | +# ECHO [ MATCH <pattern> : <value> ] ; |
| 12 | +# |
| 13 | +# fell free to add more test cases... |
| 14 | + |
| 15 | +# remember to use raw strings to avoid surprises with escaping |
| 16 | +trials = [ |
| 17 | + (r'', r'', r''), |
| 18 | + # nothing captured (no parentheses in the pattern) |
| 19 | + (r'"hello world"', r'"hello world"', r''), |
| 20 | + # captures (more than one) |
| 21 | + (r'(first(second))(third)', r'firstsecondthird', r'firstsecond second third'), |
| 22 | + # ^ matches at start of line |
| 23 | + (r'^(world)', r'"hello world"', r''), |
| 24 | + (r'(world)', r'"hello world"', r'world'), |
| 25 | + # $ matches at end of line |
| 26 | + (r'(hello)$', r'"hello world"', r''), |
| 27 | + # . matches any single character |
| 28 | + (r'(.)', r'x', r'x'), |
| 29 | + # literal dot (with escaping looses special meaning) |
| 30 | + # NOTE: a \ followed by one of the characters ^.[$()|*+?\ |
| 31 | + # matches that character taken as an ordinary character, |
| 32 | + # while a \ followed by any other character (but <>) does nothing! |
| 33 | + # NOTE: because of common escaping by shell/interpreters |
| 34 | + # to obtain a final \ you often have to escape itself using |
| 35 | + # \\ or enclose it in raw strings (Python r'..', C++ R"...") |
| 36 | + (r'(\\.)', r'y', r''), |
| 37 | + (r'(\\.)', r'.', r'.'), |
| 38 | + # ? matches an optional atom, matches a sequence |
| 39 | + # of 0 or 1 matches of the atom |
| 40 | + (r'bar(s)?', r'bar', r''), |
| 41 | + (r'bar(s)?', r'bars', r's'), |
| 42 | + # + matches a sequence of 1 or more matches of the atom |
| 43 | + (r'(cin)+', r'cin', r'cin'), |
| 44 | + (r'((cin)+)', r'cincin', r'cincin cin'), |
| 45 | + # * matches a sequence of 0 or more matches of the atom |
| 46 | + (r'(0)*', r'1', r''), |
| 47 | + (r'(0)*', r'1000', r''), # NOTE: this does not work as expected |
| 48 | + # at the beginning of the pattern |
| 49 | + (r'1(0)*', r'1000', r'0'), |
| 50 | + (r'1(0)*1$', r'1001', r'0'), |
| 51 | + # \< matches at the beginning of a word |
| 52 | + (r'\\<(lo)', r'hello', r''), |
| 53 | + (r'\\<(lo)', r"she's so lovely", r'lo'), |
| 54 | + # \> matches at the end of a word |
| 55 | + (r'"\\>( fi)"', r'fidel', r''), |
| 56 | + (r'"\\>( fi)"', r'"hi fi"', r' fi'), # NOTE: extra space in result too |
| 57 | + # | separate branches, matches anything that matches one of the branches |
| 58 | + (r'(left)|(right)', r'left', r'left'), |
| 59 | + (r'(left)|(right)', r'right', r' right'), # NOTE: extra space as first group is empty |
| 60 | + # [] character class (list of characters enclosed in []), matches |
| 61 | + # any single character from the list. If the list begins with ^, it |
| 62 | + # matches any single character not from the rest of the list. |
| 63 | + # If two characters in the list are separated by -, this is shorthand |
| 64 | + # for the full range of characters between those two. |
| 65 | + # To include a literal ] in the list, make it the first character |
| 66 | + # (following a possible ^). To include a literal -, make it the first |
| 67 | + # or last character. Within brackets special characters ^.[$()|*+? |
| 68 | + # loose their special meaning. |
| 69 | + (r'"([0-9]+)"', r'1980s', r'1980'), |
| 70 | + (r'"([^0-9]+)"', r'1980s', r's'), |
| 71 | + # some real life cases |
| 72 | + (r'"^([0-9]+)\\.([0-9]+)(.*)$"', r'5.4.3beta', r'5 4 .3beta'), |
| 73 | + (r'^@(.*)', r'@my-rule', r'my-rule'), |
| 74 | + (r'^(!)?(.*)', r'"!bla bla"', r'! bla bla'), |
| 75 | +] |
| 76 | + |
| 77 | +# Do not change code below ! |
| 78 | + |
| 79 | +testln = [] |
| 80 | +exptln = [] |
| 81 | +for n, c in enumerate(trials): |
| 82 | + testln.append('ECHO {} [ MATCH {} : {} ] ;'.format(n, c[0], c[1])) |
| 83 | + exptln.append('{} {}'.format(n, c[2]) if c[2] else str(n)) |
| 84 | +testln.append('EXIT : 0 ;\n') |
| 85 | +exptln.append('\n') |
| 86 | + |
| 87 | +import BoostBuild |
| 88 | + |
| 89 | +t = BoostBuild.Tester(pass_toolset=False) |
| 90 | +t.write('Jamroot', '\n'.join(testln)) |
| 91 | +t.run_build_system() |
| 92 | +t.expect_output_lines('\n'.join(exptln)) |
| 93 | +t.expect_nothing_more() |
| 94 | +t.cleanup() |
0 commit comments