Documentation
¶
Overview ¶
Package parser implements the ClassAd lexer and parser.
Package parser provides the ClassAd parser implementation. The parser is generated from classad.y using goyacc.
Index ¶
- Constants
- func Parse(input string) (ast.Node, error)
- func ParseClassAd(input string) (*ast.ClassAd, error)
- func ParseExpr(input string) (ast.Expr, error)
- func ParseOldClassAd(input string) (*ast.ClassAd, error)
- func ParseScopedIdentifier(identifier string) (string, ast.AttributeScope)
- type ByteLexer
- type LexToken
- type Lexer
- type ReaderParser
- type StreamingLexer
- type Token
Constants ¶
const AND = 57356
const BOOLEAN_LITERAL = 57350
const ELVIS = 57354
const EQ = 57357
const ERROR = 57352
const GE = 57362
const IDENTIFIER = 57346
const INT64_MIN_MAGNITUDE = 57353
const INTEGER_LITERAL = 57348
const IS = 57359
const ISNT = 57360
const LE = 57361
const LSHIFT = 57363
const NE = 57358
const OR = 57355
const REAL_LITERAL = 57349
const RSHIFT = 57364
const STRING_LITERAL = 57347
const TokEOF = 0
TokEOF is the Kind of the token Next returns at end of input.
const UNARY = 57366
const UNDEFINED = 57351
const URSHIFT = 57365
Variables ¶
This section is empty.
Functions ¶
func Parse ¶
Parse parses a ClassAd string (a bracketed record, "[ a = 1; ... ]") and returns its AST. It does not accept a bare expression; to parse a standalone expression such as "a + 1" or "{1, 2}", use ParseExpr.
func ParseClassAd ¶
ParseClassAd parses a ClassAd and returns a ClassAd AST node. It returns an error if the input is not a ClassAd (for example a bare expression).
func ParseExpr ¶ added in v0.1.0
ParseExpr parses a standalone ClassAd expression (for example "a + 1", `strcat("x", "y")`, or "{1, 2, 3}") and returns its expression AST. It returns an error if the input is not a single well-formed expression.
The grammar's top-level production is a ClassAd, so the expression is parsed inside a throwaway single-attribute wrapper and the attribute's value is returned. This keeps Parse ClassAd-only -- avoiding grammar ambiguity between a record literal and a bare expression -- while still giving callers direct expression access.
func ParseOldClassAd ¶
ParseOldClassAd parses a ClassAd in the "old" HTCondor format. Old ClassAds have attributes separated by newlines without surrounding brackets. Example:
Foo = 3 Bar = "hello" Moo = Foo =!= Undefined
This implementation converts the old format to new format and reuses the existing parser.
func ParseScopedIdentifier ¶
func ParseScopedIdentifier(identifier string) (string, ast.AttributeScope)
ParseScopedIdentifier parses an identifier that may have a scope prefix. Returns the attribute name and scope.
Types ¶
type ByteLexer ¶ added in v0.3.0
type ByteLexer struct {
// contains filtered or unexported fields
}
ByteLexer tokenizes a ClassAd expression held entirely in memory as a string, indexing directly into that string instead of pulling runes through a bufio.Reader. It produces the same LexToken stream as StreamingLexer.Next for the same input, but on the hot paths it avoids per-token allocation: an identifier or an escape-free string/quoted-name token carries a sub-slice of the source (zero copy), numbers are parsed straight from a sub-slice, and no per-rune history is recorded (line/column for an error is computed lazily from the byte offset). Only a string literal that actually contains a backslash escape allocates, to materialize the unescaped value.
It is meant for the wire-native expression parser, which already has the whole value as a string. For streaming input (an io.Reader) use StreamingLexer.
func NewByteLexer ¶ added in v0.3.0
NewByteLexer returns a lexer over src. Drive it with Next.
type LexToken ¶ added in v0.3.0
LexToken is one lexical token, for a consumer that drives the lexer directly (via Next) instead of through the goyacc parser -- e.g. an alternative parser that emits a different representation. Kind is a named token constant for multi-character tokens:
IDENTIFIER, STRING_LITERAL, INTEGER_LITERAL, REAL_LITERAL, BOOLEAN_LITERAL, UNDEFINED, ERROR, INT64_MIN_MAGNITUDE, and the operators/keywords OR AND EQ NE IS ISNT LE GE LSHIFT RSHIFT URSHIFT ELVIS
or the byte value of a single-character operator or punctuation ('+', '-', '*', '/', '%', '(', ')', '[', ']', '{', '}', '.', ',', ';', '?', ':', '<', '>', '&', '|', '^', '~', '!', '=') -- goyacc's single-char-token convention. The value carried depends on Kind:
IDENTIFIER, STRING_LITERAL -> Str INTEGER_LITERAL -> Int REAL_LITERAL -> Real BOOLEAN_LITERAL -> Bool
type Lexer ¶
type Lexer struct {
// contains filtered or unexported fields
}
Lexer wraps the streaming lexer for string inputs while retaining the input and position fields used in existing tests.
func (*Lexer) Result ¶
Result returns the parsed result and any error. It must surface an error recorded on the underlying streaming lexer even when the parser produced a (partial) result -- e.g. trailing input that triggers a lexer error after a complete ClassAd, which the reference parser rejects.
type ReaderParser ¶
type ReaderParser struct {
// contains filtered or unexported fields
}
ReaderParser parses consecutive ClassAds from a buffered reader without requiring delimiters between ads. It reuses a single streaming lexer instance for efficiency.
func NewReaderParser ¶
func NewReaderParser(r io.Reader) *ReaderParser
NewReaderParser creates a reusable parser that pulls consecutive ClassAds from the provided reader without requiring delimiters. Non-buffered readers are wrapped internally for efficiency.
func (*ReaderParser) ParseClassAd ¶
func (p *ReaderParser) ParseClassAd() (*ast.ClassAd, error)
ParseClassAd parses the next ClassAd from the underlying reader. It reuses the same streaming lexer instance to avoid per-call allocations. It returns io.EOF when there is no more data to parse.
type StreamingLexer ¶
type StreamingLexer struct {
// contains filtered or unexported fields
}
StreamingLexer tokenizes ClassAds directly from an io.Reader. It stops producing tokens after the first complete ClassAd so the caller can parse multiple ads from a single stream.
func NewExprLexer ¶ added in v0.3.0
func NewExprLexer(r io.Reader) *StreamingLexer
NewExprLexer returns a StreamingLexer configured to tokenize a standalone expression: unlike the default lexer it does not stop after a bracketed record, so a record literal used as a value ([a = 1]) is lexed all the way through. Drive it with Next.
func NewStreamingLexer ¶
func NewStreamingLexer(r io.Reader) *StreamingLexer
NewStreamingLexer creates a lexer that consumes tokens directly from a reader. It wraps non-buffered readers in a bufio.Reader for efficiency.
func (*StreamingLexer) Error ¶
func (l *StreamingLexer) Error(s string)
Error implements the goyacc Lexer interface.
func (*StreamingLexer) Lex ¶
func (l *StreamingLexer) Lex(lval *yySymType) int
Lex implements the goyacc Lexer interface.
func (*StreamingLexer) Next ¶ added in v0.3.0
func (l *StreamingLexer) Next() (LexToken, error)
Next scans and returns the next token. At end of input its Kind is TokEOF. A lexical error (e.g. an unterminated string or bad escape) is returned as a non-nil error, matching what the goyacc path would report via Error.
func (*StreamingLexer) ResetForExpr ¶ added in v0.3.0
func (l *StreamingLexer) ResetForExpr()
ResetForExpr re-arms the lexer to tokenize another standalone expression from its current reader, reusing internal buffers. Reset the underlying reader (e.g. bufio.Reader.Reset) first; this clears the lexer's parse state. It lets a caller pool a lexer across many small parses instead of allocating one per parse.
func (*StreamingLexer) Result ¶
func (l *StreamingLexer) Result() (ast.Node, error)
Result returns the parsed result and any error.
func (*StreamingLexer) SetResult ¶
func (l *StreamingLexer) SetResult(node ast.Node)
SetResult sets the parse result.