github.com/cloudflare/circl@v1.5.0/abe/cpabe/tkn20/internal/dsl/parser.go (about)

     1  package dsl
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  type Parser struct {
     8  	tokens   []Token
     9  	curr     int
    10  	wires    map[attr]attrValue
    11  	gates    []gate
    12  	negative bool
    13  }
    14  
    15  func newParser(tokens []Token) Parser {
    16  	return Parser{
    17  		tokens:   tokens,
    18  		curr:     0,
    19  		wires:    make(map[attr]attrValue),
    20  		gates:    make([]gate, 0),
    21  		negative: false,
    22  	}
    23  }
    24  
    25  func (p *Parser) parse() (Ast, error) {
    26  	_, err := p.expression()
    27  	if err != nil {
    28  		return Ast{}, err
    29  	}
    30  	return Ast{
    31  		wires: p.wires,
    32  		gates: p.gates,
    33  	}, nil
    34  }
    35  
    36  func (p *Parser) expression() (Expr, error) {
    37  	return p.or()
    38  }
    39  
    40  func (p *Parser) or() (Expr, error) {
    41  	expr, err := p.and()
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	for p.tokens[p.curr].Type == Or {
    47  		orToken := p.tokens[p.curr]
    48  		p.curr++
    49  		right, err := p.and()
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  		in1 := extractAttr(expr)
    54  		in2 := extractAttr(right)
    55  		newGate := gate{
    56  			op:  Or,
    57  			in1: in1,
    58  			in2: in2,
    59  			out: attr{
    60  				key: "",
    61  				id:  -(len(p.gates) + 1),
    62  			},
    63  		}
    64  		if p.negative {
    65  			newGate.op = And
    66  		}
    67  		p.gates = append(p.gates, newGate)
    68  
    69  		expr = Binary{
    70  			Left:     expr,
    71  			Operator: orToken,
    72  			Right:    right,
    73  			Output:   p.gates[len(p.gates)-1].out,
    74  		}
    75  	}
    76  	return expr, nil
    77  }
    78  
    79  func (p *Parser) and() (Expr, error) {
    80  	expr, err := p.not()
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	for p.tokens[p.curr].Type == And {
    86  		andToken := p.tokens[p.curr]
    87  		p.curr++
    88  		right, err := p.not()
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  		in1 := extractAttr(expr)
    93  		in2 := extractAttr(right)
    94  		newGate := gate{
    95  			op:  And,
    96  			in1: in1,
    97  			in2: in2,
    98  			out: attr{
    99  				key: "",
   100  				id:  -(len(p.gates) + 1),
   101  			},
   102  		}
   103  		if p.negative {
   104  			newGate.op = Or
   105  		}
   106  		p.gates = append(p.gates, newGate)
   107  
   108  		expr = Binary{
   109  			Left:     expr,
   110  			Operator: andToken,
   111  			Right:    right,
   112  			Output:   p.gates[len(p.gates)-1].out,
   113  		}
   114  	}
   115  	return expr, nil
   116  }
   117  
   118  func (p *Parser) not() (Expr, error) {
   119  	if p.tokens[p.curr].Type == Not {
   120  		p.curr++
   121  		currWires := make(map[attr]int)
   122  		for wire := range p.wires {
   123  			currWires[wire] = 1
   124  		}
   125  		p.negative = !p.negative
   126  		right, err := p.not()
   127  		p.negative = !p.negative
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  		for k, v := range p.wires {
   132  			_, ok := currWires[k]
   133  			if !ok {
   134  				v.positive = !v.positive
   135  				p.wires[k] = v
   136  			}
   137  		}
   138  		return Unary{
   139  			Operator: p.tokens[p.curr-1],
   140  			Right:    right,
   141  		}, nil
   142  	}
   143  
   144  	return p.primary()
   145  }
   146  
   147  func (p *Parser) primary() (Expr, error) {
   148  	if p.tokens[p.curr].Type == LeftParen {
   149  		p.curr++
   150  		expr, err := p.expression()
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  		if !(p.tokens[p.curr].Type == RightParen) {
   155  			return nil, fmt.Errorf("expected ')' after expression")
   156  		}
   157  		p.curr++
   158  		return Grouping{
   159  			Expr: expr,
   160  		}, nil
   161  	}
   162  
   163  	if p.tokens[p.curr].Type == Identifier {
   164  		if p.tokens[p.curr+1].Type == Colon {
   165  			if p.tokens[p.curr+2].Type == Identifier {
   166  				nextToken := p.tokens[p.curr+3].Type
   167  				if (nextToken == Identifier) ||
   168  					(nextToken == Colon) ||
   169  					(nextToken == LeftParen) ||
   170  					(nextToken == Not) {
   171  					return nil, fmt.Errorf(
   172  						"unexpected token %s, expected logical operator \"and\" or \"or\"",
   173  						p.tokens[p.curr+3].Lexeme)
   174  				}
   175  				key := p.tokens[p.curr]
   176  				value := p.tokens[p.curr+2]
   177  				currAttr := attr{
   178  					key: key.Lexeme,
   179  					id:  len(p.wires),
   180  				}
   181  				attrVal := attrValue{
   182  					value:    value.Lexeme,
   183  					positive: true,
   184  				}
   185  				p.wires[currAttr] = attrVal
   186  				p.curr += 3
   187  				return Literal{
   188  					Key:   currAttr,
   189  					Value: attrVal,
   190  				}, nil
   191  			}
   192  		}
   193  	}
   194  	return nil, fmt.Errorf("expected parentheses or literal")
   195  }
   196  
   197  func extractAttr(expr Expr) attr {
   198  	i := Interpreter{}
   199  	expr.Accept(&i)
   200  	return i.Literal.Key
   201  }