1%token_prefix TK_ 2%token_type {buffer *} 3%extra_argument {ssi_ctx_t *ctx} 4%name ssiexprparser 5 6%include { 7#include "mod_ssi_expr.h" 8#include "buffer.h" 9 10#include <assert.h> 11#include <string.h> 12} 13 14%parse_failure { 15 ctx->ok = 0; 16} 17 18%type expr { ssi_val_t * } 19%type value { buffer * } 20%type exprline { ssi_val_t * } 21%type cond { int } 22%token_destructor { buffer_free($$); } 23 24%left AND. 25%left OR. 26%nonassoc EQ NE GT GE LT LE. 27%right NOT. 28 29input ::= exprline(B). { 30 ctx->val.bo = ssi_val_tobool(B); 31 ctx->val.type = SSI_TYPE_BOOL; 32 33 ssi_val_free(B); 34} 35 36exprline(A) ::= expr(B) cond(C) expr(D). { 37 int cmp; 38 39 if (B->type == SSI_TYPE_STRING && 40 D->type == SSI_TYPE_STRING) { 41 cmp = strcmp(B->str->ptr, D->str->ptr); 42 } else { 43 cmp = ssi_val_tobool(B) - ssi_val_tobool(D); 44 } 45 46 A = B; 47 48 switch(C) { 49 case SSI_COND_EQ: A->bo = (cmp == 0) ? 1 : 0; break; 50 case SSI_COND_NE: A->bo = (cmp != 0) ? 1 : 0; break; 51 case SSI_COND_GE: A->bo = (cmp >= 0) ? 1 : 0; break; 52 case SSI_COND_GT: A->bo = (cmp > 0) ? 1 : 0; break; 53 case SSI_COND_LE: A->bo = (cmp <= 0) ? 1 : 0; break; 54 case SSI_COND_LT: A->bo = (cmp < 0) ? 1 : 0; break; 55 } 56 57 A->type = SSI_TYPE_BOOL; 58 59 ssi_val_free(D); 60} 61exprline(A) ::= expr(B). { 62 A = B; 63} 64expr(A) ::= expr(B) AND expr(C). { 65 int e; 66 67 e = ssi_val_tobool(B) && ssi_val_tobool(C); 68 69 A = B; 70 A->bo = e; 71 A->type = SSI_TYPE_BOOL; 72 ssi_val_free(C); 73} 74 75expr(A) ::= expr(B) OR expr(C). { 76 int e; 77 78 e = ssi_val_tobool(B) || ssi_val_tobool(C); 79 80 A = B; 81 A->bo = e; 82 A->type = SSI_TYPE_BOOL; 83 ssi_val_free(C); 84} 85 86expr(A) ::= NOT expr(B). { 87 int e; 88 89 e = !ssi_val_tobool(B); 90 91 A = B; 92 A->bo = e; 93 A->type = SSI_TYPE_BOOL; 94} 95expr(A) ::= LPARAN exprline(B) RPARAN. { 96 A = B; 97} 98 99expr(A) ::= value(B). { 100 A = ssi_val_init(); 101 A->str = B; 102 A->type = SSI_TYPE_STRING; 103} 104 105value(A) ::= VALUE(B). { 106 A = B; 107} 108 109value(A) ::= value(B) VALUE(C). { 110 A = B; 111 buffer_append_string_buffer(A, C); 112 buffer_free(C); 113} 114 115cond(A) ::= EQ. { A = SSI_COND_EQ; } 116cond(A) ::= NE. { A = SSI_COND_NE; } 117cond(A) ::= LE. { A = SSI_COND_LE; } 118cond(A) ::= GE. { A = SSI_COND_GE; } 119cond(A) ::= LT. { A = SSI_COND_LT; } 120cond(A) ::= GT. { A = SSI_COND_GT; } 121