pattern

package module
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2019 License: BSD-3-Clause Imports: 6 Imported by: 0

README

pattern

http://godoc.org/github.com/creachadair/pattern

Go Report Card

This repository provides a reversible pattern substitution mechanism for strings.

Documentation

Overview

Package pattern implements template-based string matching and substitution.

A *pattern.P represents a template string containing a number of pattern words, named locations where substitution may occur. A pattern may be "matched" against a string to produce a set of bindings of names to substrings; or it may be "applied" to a set of bindings to produce a transformed string.

Template Grammar

A template is a string that contains zero or more pattern words. A pattern word has the general format

${name}

That is, a single word (allowing letters, digits, "/", ":", "_", "-", "+", "=", and "#") enclosed in curly brackets, prefixed by a dollar sign ($). To include a literal dollar sign, double it ($$); all other characters are interpreted as written.

Matching

Each pattern word is an anchor to a location in the template string. Binding regular expressions to the pattern words allows the the pattern to match strings.

To match a pattern against a string, use the Match method. Match succeeds if the string is a full regexp match for the expansion of the template with the pattern word bindings. A successful match returns a list of Binds that give the text of the submatches.

To find multiple matches of the pattern in the string, use the Search method. Search behaves like Match, but invokes a callback for each complete, non-overlapping match in sequence.

Substitution

String values may be substituted into a pattern using the Apply and ApplyFunc methods. Apply takes an ordered list of Bind values and interpolates them into the template; ApplyFunc invokes a callback to generate the strings to interpolate.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNoMatch = errors.New("string does not match pattern")

ErrNoMatch is reported by Match when the pattern does not match the needle.

View Source
var ErrStopSearch = errors.New("stopped searching")

ErrStopSearch is a special error value that can be returned by the callback to Search to terminate search early without error.

Functions

This section is empty.

Types

type Bind

type Bind struct {
	Name string
	Expr string
}

A Bind associates a pattern word name with a matching expression.

type BindFunc

type BindFunc func(name string, n int) (string, error)

A BindFunc synthesizes a value for the nth occurrence (indexed from 1) of a pattern word with the given name.

type Binds

type Binds []Bind

Binds is an ordered collection of bindings.

func (Binds) All

func (bs Binds) All(key string) []string

All returns all the bound values of key in bs, in order of occurrence.

func (Binds) First

func (bs Binds) First(key string) string

First returns the first bound value of key in bs, in order of occurrence. It returns "" if key is not bound.

func (Binds) Has

func (bs Binds) Has(key string) bool

Has reports whether key is bound at least once in bs.

type P

type P struct {
	// contains filtered or unexported fields
}

P contains a compiled pattern.

func MustParse

func MustParse(s string, binds []Bind) *P

MustParse parses s into a pattern template, as Parse, but panics if parsing fails. This function exists to support static initialization.

func Parse

func Parse(s string, binds []Bind) (*P, error)

Parse parses s into a pattern template, and binds the specified pattern variables to the corresponding expressions.

Example
package main

import (
	"fmt"
	"log"

	"github.com/creachadair/pattern"
)

func main() {
	// A pattern consists of a template string containing pattern words, and a
	// set of bindings that give regular expressions that each word must match.
	p, err := pattern.Parse(`Grade: ${grade}`, pattern.Binds{
		{Name: "grade", Expr: `([ABCD][-+]?|[EF])`},
	})
	if err != nil {
		log.Fatalf("Parse: %v", err)
	}

	// The string representation of a pattern is the original template string
	// from which it was parsed.
	fmt.Println(p)

}
Output:

Grade: ${grade}

func (*P) Apply

func (p *P) Apply(binds []Bind) (string, error)

Apply applies a list of bindings to the pattern template to produce a new string. It is an error if the bindings do not cover the pattern words in the template, meaning binds has at least one binding for each pattern word mentioned by the template.

If a pattern word appears in the template more often than in binds, the value of the last matching binding is repeated to fill the remaining spots.

Example
package main

import (
	"fmt"
	"log"

	"github.com/creachadair/pattern"
)

