package main import ( "fmt" ) type SubexAST interface { compileWith(next SubexState) SubexState } type SubexASTConcat struct { first, second SubexAST } func (ast SubexASTConcat) compileWith(next SubexState) SubexState { return ast.first.compileWith(ast.second.compileWith(next)) } func (ast SubexASTConcat) String() string { return fmt.Sprintf("(%v)(%v)", ast.first, ast.second) } type SubexASTStore struct { match RegexAST slot rune } func (ast SubexASTStore) compileWith(next SubexState) SubexState { return SubexStoreState { match: ast.match.compileWith(RegexNoneState{}), slot: ast.slot, next: next, } } func (ast SubexASTStore) String() string { return fmt.Sprintf("$%c(%v)", ast.slot, ast.match) } type SubexASTOr struct { first, second SubexAST } func (ast SubexASTOr) compileWith(next SubexState) SubexState { return SubexGroupState { ast.first.compileWith(next), ast.second.compileWith(next), } } type SubexASTMaximise struct { content SubexAST } func (ast SubexASTMaximise) compileWith(next SubexState) SubexState { state := &SubexGroupState { nil, next, } state.first = ast.content.compileWith(state) return state } func (ast SubexASTMaximise) String() string { return fmt.Sprintf("(%v)*", ast.content) } type SubexASTMinimise struct { content SubexAST } func (ast SubexASTMinimise) compileWith(next SubexState) SubexState { state := &SubexGroupState { next, nil, } state.second = ast.content.compileWith(state) return state } func (ast SubexASTMinimise) String() string { return fmt.Sprintf("(%v)-", ast.content) } type SubexASTRepeat struct { content SubexAST min, max int } func (ast SubexASTRepeat) compileWith(next SubexState) SubexState { for i := ast.min; i < ast.max; i += 1 { next = SubexGroupState { ast.content.compileWith(next), next, } } for i := 0; i < ast.min; i += 1 { next = ast.content.compileWith(next) } return next } type SubexASTCopyRune rune func (ast SubexASTCopyRune) compileWith(next SubexState) SubexState { return SubexCopyRuneState{ rune: rune(ast), next: next, } } type SubexASTCopyAny struct {} func (ast SubexASTCopyAny) compileWith(next SubexState) SubexState { return SubexCopyAnyState{next} } func (ast SubexASTCopyAny) String() string { return "." } type SubexASTOutput struct { replacement []TransducerOutput } func (ast SubexASTOutput) compileWith(next SubexState) SubexState { return SubexOutputState{ content: ast.replacement, next: next, } }