cmExprParser.y 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. %{
  2. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  3. file Copyright.txt or https://cmake.org/licensing for details. */
  4. /*
  5. This file must be translated to C and modified to build everywhere.
  6. Run bison like this:
  7. bison --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
  8. */
  9. #include "cmConfigure.h" // IWYU pragma: keep
  10. #include <stdint.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdexcept>
  14. /*-------------------------------------------------------------------------*/
  15. #define YYDEBUG 1
  16. #include "cmExprParserHelper.h" /* Interface to parser object. */
  17. #include "cmExprLexer.h" /* Interface to lexer object. */
  18. #include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */
  19. /* Forward declare the lexer entry point. */
  20. YY_DECL;
  21. /* Helper function to forward error callback from parser. */
  22. static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
  23. /* Disable some warnings in the generated code. */
  24. #ifdef _MSC_VER
  25. # pragma warning (disable: 4102) /* Unused goto label. */
  26. # pragma warning (disable: 4065) /* Switch statement contains default but no case. */
  27. #endif
  28. #if defined(__GNUC__) && __GNUC__ >= 8
  29. # pragma GCC diagnostic ignored "-Wconversion"
  30. #endif
  31. #if defined(__clang__) && defined(__has_warning)
  32. # if __has_warning("-Wused-but-marked-unused")
  33. # pragma clang diagnostic ignored "-Wused-but-marked-unused"
  34. # endif
  35. #endif
  36. %}
  37. /* Generate a reentrant parser object. */
  38. %define api.pure
  39. /* Configure the parser to use a lexer object. */
  40. %lex-param {yyscan_t yyscanner}
  41. %parse-param {yyscan_t yyscanner}
  42. %define parse.error verbose
  43. /*-------------------------------------------------------------------------*/
  44. /* Tokens */
  45. %token exp_PLUS
  46. %token exp_MINUS
  47. %token exp_TIMES
  48. %token exp_DIVIDE
  49. %token exp_MOD
  50. %token exp_SHIFTLEFT
  51. %token exp_SHIFTRIGHT
  52. %token exp_OPENPARENT
  53. %token exp_CLOSEPARENT
  54. %token exp_OR;
  55. %token exp_AND;
  56. %token exp_XOR;
  57. %token exp_NOT;
  58. %token exp_NUMBER;
  59. /*-------------------------------------------------------------------------*/
  60. /* grammar */
  61. %%
  62. start:
  63. exp {
  64. cmExpr_yyget_extra(yyscanner)->SetResult($<Number>1);
  65. }
  66. exp:
  67. bitwiseor {
  68. $<Number>$ = $<Number>1;
  69. }
  70. | exp exp_OR bitwiseor {
  71. $<Number>$ = $<Number>1 | $<Number>3;
  72. }
  73. bitwiseor:
  74. bitwisexor {
  75. $<Number>$ = $<Number>1;
  76. }
  77. | bitwiseor exp_XOR bitwisexor {
  78. $<Number>$ = $<Number>1 ^ $<Number>3;
  79. }
  80. bitwisexor:
  81. bitwiseand {
  82. $<Number>$ = $<Number>1;
  83. }
  84. | bitwisexor exp_AND bitwiseand {
  85. $<Number>$ = $<Number>1 & $<Number>3;
  86. }
  87. bitwiseand:
  88. shift {
  89. $<Number>$ = $<Number>1;
  90. }
  91. | bitwiseand exp_SHIFTLEFT shift {
  92. $<Number>$ = $<Number>1 << $<Number>3;
  93. }
  94. | bitwiseand exp_SHIFTRIGHT shift {
  95. $<Number>$ = $<Number>1 >> $<Number>3;
  96. }
  97. shift:
  98. term {
  99. $<Number>$ = $<Number>1;
  100. }
  101. | shift exp_PLUS term {
  102. $<Number>$ = $<Number>1 + $<Number>3;
  103. }
  104. | shift exp_MINUS term {
  105. $<Number>$ = $<Number>1 - $<Number>3;
  106. }
  107. term:
  108. unary {
  109. $<Number>$ = $<Number>1;
  110. }
  111. | term exp_TIMES unary {
  112. $<Number>$ = $<Number>1 * $<Number>3;
  113. }
  114. | term exp_DIVIDE unary {
  115. if (yyvsp[0].Number == 0) {
  116. throw std::overflow_error("divide by zero");
  117. }
  118. $<Number>$ = $<Number>1 / $<Number>3;
  119. }
  120. | term exp_MOD unary {
  121. $<Number>$ = $<Number>1 % $<Number>3;
  122. }
  123. unary:
  124. factor {
  125. $<Number>$ = $<Number>1;
  126. }
  127. | exp_PLUS unary {
  128. $<Number>$ = + $<Number>2;
  129. }
  130. | exp_MINUS unary {
  131. $<Number>$ = - $<Number>2;
  132. }
  133. | exp_NOT unary {
  134. $<Number>$ = ~ $<Number>2;
  135. }
  136. factor:
  137. exp_NUMBER {
  138. $<Number>$ = $<Number>1;
  139. }
  140. | exp_OPENPARENT exp exp_CLOSEPARENT {
  141. $<Number>$ = $<Number>2;
  142. }
  143. ;
  144. %%
  145. /* End of grammar */
  146. /*--------------------------------------------------------------------------*/
  147. void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
  148. {
  149. cmExpr_yyget_extra(yyscanner)->Error(message);
  150. }