AbaKus – a complex calculator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
5.0KB

  1. /*
  2. * lexer.ll - part of abakus
  3. * Copyright (C) 2004, 2005 Michael Pyne <michael.pyne@kdemail.net>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. %option noyywrap
  20. %{
  21. #define YY_NO_UNPUT
  22. #include <kdebug.h>
  23. #include "node.h"
  24. #include "function.h"
  25. #include "parser.h"
  26. #include "result.h"
  27. int yyCurTokenPos;
  28. int yyThisTokenLength;
  29. int yyparse(void);
  30. %}
  31. DIGITS [0-9]+
  32. HEX [0-9A-Fa-f]+
  33. %%
  34. /* Always skip whitespace */
  35. [ \t]* { yyCurTokenPos += yyThisTokenLength; yyThisTokenLength = yyleng; }
  36. /* Power operator */
  37. "**" {
  38. yyCurTokenPos += yyThisTokenLength;
  39. yyThisTokenLength = 2;
  40. return POWER;
  41. }
  42. "^" {
  43. yyCurTokenPos += yyThisTokenLength;
  44. yyThisTokenLength = 1;
  45. return POWER;
  46. }
  47. [sS][eE][tT] {
  48. yyCurTokenPos += yyThisTokenLength;
  49. yyThisTokenLength = 3;
  50. return SET;
  51. }
  52. [rR][eE][mM][oO][vV][eE] {
  53. yyCurTokenPos += yyThisTokenLength;
  54. yyThisTokenLength = 6;
  55. return REMOVE;
  56. }
  57. [dD][eE][rR][iI][vV] {
  58. yyCurTokenPos += yyThisTokenLength;
  59. yyThisTokenLength = 5;
  60. return DERIV;
  61. }
  62. /* Read numbers of the form with at least the decimal point and trailing
  63. * digits, such as .32, -234.45, .0, etc. Numbers are only read in the BEGIN
  64. * state.
  65. */
  66. {DIGITS}*([\.,]{DIGITS}+)(e[-+]?{DIGITS}+)? {
  67. yyCurTokenPos += yyThisTokenLength;
  68. yyThisTokenLength = yyleng;
  69. return NUM;
  70. }
  71. /* Read Hex */
  72. 0x({HEX}+)? {
  73. yyCurTokenPos += yyThisTokenLength;
  74. yyThisTokenLength = yyleng;
  75. return NUM;
  76. }
  77. /* Read numbers with at least the integral part, such as +4234, -34e8, etc.
  78. * Numbers are only read in the BEGIN state.
  79. */
  80. {DIGITS}+([\.,]{DIGITS}*)?(e[-+]?{DIGITS}+)? {
  81. yyCurTokenPos += yyThisTokenLength;
  82. yyThisTokenLength = yyleng;
  83. return NUM;
  84. }
  85. [nN][aA][nN] {
  86. yyCurTokenPos += yyThisTokenLength;
  87. yyThisTokenLength = yyleng;
  88. return NUM;
  89. }
  90. [iI][nN][fF] {
  91. yyCurTokenPos += yyThisTokenLength;
  92. yyThisTokenLength = yyleng;
  93. return NUM;
  94. }
  95. /* This detects textual input, and if it isn't pre-declared by the parser (in
  96. * other words, if it isn't a function), then it is returned as an identifier.
  97. */
  98. [a-zA-Z_][a-zA-Z_0-9]* {
  99. yyCurTokenPos += yyThisTokenLength;
  100. yyThisTokenLength = yyleng;
  101. if(FunctionManager::instance()->isFunction(yytext))
  102. return FN;
  103. else {
  104. return ID;
  105. }
  106. }
  107. /* All other characters are returned as-is to the parser, who can accept or
  108. * reject it as needed.
  109. */
  110. . {
  111. yyCurTokenPos += yyThisTokenLength;
  112. yyThisTokenLength = 1;
  113. return *yytext;
  114. }
  115. %%
  116. class Lexer::Private
  117. {
  118. public:
  119. YY_BUFFER_STATE buffer;
  120. int lastToken, thisToken;
  121. int lastPos, thisPos;
  122. QString lastTokenData, thisTokenData;
  123. };
  124. /* Declared in function.h, implemented here in lexer.l since this is where
  125. * all the yy_*() functions and types are defined.
  126. */
  127. Lexer::Lexer(const TQString &expr) :
  128. m_private(new Private)
  129. {
  130. const char *exprString = expr.latin1();
  131. yyCurTokenPos = 0;
  132. yyThisTokenLength = 0;
  133. m_private->buffer = yy_scan_string(exprString ? exprString : "");
  134. m_private->lastToken = -1;
  135. m_private->lastPos = -1;
  136. m_private->thisToken = yylex();
  137. m_private->thisTokenData = QString(yytext);
  138. if(yyCurTokenPos != 0)
  139. {
  140. kdError() << "yyCurTokenPos should be 0!!\n";
  141. }
  142. m_private->thisPos = yyCurTokenPos;
  143. }
  144. Lexer::~Lexer()
  145. {
  146. yy_delete_buffer(m_private->buffer);
  147. delete m_private;
  148. }
  149. bool Lexer::hasNext() const
  150. {
  151. return m_private->thisToken > 0;
  152. }
  153. int Lexer::nextType()
  154. {
  155. m_private->lastTokenData = m_private->thisTokenData;
  156. m_private->lastPos = m_private->thisPos;
  157. m_private->lastToken = m_private->thisToken;
  158. m_private->thisToken = yylex();
  159. m_private->thisTokenData = QString(yytext);
  160. m_private->thisPos = yyCurTokenPos;
  161. return m_private->lastToken;
  162. }
  163. TQString Lexer::tokenValue() const
  164. {
  165. return m_private->lastTokenData;
  166. }
  167. int Lexer::tokenPos() const
  168. {
  169. return m_private->lastPos;
  170. }
  171. /* Declared in function.h, implemented here in lexer.l since this is where
  172. * all the yy_*() functions and types are defined.
  173. */
  174. Abakus::number_t parseString(const char *str)
  175. {
  176. YY_BUFFER_STATE buffer = yy_scan_string(str);
  177. yyCurTokenPos = 0;
  178. yyThisTokenLength = 0;
  179. yyparse();
  180. yy_delete_buffer(buffer);
  181. if(Result::lastResult()->type() != Result::Value)
  182. return Abakus::number_t();
  183. return Result::lastResult()->result()->value();
  184. }