Commit d0ee0b08 authored by Francis Dupont's avatar Francis Dupont
Browse files

[4231] Added and & or operators

parent 8f6bc157
......@@ -469,8 +469,8 @@ static void yy_fatal_error (yyconst char msg[] );
(yy_c_buf_p) = yy_cp;
/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
#define YY_NUM_RULES 22
#define YY_END_OF_BUFFER 23
#define YY_NUM_RULES 24
#define YY_END_OF_BUFFER 25
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
......@@ -478,31 +478,31 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_acclist[105] =
static yyconst flex_int16_t yy_acclist[110] =
{ 0,
23, 21, 22, 1, 21, 22, 2, 22, 21, 22,
16, 21, 22, 17, 21, 22, 20, 21, 22, 21,
22, 15, 21, 22, 5, 21, 22, 5, 21, 22,
21, 22, 21, 22,16390, 18, 21, 22, 19, 21,
22, 21, 22,16390, 21, 22,16390, 21, 22,16390,
21, 22,16390, 21, 22,16390, 21, 22,16390, 21,
22,16390, 1, 2, 3, 5, 7,16390, 8198,16390,
16390,16390,16390,16390,16390,16390, 4, 13,16390,16390,
10,16390, 14,16390,16390,16390,16390,16390,16390,16390,
9,16390,16390,16390,16390, 11,16390, 8,16390,16390,
16390,16390, 12,16390
25, 23, 24, 1, 23, 24, 2, 24, 23, 24,
18, 23, 24, 19, 23, 24, 22, 23, 24, 23,
24, 17, 23, 24, 5, 23, 24, 5, 23, 24,
23, 24, 23, 24,16390, 20, 23, 24, 21, 23,
24, 23, 24,16390, 23, 24,16390, 23, 24,16390,
23, 24,16390, 23, 24,16390, 23, 24,16390, 23,
24,16390, 1, 2, 3, 5, 7,16390, 8198,16390,
16390,16390,16390,16390,16390, 16,16390,16390,16390, 4,
13,16390, 15,16390,16390, 10,16390, 14,16390,16390,
16390,16390,16390,16390,16390, 9,16390,16390,16390,16390,
11,16390, 8,16390,16390,16390,16390, 12,16390
} ;
static yyconst flex_int16_t yy_accept[67] =
static yyconst flex_int16_t yy_accept[70] =
{ 0,
1, 1, 1, 2, 4, 7, 9, 11, 14, 17,
20, 22, 25, 28, 31, 33, 36, 39, 42, 45,
48, 51, 54, 57, 60, 63, 64, 65, 65, 66,
67, 67, 68, 68, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 80, 81, 83, 85, 86,
87, 88, 89, 90, 91, 93, 94, 95, 96, 98,
100, 101, 102, 103, 105, 105
74, 75, 76, 78, 79, 80, 81, 83, 85, 86,
88, 90, 91, 92, 93, 94, 95, 96, 98, 99,
100, 101, 103, 105, 106, 107, 108, 110, 110
} ;
static yyconst flex_int32_t yy_ec[256] =
......@@ -516,10 +516,10 @@ static yyconst flex_int32_t yy_ec[256] =
12, 1, 1, 1, 13, 13, 13, 13, 13, 13,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 15, 14, 14,
16, 1, 17, 1, 18, 1, 19, 20, 13, 13,
16, 1, 17, 1, 18, 1, 19, 20, 13, 21,
21, 13, 22, 23, 24, 14, 14, 25, 14, 26,
27, 28, 14, 29, 30, 31, 32, 14, 14, 33,
22, 13, 23, 24, 25, 14, 14, 26, 14, 27,
28, 29, 14, 30, 31, 32, 33, 14, 14, 34,
14, 14, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
......@@ -537,94 +537,108 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
static yyconst flex_int32_t yy_meta[34] =
static yyconst flex_int32_t yy_meta[35] =
{ 0,
1, 2, 3, 1, 1, 1, 1, 2, 1, 4,
4, 1, 4, 2, 2, 1, 2, 2, 4, 4,
4, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2
4, 4, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2
} ;
static yyconst flex_int16_t yy_base[69] =
static yyconst flex_int16_t yy_base[72] =
{ 0,
0, 0, 135, 136, 132, 130, 128, 136, 136, 136,
24, 136, 26, 28, 119, 58, 136, 136, 75, 15,
21, 18, 19, 24, 29, 128, 126, 124, 136, 41,
0, 136, 55, 62, 102, 136, 101, 38, 48, 43,
55, 64, 57, 0, 100, 66, 99, 98, 45, 69,
70, 72, 28, 73, 97, 77, 80, 42, 96, 95,
84, 85, 63, 94, 136, 111, 114, 110
0, 0, 95, 184, 83, 73, 70, 184, 184, 184,
25, 184, 27, 29, 48, 41, 184, 184, 60, 19,
25, 28, 40, 38, 53, 55, 47, 44, 184, 62,
0, 184, 79, 81, 62, 184, 64, 73, 76, 78,
83, 87, 66, 91, 94, 0, 96, 98, 100, 103,
106, 109, 111, 113, 117, 120, 124, 126, 128, 131,
134, 136, 139, 142, 144, 149, 147, 184, 176, 179,
37
} ;
static yyconst flex_int16_t yy_def[69] =
static yyconst flex_int16_t yy_def[72] =
{ 0,
65, 1, 65, 65, 65, 65, 66, 65, 65, 65,
65, 65, 65, 65, 65, 67, 65, 65, 67, 19,
19, 19, 19, 19, 19, 65, 65, 66, 65, 65,
68, 65, 65, 19, 19, 65, 19, 19, 19, 19,
19, 19, 19, 68, 19, 19, 19, 19, 19, 19,
68, 1, 68, 68, 68, 68, 69, 68, 68, 68,
68, 68, 68, 68, 68, 70, 68, 68, 70, 19,
19, 19, 19, 19, 19, 68, 68, 69, 68, 68,
71, 68, 68, 19, 19, 68, 19, 19, 19, 19,
19, 19, 19, 19, 19, 71, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 0, 65, 65, 65
19, 19, 19, 19, 19, 19, 19, 0, 68, 68,
68
} ;
static yyconst flex_int16_t yy_nxt[170] =
static yyconst flex_int16_t yy_nxt[219] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 16, 16, 17, 18, 4, 19, 16,
20, 16, 21, 16, 16, 22, 23, 16, 16, 24,
25, 16, 16, 30, 30, 30, 30, 30, 30, 35,
31, 39, 35, 35, 40, 35, 41, 38, 35, 43,
30, 30, 35, 35, 57, 42, 33, 33, 31, 33,
33, 46, 35, 65, 65, 34, 35, 35, 53, 35,
61, 36, 35, 48, 36, 34, 33, 33, 65, 35,
47, 35, 34, 50, 64, 49, 35, 35, 35, 51,
35, 36, 34, 35, 35, 52, 35, 35, 54, 37,
55, 35, 56, 58, 35, 60, 59, 62, 35, 35,
63, 28, 28, 44, 28, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 45, 35, 29, 27, 26,
32, 29, 27, 26, 65, 3, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65
16, 20, 16, 21, 16, 16, 22, 23, 16, 16,
24, 25, 16, 16, 30, 30, 30, 30, 30, 30,
46, 31, 33, 33, 35, 35, 40, 29, 34, 27,
35, 35, 39, 35, 35, 41, 26, 36, 34, 32,
31, 33, 33, 35, 35, 35, 35, 34, 42, 43,
44, 30, 30, 29, 45, 27, 36, 34, 35, 35,
33, 33, 68, 68, 26, 37, 38, 35, 35, 47,
35, 35, 35, 48, 68, 36, 68, 68, 35, 35,
49, 35, 35, 35, 35, 68, 35, 35, 35, 35,
53, 50, 35, 35, 51, 68, 35, 35, 52, 35,
35, 35, 35, 35, 35, 35, 35, 54, 35, 35,
55, 35, 35, 56, 35, 35, 35, 35, 35, 35,
68, 57, 35, 35, 58, 35, 35, 60, 59, 35,
35, 35, 35, 35, 35, 61, 35, 63, 62, 35,
35, 35, 35, 64, 35, 35, 65, 35, 35, 35,
66, 67, 35, 35, 35, 35, 28, 28, 68, 28,
35, 35, 35, 3, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68
} ;
static yyconst flex_int16_t yy_chk[170] =
static yyconst flex_int16_t yy_chk[219] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 11, 11, 13, 13, 14, 14, 20,
13, 21, 22, 23, 22, 21, 23, 20, 24, 25,
30, 30, 53, 25, 53, 24, 33, 33, 13, 16,
16, 38, 38, 34, 34, 16, 58, 40, 49, 49,
58, 33, 39, 40, 16, 16, 19, 19, 34, 41,
39, 43, 19, 42, 63, 41, 34, 63, 42, 43,
46, 19, 19, 50, 51, 46, 52, 54, 50, 19,
51, 56, 52, 54, 57, 57, 56, 61, 61, 62,
62, 66, 66, 68, 66, 67, 67, 67, 64, 60,
59, 55, 48, 47, 45, 37, 35, 28, 27, 26,
15, 7, 6, 5, 3, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65
1, 1, 1, 1, 11, 11, 13, 13, 14, 14,
71, 13, 16, 16, 20, 20, 21, 28, 16, 27,
21, 21, 20, 22, 22, 22, 26, 16, 16, 15,
13, 19, 19, 24, 24, 23, 23, 19, 23, 23,
24, 30, 30, 7, 25, 6, 19, 19, 25, 25,
33, 33, 34, 34, 5, 19, 19, 35, 35, 37,
37, 43, 43, 38, 3, 33, 0, 34, 38, 38,
39, 39, 39, 40, 40, 0, 34, 34, 41, 41,
44, 40, 42, 42, 41, 0, 44, 44, 42, 45,
45, 47, 47, 48, 48, 49, 49, 45, 50, 50,
49, 51, 51, 52, 52, 52, 53, 53, 54, 54,
0, 53, 55, 55, 54, 56, 56, 56, 55, 57,
57, 58, 58, 59, 59, 57, 60, 60, 59, 61,
61, 62, 62, 61, 63, 63, 64, 64, 64, 65,
65, 66, 67, 67, 66, 66, 69, 69, 0, 69,
70, 70, 70, 68, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
68, 68, 68, 68, 68, 68, 68, 68
} ;
/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[23] =
static yyconst flex_int32_t yy_rule_can_match_eol[25] =
{ 0,
0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, };
0, 0, 0, 0, 0, };
extern int yy_flex_debug;
int yy_flex_debug = 1;
static yyconst flex_int16_t yy_rule_linenum[22] =
static yyconst flex_int16_t yy_rule_linenum[24] =
{ 0,
86, 90, 96, 106, 112, 126, 133, 134, 135, 136,
137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
148
147, 148, 150
} ;
static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
......@@ -709,7 +723,7 @@ static isc::eval::location loc;
// by moving it ahead by yyleng bytes. yyleng specifies the length of the
// currently matched token.
#define YY_USER_ACTION loc.columns(yyleng);
#line 713 "lexer.cc"
#line 727 "lexer.cc"
#define INITIAL 0
......@@ -998,7 +1012,7 @@ YY_DECL
loc.step();
#line 1002 "lexer.cc"
#line 1016 "lexer.cc"
while ( 1 ) /* loops until end-of-file is reached */
{
......@@ -1026,14 +1040,14 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 66 )
if ( yy_current_state >= 69 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
*(yy_state_ptr)++ = yy_current_state;
++yy_cp;
}
while ( yy_current_state != 65 );
while ( yy_current_state != 68 );
yy_find_action:
/* %% [10.0] code to find the action number goes here */
......@@ -1096,13 +1110,13 @@ do_action: /* This label is used only to access EOF actions. */
{
if ( yy_act == 0 )
fprintf( stderr, "--scanner backing up\n" );
else if ( yy_act < 22 )
else if ( yy_act < 24 )
fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
(long)yy_rule_linenum[yy_act], yytext );
else if ( yy_act == 22 )
else if ( yy_act == 24 )
fprintf( stderr, "--accepting default rule (\"%s\")\n",
yytext );
else if ( yy_act == 23 )
else if ( yy_act == 25 )
fprintf( stderr, "--(end of buffer or a NUL)\n" );
else
fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
......@@ -1222,48 +1236,58 @@ return isc::eval::EvalParser::make_NOT(loc);
case 15:
YY_RULE_SETUP
#line 141 "lexer.ll"
return isc::eval::EvalParser::make_DOT(loc);
return isc::eval::EvalParser::make_AND(loc);
YY_BREAK
case 16:
YY_RULE_SETUP
#line 142 "lexer.ll"
return isc::eval::EvalParser::make_LPAREN(loc);
return isc::eval::EvalParser::make_OR(loc);
YY_BREAK
case 17:
YY_RULE_SETUP
#line 143 "lexer.ll"
return isc::eval::EvalParser::make_RPAREN(loc);
return isc::eval::EvalParser::make_DOT(loc);
YY_BREAK
case 18:
YY_RULE_SETUP
#line 144 "lexer.ll"
return isc::eval::EvalParser::make_LBRACKET(loc);
return isc::eval::EvalParser::make_LPAREN(loc);
YY_BREAK
case 19:
YY_RULE_SETUP
#line 145 "lexer.ll"
return isc::eval::EvalParser::make_RBRACKET(loc);
return isc::eval::EvalParser::make_RPAREN(loc);
YY_BREAK
case 20:
YY_RULE_SETUP
#line 146 "lexer.ll"
return isc::eval::EvalParser::make_COMA(loc);
return isc::eval::EvalParser::make_LBRACKET(loc);
YY_BREAK
case 21:
YY_RULE_SETUP
#line 147 "lexer.ll"
return isc::eval::EvalParser::make_RBRACKET(loc);
YY_BREAK
case 22:
YY_RULE_SETUP
#line 148 "lexer.ll"
return isc::eval::EvalParser::make_COMA(loc);
YY_BREAK
case 23:
YY_RULE_SETUP
#line 150 "lexer.ll"
driver.error (loc, "Invalid character: " + std::string(yytext));
YY_BREAK
case YY_STATE_EOF(INITIAL):
#line 149 "lexer.ll"
#line 151 "lexer.ll"
return isc::eval::EvalParser::make_END(loc);
YY_BREAK
case 22:
case 24:
YY_RULE_SETUP
#line 150 "lexer.ll"
#line 152 "lexer.ll"
ECHO;
YY_BREAK
#line 1267 "lexer.cc"
#line 1291 "lexer.cc"
case YY_END_OF_BUFFER:
{
......@@ -1544,7 +1568,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 66 )
if ( yy_current_state >= 69 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
......@@ -1572,11 +1596,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 66 )
if ( yy_current_state >= 69 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
yy_is_jam = (yy_current_state == 65);
yy_is_jam = (yy_current_state == 68);
if ( ! yy_is_jam )
*(yy_state_ptr)++ = yy_current_state;
......@@ -2324,7 +2348,7 @@ void yyfree (void * ptr )
/* %ok-for-header */
#line 150 "lexer.ll"
#line 152 "lexer.ll"
......
......@@ -138,6 +138,8 @@ blank [ \t]
"substring" return isc::eval::EvalParser::make_SUBSTRING(loc);
"all" return isc::eval::EvalParser::make_ALL(loc);
"not" return isc::eval::EvalParser::make_NOT(loc);
"and" return isc::eval::EvalParser::make_AND(loc);
"or" return isc::eval::EvalParser::make_OR(loc);
"." return isc::eval::EvalParser::make_DOT(loc);
"(" return isc::eval::EvalParser::make_LPAREN(loc);
")" return isc::eval::EvalParser::make_RPAREN(loc);
......
// Generated 20151207
// Generated 20151209
// A Bison parser, made by GNU Bison 3.0.4.
// Locations for Bison parsers in C++
......
......@@ -251,19 +251,19 @@ namespace isc { namespace eval {
{
switch (that.type_get ())
{
case 27: // option_repr_type
case 29: // option_repr_type
value.move< TokenOption::RepresentationType > (that.value);
break;
case 17: // "constant string"
case 18: // "integer"
case 19: // "constant hexstring"
case 20: // "option name"
case 21: // TOKEN
case 19: // "constant string"
case 20: // "integer"
case 21: // "constant hexstring"
case 22: // "option name"
case 23: // TOKEN
value.move< std::string > (that.value);
break;
case 26: // option_code
case 28: // option_code
value.move< uint16_t > (that.value);
break;
......@@ -282,19 +282,19 @@ namespace isc { namespace eval {
state = that.state;
switch (that.type_get ())
{
case 27: // option_repr_type
case 29: // option_repr_type
value.copy< TokenOption::RepresentationType > (that.value);
break;
case 17: // "constant string"
case 18: // "integer"
case 19: // "constant hexstring"
case 20: // "option name"
case 21: // TOKEN
case 19: // "constant string"
case 20: // "integer"
case 21: // "constant hexstring"
case 22: // "option name"
case 23: // TOKEN
value.copy< std::string > (that.value);
break;
case 26: // option_code
case 28: // option_code
value.copy< uint16_t > (that.value);
break;
......@@ -334,51 +334,51 @@ namespace isc { namespace eval {
<< yysym.location << ": ";
switch (yytype)
{
case 17: // "constant string"
case 19: // "constant string"
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 342 "parser.cc" // lalr1.cc:636
break;
case 18: // "integer"
case 20: // "integer"
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 349 "parser.cc" // lalr1.cc:636
break;
case 19: // "constant hexstring"
case 21: // "constant hexstring"
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 356 "parser.cc" // lalr1.cc:636
break;
case 20: // "option name"
case 22: // "option name"
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 363 "parser.cc" // lalr1.cc:636
break;
case 21: // TOKEN
case 23: // TOKEN
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 370 "parser.cc" // lalr1.cc:636
break;
case 26: // option_code
case 28: // option_code
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< uint16_t > (); }
#line 377 "parser.cc" // lalr1.cc:636
break;
case 27: // option_repr_type
case 29: // option_repr_type
#line 72 "parser.yy" // lalr1.cc:636
#line 78 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
#line 384 "parser.cc" // lalr1.cc:636
break;
......@@ -580,19 +580,19 @@ namespace isc { namespace eval {
when using variants. */
switch (yyr1_[yyn])
{
case 27: // option_repr_type
case 29: // option_repr_type
yylhs.value.build< TokenOption::RepresentationType > ();
break;
case 17: // "constant string"
case 18: // "integer"
case 19: // "constant hexstring"
case 20: // "option name"
case 21: // TOKEN
case 19: // "constant string"
case 20: // "integer"
case 21: // "constant hexstring"
case 22: // "option name"
case 23: // TOKEN
yylhs.value.build< std::string > ();
break;
case 26: // option_code
case 28: // option_code
yylhs.value.build< uint16_t > ();
break;
......@@ -614,7 +614,7 @@ namespace isc { namespace eval {
switch (yyn)
{
case 4:
#line 86 "parser.yy" // lalr1.cc:859
#line 92 "parser.yy" // lalr1.cc:859
{
TokenPtr neg(new TokenNot());
ctx.expression.push_back(neg);
......@@ -623,120 +623,138 @@ namespace isc { namespace eval {
break;
case 5:
#line 91 "parser.yy" // lalr1.cc:859
#line 97 "parser.yy" // lalr1.cc:859
{
TokenPtr eq(new TokenEqual());
ctx.expression.push_back(eq);
TokenPtr neg(new TokenAnd());
ctx.expression.push_back(neg);
}
#line 632 "parser.cc" // lalr1.cc:859
break;
case 6:
#line 96 "parser.yy" // lalr1.cc:859
#line 102 "parser.yy" // lalr1.cc:859
{
TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS