parser.yy 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. // Tokens in an order which makes sense and related to the intented use.
  34. %token
  35. END 0 "end of file"
  36. LPAREN "("
  37. RPAREN ")"
  38. NOT "not"
  39. AND "and"
  40. OR "or"
  41. EQUAL "=="
  42. OPTION "option"
  43. RELAY4 "relay4"
  44. LBRACKET "["
  45. RBRACKET "]"
  46. DOT "."
  47. TEXT "text"
  48. HEX "hex"
  49. EXISTS "exists"
  50. SUBSTRING "substring"
  51. ALL "all"
  52. COMA ","
  53. CONCAT "concat"
  54. ;
  55. %token <std::string> STRING "constant string"
  56. %token <std::string> INTEGER "integer"
  57. %token <std::string> HEXSTRING "constant hexstring"
  58. %token <std::string> OPTION_NAME "option name"
  59. %type <uint16_t> option_code
  60. %type <TokenOption::RepresentationType> option_repr_type
  61. %left OR
  62. %left AND
  63. %precedence NOT
  64. %printer { yyoutput << $$; } <*>;
  65. %%
  66. // The whole grammar starts with an expression.
  67. %start expression;
  68. // Expression can either be a single token or a (something == something) expression
  69. expression : bool_expr
  70. ;
  71. bool_expr : "(" bool_expr ")"
  72. | NOT bool_expr
  73. {
  74. TokenPtr neg(new TokenNot());
  75. ctx.expression.push_back(neg);
  76. }
  77. | bool_expr AND bool_expr
  78. {
  79. TokenPtr neg(new TokenAnd());
  80. ctx.expression.push_back(neg);
  81. }
  82. | bool_expr OR bool_expr
  83. {
  84. TokenPtr neg(new TokenOr());
  85. ctx.expression.push_back(neg);
  86. }
  87. | string_expr EQUAL string_expr
  88. {
  89. TokenPtr eq(new TokenEqual());
  90. ctx.expression.push_back(eq);
  91. }
  92. | OPTION "[" option_code "]" "." EXISTS
  93. {
  94. TokenPtr opt(new TokenOption($3, TokenOption::EXISTS));
  95. ctx.expression.push_back(opt);
  96. }
  97. | RELAY4 "[" option_code "]" "." EXISTS
  98. {
  99. switch (ctx.getUniverse()) {
  100. case Option::V4:
  101. {
  102. TokenPtr opt(new TokenRelay4Option($3, TokenOption::EXISTS));
  103. ctx.expression.push_back(opt);
  104. break;
  105. }
  106. case Option::V6:
  107. // We will have relay6[123] for the DHCPv6.
  108. // In a very distant future we'll possibly be able
  109. // to mix both if we have DHCPv4-over-DHCPv6, so it
  110. // has some sense to make it explicit whether we
  111. // talk about DHCPv4 relay or DHCPv6 relay. However,
  112. // for the time being relay4 can be used in DHCPv4
  113. // only.
  114. error(@1, "relay4 can only be used in DHCPv4.");
  115. }
  116. }
  117. ;
  118. string_expr : STRING
  119. {
  120. TokenPtr str(new TokenString($1));
  121. ctx.expression.push_back(str);
  122. }
  123. | HEXSTRING
  124. {
  125. TokenPtr hex(new TokenHexString($1));
  126. ctx.expression.push_back(hex);
  127. }
  128. | OPTION "[" option_code "]" "." option_repr_type
  129. {
  130. TokenPtr opt(new TokenOption($3, $6));
  131. ctx.expression.push_back(opt);
  132. }
  133. | RELAY4 "[" option_code "]" "." option_repr_type
  134. {
  135. switch (ctx.getUniverse()) {
  136. case Option::V4:
  137. {
  138. TokenPtr opt(new TokenRelay4Option($3, $6));
  139. ctx.expression.push_back(opt);
  140. break;
  141. }
  142. case Option::V6:
  143. // We will have relay6[123] for the DHCPv6.
  144. // In a very distant future we'll possibly be able
  145. // to mix both if we have DHCPv4-over-DHCPv6, so it
  146. // has some sense to make it explicit whether we
  147. // talk about DHCPv4 relay or DHCPv6 relay. However,
  148. // for the time being relay4 can be used in DHCPv4
  149. // only.
  150. error(@1, "relay4 can only be used in DHCPv4.");
  151. }
  152. }
  153. | SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
  154. {
  155. TokenPtr sub(new TokenSubstring());
  156. ctx.expression.push_back(sub);
  157. }
  158. | CONCAT "(" string_expr "," string_expr ")"
  159. {
  160. TokenPtr conc(new TokenConcat());
  161. ctx.expression.push_back(conc);
  162. }
  163. ;
  164. option_code : INTEGER
  165. {
  166. $$ = ctx.convertOptionCode($1, @1);
  167. }
  168. | OPTION_NAME
  169. {
  170. $$ = ctx.convertOptionName($1, @1);
  171. }
  172. ;
  173. option_repr_type : TEXT
  174. {
  175. $$ = TokenOption::TEXTUAL;
  176. }
  177. | HEX
  178. {
  179. $$ = TokenOption::HEXADECIMAL;
  180. }
  181. ;
  182. start_expr : INTEGER
  183. {
  184. TokenPtr str(new TokenString($1));
  185. ctx.expression.push_back(str);
  186. }
  187. ;
  188. length_expr : INTEGER
  189. {
  190. TokenPtr str(new TokenString($1));
  191. ctx.expression.push_back(str);
  192. }
  193. | ALL
  194. {
  195. TokenPtr str(new TokenString("all"));
  196. ctx.expression.push_back(str);
  197. }
  198. ;
  199. %%
  200. void
  201. isc::eval::EvalParser::error(const location_type& loc,
  202. const std::string& what)
  203. {
  204. ctx.error(loc, what);
  205. }