рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╡рдВрд╢ рдХрд╛рд░реНрдп рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЖрдк рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдФрд░ рдЯреЛрдХрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдб рдХреЗ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд░реНрдгрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рднрд╛рд╡ рдЪрд┐рддреНрд░ рдХреЛ рдЦрд░рд╛рдм рдХрд░рддреЗ рд╣реИрдВ : рдкреЛрд╕реНрдЯрдлрд╝рд┐рдХреНрд╕, рдЗрдиреНрдлрд┐рдХреНрд╕ рдФрд░ рдЕрдиреНрдпред рд╕рдорд╕реНрдпрд╛: рдЖрдк рд╕рдордЭ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм рддрдХ рдЖрдк рдЗрд╕рдХреА рдкрд╣рд▓реА рдЫрдорд╛рд╣реА рдХреЛ рдкрд╛рд░реНрд╕ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рддрдм рддрдХ рдЖрдк рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЕрдХреНрд╕рд░ рдСрдкрд░реЗрд╢рди рдХреА рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдФрд░ рдЗрд╕рдХреА рд╕рд╣рдпреЛрдЧреАрддрд╛ рдЖрдкрдХреЗ рд▓рд┐рдП рднреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рддрд╛рдХрд┐ рдирд┐рд░реНрдорд┐рдд рдПрдПрд╕рдЯреА рдореЗрдВ рд╕рд╣реА рд╕рдВрд░рдЪрдирд╛ рд╣реЛред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЧреЛ рдмреЛрд▓реА рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦреЗрдВрдЧреЗ, рдЬрд┐рди рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдкрд░ рд╣рдо рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░реИрдЯ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣рдорд╛рд░реА рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред

