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  }