func main() {
	p := pattern.MustParse(`type ${name} struct {
  ${lhs} int
  ${rhs} int
}`, nil)

	s, err := p.Apply(pattern.Binds{
		{Name: "name", Expr: "binop"},
		{Name: "lhs", Expr: "X"},
		{Name: "rhs", Expr: "Y"},
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(s)
}
Output:

type binop struct {
  X int
  Y int
}

func (*P) ApplyFunc

func (p *P) ApplyFunc(f BindFunc) (string, error)

ApplyFunc applies bindings generated by f to the pattern template of p to produce a new string. If f reports an error, application fails. ApplyFunc will panic if f == nil.

Example
package main

import (
	"fmt"
	"log"

	"github.com/creachadair/pattern"
)

func main() {
	p := pattern.MustParse(`type ${name} struct {
  ${arg} string `+"`json:\"${arg},omitempty\"`"+`
}`, nil)

	s, err := p.ApplyFunc(func(name string, n int) (string, error) {
		if name == "name" {
			return "Argument", nil
		} else if n == 1 {
			return "X", nil
		}
		return "value", nil
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(s)
}
Output:

type Argument struct {
  X string `json:"value,omitempty"`
}

func (*P) Bind

func (p *P) Bind(binds Binds) *P

Bind returns a copy of p with the specified bindings updated. Existing bindings of p not mentioned in binds are copied intact from p to the result.

func (*P) Binds

func (p *P) Binds() Binds

Binds returns a list of bindings for p, in parsed order, populated with the currently-bound expression strings. Modifying the result has no effect on p, the caller may use this to generate a list of bindings to fill with values.

func (*P) Derive

func (p *P) Derive(s string) (*P, error)

Derive constructs a new compiled pattern, using the same pattern words as p but with s as the template instead. It is an error if s refers to a pattern word not known to p.

func (*P) Match

func (p *P) Match(needle string) (Binds, error)

Match reports whether needle matches p, and if so returns a list of bindings for the pattern words occurring in s. Because the same pattern word may occur multiple times in the pattern, the order of bindings is significant.

If matching fails, Match returns nil, ErrNoMatch. If matching succeeds but no bindings are found, Match returns nil, nil.

Example
package main

import (
	"fmt"
	"log"

	"github.com/creachadair/pattern"
)

func main() {
	p := pattern.MustParse(`[${text}](${link})`, pattern.Binds{
		{Name: "text", Expr: ".+"},
		{Name: "link", Expr: "\\S+"},
	})

	m, err := p.Match(`[docs](http://godoc.org/net/url)`)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("link text: %s\n", m.First("text"))
	fmt.Printf("URL: %s\n", m.First("link"))

}
Output:

link text: docs
URL: http://godoc.org/net/url

func (*P) Search

func (p *P) Search(needle string, f func(start, end int, binds Binds) error) error

Search scans needle for all non-overlapping matches of p. For each match, Search calls f with the starting and ending offsets of the match, along with the bindings captured from the match. If f reports an error, the search ends. If the error is ErrStopSearch, Search returns nil. Otherwise Search returns the error from f.

Example
package main

import (
	"fmt"
	"log"

	"github.com/creachadair/pattern"
)

func main() {
	p := pattern.MustParse("${word}:", pattern.Binds{
		{Name: "word", Expr: "\\w+"},
	})

	const text = `
Do: a deer, a female deer, Re: a drop of golden sun.
Mi: a name I call myself, Fa: a long long way to run.
`
	if err := p.Search(text, func(i, j int, m pattern.Binds) error {
		fmt.Printf("At %d: %q\n", i, m.First("word"))
		return nil
	}); err != nil {
		log.Fatal(err)
	}

}
Output:

At 1: "Do"
At 28: "Re"
At 54: "Mi"
At 80: "Fa"

func (*P) String

func (p *P) String() string

String returns the original template string from which p was parsed.

type ParseError

type ParseError struct {
	Pos     int    // offset where error occurred
	Message string // description of error
}

ParseError is the concrete type of parsing errors.

func (*ParseError) Error

func (p *ParseError) Error() string

Directories

Path Synopsis
Program madlib is a lighthearted demonstration program for how to use the github.com/creachadair/pattern package.
Program madlib is a lighthearted demonstration program for how to use the github.com/creachadair/pattern package.
Package transform implements transformations between pairs of string patterns, as defined by the github.com/creachadair/pattern package.
Package transform implements transformations between pairs of string patterns, as defined by the github.com/creachadair/pattern package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL