github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/ast/binopexp.go (about)

     1  package ast
     2  
     3  import (
     4  	"github.com/arnodel/golua/ops"
     5  	"github.com/arnodel/golua/token"
     6  )
     7  
     8  // A BinOp is a expression node that represents any binary operator.  The right
     9  // hand side can be a list of operations of the same type (OpType).  All
    10  // operations of the same type have the same precedence and can be merged into a
    11  // list.
    12  type BinOp struct {
    13  	Location
    14  	Left   ExpNode
    15  	OpType ops.Op
    16  	Right  []Operation
    17  }
    18  
    19  var _ ExpNode = BinOp{}
    20  
    21  // An Operation is a pair (operator, operand) which can be applied to an
    22  // expression node (e.g. "+ 2" or "/ 5").
    23  type Operation struct {
    24  	Op      ops.Op
    25  	Operand ExpNode
    26  }
    27  
    28  // NewBinOp creates a new BinOp from the given arguments.  If the left node is
    29  // already a BinOp node with the same operator type, a new node based on that
    30  // will be created.
    31  func NewBinOp(left ExpNode, op ops.Op, opTok *token.Token, right ExpNode) *BinOp {
    32  	loc := MergeLocations(left, right)
    33  	leftOp, ok := left.(*BinOp)
    34  	opType := op.Type()
    35  	if ok && leftOp.OpType == opType {
    36  		return &BinOp{
    37  			Location: loc,
    38  			Left:     leftOp.Left,
    39  			OpType:   opType,
    40  			Right:    append(leftOp.Right, Operation{op, right}),
    41  		}
    42  	}
    43  	return &BinOp{
    44  		Location: LocFromToken(opTok),
    45  		Left:     left,
    46  		OpType:   opType,
    47  		Right:    []Operation{{op, right}},
    48  	}
    49  }
    50  
    51  // ProcessExp uses the given ExpProcessor to process the receiver.
    52  func (b BinOp) ProcessExp(p ExpProcessor) {
    53  	p.ProcessBinOpExp(b)
    54  }
    55  
    56  // HWrite prints a tree representation of the node.
    57  func (b BinOp) HWrite(w HWriter) {
    58  	w.Writef("binop: %d", b.OpType)
    59  	w.Indent()
    60  	w.Next()
    61  	b.Left.HWrite(w)
    62  	for _, r := range b.Right {
    63  		w.Next()
    64  		w.Writef("op: %s", r.Op)
    65  		w.Next()
    66  		w.Writef("right: ")
    67  		r.Operand.HWrite(w)
    68  	}
    69  	w.Dedent()
    70  }