// Code generated by re2c, DO NOT EDIT.
//line "go/submatch/02_mtags.re":1
//go:generate re2go $INPUT -o $OUTPUT
package main

import (
	"reflect"
	"testing"
)

const (
	mtagRoot int = -1
	mtagNil int = -2
)

type mtagElem struct {
	val  int
	pred int
}

type mtagTrie = []mtagElem

func createTrie(capacity int) mtagTrie {
	return make([]mtagElem, 0, capacity)
}

func mtag(trie *mtagTrie, tag int, val int) int {
	*trie = append(*trie, mtagElem{val, tag})
	return len(*trie) - 1
}

// Recursively unwind both tag histories and consruct submatches.
func unwind(trie mtagTrie, x int, y int, str string) []string {
	if x == mtagRoot && y == mtagRoot {
		return []string{}
	} else if x == mtagRoot || y == mtagRoot {
		panic("tag histories have different length")
	} else {
		xval := trie[x].val
		yval := trie[y].val
		ss := unwind(trie, trie[x].pred, trie[y].pred, str)

		// Either both tags should be nil, or none of them.
		if xval == mtagNil && yval == mtagNil {
			return ss
		} else if xval == mtagNil || yval == mtagNil {
			panic("tag histories positive/negative tag mismatch")
		} else {
			s := str[xval:yval]
			return append(ss, s)
		}
	}
}

func lex(str string) []string {
	var cursor, marker int
	trie := createTrie(256)
	x := mtagRoot
	y := mtagRoot
	
//line "go/submatch/02_mtags.go":62
	yyt1 := mtagRoot
	yyt2 := mtagRoot
//line "go/submatch/02_mtags.re":58


	
//line "go/submatch/02_mtags.go":69
{
	var yych byte
	yych = str[cursor]
	switch (yych) {
	case 0x00:
		yyt2 = mtag(&trie, yyt2, mtagNil)
		yyt1 = mtag(&trie, yyt1, mtagNil)
		goto yy2
	case 'a':
		fallthrough
	case 'b':
		fallthrough
	case 'c':
		fallthrough
	case 'd':
		fallthrough
	case 'e':
		fallthrough
	case 'f':
		fallthrough
	case 'g':
		fallthrough
	case 'h':
		fallthrough
	case 'i':
		fallthrough
	case 'j':
		fallthrough
	case 'k':
		fallthrough
	case 'l':
		fallthrough
	case 'm':
		fallthrough
	case 'n':
		fallthrough
	case 'o':
		fallthrough
	case 'p':
		fallthrough
	case 'q':
		fallthrough
	case 'r':
		fallthrough
	case 's':
		fallthrough
	case 't':
		fallthrough
	case 'u':
		fallthrough
	case 'v':
		fallthrough
	case 'w':
		fallthrough
	case 'x':
		fallthrough
	case 'y':
		fallthrough
	case 'z':
		yyt1 = mtag(&trie, yyt1, cursor)
		goto yy6
	default:
		goto yy4
	}
yy2:
	cursor += 1
	x = yyt1
	y = yyt2
//line "go/submatch/02_mtags.re":73
	{ return unwind(trie, x, y, str) }
//line "go/submatch/02_mtags.go":140
yy4:
	cursor += 1
yy5:
//line "go/submatch/02_mtags.re":74
	{ return nil }
//line "go/submatch/02_mtags.go":146
yy6:
	cursor += 1
	marker = cursor
	yych = str[cursor]
	switch (yych) {
	case ';':
		yyt2 = mtag(&trie, yyt2, cursor)
		goto yy7
	case 'a':
		fallthrough
	case 'b':
		fallthrough
	case 'c':
		fallthrough
	case 'd':
		fallthrough
	case 'e':
		fallthrough
	case 'f':
		fallthrough
	case 'g':
		fallthrough
	case 'h':
		fallthrough
	case 'i':
		fallthrough
	case 'j':
		fallthrough
	case 'k':
		fallthrough
	case 'l':
		fallthrough
	case 'm':
		fallthrough
	case 'n':
		fallthrough
	case 'o':
		fallthrough
	case 'p':
		fallthrough
	case 'q':
		fallthrough
	case 'r':
		fallthrough
	case 's':
		fallthrough
	case 't':
		fallthrough
	case 'u':
		fallthrough
	case 'v':
		fallthrough
	case 'w':
		fallthrough
	case 'x':
		fallthrough
	case 'y':
		fallthrough
	case 'z':
		goto yy9
	default:
		goto yy5
	}
yy7:
	cursor += 1
	yych = str[cursor]
	switch (yych) {
	case 0x00:
		goto yy2
	case 'a':
		fallthrough
	case 'b':
		fallthrough
	case 'c':
		fallthrough
	case 'd':
		fallthrough
	case 'e':
		fallthrough
	case 'f':
		fallthrough
	case 'g':
		fallthrough
	case 'h':
		fallthrough
	case 'i':
		fallthrough
	case 'j':
		fallthrough
	case 'k':
		fallthrough
	case 'l':
		fallthrough
	case 'm':
		fallthrough
	case 'n':
		fallthrough
	case 'o':
		fallthrough
	case 'p':
		fallthrough
	case 'q':
		fallthrough
	case 'r':
		fallthrough
	case 's':
		fallthrough
	case 't':
		fallthrough
	case 'u':
		fallthrough
	case 'v':
		fallthrough
	case 'w':
		fallthrough
	case 'x':
		fallthrough
	case 'y':
		fallthrough
	case 'z':
		yyt1 = mtag(&trie, yyt1, cursor)
		goto yy9
	default:
		goto yy8
	}
yy8:
	cursor = marker
	goto yy5
yy9:
	cursor += 1
	yych = str[cursor]
	switch (yych) {
	case ';':
		yyt2 = mtag(&trie, yyt2, cursor)
		goto yy7
	case 'a':
		fallthrough
	case 'b':
		fallthrough
	case 'c':
		fallthrough
	case 'd':
		fallthrough
	case 'e':
		fallthrough
	case 'f':
		fallthrough
	case 'g':
		fallthrough
	case 'h':
		fallthrough
	case 'i':
		fallthrough
	case 'j':
		fallthrough
	case 'k':
		fallthrough
	case 'l':
		fallthrough
	case 'm':
		fallthrough
	case 'n':
		fallthrough
	case 'o':
		fallthrough
	case 'p':
		fallthrough
	case 'q':
		fallthrough
	case 'r':
		fallthrough
	case 's':
		fallthrough
	case 't':
		fallthrough
	case 'u':
		fallthrough
	case 'v':
		fallthrough
	case 'w':
		fallthrough
	case 'x':
		fallthrough
	case 'y':
		fallthrough
	case 'z':
		goto yy9
	default:
		goto yy8
	}
}
//line "go/submatch/02_mtags.re":75

}

func TestLex(t *testing.T) {
	var tests = []struct {
		str string
		res []string
	}{
		{"\000", []string{}},
		{"one;two;three;\000", []string{"one", "two", "three"}},
		{"one;two\000", nil},
	}

	for _, x := range tests {
		t.Run(x.str, func(t *testing.T) {
			res := lex(x.str)
			if !reflect.DeepEqual(res, x.res) {
				t.Errorf("got %v, want %v", res, x.res)
			}
		})
	}
}
