parser.yy 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. LPAREN "("
  36. RPAREN ")"
  37. NOT "not"
  38. AND "and"
  39. OR "or"
  40. EQUAL "=="
  41. OPTION "option"
  42. RELAY4 "relay4"
  43. LBRACKET "["
  44. RBRACKET "]"
  45. DOT "."
  46. TEXT "text"
  47. HEX "hex"
  48. EXISTS "exists"
  49. SUBSTRING "substring"
  50. ALL "all"
  51. COMA ","
  52. CONCAT "concat"
  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. | RELAY4 "[" option_code "]" "." EXISTS
  97. {
  98. switch (ctx.getUniverse()) {
  99. case Option::V4:
  100. {
  101. TokenPtr opt(new TokenRelay4Option($3, TokenOption::EXISTS));
  102. ctx.expression.push_back(opt);
  103. break;
  104. }
  105. case Option::V6:
  106. // We will have relay6[123] for the DHCPv6.
  107. // In a very distant future we'll possibly be able
  108. // to mix both if we have DHCPv4-over-DHCPv6, so it
  109. // has some sense to make it explicit whether we
  110. // talk about DHCPv4 relay or DHCPv6 relay. However,
  111. // for the time being relay4 can be used in DHCPv4
  112. // only.
  113. error(@1, "relay4 can only be used in DHCPv4.");
  114. }
  115. }
  116. ;
  117. string_expr : STRING
  118. {
  119. TokenPtr str(new TokenString($1));
  120. ctx.expression.push_back(str);
  121. }
  122. | HEXSTRING
  123. {
  124. TokenPtr hex(new TokenHexString($1));
  125. ctx.expression.push_back(hex);
  126. }
  127. | OPTION "[" option_code "]" "." option_repr_type
  128. {
  129. TokenPtr opt(new TokenOption($3, $6));
  130. ctx.expression.push_back(opt);
  131. }
  132. | RELAY4 "[" option_code "]" "." option_repr_type
  133. {
  134. switch (ctx.getUniverse()) {
  135. case Option::V4:
  136. {
  137. TokenPtr opt(new TokenRelay4Option($3, $6));
  138. ctx.expression.push_back(opt);
  139. break;
  140. }
  141. case Option::V6:
  142. // We will have relay6[123] for the DHCPv6.
  143. // In a very distant future we'll possibly be able
  144. // to mix both if we have DHCPv4-over-DHCPv6, so it
  145. // has some sense to make it explicit whether we
  146. // talk about DHCPv4 relay or DHCPv6 relay. However,
  147. // for the time being relay4 can be used in DHCPv4
  148. // only.
  149. error(@1, "relay4 can only be used in DHCPv4.");
  150. }
  151. }
  152. | SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
  153. {
  154. TokenPtr sub(new TokenSubstring());
  155. ctx.expression.push_back(sub);
  156. }
  157. | CONCAT "(" string_expr "," string_expr ")"
  158. {
  159. TokenPtr conc(new TokenConcat());
  160. ctx.expression.push_back(conc);
  161. }
  162. ;
  163. option_code : INTEGER
  164. {
  165. $$ = ctx.convertOptionCode($1, @1);
  166. }
  167. | OPTION_NAME
  168. {
  169. $$ = ctx.convertOptionName($1, @1);
  170. }
  171. ;
  172. option_repr_type : TEXT
  173. {
  174. $$ = TokenOption::TEXTUAL;
  175. }
  176. | HEX
  177. {
  178. $$ = TokenOption::HEXADECIMAL;
  179. }
  180. ;
  181. start_expr : INTEGER
  182. {
  183. TokenPtr str(new TokenString($1));
  184. ctx.expression.push_back(str);
  185. }
  186. ;
  187. length_expr : INTEGER
  188. {
  189. TokenPtr str(new TokenString($1));
  190. ctx.expression.push_back(str);
  191. }
  192. | ALL
  193. {
  194. TokenPtr str(new TokenString("all"));
  195. ctx.expression.push_back(str);
  196. }
  197. ;
  198. %%
  199. void
  200. isc::eval::EvalParser::error(const location_type& loc,
  201. const std::string& what)
  202. {
  203. ctx.error(loc, what);
  204. }