gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/common/interpreter/logic.y (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This is an example of a goyacc program.
     6  // To build it:
     7  // goyacc -p "expr" expr.y (produces y.go)
     8  // go build -o expr y.go
     9  // expr
    10  // > <type an expression>
    11  // https://zhuanlan.zhihu.com/p/260180638
    12  /*
    13  1. Length判断
    14  2. Value判断 (None: Value==nil)
    15  3. 支持<, <=, ==, >, >=
    16  4. 支持&&, ||, !
    17  
    18  5. 进行类型自适应 Number, String, Bool
    19  6. 支持数值运算 +-x/()
    20  7. 支持函数调用 Rand [min, max]
    21  8. 支持变量设置和获取 = Name
    22  类型
    23  */
    24  
    25  %{
    26  
    27  package interpreter
    28  
    29  import (
    30  	"bytes"
    31  	"fmt"
    32  	"log"
    33  	"unicode/utf8"
    34  	"strconv"
    35  	"math/rand"
    36  )
    37  
    38  var (
    39  	LogDebug = func(string, ...any){}
    40  	LogInfo = func(string, ...any){}
    41  	LogError = func(string, ...any){}
    42  )
    43  
    44  type exprtype int8
    45  const (
    46  	EXPR_TYPE_STRING exprtype = iota 
    47  	EXPR_TYPE_BOOL
    48  	EXPR_TYPE_INT
    49  	EXPR_TYPE_FLOAT
    50  	EXPR_TYPE_NIL
    51  	EXPR_TYPE_CNT
    52  )
    53  
    54  func exprGet(v *logicSymType, info string) (any, error) {
    55  	switch v.expr_type {
    56  	case EXPR_TYPE_STRING:
    57  		return v.string_type, nil
    58  	case EXPR_TYPE_BOOL:
    59  		return v.bool_type, nil
    60  	case EXPR_TYPE_INT:
    61  		return v.int_type, nil
    62  	case EXPR_TYPE_FLOAT:
    63  		return v.float_type, nil
    64  	case EXPR_TYPE_NIL:
    65  		return nil, nil
    66  	}
    67  	
    68  	return nil, fmt.Errorf("%s type:%d", info, v.expr_type)	
    69  }
    70  
    71  func exprSet(s *logicSymType, d *logicSymType, info string) (err error) {
    72  	d.expr_type = s.expr_type
    73  
    74  	switch s.expr_type {
    75  	case EXPR_TYPE_STRING:
    76  		d.string_type = s.string_type
    77  	case EXPR_TYPE_BOOL:
    78  		d.bool_type = s.bool_type
    79  	case EXPR_TYPE_INT:
    80  		d.int_type = s.int_type
    81  	case EXPR_TYPE_FLOAT:
    82  		d.float_type = s.float_type
    83  	case EXPR_TYPE_NIL:	
    84  	default:
    85  		err = fmt.Errorf("%s type:%d", info, s.expr_type)
    86  	}
    87  	
    88  	return	
    89  }
    90  
    91  func exprBool(s *logicSymType) bool {
    92  	switch s.expr_type {
    93  		case EXPR_TYPE_STRING:
    94  			return len(s.string_type) > 0
    95  		case EXPR_TYPE_BOOL:
    96  			return s.bool_type
    97  		case EXPR_TYPE_INT:
    98  			return s.int_type != 0
    99  		case EXPR_TYPE_FLOAT:
   100  			return s.float_type != 0
   101  	}
   102  	return false
   103  }
   104  
   105  func typeGo2Script(v any, s *logicSymType) error {
   106  	switch v.(type) {
   107  	case nil:
   108  		s.expr_type = EXPR_TYPE_NIL
   109  	case int:
   110  		s.expr_type = EXPR_TYPE_INT
   111  		s.int_type = int64(v.(int))		
   112  	case int8:
   113  		s.expr_type = EXPR_TYPE_INT
   114  		s.int_type = int64(v.(int8))
   115  	case int16:
   116  		s.expr_type = EXPR_TYPE_INT
   117  		s.int_type = int64(v.(int16))
   118  	case int32:
   119  		s.expr_type = EXPR_TYPE_INT
   120  		s.int_type = int64(v.(int32))
   121  	case int64:
   122  		s.expr_type = EXPR_TYPE_INT
   123  		s.int_type = v.(int64)
   124  	case uint8:
   125  		s.expr_type = EXPR_TYPE_INT
   126  		s.int_type = int64(v.(uint8))
   127  	case uint16:
   128  		s.expr_type = EXPR_TYPE_INT
   129  		s.int_type = int64(v.(uint16))
   130  	case uint32:
   131  		s.expr_type = EXPR_TYPE_INT
   132  		s.int_type = int64(v.(uint32))
   133  	case uint64:
   134  		s.expr_type = EXPR_TYPE_INT
   135  		s.int_type = int64(v.(uint64))																	
   136  	case float32:
   137  		s.expr_type = EXPR_TYPE_FLOAT
   138  		s.float_type = float64(v.(float32))
   139  	case float64:
   140  		s.expr_type = EXPR_TYPE_FLOAT
   141  		s.float_type = v.(float64)			
   142  	case string:
   143  		s.expr_type = EXPR_TYPE_STRING
   144  		s.string_type = v.(string)
   145  	default:
   146  		return fmt.Errorf("unrecognized Value %v type:%T", v, v)
   147  	}
   148  	return nil	
   149  }
   150  %}
   151  
   152  %union {
   153  	string_type string
   154  	bool_type bool
   155  	int_type int64
   156  	float_type float64
   157  	expr_type exprtype
   158  }
   159  
   160  %type <expr_type> expr expr0 expr1
   161  %type <expr_type> logic logic1
   162  %type <expr_type> calc1 calc2 calc3
   163  
   164  %token '='
   165  %token ';'
   166  %token '+' '-' EQ LS LE GT GE AND OR NOT '(' ')' GET SET
   167  %token '*' '/'
   168  
   169  %token <expr_type> DATA RAND
   170  // %token <string_type> STRING
   171  // %token <bool_type> BOOL
   172  // %token <int_type> NUM
   173  // %token <float_type> FLOAT
   174  %token <string_type> VARIABLE
   175  
   176  %right '='
   177  %left ';'
   178  %right NOT
   179  %left AND OR
   180  %left EQ LS LE GT GE
   181  %left '+' '-'
   182  %left '*' '/'
   183  
   184  %%
   185  expr:
   186  	expr0
   187  	{
   188  		LogDebug("expr.expr0")
   189  		var err error
   190  		logiclex.(*logicLex).result, err = exprGet(&logicDollar[1], "expr.expr0")
   191  		if err != nil {
   192  			logiclex.(*logicLex).Error(err.Error())
   193  		}
   194  	}	
   195  expr0:
   196  	expr1
   197  	{
   198  		LogDebug("expr0.expr1")
   199  		err := exprSet(&logicDollar[1], &logicVAL, "expr0.expr1")
   200  		if err != nil {
   201  			logiclex.(*logicLex).Error(err.Error())
   202  		}
   203  	}
   204  | 	expr0 ';' expr1
   205  	{
   206  		LogDebug("expr0.expr0 ';' expr1")
   207  		err := exprSet(&logicDollar[3], &logicVAL, "expr0.expr0 ';' expr1")
   208  		if err != nil {
   209  			logiclex.(*logicLex).Error(err.Error())
   210  		}
   211  	}
   212  |	GET expr1
   213  	{
   214  		LogDebug("expr0.GET expr1")
   215  		if logicDollar[2].expr_type != EXPR_TYPE_STRING {
   216  			logiclex.(*logicLex).Error(fmt.Sprintf("expr0.GET expr1 $2:%d string need", logicDollar[2].expr_type))
   217  		} else {
   218  			r, ok := logiclex.(*logicLex).ctx.Get(logicDollar[2].string_type)
   219  			if !ok {
   220  				logicVAL.expr_type = EXPR_TYPE_NIL
   221  			} else {
   222  				err := typeGo2Script(r, &logicVAL)
   223  				if err != nil {
   224  					logiclex.(*logicLex).Error(fmt.Sprintf("expr0.GET expr1 typeGo2Script err:%s", err.Error()))
   225  				}
   226  			}	
   227  		}	
   228  	}	
   229  expr1:
   230  	logic
   231  	{
   232  		LogDebug("expr1.logic")
   233  		err := exprSet(&logicDollar[1], &logicVAL, "expr1.logic")
   234  		if err != nil {
   235  			logiclex.(*logicLex).Error(err.Error())
   236  		}
   237  	}
   238  |	VARIABLE '=' expr1
   239  	{
   240  		LogDebug("expr0.VARIABLE '=' expr1 v:%s", logicDollar[1].string_type)
   241  		v, err := exprGet(&logicDollar[3], "expr1.VARIABLE '=' expr1")
   242  		if err != nil {
   243  			logiclex.(*logicLex).Error(err.Error())
   244  		} else {
   245  			logiclex.(*logicLex).ctx.Set(logicDollar[1].string_type, v)
   246  			exprSet(&logicDollar[3], &logicVAL, "expr1.VARIABLE '=' expr1")
   247  		}		
   248  	}	
   249  logic:
   250  	logic1
   251  	{
   252  		LogDebug("logic.logic1")
   253  		err := exprSet(&logicDollar[1], &logicVAL, "logic.logic1")
   254  		if err != nil {
   255  			logiclex.(*logicLex).Error(err.Error())
   256  		}
   257  	}	
   258  |	logic AND logic
   259  	{
   260  		LogDebug("%v AND %v\n", $1, $3)
   261  		logicVAL.expr_type = EXPR_TYPE_BOOL
   262  		logicVAL.bool_type = exprBool(&logicDollar[1]) && exprBool(&logicDollar[3])
   263  	}
   264  |	logic OR logic
   265  	{
   266  		LogDebug("%v AND %v\n", $1, $3)
   267  		logicVAL.expr_type = EXPR_TYPE_BOOL
   268  		logicVAL.bool_type = exprBool(&logicDollar[1]) || exprBool(&logicDollar[3])
   269  	}
   270  logic1:
   271  	calc1
   272  	{
   273  		LogDebug("logic1.calc1")
   274  		err := exprSet(&logicDollar[1], &logicVAL, "logic1.calc1")
   275  		if err != nil {
   276  			logiclex.(*logicLex).Error(err.Error())
   277  		}
   278  	}	
   279  |	'+' calc1
   280  	{
   281  		switch logicDollar[1].expr_type {
   282  		case EXPR_TYPE_INT:
   283  			logicVAL.expr_type = logicDollar[1].expr_type
   284  			logicVAL.int_type = logicDollar[1].int_type
   285  		case EXPR_TYPE_FLOAT:
   286  			logicVAL.expr_type = logicDollar[1].expr_type
   287  			logicVAL.float_type = logicDollar[1].float_type	
   288  		default:
   289  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.'+' calc1 type:%d", logicDollar[1].expr_type))
   290  		}
   291  	}
   292  |	'-' calc1
   293  	{
   294  		switch logicDollar[1].expr_type {
   295  		case EXPR_TYPE_INT:
   296  			logicVAL.expr_type = logicDollar[1].expr_type
   297  			logicVAL.int_type = - logicDollar[1].int_type
   298  		case EXPR_TYPE_FLOAT:
   299  			logicVAL.expr_type = logicDollar[1].expr_type
   300  			logicVAL.float_type = - logicDollar[1].float_type	
   301  		default:
   302  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.'-' calc1 type:%d", logicDollar[1].expr_type))	
   303  		}
   304  	}
   305  |	NOT logic1	
   306  	{
   307  		LogDebug("NOT %v\n", $2)
   308  		logicVAL.expr_type = EXPR_TYPE_BOOL
   309  		logicVAL.bool_type = !exprBool(&logicDollar[2])
   310  	}
   311  |	logic1 LS logic1
   312  	{
   313  		LogDebug("LS NUM\n")
   314  
   315  		logicVAL.expr_type = EXPR_TYPE_BOOL	
   316  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   317  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   318  				logicVAL.bool_type = logicDollar[1].int_type < logicDollar[3].int_type
   319  			}
   320  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   321  				logicVAL.bool_type = float64(logicDollar[1].int_type) < logicDollar[3].float_type
   322  			}
   323  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   324  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   325  				logicVAL.bool_type = logicDollar[1].float_type < float64(logicDollar[3].int_type)
   326  			}
   327  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   328  				logicVAL.bool_type = logicDollar[1].float_type < logicDollar[3].float_type
   329  			}
   330  		} else {
   331  			logicVAL.expr_type = EXPR_TYPE_NIL
   332  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.logic1 LS logic1 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))
   333  		}
   334  	}
   335  |	logic1 LE logic1
   336  	{
   337  		LogDebug("LE NUM\n")
   338  		logicVAL.expr_type = EXPR_TYPE_BOOL	
   339  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   340  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   341  				logicVAL.bool_type = logicDollar[1].int_type <= logicDollar[3].int_type
   342  			}
   343  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   344  				logicVAL.bool_type = float64(logicDollar[1].int_type) <= logicDollar[3].float_type
   345  			}
   346  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   347  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   348  				logicVAL.bool_type = logicDollar[1].float_type <= float64(logicDollar[3].int_type)
   349  			}
   350  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   351  				logicVAL.bool_type = logicDollar[1].float_type <= logicDollar[3].float_type
   352  			}
   353  		} else {
   354  			logicVAL.expr_type = EXPR_TYPE_NIL
   355  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.logic1 LE logic1 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))
   356  		}
   357  	}
   358  |	logic1 GT logic1
   359  	{
   360  		LogDebug("GT NUM\n")
   361  		logicVAL.expr_type = EXPR_TYPE_BOOL	
   362  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   363  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   364  				logicVAL.bool_type = logicDollar[1].int_type > logicDollar[3].int_type
   365  			}
   366  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   367  				logicVAL.bool_type = float64(logicDollar[1].int_type) > logicDollar[3].float_type
   368  			}
   369  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   370  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   371  				logicVAL.bool_type = logicDollar[1].float_type > float64(logicDollar[3].int_type)
   372  			}
   373  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   374  				logicVAL.bool_type = logicDollar[1].float_type > logicDollar[3].float_type
   375  			}
   376  		} else {
   377  			logicVAL.expr_type = EXPR_TYPE_NIL
   378  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.logic1 GT logic1 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))
   379  		}
   380  	}
   381  |	logic1 GE logic1
   382  	{
   383  		LogDebug("GE NUM\n")
   384  		logicVAL.expr_type = EXPR_TYPE_BOOL	
   385  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   386  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   387  				logicVAL.bool_type = logicDollar[1].int_type >= logicDollar[3].int_type
   388  			}
   389  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   390  				logicVAL.bool_type = float64(logicDollar[1].int_type) >= logicDollar[3].float_type
   391  			}
   392  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   393  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   394  				logicVAL.bool_type = logicDollar[1].float_type >= float64(logicDollar[3].int_type)
   395  			}
   396  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   397  				logicVAL.bool_type = logicDollar[1].float_type >= logicDollar[3].float_type
   398  			}
   399  		} else {
   400  			logicVAL.expr_type = EXPR_TYPE_NIL
   401  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.logic1 GE logic1 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))
   402  		}
   403  	}
   404  |	logic1 EQ logic1
   405  	{
   406  		LogDebug("EQ NUM\n")
   407  		logicVAL.expr_type = EXPR_TYPE_BOOL	
   408  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   409  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   410  				logicVAL.bool_type = logicDollar[1].int_type == logicDollar[3].int_type
   411  			}
   412  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   413  				logicVAL.bool_type = float64(logicDollar[1].int_type) == logicDollar[3].float_type
   414  			}
   415  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   416  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   417  				logicVAL.bool_type = logicDollar[1].float_type == float64(logicDollar[3].int_type)
   418  			}
   419  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   420  				logicVAL.bool_type = logicDollar[1].float_type == logicDollar[3].float_type
   421  			}
   422  		} else if logicDollar[1].expr_type == EXPR_TYPE_BOOL && logicDollar[3].expr_type == EXPR_TYPE_BOOL {
   423  			logicVAL.bool_type = logicDollar[1].bool_type == logicDollar[3].bool_type
   424  		} else if  logicDollar[1].expr_type == EXPR_TYPE_STRING && logicDollar[3].expr_type == EXPR_TYPE_STRING {
   425  			logicVAL.bool_type = logicDollar[1].string_type == logicDollar[3].string_type
   426  		} else {
   427  			logicVAL.expr_type = EXPR_TYPE_NIL
   428  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.logic1 EQ logic1 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))	
   429  		}	
   430  	}
   431  calc1:
   432  	calc2
   433  	{
   434  		LogDebug("calc1.calc2")
   435  		err := exprSet(&logicDollar[1], &logicVAL, "calc1.calc2")
   436  		if err != nil {
   437  			logiclex.(*logicLex).Error(err.Error())
   438  		}		
   439  	}
   440  |	calc1 '+' calc2
   441  	{
   442  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   443  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   444  				logicVAL.expr_type = EXPR_TYPE_INT
   445  				logicVAL.int_type = logicDollar[1].int_type + logicDollar[3].int_type
   446  				LogDebug("calc1.calc1 '+' calc2 int+int %d+%d=%d", logicDollar[1].int_type, logicDollar[3].int_type, logicVAL.int_type)
   447  			}
   448  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   449  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   450  				logicVAL.float_type = float64(logicDollar[1].int_type) + logicDollar[3].float_type
   451  				LogDebug("calc1.calc1 '+' calc2 int+float %d+%f=%f", logicDollar[1].int_type, logicDollar[3].float_type, logicVAL.float_type)
   452  			}
   453  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   454  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   455  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   456  				logicVAL.float_type = logicDollar[1].float_type + float64(logicDollar[3].int_type)
   457  				LogDebug("calc1.calc1 '+' calc2 float+int %f+%d=%f", logicDollar[1].float_type, logicDollar[3].int_type, logicVAL.float_type)
   458  			}
   459  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   460  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   461  				logicVAL.float_type = logicDollar[1].float_type + logicDollar[3].float_type
   462  				LogDebug("calc1.calc1 '+' calc2 float+float %f+%f=%f", logicDollar[1].float_type, logicDollar[3].float_type, logicVAL.float_type)
   463  			}
   464  		} else if  logicDollar[1].expr_type == EXPR_TYPE_STRING && logicDollar[3].expr_type == EXPR_TYPE_STRING {
   465  			logicVAL.expr_type = EXPR_TYPE_STRING
   466  			logicVAL.string_type = logicDollar[1].string_type + logicDollar[3].string_type
   467  			LogDebug("calc1.calc1 '+' calc2 string %s+%s=%s", logicDollar[1].string_type, logicDollar[3].string_type, logicVAL.string_type)
   468  		} else if  logicDollar[1].expr_type == EXPR_TYPE_STRING && logicDollar[3].expr_type == EXPR_TYPE_INT {
   469  			logicVAL.expr_type = EXPR_TYPE_STRING
   470  			logicVAL.string_type = fmt.Sprintf("%s%d", logicDollar[1].string_type, logicDollar[3].int_type)
   471  			LogDebug("calc1.calc1 '+' calc2 string %s+%d=%s", logicDollar[1].string_type, logicDollar[3].int_type, logicVAL.string_type)
   472  		} else if  logicDollar[1].expr_type == EXPR_TYPE_STRING && logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   473  			logicVAL.expr_type = EXPR_TYPE_STRING
   474  			logicVAL.string_type = fmt.Sprintf("%s%f", logicDollar[1].string_type, logicDollar[3].float_type)
   475  			LogDebug("calc1.calc1 '+' calc2 string %s+%f=%s", logicDollar[1].string_type, logicDollar[3].float_type, logicVAL.string_type)
   476  		} else {
   477  			logicVAL.expr_type = EXPR_TYPE_NIL
   478  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.calc1 '+' calc2 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))	
   479  			LogDebug("calc1.calc1 '+' calc2 type:%d, %d", logicDollar[1].expr_type, logicDollar[3].expr_type)
   480  		}
   481  	}
   482  |	calc1 '-' calc2
   483  	{
   484  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   485  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   486  				logicVAL.expr_type = EXPR_TYPE_INT
   487  				logicVAL.int_type = logicDollar[1].int_type - logicDollar[3].int_type
   488  			}
   489  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   490  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   491  				logicVAL.float_type = float64(logicDollar[1].int_type) - logicDollar[3].float_type
   492  			}
   493  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   494  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   495  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   496  				logicVAL.float_type = logicDollar[1].float_type - float64(logicDollar[3].int_type)
   497  			}
   498  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   499  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   500  				logicVAL.float_type = logicDollar[1].float_type - logicDollar[3].float_type
   501  			}
   502  		} else {
   503  			logicVAL.expr_type = EXPR_TYPE_NIL
   504  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.calc1 '-' calc2 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))
   505  		}
   506  	}
   507  calc2:
   508  	calc3
   509  	{
   510  		LogDebug("calc2.calc3")
   511  		err := exprSet(&logicDollar[1], &logicVAL, "calc1.calc2")
   512  		if err != nil {
   513  			logiclex.(*logicLex).Error(err.Error())
   514  		}			
   515  	}
   516  |	calc2 '*' DATA
   517  	{
   518  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   519  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   520  				logicVAL.expr_type = EXPR_TYPE_INT
   521  				logicVAL.int_type = logicDollar[1].int_type * logicDollar[3].int_type
   522  			}
   523  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   524  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   525  				logicVAL.float_type = float64(logicDollar[1].int_type) * logicDollar[3].float_type
   526  			}
   527  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   528  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   529  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   530  				logicVAL.float_type = logicDollar[1].float_type * float64(logicDollar[3].int_type)
   531  			}
   532  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   533  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   534  				logicVAL.float_type = logicDollar[1].float_type * logicDollar[3].float_type
   535  			}
   536  		} else {
   537  			logicVAL.expr_type = EXPR_TYPE_NIL
   538  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.calc1 '*' calc2 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))	
   539  		}
   540  	}
   541  |	calc2 '/' DATA
   542  	{
   543  		if logicDollar[1].expr_type == EXPR_TYPE_INT {
   544  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   545  				logicVAL.expr_type = EXPR_TYPE_INT
   546  				logicVAL.int_type = logicDollar[1].int_type / logicDollar[3].int_type
   547  			}
   548  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   549  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   550  				logicVAL.float_type = float64(logicDollar[1].int_type) / logicDollar[3].float_type
   551  			}
   552  		} else if logicDollar[1].expr_type == EXPR_TYPE_FLOAT {
   553  			if logicDollar[3].expr_type == EXPR_TYPE_INT {
   554  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   555  				logicVAL.float_type = logicDollar[1].float_type / float64(logicDollar[3].int_type)
   556  			}
   557  			if logicDollar[3].expr_type == EXPR_TYPE_FLOAT {
   558  				logicVAL.expr_type = EXPR_TYPE_FLOAT
   559  				logicVAL.float_type = logicDollar[1].float_type / logicDollar[3].float_type
   560  			}
   561  		} else {
   562  			logicVAL.expr_type = EXPR_TYPE_NIL
   563  			logiclex.(*logicLex).Error(fmt.Sprintf("logic1.calc1 '/' calc2 type:%d - %d", logicDollar[1].expr_type, logicDollar[3].expr_type))	
   564  		}
   565  	}
   566  calc3:
   567  	'(' calc3 ')'
   568  	{
   569  		err := exprSet(&logicDollar[2], &logicVAL, "calc3.'(' calc3 ')'")
   570  		if err != nil {
   571  			logiclex.(*logicLex).Error(err.Error())
   572  		}
   573  	}
   574  |	VARIABLE
   575  	{
   576  		LogDebug("calc3.VARIABLE %s", logicDollar[1].string_type)
   577  		r, ok := logiclex.(*logicLex).ctx.Get(logicDollar[1].string_type)
   578  		if !ok {
   579  			logicVAL.expr_type = EXPR_TYPE_NIL
   580  		} else {
   581  			err := typeGo2Script(r, &logicVAL)
   582  			if err != nil {
   583  				logiclex.(*logicLex).Error(fmt.Sprintf("calc3.VARIABLE v:%s err:%s", logicDollar[1].string_type, err.Error()))
   584  			}
   585  		}
   586  	}
   587  |	RAND
   588  	{
   589  		LogDebug("calc3.RAND")
   590  		logicVAL.expr_type = EXPR_TYPE_INT
   591  		logicVAL.int_type = rand.Int63()			
   592  		LogDebug("RAND:%d\n", logicVAL.int_type)
   593  	}
   594  |	RAND DATA DATA
   595  	{
   596  		min := int64(0)
   597  		if logicDollar[2].expr_type == EXPR_TYPE_INT {
   598  			min = logicDollar[2].int_type
   599  		} else {
   600  			min = int64(logicDollar[2].float_type)
   601  		}
   602  		max := int64(0)
   603  		if logicDollar[3].expr_type == EXPR_TYPE_INT {
   604  			max = logicDollar[3].int_type
   605  		} else {
   606  			max = int64(logicDollar[3].float_type)
   607  		}	
   608  		logicVAL.expr_type = EXPR_TYPE_INT
   609  		logicVAL.int_type = rand.Int63n(max-min)+min
   610  		LogDebug("RAND (%d %d):%d\n", min, max, logicVAL.int_type)
   611  	}
   612  |	DATA
   613  	{
   614  		LogDebug("calc3.DATA")
   615  		err := exprSet(&logicDollar[1], &logicVAL, "calc3.DATA")
   616  		if err != nil {
   617  			logiclex.(*logicLex).Error(err.Error())
   618  		}		
   619  	}
   620  %%
   621  
   622  // The parser expects the lexer to return 0 on EOF.  Give it a name
   623  // for clarity.
   624  const eof = 0
   625  
   626  type DataCtx interface {
   627  	Get(string) (any, bool)
   628  	Set(string, any)	
   629  }
   630  // The parser uses the type <prefix>Lex as a lexer. It must provide
   631  // the methods Lex(*<prefix>SymType) int and Error(string).
   632  type logicLex struct {
   633  	line []byte
   634  	peek rune
   635  
   636  	result any // 输出结果
   637  	err error // 错误信息
   638  
   639  	ctx DataCtx
   640  	length int32 // 外部传入数据,节点长度
   641  	value any // 外部传入数据,节点数据	
   642  }
   643  
   644  // The parser calls this method to get each new token. This
   645  // implementation returns operators and NUM.
   646  func (x *logicLex) Lex(yylval *logicSymType) int {
   647  	for {
   648  		c := x.next()
   649  		LogDebug("c:%q", c)
   650  		switch c {
   651  		case eof:
   652  			return eof
   653  		case '+', '-', '*', '/', '(', ')', ';':
   654  			return int(c)
   655  		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
   656  			return x.num(c, yylval)
   657  		case '"':
   658  			return x.string(c, yylval)
   659  		case '<':
   660  			c = x.next()
   661  			if c != '=' {
   662  				x.peek = c
   663  				return LS
   664  			}
   665  			return LE
   666  		case '>':
   667  			c = x.next()
   668  			if c != '=' {
   669  				x.peek = c
   670  				return GT
   671  			}
   672  			return GE
   673  		case '=':
   674  			c = x.next()
   675  			if c != '=' {
   676  				x.peek = c
   677  				return int('=')
   678  			}
   679  			return EQ
   680  
   681  		case '&':
   682  			c = x.next()
   683  			if c != '&' {
   684  				x.err = fmt.Errorf("unrecognized character =%q", c)
   685  				return eof
   686  			}
   687  			return AND		
   688  		case '|':
   689  			c = x.next()
   690  			if c != '|' {
   691  				x.err = fmt.Errorf("unrecognized character =%q", c)
   692  				return eof
   693  			}
   694  			return OR		
   695  		case '!':
   696  			return NOT					
   697  		// Recognize Unicode multiplication and division
   698  		// symbols, returning what the parser expects.
   699  		case ' ', '\t', '\n', '\r':
   700  		default:
   701  			if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') {
   702  				return x.variable(c, yylval)
   703  			}
   704  
   705  			x.err = fmt.Errorf("unrecognized character %q", c)
   706  			return eof
   707  		}
   708  	}
   709  }
   710  
   711  // Lex a number.
   712  func (x *logicLex) num(c rune, yylval *logicSymType) int {
   713  	add := func(b *bytes.Buffer, c rune) {
   714  		if _, x.err = b.WriteRune(c); x.err != nil {
   715  			log.Fatalf("WriteRune: %s", x.err)
   716  		}
   717  	}
   718  
   719  	bFloat := false
   720  	if c == '.' {
   721  		bFloat = true
   722  	}
   723  
   724  	var b bytes.Buffer
   725  	
   726  	add(&b, c)
   727  	L: for {
   728  		c = x.next()
   729  		switch c {
   730  		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E':
   731  			add(&b, c)
   732  		case '.':
   733  			add(&b, c)
   734  			if bFloat {
   735  				x.err = fmt.Errorf("%s double .", b.String())
   736  				return eof
   737  			}
   738  			bFloat = true
   739  		default:
   740  			break L
   741  		}
   742  	}
   743  	if c != eof {
   744  		x.peek = c
   745  	}
   746  
   747  	if !bFloat {
   748  		var number uint64
   749  		number, x.err = strconv.ParseUint(b.String(), 10, 64)
   750  		yylval.expr_type = EXPR_TYPE_INT
   751  		yylval.int_type = int64(number)
   752  		if x.err != nil {
   753  			x.err = fmt.Errorf("%s ParseInt err:%s", b.String(), x.err.Error())
   754  			return eof
   755  		}
   756  	} else {
   757  		yylval.float_type, x.err = strconv.ParseFloat(b.String(), 64)
   758  		if x.err != nil {
   759  			x.err = fmt.Errorf("%s ParseFloat err:%s", b.String(), x.err.Error())
   760  			return eof
   761  		}
   762  		yylval.expr_type = EXPR_TYPE_FLOAT
   763  	}
   764  	return DATA
   765  }
   766  
   767  // Lex a string.
   768  func (x *logicLex) string(c rune, yylval *logicSymType) int {
   769  	add := func(b *bytes.Buffer, c rune) {
   770  		if _, x.err = b.WriteRune(c); x.err != nil {
   771  			log.Fatalf("WriteRune: %s", x.err)
   772  		}
   773  	}
   774  
   775  	var b bytes.Buffer
   776  	L: for {
   777  		c = x.next()
   778  		switch c {
   779  		case eof:
   780  			return eof
   781  		case '"':
   782  			break L
   783  		default:
   784  			add(&b, c)
   785  		}
   786  	}
   787  
   788  	yylval.expr_type = EXPR_TYPE_STRING
   789  	yylval.string_type = b.String()
   790  
   791  	return DATA
   792  }
   793  
   794  // Lex a Value or reserve word.
   795  func (x *logicLex) variable(c rune, yylval *logicSymType) int {
   796  	add := func(b *bytes.Buffer, c rune) {
   797  		if _, x.err = b.WriteRune(c); x.err != nil {
   798  			log.Fatalf("value WriteRune: %s", x.err)
   799  		}
   800  	}
   801  
   802  	var b bytes.Buffer
   803  	for {
   804  		if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || ( c >= '0' && c <= '9' ) {
   805  			add(&b, c)
   806  			c = x.next()
   807  		} else {
   808  			x.peek = c
   809  			break
   810  		}
   811  	}
   812  
   813  	s := b.String()
   814  	switch s {
   815  	case "Value":
   816  		err := typeGo2Script(x.value, yylval)
   817  		if err != nil {
   818  			x.Error(err.Error())
   819  			return eof
   820  		}
   821  		return DATA
   822  	case "Length":
   823  		yylval.expr_type = EXPR_TYPE_INT
   824  		yylval.int_type = int64(x.length)
   825  		return DATA	
   826  	case "None":
   827  		yylval.expr_type = EXPR_TYPE_BOOL
   828  		yylval.bool_type = x.value == nil
   829  		return DATA	
   830  	case "Rand":
   831  		return RAND	
   832  	case "Get":
   833  		return GET
   834  	}
   835  
   836  	yylval.expr_type = EXPR_TYPE_STRING
   837  	yylval.string_type = s
   838  	return VARIABLE
   839  }
   840  
   841  // Return the next rune for the lexer.
   842  func (x *logicLex) next() rune {
   843  	if x.peek != eof {
   844  		r := x.peek
   845  		x.peek = eof
   846  		return r
   847  	}
   848  	if len(x.line) == 0 {
   849  		return eof
   850  	}
   851  	c, size := utf8.DecodeRune(x.line)
   852  	x.line = x.line[size:]
   853  	if c == utf8.RuneError && size == 1 {
   854  		x.err = fmt.Errorf("invalid utf8")
   855  		return x.next()
   856  	}
   857  	return c
   858  }
   859  
   860  // The parser calls this method on a parse error.
   861  func (x *logicLex) Error(s string) {
   862  	if x.err == nil {
   863  		x.err = fmt.Errorf("Value:%v Length:%d err:%s", x.value, x.length, s)
   864  	} else {
   865  		x.err = fmt.Errorf("%s\nValue:%v Length:%d err:%s", x.err.Error(), x.value, x.length, s)
   866  	}
   867  }
   868  
   869  func DoString(in []byte, v any, l int32, ctx DataCtx) (any, error) {
   870  	lex := logicLex{line: in, result:false, value:v, length:l, ctx:ctx}
   871  
   872  	a := logicParse(&lex)
   873  
   874  	LogDebug("value:%v length:%d in:%s a:%d result:%v err:%v", lex.value, lex.length, string(in), a, lex.result, lex.err)
   875  
   876  	return lex.result, lex.err
   877  }