main.go raw

   1  // Command regexp_ref prints the same case table tests/data/regexp/main.mx
   2  // prints, using Go's regexp. Legacy's -print-allocs matches with Go's regexp,
   3  // so this is the reference for the stage4 matcher in pkg/mxregexp: the two
   4  // outputs must be byte identical.
   5  package main
   6  
   7  import (
   8  	"fmt"
   9  	"os"
  10  	"regexp"
  11  	"strings"
  12  )
  13  
  14  func unescape(s string) string {
  15  	if !strings.Contains(s, `\`) {
  16  		return s
  17  	}
  18  	var b strings.Builder
  19  	for i := 0; i < len(s); {
  20  		if s[i] == '\\' && i+1 < len(s) {
  21  			switch s[i+1] {
  22  			case 'n':
  23  				b.WriteByte('\n')
  24  				i += 2
  25  				continue
  26  			case 't':
  27  				b.WriteByte('\t')
  28  				i += 2
  29  				continue
  30  			case 'r':
  31  				b.WriteByte('\r')
  32  				i += 2
  33  				continue
  34  			case '\\':
  35  				b.WriteByte('\\')
  36  				i += 2
  37  				continue
  38  			}
  39  		}
  40  		b.WriteByte(s[i])
  41  		i++
  42  	}
  43  	return b.String()
  44  }
  45  
  46  func main() {
  47  	if len(os.Args) < 2 {
  48  		fmt.Fprintln(os.Stderr, "usage: regexp_ref <cases-file>")
  49  		os.Exit(2)
  50  	}
  51  	data, err := os.ReadFile(os.Args[1])
  52  	if err != nil {
  53  		fmt.Fprintln(os.Stderr, err)
  54  		os.Exit(2)
  55  	}
  56  	for i, line := range strings.Split(string(data), "\n") {
  57  		if line == "" {
  58  			continue
  59  		}
  60  		tab := strings.IndexByte(line, '\t')
  61  		if tab < 0 {
  62  			fmt.Printf("case %d: missing tab\n", i)
  63  			os.Exit(1)
  64  		}
  65  		pattern, text := line[:tab], unescape(line[tab+1:])
  66  		re, cerr := regexp.Compile(pattern)
  67  		if cerr != nil {
  68  			fmt.Printf("%d error\n", i)
  69  			continue
  70  		}
  71  		fmt.Printf("%d %t\n", i, re.MatchString(text))
  72  	}
  73  }
  74