рд╢рдмреНрджрд╛рд╡рд▓реА
. , , - .
: , (, ).
: , .
/expression: , . : .
Statement: , . : .
/precedence: .
: , . : x++
.
: , . : ++x
.
: , . : x+y
.
/left-associative: .
/right-associative: .
non-associative: .
: , AST .
AST: , .
/: , .
: .
: .
: ().
: , .
: , .
рдЧреЛ ++ рдФрд░ ++ рдЧреЛ
рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдкрд░ рд╕рдордп рдмрд░реНрдмрд╛рдж рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП , рд╣рдо рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ рдЕрдкрдиреА рдЬрд░реВрд░рдд рдХреА рд╣рд░ рдЪреАрдЬ рд▓реЗрдВрдЧреЗ:
- рдЧреЛ / рд╕реНрдХреИрдирд░ рдЖрдкрдХреЛ рдкрд╛рда рд╕реЗ рдЯреЛрдХрди рдХрд╛ рдПрдХ рд╕реЗрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ
- go/token ,
scanner
, , :
type Token struct {
kind token.Token
value string
}
scanner.Scanner lexer
, :
Peek()
тАФ ,Consume()
тАФ ,
go/ast, , .
Go right-associative , .
Go тАФ statement, expression. . , .
. , , .
. , README : github.com/richardjennings/prattparser.
, .
type exprNode interface {
expr()
}
type nameExpr struct {
Value string
}
type prefixExpr struct {
Op token.Token
Arg exprNode
}
func (e *nameExpr) expr() {}
func (e *prefixExpr) expr() {}
, parseExpr()
, :
func (p *exprParser) parseExpr() exprNode {
tok := p.lexer.Consume()
switch tok.kind {
case token.IDENT:
return p.parseName(tok)
case token.ADD, token.SUB:
return p.parsePrefixExpr(tok)
case token.LPAREN:
return p.parseParenExpr(tok)
}
}
func (p *exprParser) parseName(tok Token) exprNode {
return &nameExpr{Value: tok.value}
}
func (p *exprParser) parsePrefixExpr(tok Token) exprNode {
arg := p.parseExpr()
return &prefixExpr{Op: tok.kind, Arg: arg}
}
- .
, . , -, parsePrefixExpr()
, map
, . , , map
.
, prefixParselet
:
type prefixParselet func(Token) exprNode
map[token.Token]prefixParselet
. :
func newExprParser() *exprParser {
p := &exprParser{
prefixParselets: make(map[token.Token]prefixParselet),
}
prefixExpr := func(kinds ...token.Token) {
for _, kind := range kinds {
p.prefixParselets[kind] = p.parsePrefixExpr
}
}
p.prefixParselets[token.IDENT] = p.parseName
prefixExpr(token.ADD, token.SUB)
return p
}
prefixExpr()
. , (. ).
func (p *exprParser) parseExpr() exprNode {
tok := p.lexer.consume()
prefix, ok := p.prefixParselets[tok.kind]
if !ok {
}
return prefix(tok)
}
, x+y
.
nameExpr{Value:"x"}
, +
. , .
infixParselet
, prefixParselet
, Expr
, . x+y
x
.
type infixParselet func(left exprNode, tok Token) exprNode
map
. , .
, +
-
binaryExpr
:
func (p *exprParser) parseBinaryExpr(left exprNode, tok token) exprNode {
right := p.parseExpr()
return &binaryExpr{Op: tok.kind, Left: left, Right: right}
}
parseExpr()
:
func (p *exprParser) parseExpr() exprNode {
tok := p.lexer.Consume()
prefix, ok := p.prefixParselets[tok.kind]
if !ok {
}
left := prefix(tok)
tok = p.lexer.Peek()
infix, ok := p.infixParselets[tok.kind]
if !ok {
return left
}
p.lexer.Consume()
return infix(left, tok)
}
:
- -:
x-y-z
=> x-(y-z)
- :
x*y+z
=> x*(y+z)
, .
{token.Token => precedence}
. , , :
p.prefixPrecedenceTab = map[token.Token]int{
token.ADD: 4,
token.SUB: 4,
}
p.infixPrecedenceTab = map[token.Token]int{
token.ADD: 2,
token.SUB: 2,
token.MUL: 3,
token.QUO: 3,
}
parseExpr()
precedence
:
func (p *exprParser) parseExpr(precedence int) exprNode {
tok := p.lexer.Consume()
prefix, ok := p.prefixParselets[tok.kind]
if !ok {
}
left := prefix(tok)
for precedence < p.infixPrecedenceTab[p.lexer.Peek().kind] {
tok := p.lexer.Consume()
infix := p.infixParselets[tok.kind]
left = infix(left, tok)
}
return left
}
, , , AST.
precedence
() parseExpr()
:
func (p *exprParser) parseBinaryExpr(left exprNode, tok Token) exprNode {
right := p.parseExpr(p.infixPrecedenceTab[tok.kind])
return &binaryExpr{Op: tok.kind, Left: left, Right: right}
}
parseBinaryExpr()
-. - , 1 :
func (p *exprParser) rparseBinaryExpr(left exprNode, tok Token) exprNode {
right := p.parseExpr(p.infixPrecedenceTab[tok.kind] - 1)
return &binaryExpr{Op: tok.kind, Left: left, Right: right}
}
, <<
-, rparseBinaryExpr()
.
тАФ infixParselet
, '('
parseExpr(0)
, ')'
.
() тАФ prefixParselet
, '('
parseExpr(0)
, ')'
.
func (p *exprParser) parseParenExpr(tok Token) exprNode {
x := p.parseExpr(0)
p.expect(token.RPAREN)
return x
}
тАФ infixParselet
:
func (p *exprParser) parsePostfixExpr(left exprNode, tok Token) exprNode {
return &postfixExpr{Op: tok.kind, Arg: left}
}
, , .
, , , helper- precedence
:
prefixExpr := func(precedence int, kinds ...token.Token) {
for _, kind := range kinds {
p.prefixParselets[kind] = p.parsePrefixExpr
p.prefixPrecedenceTab[kind] = precedence
}
}
:
addPrefixParselet(token.LPAREN, 0, p.parseParenExpr)
addPrefixParselet(token.IDENT, 0, p.parseNameExpr)
leftAssocBinaryExpr(1, token.LOR)
leftAssocBinaryExpr(2, token.LAND)
leftAssocBinaryExpr(3,
token.EQL,
token.NEQ,
)
rightAssocBinaryExpr(4,
token.SHL,
)
leftAssocBinaryExpr(4,
token.ADD,
token.SUB,
token.SHR,
)
leftAssocBinaryExpr(5,
token.MUL,
token.QUO,
token.REM,
)
prefixExpr(6,
token.ADD,
token.SUB,
token.INC,
token.DEC,
)
postfixExpr(7,
token.INC,
token.DEC,
)
addInfixParselet(token.LPAREN, 8, p.parseCallExpr)
, , PrecAdd=3
, PrecMult=4
.
map
.
, , newExprParser
. prefixParselet
infixParslet
, тАФ *exprParser
.
, , . , : , тАФ .
Pratt Parsers: Expression Parsing Made Easy (Bob Nystrom). , , , , ", ".
, .
github.com/quasilyte/pratt-parsers-go.
: github.com/richardjennings/prattparser.
: