Documentation ¶
Overview ¶
Package codf is used to lex and parse codf configuration files.
Codf is similar in syntax to nginx configurations, albeit with differences (to keep parsing simple). Like its peers, codf structures configuration as a combination of sections and statements, both of which may accept values. For example, an HTTP server's configuration might look like the following (in keeping with the nginx references):
server go.spiff.io { listen 0.0.0.0:80; control unix:///var/run/httpd.sock; proxy unix:///var/run/go-redirect.sock { strip-x-headers yes; log-access no; } // keep caches in 64mb of memory cache memory 64mb { expire 10m 404; expire 1h 301 302; expire 5m 200; } }
codf is intended to accept generic input that is then filtered by the program using it, so syntax is kept restrictive enough to avoid too-complex parsing rules.
Index ¶
- Constants
- Variables
- func BigFloat(node Node) (v *big.Float)
- func BigInt(node Node) (v *big.Int)
- func BigRat(node Node) (v *big.Rat)
- func Bool(node Node) (v, ok bool)
- func Duration(node Node) (v time.Duration, ok bool)
- func Float64(node Node) (v float64, ok bool)
- func Int64(node Node) (v int64, ok bool)
- func Quote(node Node) (str string, ok bool)
- func Regexp(node Node) (v *regexp.Regexp)
- func String(node Node) (str string, ok bool)
- func Value(node Node) any
- func Walk(parent ParentNode, walker Walker) (err error)
- func Word(node Node) (str string, ok bool)
- type Array
- type Document
- type ExpectedError
- type ExprNode
- type Lexer
- type LexerFlag
- type Literal
- type Location
- type Map
- type MapEntry
- type NamedReader
- type Node
- type ParamNode
- type ParentNode
- type Parser
- type Section
- type Statement
- type Token
- type TokenKind
- type TokenReader
- type WalkError
- type WalkExiter
- type WalkMapper
- type Walker
Constants ¶
const ( TEOF // !. TWhitespace // [ \n\r\t]+ TComment // '//' { !EOL . } ( EOL | EOF ) TWord // BarewordRune {BarewordRune} TSemicolon // ';' TCurlOpen // '{' TCurlClose // '}' TBracketOpen // '[' TBracketClose // ']' TMapOpen // '#{' TRegexp // '#/' { '\\/' | [^/] } '/' // Strings also include TWord, above, which is an unquoted string. // Escape := '\\' ( [abfnrtv\\"] | 'x' Hex2 | 'u' Hex4 | 'U' Hex8 | Oct3 ) TString // '"' ( Escape | [^"] )* '"' TRawString // '`' ( '“' | [^`] )* '`' // TBoolean is produced by the parser transforming a boolean TWord into a TBoolean with // a corresponding bool value. TBoolean // Title/lower/UPPER of: 'true' | 'false' | 'yes' | 'no TInteger // '0' | [1-9] [0-9]* TFloat // Integer '.' Integer Exponent? | Integer Exponent THex // '0' [Xx] [a-fA-F0-9]+ TOctal // '0' [0-7]+ TBinary // '0' [bB] [01]+ TBaseInt // 2-36 '#' [a-zA-Z0-9]+ (corresponding to base) TDuration // 1m1.033s1h... TRational // Integer '/' Integer )
Lex-able Token kinds encountered in codf.
const DefaultPrecision = 80
DefaultPrecision is the default precision of TFloat tokens produced by Lexer. This can be overridden in the Lexer by setting its Precision field to a non-zero value.
Variables ¶
var ErrTooManyExprs = errors.New("too many expresssions")
ErrTooManyExprs is returned by ParseExpr when ParseExpr would return more than a single ExprNode.
var ErrUnexpectedEOF = errors.New("unexpected EOF")
ErrUnexpectedEOF is returned by the Lexer when EOF is encountered mid-token where a valid token cannot be cut off.
Functions ¶
func BigFloat ¶
BigFloat returns the value held by node as a *big.Float. If the node doesn't hold a float, it returns nil.
func BigInt ¶
BigInt returns the value held by node as a *big.Int. If the node doesn't hold an integer, it returns nil.
func BigRat ¶
BigRat returns the value held by node as a *big.Rat. If the node doesn't hold a rational, it returns nil.
func Bool ¶
Bool returns the value held by node as a boolean and true. If the node doesn't hold a boolean, it returns false for both values (v and ok).
func Duration ¶
Duration returns the value held by node as a time.Duration and true. If the node doesn't hold a duration, it returns 0 and false.
func Float64 ¶
Float64 returns the value held by node as a float64 and true. Integer and rational nodes are converted to floats. If the node doesn't hold a float, integer, or rational, it returns 0 and false.
func Int64 ¶
Int64 returns the value held by node as an int64 and true. Float and rational nodes are converted to floats. If the node is a rational and it is not an integer already, it is converted to a float and truncated to an integer. If the node doesn't hold an integer, float, or rational, it returns 0 and false.
func Regexp ¶
Regexp returns the value held by node as a *regexp.Regexp. If the node doesn't hold a regexp, it returns nil.
func String ¶
String returns the value held by node as a string and true. If the node doesn't hold a string or word, it returns the empty string and false.
func Value ¶
Value returns the value of node. If node is an ExprNode, it will return that node's value. Otherwise, it will return any value associated with the node's token. It may be nil for nodes whose token is punctuation or an opening brace or bracket.
func Walk ¶
func Walk(parent ParentNode, walker Walker) (err error)
Walk walks a codf AST starting with but not including parent. It is assumed that by having the parent, it has already been walked.
Walk will call walker.Statement for each statement encountered in parent and walker.EnterSection for each section (and walker.ExitSection if implemented).
If walker.EnterSection returns a non-nil Walker, Walk will recursively call Walk with the section and the returned Walker.
Walk will return a *WalkError if any error occurs during a walk. The WalkError will contain both the parent and child node that the error occurred for.
If the walker is a WalkMapper, any error in attempting to map a node will return a WalkError with the original node, not any resulting node. If the mapping is to a nil node without error, the node is deleted from the parent.
Nil child nodes are skipped.
Types ¶
type Array ¶
Array is an ExprNode for a '[ value ]' array in a document.
type Document ¶
type Document struct { // Name is usually a filename assigned by the user. It is not assigned by a parser and is // just metadata on the Document. Name string Children []Node // Sections and Statements that make up the Document. }
Document is the root of a codf document -- it is functionally similar to a Section, has no parameters.
type ExpectedError ¶
type ExpectedError struct { // Tok is the token that did not meet expectations. Tok Token // Msg is a message describing the expected token(s). Msg string }
ExpectedError is returned when a token, Tok, is encountered that does not meet expectations.
func (*ExpectedError) Error ¶
func (e *ExpectedError) Error() string
Error is an implementation of error.
type ExprNode ¶
ExprNode is a Node that has a concrete value associated with itself, such as a string, bool, rational, or other parse-able value.
type Lexer ¶
type Lexer struct { // Precision is the precision used in *big.Float when taking the actual value of a TFloat // token. Precision uint // Name is the name of the token source currently being lexed. It is used to identify the // source of a location by name. It is not necessarily a filename, but usually is. // // If the scanner provided to the Lexer implements NamedScanner, the scanner's name takes // priority. Name string // Flags is a set of Lex flags that can be used to change lexer behavior. Flags LexerFlag // contains filtered or unexported fields }
Lexer takes an input sequence of runes and constructs Tokens from it.
type LexerFlag ¶
type LexerFlag uint64
LexerFlag is a bitset representing a combination of zero or more Lex flags, such as LexNoRegexps, LexWordLiterals, and others. These Lex flags affect the Lexer's output, allowing one to disable specific tokenization behavior.
const ( // LexDefaultFlags is the empty flag set (the default). LexDefaultFlags LexerFlag = 0 // LexWordLiterals treats all literals, other than strings and compounds (maps, arrays) as // words. This is the union of LexNo* flags. LexWordLiterals = LexNoRegexps | LexNoBools | LexNoDurations | LexNoRationals | LexNoFloats | LexNoBaseInts | LexNoNumbers )
const ( // LexNoRegexps disables regular expressions. LexNoRegexps LexerFlag = 1 << iota // LexNoBools disables true/false/yes/no parsing. LexNoBools // LexNoDurations disables durations. LexNoDurations // LexNoRationals disables rationals. LexNoRationals // LexNoFloats disables floating point numbers. LexNoFloats // LexNoBaseInts disables non-base-10 number forms. LexNoBaseInts // LexNoNumbers disables all numbers. // Implies NoBaseInts, NoFloats, NoRationals, and NoDurations LexNoNumbers )
type Literal ¶
type Literal struct {
Tok Token
}
Literal is an ExprNode containing a value that is either a string, number (integer, float, or rational), regexp, duration, or boolean.
type Location ¶
type Location struct { Name string // Name is an identifier, usually a file path, for the location. Offset int // A byte offset into an input sequence. Starts at 0. Line int // A line number, delimited by '\n'. Starts at 1. Column int // A column number. Starts at 1. }
Location describes a location in an input byte sequence.
type Map ¶
type Map struct { StartTok Token EndTok Token // Elems is a map of the string keys to their key-value pairs. Elems map[string]*MapEntry }
Map is an ExprNode for a '#{ key value }' map in a document.
func (*Map) Pairs ¶
Pairs returns the map's elements as a []*MapEntry. The returned slice ordered by each MapEntry's Ord field (i.e., the parsing order).
type MapEntry ¶
type MapEntry struct { // Ord is an integer for ordering entries in the map. // There can be gaps in Ord for a range. Duplicate keys // increase Ord and replace the conflicting MapEntry. Ord uint // Key and Val are the key-value pair. Key ExprNode Val ExprNode }
MapEntry is an entry in a codf map, containing the key, value, and an ord field -- an integer for determining the order of keys in the map as parsed. The order of keys in a map is unordered and information is only retained for writing tools.
type NamedReader ¶
type NamedReader interface { io.Reader // Name returns a non-empty string identifying the reader's data source. This may be a file, // URL, resource ID, or some other thing. If the returned string is empty, it will be // treated as unnamed. Name() string }
NamedReader is an optional interface that an io.Reader can implement to provide a name for its data source.
type Node ¶
type Node interface { Token() Token // contains filtered or unexported methods }
Node is any parsed element of a codf document. This includes the Section, Statement, Literal, Array, Map, and other types.
type ParentNode ¶
ParentNode is a node that has sub-nodes.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser consumes tokens from a TokenReader and constructs a codf *Document from it.
The Document produced by the Parser is kept for the duration of the parser's lifetime, so it is possible to read multiple TokenReaders into a Parser and produce a combined document.
func (*Parser) Document ¶
Document returns the document constructed by Parser. Each call to Parse() modifies the Document, so it is unsafe to use the Document from multiple goroutines during parsing.
func (*Parser) Parse ¶
func (p *Parser) Parse(tr TokenReader) (err error)
Parse consumes tokens from a TokenReader and constructs a Document from its tokens.
If an error occurs during parsing, Parse will return that error for all subsequent calls to Parse, as the parser has been left in a middle-of-parsing state.
func (*Parser) ParseExpr ¶
func (p *Parser) ParseExpr(tr TokenReader) (ExprNode, error)
ParseExpr consumes tokens from a TokenReader and constructs a single ExprNode from its tokens. It returns an error if no ExprNode is produced or if it would parse more than one ExprNode.
If an error occurs during parsing, it has no effect on the behavior of subsequent Parse or ParseExpr calls. Errors returned by Parse do not affect ParseExpr.
If ParseExpr would return more than one ExprNode, it returns nil and ErrTooManyExprs.
type Section ¶
type Section struct { NameTok *Literal Params []ExprNode Children []Node StartTok Token EndTok Token }
Section is a single word follow by an optional set of ExprNodes for parameters. A Section may contain children Statements and Sections.
func (*Section) Name ¶
Name returns the name of the Section. For example, the section "proxy http { }" has the name "proxy".
func (*Section) Parameters ¶
Parameters returns the parameters the section holds.
type Statement ¶
Statement is any single word followed by an optional set of ExprNodes for parameters.
func (*Statement) Name ¶
Name returns the name of the Statement. For example, the statement "enable-gophers yes;" has the name "enable-gophers".
func (*Statement) Parameters ¶
Parameters returns the parameters the statement holds.
type Token ¶
Token is a token with a kind and a start and end location. Start, end, and raw fields are considered metadata and should not be used by a parser except to provide information to the user.
Kind is a TokenKind, such as TWord, and Value is the corresponding value of that TokenKind. Depending on the Kind, the Token must have a Value of the types described below. For all other TokenKinds not in the table below, a Value is not expected.
| Kind | Value Type | |-----------+----------------| | TWord | string | | TString | string | | TRegexp | *regexp.Regexp | | TBoolean | bool | | TFloat | *big.Float | | TRational | *big.Rat | | TInteger | *big.Int | | THex | *big.Int | | TOctal | *big.Int | | TBinary | *big.Int | | TBaseInt | *big.Int | | TDuration | time.Duration |
type TokenKind ¶
type TokenKind uint
TokenKind is an enumeration of the kinds of tokens produced by a Lexer and consumed by a Parser.
type TokenReader ¶
TokenReader is anything capable of reading a token and returning either it or an error.
type WalkError ¶
type WalkError struct { // Document is the document the context and node were found in, if the Walk root was // a document. Document *Document // Context is the ParentNode that Node is a child of. Context ParentNode // Node is the node that was encountered when the error occurred. Node Node // Err is the error that a Walker returned. Err error }
WalkError is an error returned by Walk if an error occurs during a Walk call.
type WalkExiter ¶
type WalkExiter interface { Walker // ExitSection is called with the parent Walker, the exited node, and its parent node // (either the root document given to Walk or a section). ExitSection(Walker, *Section, ParentNode) error }
WalkExiter is an optional interface implemented for a Walker to have Walk call ExitSection when it has finished consuming all children in a section.
type WalkMapper ¶
WalkMapper is an optional interface implemented for a Walker to have Walk replace the node passed to Map with the returned Node. If Map returns a nil node without an error, the mapped node is removed from its parent.