KOffice – TDE office suite
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.

fsparser.cc 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /* This file is part of the KDE project
  2. Copyright (C) 2002 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. * Boston, MA 02110-1301, USA.
  15. */
  16. #include <tqptrlist.h>
  17. #include <kdebug.h>
  18. #include <tdelocale.h>
  19. #include <kformuladefs.h>
  20. #include <kformuladocument.h>
  21. #include <symboltable.h>
  22. #include "fsparser.h"
  23. using namespace std;
  24. class ParserNode {
  25. public:
  26. ParserNode() { debugCount++; }
  27. virtual ~ParserNode() { debugCount--; }
  28. //virtual void output( ostream& ) = 0;
  29. virtual void buildXML( TQDomDocument& doc, TQDomElement element ) = 0;
  30. virtual bool isSimple() { return false; }
  31. static int debugCount;
  32. };
  33. int ParserNode::debugCount = 0;
  34. class PrimaryNode : public ParserNode {
  35. public:
  36. PrimaryNode( TQString primary ) : m_primary( primary ), m_functionName( false ) {}
  37. //virtual void output( ostream& stream ) { stream << "PrimaryNode {" << m_primary << "}" << endl; }
  38. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  39. virtual bool isSimple() { return true; }
  40. void setUnicode( TQChar unicode ) { m_unicode = unicode; }
  41. void setFunctionName( bool functionName ) { m_functionName = functionName; }
  42. TQString primary() const { return m_primary; }
  43. private:
  44. TQString m_primary;
  45. TQChar m_unicode;
  46. bool m_functionName;
  47. };
  48. void PrimaryNode::buildXML( TQDomDocument& doc, TQDomElement element )
  49. {
  50. if ( m_unicode != TQChar::null ) {
  51. TQDomElement de = doc.createElement( "TEXT" );
  52. de.setAttribute( "CHAR", TQString( m_unicode ) );
  53. de.setAttribute( "SYMBOL", "3" );
  54. element.appendChild( de );
  55. }
  56. else {
  57. if ( m_functionName ) {
  58. TQDomElement namesequence = doc.createElement( "NAMESEQUENCE" );
  59. element.appendChild( namesequence );
  60. element = namesequence;
  61. }
  62. for ( uint i = 0; i < m_primary.length(); i++ ) {
  63. TQDomElement de = doc.createElement( "TEXT" );
  64. de.setAttribute( "CHAR", TQString( m_primary[i] ) );
  65. element.appendChild( de );
  66. }
  67. }
  68. }
  69. class UnaryMinus : public ParserNode {
  70. public:
  71. UnaryMinus( ParserNode* primary ) : m_primary( primary ) {}
  72. ~UnaryMinus() { delete m_primary; }
  73. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  74. private:
  75. ParserNode* m_primary;
  76. };
  77. void UnaryMinus::buildXML( TQDomDocument& doc, TQDomElement element )
  78. {
  79. TQDomElement de = doc.createElement( "TEXT" );
  80. de.setAttribute( "CHAR", "-" );
  81. element.appendChild( de );
  82. m_primary->buildXML( doc, element );
  83. }
  84. class OperatorNode : public ParserNode {
  85. public:
  86. OperatorNode( TQString type, ParserNode* lhs, ParserNode* rhs )
  87. : m_type( type ), m_lhs( lhs ), m_rhs( rhs ) {}
  88. ~OperatorNode() { delete m_rhs; delete m_lhs; }
  89. // virtual void output( ostream& stream ) {
  90. // stream << "OperatorNode {";
  91. // m_lhs->output( stream ); stream << m_type; m_rhs->output( stream );
  92. // stream << "}" << endl; }
  93. protected:
  94. TQString m_type;
  95. ParserNode* m_lhs;
  96. ParserNode* m_rhs;
  97. };
  98. class AssignNode : public OperatorNode {
  99. public:
  100. AssignNode( TQString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {}
  101. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  102. };
  103. void AssignNode::buildXML( TQDomDocument& doc, TQDomElement element )
  104. {
  105. m_lhs->buildXML( doc, element );
  106. TQDomElement de = doc.createElement( "TEXT" );
  107. de.setAttribute( "CHAR", TQString( m_type ) );
  108. element.appendChild( de );
  109. m_rhs->buildXML( doc, element );
  110. }
  111. class ExprNode : public OperatorNode {
  112. public:
  113. ExprNode( TQString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {}
  114. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  115. };
  116. void ExprNode::buildXML( TQDomDocument& doc, TQDomElement element )
  117. {
  118. m_lhs->buildXML( doc, element );
  119. TQDomElement de = doc.createElement( "TEXT" );
  120. de.setAttribute( "CHAR", TQString( m_type ) );
  121. element.appendChild( de );
  122. m_rhs->buildXML( doc, element );
  123. }
  124. class TermNode : public OperatorNode {
  125. public:
  126. TermNode( TQString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {}
  127. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  128. };
  129. void TermNode::buildXML( TQDomDocument& doc, TQDomElement element )
  130. {
  131. if ( m_type == "*" ) {
  132. m_lhs->buildXML( doc, element );
  133. TQDomElement de = doc.createElement( "TEXT" );
  134. de.setAttribute( "CHAR", TQString( m_type ) );
  135. element.appendChild( de );
  136. m_rhs->buildXML( doc, element );
  137. }
  138. else {
  139. TQDomElement fraction = doc.createElement( "FRACTION" );
  140. TQDomElement numerator = doc.createElement( "NUMERATOR" );
  141. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  142. m_lhs->buildXML( doc, sequence );
  143. numerator.appendChild( sequence );
  144. fraction.appendChild( numerator );
  145. TQDomElement denominator = doc.createElement( "DENOMINATOR" );
  146. sequence = doc.createElement( "SEQUENCE" );
  147. m_rhs->buildXML( doc, sequence );
  148. denominator.appendChild( sequence );
  149. fraction.appendChild( denominator );
  150. element.appendChild( fraction );
  151. }
  152. }
  153. class PowerNode : public OperatorNode {
  154. public:
  155. PowerNode( TQString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {}
  156. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  157. };
  158. void PowerNode::buildXML( TQDomDocument& doc, TQDomElement element )
  159. {
  160. TQDomElement index = doc.createElement( "INDEX" );
  161. TQDomElement content = doc.createElement( "CONTENT" );
  162. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  163. content.appendChild( sequence );
  164. index.appendChild( content );
  165. if ( !m_lhs->isSimple() ) {
  166. TQDomElement bracket = doc.createElement( "BRACKET" );
  167. bracket.setAttribute( "LEFT", '(' );
  168. bracket.setAttribute( "RIGHT", ')' );
  169. sequence.appendChild( bracket );
  170. content = doc.createElement( "CONTENT" );
  171. bracket.appendChild( content );
  172. sequence = doc.createElement( "SEQUENCE" );
  173. content.appendChild( sequence );
  174. }
  175. m_lhs->buildXML( doc, sequence );
  176. if ( m_type == "_" ) {
  177. TQDomElement lowerRight = doc.createElement( "LOWERRIGHT" );
  178. sequence = doc.createElement( "SEQUENCE" );
  179. m_rhs->buildXML( doc, sequence );
  180. lowerRight.appendChild( sequence );
  181. index.appendChild( lowerRight );
  182. }
  183. else {
  184. TQDomElement upperRight = doc.createElement( "UPPERRIGHT" );
  185. sequence = doc.createElement( "SEQUENCE" );
  186. m_rhs->buildXML( doc, sequence );
  187. upperRight.appendChild( sequence );
  188. index.appendChild( upperRight );
  189. }
  190. element.appendChild( index );
  191. }
  192. class FunctionNode : public ParserNode {
  193. public:
  194. FunctionNode( PrimaryNode* name, TQPtrList<ParserNode>& args ) : m_name( name ), m_args( args ) {
  195. m_args.setAutoDelete( true );
  196. }
  197. ~FunctionNode() { delete m_name; }
  198. //virtual void output( ostream& stream );
  199. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  200. private:
  201. void buildSymbolXML( TQDomDocument& doc, TQDomElement element, KFormula::SymbolType type );
  202. PrimaryNode* m_name;
  203. TQPtrList<ParserNode> m_args;
  204. };
  205. void FunctionNode::buildSymbolXML( TQDomDocument& doc, TQDomElement element, KFormula::SymbolType type )
  206. {
  207. TQDomElement symbol = doc.createElement( "SYMBOL" );
  208. symbol.setAttribute( "TYPE", type );
  209. TQDomElement content = doc.createElement( "CONTENT" );
  210. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  211. m_args.at( 0 )->buildXML( doc, sequence );
  212. content.appendChild( sequence );
  213. symbol.appendChild( content );
  214. if ( m_args.count() > 2 ) {
  215. ParserNode* lowerLimit = m_args.at( m_args.count()-2 );
  216. ParserNode* upperLimit = m_args.at( m_args.count()-1 );
  217. TQDomElement lower = doc.createElement( "LOWER" );
  218. sequence = doc.createElement( "SEQUENCE" );
  219. lowerLimit->buildXML( doc, sequence );
  220. lower.appendChild( sequence );
  221. symbol.appendChild( lower );
  222. TQDomElement upper = doc.createElement( "UPPER" );
  223. sequence = doc.createElement( "SEQUENCE" );
  224. upperLimit->buildXML( doc, sequence );
  225. upper.appendChild( sequence );
  226. symbol.appendChild( upper );
  227. }
  228. element.appendChild( symbol );
  229. }
  230. void FunctionNode::buildXML( TQDomDocument& doc, TQDomElement element )
  231. {
  232. if ( ( m_name->primary() == "sqrt" ) && ( m_args.count() == 1 ) ) {
  233. TQDomElement root = doc.createElement( "ROOT" );
  234. TQDomElement content = doc.createElement( "CONTENT" );
  235. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  236. m_args.at( 0 )->buildXML( doc, sequence );
  237. content.appendChild( sequence );
  238. root.appendChild( content );
  239. element.appendChild( root );
  240. }
  241. else if ( ( m_name->primary() == "pow" ) && ( m_args.count() == 2 ) ) {
  242. TQDomElement index = doc.createElement( "INDEX" );
  243. TQDomElement content = doc.createElement( "CONTENT" );
  244. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  245. m_args.at( 0 )->buildXML( doc, sequence );
  246. content.appendChild( sequence );
  247. index.appendChild( content );
  248. TQDomElement upperRight = doc.createElement( "UPPERRIGHT" );
  249. sequence = doc.createElement( "SEQUENCE" );
  250. m_args.at( 1 )->buildXML( doc, sequence );
  251. upperRight.appendChild( sequence );
  252. index.appendChild( upperRight );
  253. element.appendChild( index );
  254. }
  255. else if ( ( m_name->primary() == "sum" ) && ( m_args.count() > 0 ) ) {
  256. buildSymbolXML( doc, element, KFormula::Sum );
  257. }
  258. else if ( ( m_name->primary() == "prod" ) && ( m_args.count() > 0 ) ) {
  259. buildSymbolXML( doc, element, KFormula::Product );
  260. }
  261. else if ( ( ( m_name->primary() == "int" ) ||
  262. ( m_name->primary() == "integrate" ) ||
  263. ( m_name->primary() == "quad" ) )
  264. && ( m_args.count() > 0 ) ) {
  265. buildSymbolXML( doc, element, KFormula::Integral );
  266. }
  267. else {
  268. m_name->buildXML( doc, element );
  269. TQDomElement bracket = doc.createElement( "BRACKET" );
  270. bracket.setAttribute( "LEFT", '(' );
  271. bracket.setAttribute( "RIGHT", ')' );
  272. TQDomElement content = doc.createElement( "CONTENT" );
  273. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  274. for ( uint i = 0; i < m_args.count(); i++ ) {
  275. m_args.at( i )->buildXML( doc, sequence );
  276. if ( i < m_args.count()-1 ) {
  277. TQDomElement de = doc.createElement( "TEXT" );
  278. de.setAttribute( "CHAR", "," );
  279. sequence.appendChild( de );
  280. }
  281. }
  282. content.appendChild( sequence );
  283. bracket.appendChild( content );
  284. element.appendChild( bracket );
  285. }
  286. }
  287. // void FunctionNode::output( ostream& stream )
  288. // {
  289. // m_name->output( stream );
  290. // for ( uint i = 0; i < m_args.count(); i++ ) {
  291. // m_args.at( i )->output( stream );
  292. // }
  293. // }
  294. class RowNode : public ParserNode {
  295. public:
  296. RowNode( TQPtrList<ParserNode> row ) : m_row( row ) { m_row.setAutoDelete( true ); }
  297. //virtual void output( ostream& stream );
  298. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  299. uint columns() const { return m_row.count(); }
  300. void setRequiredColumns( uint requiredColumns ) { m_requiredColumns = requiredColumns; }
  301. private:
  302. TQPtrList<ParserNode> m_row;
  303. uint m_requiredColumns;
  304. };
  305. void RowNode::buildXML( TQDomDocument& doc, TQDomElement element )
  306. {
  307. for ( uint i = 0; i < m_requiredColumns; i++ ) {
  308. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  309. if ( i < m_row.count() ) {
  310. m_row.at( i )->buildXML( doc, sequence );
  311. }
  312. else {
  313. TQDomElement de = doc.createElement( "TEXT" );
  314. de.setAttribute( "CHAR", "0" );
  315. sequence.appendChild( de );
  316. }
  317. element.appendChild( sequence );
  318. }
  319. }
  320. // void RowNode::output( ostream& stream )
  321. // {
  322. // stream << "[";
  323. // for ( uint i = 0; i < m_row.count(); i++ ) {
  324. // m_row.at( i )->output( stream );
  325. // if ( i < m_row.count()-1 ) {
  326. // stream << ", ";
  327. // }
  328. // }
  329. // stream << "]";
  330. // }
  331. class MatrixNode : public ParserNode {
  332. public:
  333. MatrixNode( TQPtrList<RowNode> rows ) : m_rows( rows ) { m_rows.setAutoDelete( true ); }
  334. //virtual void output( ostream& stream );
  335. virtual void buildXML( TQDomDocument& doc, TQDomElement element );
  336. virtual bool isSimple() { return true; }
  337. uint columns();
  338. uint rows() { return m_rows.count(); }
  339. private:
  340. TQPtrList<RowNode> m_rows;
  341. };
  342. uint MatrixNode::columns()
  343. {
  344. uint columns = 0;
  345. for ( uint i = 0; i < m_rows.count(); i++ ) {
  346. columns = TQMAX( columns, m_rows.at( i )->columns() );
  347. }
  348. return columns;
  349. }
  350. void MatrixNode::buildXML( TQDomDocument& doc, TQDomElement element )
  351. {
  352. TQDomElement bracket = doc.createElement( "BRACKET" );
  353. bracket.setAttribute( "LEFT", '(' );
  354. bracket.setAttribute( "RIGHT", ')' );
  355. TQDomElement content = doc.createElement( "CONTENT" );
  356. TQDomElement sequence = doc.createElement( "SEQUENCE" );
  357. uint cols = columns();
  358. TQDomElement matrix = doc.createElement( "MATRIX" );
  359. matrix.setAttribute( "ROWS", m_rows.count() );
  360. matrix.setAttribute( "COLUMNS", cols );
  361. for ( uint i = 0; i < m_rows.count(); i++ ) {
  362. m_rows.at( i )->setRequiredColumns( cols );
  363. m_rows.at( i )->buildXML( doc, matrix );
  364. matrix.appendChild( doc.createComment( "end of row" ) );
  365. }
  366. sequence.appendChild( matrix );
  367. content.appendChild( sequence );
  368. bracket.appendChild( content );
  369. element.appendChild( bracket );
  370. }
  371. // void MatrixNode::output( ostream& stream )
  372. // {
  373. // stream << "[";
  374. // for ( uint i = 0; i < m_rows.count(); i++ ) {
  375. // m_rows.at( i )->output( stream );
  376. // if ( i < m_rows.count()-1 ) {
  377. // stream << ", ";
  378. // }
  379. // }
  380. // stream << "]";
  381. // }
  382. FormulaStringParser::FormulaStringParser( const KFormula::SymbolTable& symbolTable, TQString formula )
  383. : m_symbolTable( symbolTable ), m_formula( formula ),
  384. pos( 0 ), line( 1 ), column( 1 ), m_newlineIsSpace( true )
  385. {
  386. }
  387. FormulaStringParser::~FormulaStringParser()
  388. {
  389. delete head;
  390. if ( ParserNode::debugCount != 0 ) {
  391. kdDebug( KFormula::DEBUGID ) << "ParserNode::debugCount = " << ParserNode::debugCount << endl;
  392. }
  393. }
  394. TQDomDocument FormulaStringParser::parse()
  395. {
  396. nextToken();
  397. head = parseAssign();
  398. //head->output( cout );
  399. if ( !eol() ) {
  400. error( TQString( i18n( "Aborted parsing at %1:%2" ) ).arg( line ).arg( column ) );
  401. }
  402. TQDomDocument doc = KFormula::Document::createDomDocument();
  403. TQDomElement root = doc.documentElement();
  404. TQDomElement de = doc.createElement( "FORMULA" );
  405. // here comes the current version of FormulaElement
  406. //de.setAttribute( "VERSION", "4" );
  407. head->buildXML( doc, de );
  408. root.appendChild(de);
  409. kdDebug( 39001 ) << doc.toString() << endl;
  410. return doc;
  411. }
  412. ParserNode* FormulaStringParser::parseAssign()
  413. {
  414. ParserNode* lhs = parseExpr();
  415. for ( ;; ) {
  416. switch ( currentType ) {
  417. case ASSIGN: {
  418. TQString c = current;
  419. nextToken();
  420. lhs = new AssignNode( c, lhs, parseExpr() );
  421. break;
  422. }
  423. default:
  424. return lhs;
  425. }
  426. }
  427. }
  428. ParserNode* FormulaStringParser::parseExpr()
  429. {
  430. ParserNode* lhs = parseTerm();
  431. for ( ;; ) {
  432. switch ( currentType ) {
  433. case PLUS:
  434. case SUB: {
  435. TQString c = current;
  436. nextToken();
  437. lhs = new ExprNode( c, lhs, parseTerm() );
  438. break;
  439. }
  440. default:
  441. return lhs;
  442. }
  443. }
  444. }
  445. ParserNode* FormulaStringParser::parseTerm()
  446. {
  447. ParserNode* lhs = parsePower();
  448. for ( ;; ) {
  449. switch ( currentType ) {
  450. case MUL:
  451. case DIV: {
  452. TQString c = current;
  453. nextToken();
  454. lhs = new TermNode( c, lhs, parsePower() );
  455. break;
  456. }
  457. default:
  458. return lhs;
  459. }
  460. }
  461. }
  462. ParserNode* FormulaStringParser::parsePower()
  463. {
  464. ParserNode* lhs = parsePrimary();
  465. for ( ;; ) {
  466. switch ( currentType ) {
  467. case INDEX:
  468. case POW: {
  469. TQString c = current;
  470. nextToken();
  471. lhs = new PowerNode( c, lhs, parsePrimary() );
  472. break;
  473. }
  474. default:
  475. return lhs;
  476. }
  477. }
  478. }
  479. ParserNode* FormulaStringParser::parsePrimary()
  480. {
  481. switch ( currentType ) {
  482. case NUMBER: {
  483. PrimaryNode* node = new PrimaryNode( current );
  484. nextToken();
  485. return node;
  486. }
  487. case NAME: {
  488. PrimaryNode* node = new PrimaryNode( current );
  489. node->setUnicode( m_symbolTable.unicode( current ) );
  490. nextToken();
  491. if ( currentType == LP ) {
  492. nextToken();
  493. TQPtrList<ParserNode> args;
  494. args.setAutoDelete( false );
  495. while ( ( currentType != EOL ) && ( currentType != RP ) ) {
  496. ParserNode* node = parseExpr();
  497. args.append( node );
  498. if ( currentType == COMMA ) {
  499. nextToken();
  500. }
  501. }
  502. expect( RP, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ")" ) );
  503. node->setFunctionName( true );
  504. return new FunctionNode( node, args );
  505. }
  506. return node;
  507. }
  508. case SUB: {
  509. nextToken();
  510. //ParserNode* node = new UnaryMinus( parsePrimary() );
  511. ParserNode* node = new UnaryMinus( parseTerm() );
  512. return node;
  513. }
  514. case LP: {
  515. nextToken();
  516. ParserNode* node = parseExpr();
  517. expect( RP, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ")" ) );
  518. return node;
  519. }
  520. case LB: {
  521. nextToken();
  522. TQPtrList<RowNode> rows;
  523. rows.setAutoDelete( false );
  524. bool innerBrackets = currentType == LB;
  525. m_newlineIsSpace = innerBrackets;
  526. while ( ( currentType != EOL ) && ( currentType != RB ) ) {
  527. if ( innerBrackets ) {
  528. expect( LB, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "[" ) );
  529. }
  530. TQPtrList<ParserNode> row;
  531. row.setAutoDelete( false );
  532. while ( ( currentType != EOL ) && ( currentType != RB ) &&
  533. ( innerBrackets || ( currentType != SEMIC && currentType != NEWLINE ) ) ) {
  534. row.append( parseExpr() );
  535. if ( currentType == COMMA ) {
  536. nextToken();
  537. }
  538. }
  539. if ( innerBrackets ) {
  540. expect( RB, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "]" ) );
  541. if ( currentType == COMMA ) {
  542. nextToken();
  543. }
  544. }
  545. else {
  546. if ( currentType != RB ) {
  547. if ( currentType == NEWLINE ) {
  548. nextToken();
  549. }
  550. else {
  551. expect( SEMIC, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ";" ) );
  552. }
  553. }
  554. }
  555. rows.append( new RowNode( row ) );
  556. }
  557. m_newlineIsSpace = true;
  558. expect( RB, TQString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "]" ) );
  559. MatrixNode* node = new MatrixNode( rows );
  560. if ( node->columns() == 0 ) {
  561. error( TQString( i18n( "Null columns in Matrix at %1:%2" ) ).arg( line ).arg( column ) );
  562. }
  563. if ( node->rows() == 0 ) {
  564. error( TQString( i18n( "Null rows in Matrix at %1:%2" ) ).arg( line ).arg( column ) );
  565. }
  566. return node;
  567. }
  568. case OTHER: {
  569. ParserNode* node = new PrimaryNode( current );
  570. nextToken();
  571. return node;
  572. }
  573. default:
  574. error( TQString( i18n( "Unexpected token at %1:%2" ) ).arg( line ).arg( column ) );
  575. return new PrimaryNode( "?" );
  576. }
  577. }
  578. void FormulaStringParser::expect( TokenType type, TQString msg )
  579. {
  580. if ( currentType == type ) {
  581. nextToken();
  582. }
  583. else {
  584. error( msg );
  585. }
  586. }
  587. TQString FormulaStringParser::nextToken()
  588. {
  589. // We skip any ' or " so that we can parse string literals.
  590. while ( !eol() && ( m_formula[pos].isSpace() ||
  591. ( m_formula[pos] == '"' ) ||
  592. ( m_formula[pos] == '\'' ) ) ) {
  593. if ( m_formula[pos] == '\n' ) {
  594. line++;
  595. if ( m_newlineIsSpace ) {
  596. column = 0;
  597. }
  598. else {
  599. pos++;
  600. column = 1;
  601. currentType = NEWLINE;
  602. return current = "\n";
  603. }
  604. }
  605. pos++; column++;
  606. }
  607. if ( eol() ) {
  608. currentType = EOL;
  609. return TQString();
  610. }
  611. if ( m_formula[pos].isDigit() || m_formula[pos] == '.' ) {
  612. uint begin = pos;
  613. readNumber();
  614. currentType = NUMBER;
  615. current = m_formula.mid( begin, pos-begin );
  616. if ( current[0] == '.' ) {
  617. current = "0" + current;
  618. }
  619. if ( current[current.length()-1] == '.' ) {
  620. current = current + "0";
  621. }
  622. return current;
  623. }
  624. else if ( m_formula[pos].isLetter() ) {
  625. uint begin = pos;
  626. pos++; column++;
  627. while ( !eol() && m_formula[pos].isLetter() ) {
  628. pos++; column++;
  629. }
  630. currentType = NAME;
  631. return current = m_formula.mid( begin, pos-begin );
  632. }
  633. else {
  634. switch ( m_formula[pos].latin1() ) {
  635. case '+':
  636. pos++; column++;
  637. currentType = PLUS;
  638. return current = "+";
  639. case '-':
  640. pos++; column++;
  641. currentType = SUB;
  642. return current = "-";
  643. case '*':
  644. pos++; column++;
  645. if ( !eol() && m_formula[pos] == '*' ) {
  646. pos++; column++;
  647. currentType = POW;
  648. return current = "**";
  649. }
  650. currentType = MUL;
  651. return current = "*";
  652. case '/':
  653. pos++; column++;
  654. currentType = DIV;
  655. return current = "/";
  656. case '^':
  657. pos++; column++;
  658. currentType = POW;
  659. return current = "**";
  660. case '_':
  661. pos++; column++;
  662. currentType = INDEX;
  663. return current = "_";
  664. case '(':
  665. pos++; column++;
  666. currentType = LP;
  667. return current = "(";
  668. case ')':
  669. pos++; column++;
  670. currentType = RP;
  671. return current = ")";
  672. case '[':
  673. pos++; column++;
  674. currentType = LB;
  675. return current = "[";
  676. case ']':
  677. pos++; column++;
  678. currentType = RB;
  679. return current = "]";
  680. case ',':
  681. pos++; column++;
  682. currentType = COMMA;
  683. return current = ",";
  684. case ';':
  685. pos++; column++;
  686. currentType = SEMIC;
  687. return current = ";";
  688. case '=':
  689. pos++; column++;
  690. currentType = ASSIGN;
  691. return current = "=";
  692. default:
  693. pos++; column++;
  694. currentType = OTHER;
  695. return current = m_formula.mid( pos-1, 1 );
  696. }
  697. }
  698. }
  699. void FormulaStringParser::readNumber()
  700. {
  701. bool digitsBeforeDot = m_formula[pos] != '.';
  702. readDigits();
  703. if ( pos < m_formula.length()-1 ) {
  704. TQChar ch = m_formula[pos];
  705. // Look for a dot.
  706. if ( ch == '.' ) {
  707. pos++;
  708. column++;
  709. ch = m_formula[pos];
  710. if ( ch.isDigit() ) {
  711. readDigits();
  712. }
  713. else if ( !digitsBeforeDot ) {
  714. error( TQString( i18n( "A single '.' is not a number at %1:%2" ) ).arg( line ).arg( column ) );
  715. return;
  716. }
  717. }
  718. // there might as well be an exponent
  719. if ( pos < m_formula.length()-1 ) {
  720. ch = m_formula[pos];
  721. if ( ( ch == 'E' ) || ( ch == 'e' ) ) {
  722. pos++;
  723. column++;
  724. ch = m_formula[pos];
  725. // signs are allowed after the exponent
  726. if ( ( ( ch == '+' ) || ( ch == '-' ) ) &&
  727. ( pos < m_formula.length()-1 ) ) {
  728. pos++;
  729. column++;
  730. ch = m_formula[pos];
  731. if ( ch.isDigit() ) {
  732. readDigits();
  733. }
  734. else {
  735. pos -= 2;
  736. column -= 2;
  737. return;
  738. }
  739. }
  740. else if ( ch.isDigit() ) {
  741. readDigits();
  742. }
  743. else {
  744. pos--;
  745. column--;
  746. }
  747. }
  748. }
  749. }
  750. }
  751. void FormulaStringParser::readDigits()
  752. {
  753. while ( !eol() && m_formula[pos].isDigit() ) {
  754. pos++;
  755. column++;
  756. }
  757. }
  758. void FormulaStringParser::error( TQString err )
  759. {
  760. kdDebug( KFormula::DEBUGID ) << err << " (" << currentType << "; " << current << ")" << endl;
  761. m_errorList.push_back( err );
  762. }