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 }