promql: Allow injecting fake tokens into the generated parser (#6381)
* promql: Allow injecting fake tokens into the generated parser Yacc grammars do not support having multiple start symbols. To work around that restriction, it is possible to inject fake tokens into the lexer stream, as described here https://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html . This is part of the parser rewrite effort described in #6256. Signed-off-by: Tobias Guggenmos <tguggenm@redhat.com>
This commit is contained in:
parent
fa1489e35c
commit
408574a6e1
|
@ -193,6 +193,10 @@ const (
|
|||
GROUP_RIGHT
|
||||
BOOL
|
||||
keywordsEnd
|
||||
|
||||
startSymbolsStart
|
||||
// Start symbols for the generated parser.
|
||||
startSymbolsEnd
|
||||
)
|
||||
|
||||
var key = map[string]ItemType{
|
||||
|
|
|
@ -35,6 +35,9 @@ type parser struct {
|
|||
lex *lexer
|
||||
token item
|
||||
peeking bool
|
||||
|
||||
inject item
|
||||
injecting bool
|
||||
}
|
||||
|
||||
// ParseErr wraps a parsing error with line and position context.
|
||||
|
@ -352,7 +355,12 @@ type yySymType item
|
|||
//
|
||||
// For more information, see https://godoc.org/golang.org/x/tools/cmd/goyacc.
|
||||
func (p *parser) Lex(lval *yySymType) int {
|
||||
*lval = yySymType(p.next())
|
||||
if p.injecting {
|
||||
*lval = yySymType(p.inject)
|
||||
p.injecting = false
|
||||
} else {
|
||||
*lval = yySymType(p.next())
|
||||
}
|
||||
|
||||
return int(item(*lval).typ)
|
||||
}
|
||||
|
@ -364,6 +372,26 @@ func (p *parser) Error(e string) {
|
|||
p.errorf(e)
|
||||
}
|
||||
|
||||
// InjectItem allows injecting a single item at the beginning of the token stream
|
||||
// consumed by the generated parser.
|
||||
// This allows having multiple start symbols as described in
|
||||
// https://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html .
|
||||
// Only the Lex function used by the generated parser is affected by this injected item.
|
||||
// Trying to inject when a previously injected item has not yet been consumed will panic.
|
||||
// Only item types that are supposed to be used as start symbols are allowed as an argument.
|
||||
func (p *parser) InjectItem(typ ItemType) {
|
||||
if p.injecting {
|
||||
panic("cannot inject multiple items into the token stream")
|
||||
}
|
||||
|
||||
if typ <= startSymbolsStart || typ >= startSymbolsEnd {
|
||||
panic("cannot inject symbol that isn't start symbol")
|
||||
}
|
||||
|
||||
p.inject = item{typ: typ}
|
||||
p.injecting = true
|
||||
}
|
||||
|
||||
// expr parses any expression.
|
||||
func (p *parser) expr() Expr {
|
||||
// Parse the starting expression.
|
||||
|
|
Loading…
Reference in New Issue