eval.dox 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. /**
  15. @page dhcpEval libeval - Expression evaluation and client classification
  16. @section dhcpEvalIntroduction Introduction
  17. The core of the libeval library is a parser that is able to parse an
  18. expression (e.g. option[123].text == 'APC'). This is currently used for
  19. client classification, but in the future may be also used for other
  20. applications.
  21. The external interface to the library is the @ref isc::eval::EvalContext
  22. class. Once instantiated, it offers a major method:
  23. @ref isc::eval::EvalContext::parseString, which parses the specified
  24. string. Once the expression is parsed, it is converted to a collection of
  25. tokens that are stored in Reverse Polish Notation in
  26. EvalContext::expression.
  27. Internally, the parser code is generated by flex and bison. These two
  28. tools convert lexer.ll and parser.yy files into a number of .cc and .hh files.
  29. To avoid a build of Kea depending on the presence of flex and bison, the
  30. result of the generation is checked into the github repository and is
  31. distributed in the tarballs.
  32. @section dhcpEvalLexer Lexer generation using flex
  33. Flex is used to generate the lexer, a piece of code that converts input
  34. data into a series of tokens. It contains a small number of directives,
  35. but the majority of the code consists of the definitions of tokens. These
  36. definitions are regular expressions that define various tokens, e.g. strings,
  37. numbers, parentheses, etc. Once the expression is matched, the associated
  38. action is executed. In the majority of the cases a generator method from
  39. @ref isc::eval::EvalParser is called, which returns returns a newly created
  40. bison token. The purpose of the lexer is to generate a stream
  41. of tokens that are consumed by the parser.
  42. lexer.cc and lexer.hh must not be edited. If there is a need
  43. to introduce changes, lexer.ll must be updated and the .cc and .hh files
  44. regenerated.
  45. @section dhcpEvalParser Parser generation using bison
  46. Bison is used to generate the parser, a piece of code that consumes a
  47. stream of tokens and attempts to match it against a defined grammar.
  48. The bison parser is created from parser.yy. It contains
  49. a number of directives, but the two most important sections are:
  50. a list of tokens (for each token defined here, bison will generate the
  51. make_NAMEOFTOKEN method in the @ref isc::eval::EvalParser class) and
  52. the grammar. The Grammar is a tree like structure with possible loops.
  53. Here is an over-simplified version of the grammar:
  54. @code
  55. 01. %start expression;
  56. 02.
  57. 03. expression : token EQUAL token
  58. 04. | token
  59. 05. ;
  60. 06.
  61. 07. token : STRING
  62. 08. {
  63. 09. TokenPtr str(new TokenString($1));
  64. 10. ctx.expression.push_back(str);
  65. 11. }
  66. 12. | HEXSTRING
  67. 13. {
  68. 14. TokenPtr hex(new TokenHexString($1));
  69. 15. ctx.expression.push_back(hex);
  70. 16. }
  71. 17. | OPTION '[' INTEGER ']' DOT TEXT
  72. 18. {
  73. 19. TokenPtr opt(new TokenOption($3, TokenOption::TEXTUAL));
  74. 20. ctx.expression.push_back(opt);
  75. 21. }
  76. 22. | OPTION '[' INTEGER ']' DOT HEX
  77. 23. {
  78. 24. TokenPtr opt(new TokenOption($3, TokenOption::HEXADECIMAL));
  79. 25. ctx.expression.push_back(opt);
  80. 26. }
  81. 27. ;
  82. @endcode
  83. This code determines that the grammar starts from expression (line 1).
  84. The actual definition of expression (lines 3-5) may either be a
  85. single token or an expression "token == token" (EQUAL has been defined as
  86. "==" elsewhere). Token is further
  87. defined in lines 7-22: it may either be a string (lines 7-11),
  88. a hex string (lines 12-16), option in the textual format (lines 17-21)
  89. or option in a hexadecimal format (lines 22-26).
  90. When the actual case is determined, the respective C++ action
  91. is executed. For example, if the token is a string, the TokenString class is
  92. instantiated with the appropriate value and put onto the expression vector.
  93. @section dhcpEvalMakefile Generating parser files
  94. In the general case, we want to avoid generating parser files, so an
  95. average user interested in just compiling Kea would not need flex or
  96. bison. Therefore the generated files are already included in the
  97. git repository and will be included in the tarball releases.
  98. However, there will be cases when one of the developers would want
  99. to tweak the lexer.ll and parser.yy files and then regenerate
  100. the code. For this purpose, two makefile targets are defined:
  101. @code
  102. make parser
  103. @endcode
  104. will generate the parsers and
  105. @code
  106. make parser-clean
  107. @endcode
  108. will remove the files. Generated files removal was also hooked
  109. into the maintainer-clean target.
  110. @section dhcpEvalConfigure Configure options
  111. Since the flex/bison tools are not necessary for a regular compilation,
  112. checks conducted during configure, but the lack of flex or
  113. bison tools does not stop the configure process. There is a flag
  114. (--enable-generate-parser) that tells configure script that the
  115. parser will be generated. With this flag, the checks for flex/bison
  116. are mandatory. If either tool is missing or at too early a version, the
  117. configure process will terminate with an error.
  118. */