github.com/apex/up@v1.7.1/internal/logs/parser/parser.go (about) 1 //go:generate peg -inline -switch grammar.peg 2 3 // Package parser provides a parser for Up's 4 // log query language, abstracting away provider 5 // specifics. 6 package parser 7 8 import ( 9 "strconv" 10 11 "github.com/apex/up/internal/logs/parser/ast" 12 ) 13 14 // Parse query string. 15 func Parse(s string) (ast.Node, error) { 16 p := &parser{Buffer: s} 17 p.Init() 18 19 if err := p.Parse(); err != nil { 20 return nil, err 21 } 22 23 p.Execute() 24 n := ast.Root{Node: p.stack[0]} 25 return n, nil 26 } 27 28 // push node. 29 func (p *parser) push(n ast.Node) { 30 p.stack = append(p.stack, n) 31 } 32 33 // pop node. 34 func (p *parser) pop() ast.Node { 35 if len(p.stack) == 0 { 36 panic("pop: no nodes") 37 } 38 39 n := p.stack[len(p.stack)-1] 40 p.stack = p.stack[:len(p.stack)-1] 41 return n 42 } 43 44 // AddLevel node. 45 func (p *parser) AddLevel(s string) { 46 p.AddField("level") 47 p.AddString(s) 48 p.AddBinary(ast.EQ) 49 p.AddExpr() 50 } 51 52 // AddExpr node. 53 func (p *parser) AddExpr() { 54 p.push(ast.Expr{ 55 Node: p.pop(), 56 }) 57 } 58 59 // AddField node. 60 func (p *parser) AddField(s string) { 61 switch s { 62 case "level", "message", "timestamp": 63 p.push(ast.Property(s)) 64 default: 65 p.push(ast.Field(s)) 66 } 67 } 68 69 // AddString node. 70 func (p *parser) AddString(s string) { 71 p.push(ast.String(s)) 72 } 73 74 // AddSubscript node. 75 func (p *parser) AddSubscript(s string) { 76 p.push(ast.Subscript{ 77 Left: p.pop(), 78 Right: ast.Literal(s), 79 }) 80 } 81 82 // AddMember node. 83 func (p *parser) AddMember(s string) { 84 p.push(ast.Member{ 85 Left: p.pop(), 86 Right: ast.Literal(s), 87 }) 88 } 89 90 // SetNumber text. 91 func (p *parser) SetNumber(s string) { 92 p.number = s 93 } 94 95 // AddNumber node. 96 func (p *parser) AddNumber(unit string) { 97 f, _ := strconv.ParseFloat(p.number, 64) 98 p.push(ast.Number{ 99 Value: f, 100 Unit: unit, 101 }) 102 } 103 104 // AddTuple node. 105 func (p *parser) AddTuple() { 106 p.push(ast.Tuple{}) 107 } 108 109 // AddTupleValue node. 110 func (p *parser) AddTupleValue() { 111 v := p.pop() 112 t := p.pop().(ast.Tuple) 113 t = append(t, v) 114 p.push(t) 115 } 116 117 // AddBinary node. 118 func (p *parser) AddBinary(op ast.Op) { 119 p.push(ast.Binary{ 120 Op: op, 121 Right: p.pop(), 122 Left: p.pop(), 123 }) 124 } 125 126 // AddStage node. 127 func (p *parser) AddStage(stage string) { 128 p.push(ast.Binary{ 129 Op: ast.EQ, 130 Left: ast.Field("stage"), 131 Right: ast.String(stage), 132 }) 133 } 134 135 // AddBinaryContains node. 136 func (p *parser) AddBinaryContains() { 137 p.push(ast.Binary{ 138 Op: ast.EQ, 139 Right: ast.Contains{Node: p.pop()}, 140 Left: p.pop(), 141 }) 142 } 143 144 // AddUnary node. 145 func (p *parser) AddUnary(op ast.Op) { 146 p.push(ast.Unary{ 147 Op: op, 148 Right: p.pop(), 149 }) 150 }