parser.yy 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
  2. This Source Code Form is subject to the terms of the Mozilla Public
  3. License, v. 2.0. If a copy of the MPL was not distributed with this
  4. file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. %skeleton "lalr1.cc" /* -*- C++ -*- */
  6. %require "3.0.0"
  7. %defines
  8. %define parser_class_name {EvalParser}
  9. %define api.token.constructor
  10. %define api.value.type variant
  11. %define api.namespace {isc::eval}
  12. %define parse.assert
  13. %code requires
  14. {
  15. #include <string>
  16. #include <eval/token.h>
  17. #include <eval/eval_context_decl.h>
  18. #include <dhcp/option.h>
  19. #include <boost/lexical_cast.hpp>
  20. using namespace isc::dhcp;
  21. using namespace isc::eval;
  22. }
  23. // The parsing context.
  24. %param { EvalContext& ctx }
  25. %locations
  26. %define parse.trace
  27. %define parse.error verbose
  28. %code
  29. {
  30. # include "eval_context.h"
  31. }
  32. %define api.token.prefix {TOKEN_}
  33. %token
  34. END 0 "end of file"
  35. EQUAL "=="
  36. OPTION "option"
  37. SUBSTRING "substring"
  38. CONCAT "concat"
  39. NOT "not"
  40. AND "and"
  41. OR "or"
  42. TEXT "text"
  43. RELAY4 "relay4"
  44. HEX "hex"
  45. EXISTS "exists"
  46. ALL "all"
  47. DOT "."
  48. COMA ","
  49. LPAREN "("
  50. RPAREN ")"
  51. LBRACKET "["
  52. RBRACKET "]"
  53. ;
  54. %token <std::string> STRING "constant string"
  55. %token <std::string> INTEGER "integer"
  56. %token <std::string> HEXSTRING "constant hexstring"
  57. %token <std::string> OPTION_NAME "option name"
  58. %type <uint16_t> option_code
  59. %type <TokenOption::RepresentationType> option_repr_type
  60. %left OR
  61. %left AND
  62. %precedence NOT
  63. %printer { yyoutput << $$; } <*>;
  64. %%
  65. // The whole grammar starts with an expression.
  66. %start expression;
  67. // Expression can either be a single token or a (something == something) expression
  68. expression : bool_expr
  69. ;
  70. bool_expr : "(" bool_expr ")"
  71. | NOT bool_expr
  72. {
  73. TokenPtr neg(new TokenNot());
  74. ctx.expression.push_back(neg);
  75. }
  76. | bool_expr AND bool_expr
  77. {
  78. TokenPtr neg(new TokenAnd());
  79. ctx.expression.push_back(neg);
  80. }
  81. | bool_expr OR bool_expr
  82. {
  83. TokenPtr neg(new TokenOr());
  84. ctx.expression.push_back(neg);
  85. }
  86. | string_expr EQUAL string_expr
  87. {
  88. TokenPtr eq(new TokenEqual());
  89. ctx.expression.push_back(eq);
  90. }
  91. | OPTION "[" option_code "]" "." EXISTS
  92. {
  93. TokenPtr opt(new TokenOption($3, TokenOption::EXISTS));
  94. ctx.expression.push_back(opt);
  95. }
  96. ;
  97. string_expr : STRING
  98. {
  99. TokenPtr str(new TokenString($1));
  100. ctx.expression.push_back(str);
  101. }
  102. | HEXSTRING
  103. {
  104. TokenPtr hex(new TokenHexString($1));
  105. ctx.expression.push_back(hex);
  106. }
  107. | OPTION "[" option_code "]" "." option_repr_type
  108. {
  109. TokenPtr opt(new TokenOption($3, $6));
  110. ctx.expression.push_back(opt);
  111. }
  112. | RELAY4 "[" option_code "]" "." option_repr_type
  113. {
  114. switch (ctx.getUniverse()) {
  115. case Option::V4:
  116. {
  117. TokenPtr opt(new TokenRelay4Option($3, $6));
  118. ctx.expression.push_back(opt);
  119. break;
  120. }
  121. case Option::V6:
  122. // We will have relay6[123] for the DHCPv6.
  123. // In a very distant future we'll possibly be able
  124. // to mix both if we have DHCPv4-over-DHCPv6, so it
  125. // has some sense to make it explicit whether we
  126. // talk about DHCPv4 relay or DHCPv6 relay. However,
  127. // for the time being relay4 can be used in DHCPv4
  128. // only.
  129. error(@1, "relay4 can only be used in DHCPv4.");
  130. }
  131. }
  132. | SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
  133. {
  134. TokenPtr sub(new TokenSubstring());
  135. ctx.expression.push_back(sub);
  136. }
  137. | CONCAT "(" string_expr "," string_expr ")"
  138. {
  139. TokenPtr conc(new TokenConcat());
  140. ctx.expression.push_back(conc);
  141. }
  142. ;
  143. option_code : INTEGER
  144. {
  145. $$ = ctx.convertOptionCode($1, @1);
  146. }
  147. | OPTION_NAME
  148. {
  149. $$ = ctx.convertOptionName($1, @1);
  150. }
  151. ;
  152. option_repr_type : TEXT
  153. {
  154. $$ = TokenOption::TEXTUAL;
  155. }
  156. | HEX
  157. {
  158. $$ = TokenOption::HEXADECIMAL;
  159. }
  160. ;
  161. start_expr : INTEGER
  162. {
  163. TokenPtr str(new TokenString($1));
  164. ctx.expression.push_back(str);
  165. }
  166. ;
  167. length_expr : INTEGER
  168. {
  169. TokenPtr str(new TokenString($1));
  170. ctx.expression.push_back(str);
  171. }
  172. | ALL
  173. {
  174. TokenPtr str(new TokenString("all"));
  175. ctx.expression.push_back(str);
  176. }
  177. ;
  178. %%
  179. void
  180. isc::eval::EvalParser::error(const location_type& loc,
  181. const std::string& what)
  182. {
  183. ctx.error(loc, what);
  184. }