parser.yy 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. Permission to use, copy, modify, and/or distribute this software for any
  3. purpose with or without fee is hereby granted, provided that the above
  4. copyright notice and this permission notice appear in all copies.
  5. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  6. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  7. AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  8. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  9. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  10. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  11. PERFORMANCE OF THIS SOFTWARE. */
  12. %skeleton "lalr1.cc" /* -*- C++ -*- */
  13. %require "3.0.0"
  14. %defines
  15. %define parser_class_name {EvalParser}
  16. %define api.token.constructor
  17. %define api.value.type variant
  18. %define api.namespace {isc::eval}
  19. %define parse.assert
  20. %code requires
  21. {
  22. #include <string>
  23. #include <eval/token.h>
  24. #include <eval/eval_context_decl.h>
  25. #include <dhcp/option.h>
  26. #include <boost/lexical_cast.hpp>
  27. using namespace isc::dhcp;
  28. using namespace isc::eval;
  29. }
  30. // The parsing context.
  31. %param { EvalContext& ctx }
  32. %locations
  33. %define parse.trace
  34. %define parse.error verbose
  35. %code
  36. {
  37. # include "eval_context.h"
  38. }
  39. // Option universe: DHCPv4 or DHCPv6. This is required to use correct option
  40. // definition set to map option names to codes.
  41. %parse-param { const Option::Universe& option_universe }
  42. %define api.token.prefix {TOKEN_}
  43. %token
  44. END 0 "end of file"
  45. EQUAL "=="
  46. OPTION "option"
  47. SUBSTRING "substring"
  48. TEXT "text"
  49. HEX "hex"
  50. ALL "all"
  51. DOT "."
  52. COMA ","
  53. LPAREN "("
  54. RPAREN ")"
  55. LBRACKET "["
  56. RBRACKET "]"
  57. ;
  58. %token <std::string> STRING "constant string"
  59. %token <std::string> INTEGER "integer"
  60. %token <std::string> HEXSTRING "constant hexstring"
  61. %token <std::string> OPTION_NAME "option name"
  62. %token <std::string> TOKEN
  63. %printer { yyoutput << $$; } <*>;
  64. %code
  65. {
  66. namespace {
  67. /* Convert option code specified as string to an 16 bit unsigned
  68. representation. If the option code is not within the range of
  69. 0..65535 an error is reported. */
  70. uint16_t
  71. convert_option_code(const std::string& option_code,
  72. const isc::eval::EvalParser::location_type& loc,
  73. EvalContext& ctx) {
  74. int n = 0;
  75. try {
  76. n = boost::lexical_cast<int>(option_code);
  77. } catch (const boost::bad_lexical_cast &) {
  78. // This can't happen...
  79. ctx.error(loc, "Option code has invalid value in " + option_code);
  80. }
  81. if (n < 0 || n > 65535) {
  82. ctx.error(loc, "Option code has invalid value in "
  83. + option_code + ". Allowed range: 0..65535");
  84. }
  85. return (static_cast<uint16_t>(n));
  86. }
  87. }
  88. }
  89. %%
  90. // The whole grammar starts with an expression.
  91. %start expression;
  92. // Expression can either be a single token or a (something == something) expression
  93. expression : bool_expr
  94. ;
  95. bool_expr : string_expr EQUAL string_expr
  96. {
  97. TokenPtr eq(new TokenEqual());
  98. ctx.expression.push_back(eq);
  99. }
  100. ;
  101. string_expr : STRING
  102. {
  103. TokenPtr str(new TokenString($1));
  104. ctx.expression.push_back(str);
  105. }
  106. | HEXSTRING
  107. {
  108. TokenPtr hex(new TokenHexString($1));
  109. ctx.expression.push_back(hex);
  110. }
  111. | OPTION "[" INTEGER "]" DOT TEXT
  112. {
  113. uint16_t numeric_code = convert_option_code($3, @3, ctx);
  114. TokenPtr opt(new TokenOption(numeric_code, TokenOption::TEXTUAL));
  115. ctx.expression.push_back(opt);
  116. }
  117. | OPTION "[" INTEGER "]" DOT HEX
  118. {
  119. uint16_t numeric_code = convert_option_code($3, @3, ctx);
  120. TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL));
  121. ctx.expression.push_back(opt);
  122. }
  123. | OPTION "[" OPTION_NAME "]" DOT TEXT
  124. {
  125. try {
  126. // This may result in exception if the specified
  127. // name is unknown.
  128. TokenPtr opt(new TokenOption($3, option_universe,
  129. TokenOption::TEXTUAL));
  130. ctx.expression.push_back(opt);
  131. } catch (const std::exception& ex) {
  132. ctx.error(@3, ex.what());
  133. }
  134. }
  135. | OPTION "[" OPTION_NAME "]" DOT HEX
  136. {
  137. try {
  138. // This may result in exception if the specified
  139. // name is unknown.
  140. TokenPtr opt(new TokenOption($3, option_universe,
  141. TokenOption::HEXADECIMAL));
  142. ctx.expression.push_back(opt);
  143. } catch (const std::exception& ex) {
  144. ctx.error(@3, ex.what());
  145. }
  146. }
  147. | SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
  148. {
  149. TokenPtr sub(new TokenSubstring());
  150. ctx.expression.push_back(sub);
  151. }
  152. | TOKEN
  153. // Temporary unused token to avoid explict but long errors
  154. ;
  155. start_expr : INTEGER
  156. {
  157. TokenPtr str(new TokenString($1));
  158. ctx.expression.push_back(str);
  159. }
  160. ;
  161. length_expr : INTEGER
  162. {
  163. TokenPtr str(new TokenString($1));
  164. ctx.expression.push_back(str);
  165. }
  166. | ALL
  167. {
  168. TokenPtr str(new TokenString("all"));
  169. ctx.expression.push_back(str);
  170. }
  171. ;
  172. %%
  173. void
  174. isc::eval::EvalParser::error(const location_type& loc,
  175. const std::string& what)
  176. {
  177. ctx.error(loc, what);
  178. }