diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kformula/fsparser.cc | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kformula/fsparser.cc')
-rw-r--r-- | kformula/fsparser.cc | 829 |
1 files changed, 829 insertions, 0 deletions
diff --git a/kformula/fsparser.cc b/kformula/fsparser.cc new file mode 100644 index 00000000..4b7f1c88 --- /dev/null +++ b/kformula/fsparser.cc @@ -0,0 +1,829 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <qptrlist.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <kformuladefs.h> +#include <kformuladocument.h> +#include <symboltable.h> + +#include "fsparser.h" + + +using namespace std; + +class ParserNode { +public: + ParserNode() { debugCount++; } + virtual ~ParserNode() { debugCount--; } + //virtual void output( ostream& ) = 0; + virtual void buildXML( QDomDocument& doc, QDomElement element ) = 0; + virtual bool isSimple() { return false; } + + static int debugCount; +}; + +int ParserNode::debugCount = 0; + +class PrimaryNode : public ParserNode { +public: + PrimaryNode( QString primary ) : m_primary( primary ), m_functionName( false ) {} + //virtual void output( ostream& stream ) { stream << "PrimaryNode {" << m_primary << "}" << endl; } + virtual void buildXML( QDomDocument& doc, QDomElement element ); + virtual bool isSimple() { return true; } + void setUnicode( QChar unicode ) { m_unicode = unicode; } + void setFunctionName( bool functionName ) { m_functionName = functionName; } + QString primary() const { return m_primary; } +private: + QString m_primary; + QChar m_unicode; + bool m_functionName; +}; + +void PrimaryNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + if ( m_unicode != QChar::null ) { + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", QString( m_unicode ) ); + de.setAttribute( "SYMBOL", "3" ); + element.appendChild( de ); + } + else { + if ( m_functionName ) { + QDomElement namesequence = doc.createElement( "NAMESEQUENCE" ); + element.appendChild( namesequence ); + element = namesequence; + } + for ( uint i = 0; i < m_primary.length(); i++ ) { + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", QString( m_primary[i] ) ); + element.appendChild( de ); + } + } +} + +class UnaryMinus : public ParserNode { +public: + UnaryMinus( ParserNode* primary ) : m_primary( primary ) {} + ~UnaryMinus() { delete m_primary; } + virtual void buildXML( QDomDocument& doc, QDomElement element ); +private: + ParserNode* m_primary; +}; + +void UnaryMinus::buildXML( QDomDocument& doc, QDomElement element ) +{ + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", "-" ); + element.appendChild( de ); + m_primary->buildXML( doc, element ); +} + +class OperatorNode : public ParserNode { +public: + OperatorNode( QString type, ParserNode* lhs, ParserNode* rhs ) + : m_type( type ), m_lhs( lhs ), m_rhs( rhs ) {} + ~OperatorNode() { delete m_rhs; delete m_lhs; } +// virtual void output( ostream& stream ) { +// stream << "OperatorNode {"; +// m_lhs->output( stream ); stream << m_type; m_rhs->output( stream ); +// stream << "}" << endl; } +protected: + QString m_type; + ParserNode* m_lhs; + ParserNode* m_rhs; +}; + +class AssignNode : public OperatorNode { +public: + AssignNode( QString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {} + virtual void buildXML( QDomDocument& doc, QDomElement element ); +}; + +void AssignNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + m_lhs->buildXML( doc, element ); + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", QString( m_type ) ); + element.appendChild( de ); + m_rhs->buildXML( doc, element ); +} + +class ExprNode : public OperatorNode { +public: + ExprNode( QString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {} + virtual void buildXML( QDomDocument& doc, QDomElement element ); +}; + +void ExprNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + m_lhs->buildXML( doc, element ); + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", QString( m_type ) ); + element.appendChild( de ); + m_rhs->buildXML( doc, element ); +} + +class TermNode : public OperatorNode { +public: + TermNode( QString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {} + virtual void buildXML( QDomDocument& doc, QDomElement element ); +}; + +void TermNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + if ( m_type == "*" ) { + m_lhs->buildXML( doc, element ); + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", QString( m_type ) ); + element.appendChild( de ); + m_rhs->buildXML( doc, element ); + } + else { + QDomElement fraction = doc.createElement( "FRACTION" ); + QDomElement numerator = doc.createElement( "NUMERATOR" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + m_lhs->buildXML( doc, sequence ); + numerator.appendChild( sequence ); + fraction.appendChild( numerator ); + QDomElement denominator = doc.createElement( "DENOMINATOR" ); + sequence = doc.createElement( "SEQUENCE" ); + m_rhs->buildXML( doc, sequence ); + denominator.appendChild( sequence ); + fraction.appendChild( denominator ); + element.appendChild( fraction ); + } +} + + +class PowerNode : public OperatorNode { +public: + PowerNode( QString type, ParserNode* lhs, ParserNode* rhs ) : OperatorNode( type, lhs, rhs ) {} + virtual void buildXML( QDomDocument& doc, QDomElement element ); +}; + +void PowerNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + QDomElement index = doc.createElement( "INDEX" ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + index.appendChild( content ); + + if ( !m_lhs->isSimple() ) { + QDomElement bracket = doc.createElement( "BRACKET" ); + bracket.setAttribute( "LEFT", '(' ); + bracket.setAttribute( "RIGHT", ')' ); + sequence.appendChild( bracket ); + + content = doc.createElement( "CONTENT" ); + bracket.appendChild( content ); + + sequence = doc.createElement( "SEQUENCE" ); + content.appendChild( sequence ); + } + m_lhs->buildXML( doc, sequence ); + if ( m_type == "_" ) { + QDomElement lowerRight = doc.createElement( "LOWERRIGHT" ); + sequence = doc.createElement( "SEQUENCE" ); + m_rhs->buildXML( doc, sequence ); + lowerRight.appendChild( sequence ); + index.appendChild( lowerRight ); + } + else { + QDomElement upperRight = doc.createElement( "UPPERRIGHT" ); + sequence = doc.createElement( "SEQUENCE" ); + m_rhs->buildXML( doc, sequence ); + upperRight.appendChild( sequence ); + index.appendChild( upperRight ); + } + element.appendChild( index ); +} + + +class FunctionNode : public ParserNode { +public: + FunctionNode( PrimaryNode* name, QPtrList<ParserNode>& args ) : m_name( name ), m_args( args ) { + m_args.setAutoDelete( true ); + } + ~FunctionNode() { delete m_name; } + //virtual void output( ostream& stream ); + virtual void buildXML( QDomDocument& doc, QDomElement element ); +private: + void buildSymbolXML( QDomDocument& doc, QDomElement element, KFormula::SymbolType type ); + PrimaryNode* m_name; + QPtrList<ParserNode> m_args; +}; + +void FunctionNode::buildSymbolXML( QDomDocument& doc, QDomElement element, KFormula::SymbolType type ) +{ + QDomElement symbol = doc.createElement( "SYMBOL" ); + symbol.setAttribute( "TYPE", type ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + m_args.at( 0 )->buildXML( doc, sequence ); + content.appendChild( sequence ); + symbol.appendChild( content ); + if ( m_args.count() > 2 ) { + ParserNode* lowerLimit = m_args.at( m_args.count()-2 ); + ParserNode* upperLimit = m_args.at( m_args.count()-1 ); + + QDomElement lower = doc.createElement( "LOWER" ); + sequence = doc.createElement( "SEQUENCE" ); + lowerLimit->buildXML( doc, sequence ); + lower.appendChild( sequence ); + symbol.appendChild( lower ); + + QDomElement upper = doc.createElement( "UPPER" ); + sequence = doc.createElement( "SEQUENCE" ); + upperLimit->buildXML( doc, sequence ); + upper.appendChild( sequence ); + symbol.appendChild( upper ); + } + element.appendChild( symbol ); +} + +void FunctionNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + if ( ( m_name->primary() == "sqrt" ) && ( m_args.count() == 1 ) ) { + QDomElement root = doc.createElement( "ROOT" ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + m_args.at( 0 )->buildXML( doc, sequence ); + content.appendChild( sequence ); + root.appendChild( content ); + element.appendChild( root ); + } + else if ( ( m_name->primary() == "pow" ) && ( m_args.count() == 2 ) ) { + QDomElement index = doc.createElement( "INDEX" ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + m_args.at( 0 )->buildXML( doc, sequence ); + content.appendChild( sequence ); + index.appendChild( content ); + QDomElement upperRight = doc.createElement( "UPPERRIGHT" ); + sequence = doc.createElement( "SEQUENCE" ); + m_args.at( 1 )->buildXML( doc, sequence ); + upperRight.appendChild( sequence ); + index.appendChild( upperRight ); + element.appendChild( index ); + } + else if ( ( m_name->primary() == "sum" ) && ( m_args.count() > 0 ) ) { + buildSymbolXML( doc, element, KFormula::Sum ); + } + else if ( ( m_name->primary() == "prod" ) && ( m_args.count() > 0 ) ) { + buildSymbolXML( doc, element, KFormula::Product ); + } + else if ( ( ( m_name->primary() == "int" ) || + ( m_name->primary() == "integrate" ) || + ( m_name->primary() == "quad" ) ) + && ( m_args.count() > 0 ) ) { + buildSymbolXML( doc, element, KFormula::Integral ); + } + else { + m_name->buildXML( doc, element ); + QDomElement bracket = doc.createElement( "BRACKET" ); + bracket.setAttribute( "LEFT", '(' ); + bracket.setAttribute( "RIGHT", ')' ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + + for ( uint i = 0; i < m_args.count(); i++ ) { + m_args.at( i )->buildXML( doc, sequence ); + if ( i < m_args.count()-1 ) { + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", "," ); + sequence.appendChild( de ); + } + } + + content.appendChild( sequence ); + bracket.appendChild( content ); + element.appendChild( bracket ); + } +} + +// void FunctionNode::output( ostream& stream ) +// { +// m_name->output( stream ); +// for ( uint i = 0; i < m_args.count(); i++ ) { +// m_args.at( i )->output( stream ); +// } +// } + +class RowNode : public ParserNode { +public: + RowNode( QPtrList<ParserNode> row ) : m_row( row ) { m_row.setAutoDelete( true ); } + //virtual void output( ostream& stream ); + virtual void buildXML( QDomDocument& doc, QDomElement element ); + uint columns() const { return m_row.count(); } + void setRequiredColumns( uint requiredColumns ) { m_requiredColumns = requiredColumns; } +private: + QPtrList<ParserNode> m_row; + uint m_requiredColumns; +}; + +void RowNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + for ( uint i = 0; i < m_requiredColumns; i++ ) { + QDomElement sequence = doc.createElement( "SEQUENCE" ); + if ( i < m_row.count() ) { + m_row.at( i )->buildXML( doc, sequence ); + } + else { + QDomElement de = doc.createElement( "TEXT" ); + de.setAttribute( "CHAR", "0" ); + sequence.appendChild( de ); + } + element.appendChild( sequence ); + } +} + +// void RowNode::output( ostream& stream ) +// { +// stream << "["; +// for ( uint i = 0; i < m_row.count(); i++ ) { +// m_row.at( i )->output( stream ); +// if ( i < m_row.count()-1 ) { +// stream << ", "; +// } +// } +// stream << "]"; +// } + +class MatrixNode : public ParserNode { +public: + MatrixNode( QPtrList<RowNode> rows ) : m_rows( rows ) { m_rows.setAutoDelete( true ); } + //virtual void output( ostream& stream ); + virtual void buildXML( QDomDocument& doc, QDomElement element ); + virtual bool isSimple() { return true; } + uint columns(); + uint rows() { return m_rows.count(); } +private: + QPtrList<RowNode> m_rows; +}; + +uint MatrixNode::columns() +{ + uint columns = 0; + for ( uint i = 0; i < m_rows.count(); i++ ) { + columns = QMAX( columns, m_rows.at( i )->columns() ); + } + return columns; +} + +void MatrixNode::buildXML( QDomDocument& doc, QDomElement element ) +{ + QDomElement bracket = doc.createElement( "BRACKET" ); + bracket.setAttribute( "LEFT", '(' ); + bracket.setAttribute( "RIGHT", ')' ); + QDomElement content = doc.createElement( "CONTENT" ); + QDomElement sequence = doc.createElement( "SEQUENCE" ); + + uint cols = columns(); + QDomElement matrix = doc.createElement( "MATRIX" ); + matrix.setAttribute( "ROWS", m_rows.count() ); + matrix.setAttribute( "COLUMNS", cols ); + for ( uint i = 0; i < m_rows.count(); i++ ) { + m_rows.at( i )->setRequiredColumns( cols ); + m_rows.at( i )->buildXML( doc, matrix ); + matrix.appendChild( doc.createComment( "end of row" ) ); + } + sequence.appendChild( matrix ); + content.appendChild( sequence ); + bracket.appendChild( content ); + element.appendChild( bracket ); +} + +// void MatrixNode::output( ostream& stream ) +// { +// stream << "["; +// for ( uint i = 0; i < m_rows.count(); i++ ) { +// m_rows.at( i )->output( stream ); +// if ( i < m_rows.count()-1 ) { +// stream << ", "; +// } +// } +// stream << "]"; +// } + + +FormulaStringParser::FormulaStringParser( const KFormula::SymbolTable& symbolTable, QString formula ) + : m_symbolTable( symbolTable ), m_formula( formula ), + pos( 0 ), line( 1 ), column( 1 ), m_newlineIsSpace( true ) +{ +} + +FormulaStringParser::~FormulaStringParser() +{ + delete head; + if ( ParserNode::debugCount != 0 ) { + kdDebug( KFormula::DEBUGID ) << "ParserNode::debugCount = " << ParserNode::debugCount << endl; + } +} + +QDomDocument FormulaStringParser::parse() +{ + nextToken(); + head = parseAssign(); + //head->output( cout ); + if ( !eol() ) { + error( QString( i18n( "Aborted parsing at %1:%2" ) ).arg( line ).arg( column ) ); + } + + QDomDocument doc = KFormula::Document::createDomDocument(); + QDomElement root = doc.documentElement(); + QDomElement de = doc.createElement( "FORMULA" ); + // here comes the current version of FormulaElement + //de.setAttribute( "VERSION", "4" ); + head->buildXML( doc, de ); + root.appendChild(de); + + kdDebug( 39001 ) << doc.toString() << endl; + return doc; +} + +ParserNode* FormulaStringParser::parseAssign() +{ + ParserNode* lhs = parseExpr(); + for ( ;; ) { + switch ( currentType ) { + case ASSIGN: { + QString c = current; + nextToken(); + lhs = new AssignNode( c, lhs, parseExpr() ); + break; + } + default: + return lhs; + } + } +} + +ParserNode* FormulaStringParser::parseExpr() +{ + ParserNode* lhs = parseTerm(); + for ( ;; ) { + switch ( currentType ) { + case PLUS: + case SUB: { + QString c = current; + nextToken(); + lhs = new ExprNode( c, lhs, parseTerm() ); + break; + } + default: + return lhs; + } + } +} + +ParserNode* FormulaStringParser::parseTerm() +{ + ParserNode* lhs = parsePower(); + for ( ;; ) { + switch ( currentType ) { + case MUL: + case DIV: { + QString c = current; + nextToken(); + lhs = new TermNode( c, lhs, parsePower() ); + break; + } + default: + return lhs; + } + } +} + +ParserNode* FormulaStringParser::parsePower() +{ + ParserNode* lhs = parsePrimary(); + for ( ;; ) { + switch ( currentType ) { + case INDEX: + case POW: { + QString c = current; + nextToken(); + lhs = new PowerNode( c, lhs, parsePrimary() ); + break; + } + default: + return lhs; + } + } +} + +ParserNode* FormulaStringParser::parsePrimary() +{ + switch ( currentType ) { + case NUMBER: { + PrimaryNode* node = new PrimaryNode( current ); + nextToken(); + return node; + } + case NAME: { + PrimaryNode* node = new PrimaryNode( current ); + node->setUnicode( m_symbolTable.unicode( current ) ); + nextToken(); + if ( currentType == LP ) { + nextToken(); + QPtrList<ParserNode> args; + args.setAutoDelete( false ); + while ( ( currentType != EOL ) && ( currentType != RP ) ) { + ParserNode* node = parseExpr(); + args.append( node ); + if ( currentType == COMMA ) { + nextToken(); + } + } + expect( RP, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ")" ) ); + node->setFunctionName( true ); + return new FunctionNode( node, args ); + } + return node; + } + case SUB: { + nextToken(); + //ParserNode* node = new UnaryMinus( parsePrimary() ); + ParserNode* node = new UnaryMinus( parseTerm() ); + return node; + } + case LP: { + nextToken(); + ParserNode* node = parseExpr(); + expect( RP, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ")" ) ); + return node; + } + case LB: { + nextToken(); + QPtrList<RowNode> rows; + rows.setAutoDelete( false ); + bool innerBrackets = currentType == LB; + m_newlineIsSpace = innerBrackets; + while ( ( currentType != EOL ) && ( currentType != RB ) ) { + if ( innerBrackets ) { + expect( LB, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "[" ) ); + } + QPtrList<ParserNode> row; + row.setAutoDelete( false ); + while ( ( currentType != EOL ) && ( currentType != RB ) && + ( innerBrackets || ( currentType != SEMIC && currentType != NEWLINE ) ) ) { + row.append( parseExpr() ); + if ( currentType == COMMA ) { + nextToken(); + } + } + if ( innerBrackets ) { + expect( RB, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "]" ) ); + if ( currentType == COMMA ) { + nextToken(); + } + } + else { + if ( currentType != RB ) { + if ( currentType == NEWLINE ) { + nextToken(); + } + else { + expect( SEMIC, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( ";" ) ); + } + } + } + rows.append( new RowNode( row ) ); + } + m_newlineIsSpace = true; + expect( RB, QString( i18n( "'%3' expected at %1:%2" ) ).arg( line ).arg( column ).arg( "]" ) ); + MatrixNode* node = new MatrixNode( rows ); + if ( node->columns() == 0 ) { + error( QString( i18n( "Null columns in Matrix at %1:%2" ) ).arg( line ).arg( column ) ); + } + if ( node->rows() == 0 ) { + error( QString( i18n( "Null rows in Matrix at %1:%2" ) ).arg( line ).arg( column ) ); + } + return node; + } + case OTHER: { + ParserNode* node = new PrimaryNode( current ); + nextToken(); + return node; + } + default: + error( QString( i18n( "Unexpected token at %1:%2" ) ).arg( line ).arg( column ) ); + return new PrimaryNode( "?" ); + } +} + +void FormulaStringParser::expect( TokenType type, QString msg ) +{ + if ( currentType == type ) { + nextToken(); + } + else { + error( msg ); + } +} + +QString FormulaStringParser::nextToken() +{ + // We skip any ' or " so that we can parse string literals. + while ( !eol() && ( m_formula[pos].isSpace() || + ( m_formula[pos] == '"' ) || + ( m_formula[pos] == '\'' ) ) ) { + if ( m_formula[pos] == '\n' ) { + line++; + if ( m_newlineIsSpace ) { + column = 0; + } + else { + pos++; + column = 1; + currentType = NEWLINE; + return current = "\n"; + } + } + pos++; column++; + } + if ( eol() ) { + currentType = EOL; + return QString::null; + } + if ( m_formula[pos].isDigit() || m_formula[pos] == '.' ) { + uint begin = pos; + readNumber(); + currentType = NUMBER; + current = m_formula.mid( begin, pos-begin ); + if ( current[0] == '.' ) { + current = "0" + current; + } + if ( current[current.length()-1] == '.' ) { + current = current + "0"; + } + return current; + } + else if ( m_formula[pos].isLetter() ) { + uint begin = pos; + pos++; column++; + while ( !eol() && m_formula[pos].isLetter() ) { + pos++; column++; + } + currentType = NAME; + return current = m_formula.mid( begin, pos-begin ); + } + else { + switch ( m_formula[pos].latin1() ) { + case '+': + pos++; column++; + currentType = PLUS; + return current = "+"; + case '-': + pos++; column++; + currentType = SUB; + return current = "-"; + case '*': + pos++; column++; + if ( !eol() && m_formula[pos] == '*' ) { + pos++; column++; + currentType = POW; + return current = "**"; + } + currentType = MUL; + return current = "*"; + case '/': + pos++; column++; + currentType = DIV; + return current = "/"; + case '^': + pos++; column++; + currentType = POW; + return current = "**"; + case '_': + pos++; column++; + currentType = INDEX; + return current = "_"; + case '(': + pos++; column++; + currentType = LP; + return current = "("; + case ')': + pos++; column++; + currentType = RP; + return current = ")"; + case '[': + pos++; column++; + currentType = LB; + return current = "["; + case ']': + pos++; column++; + currentType = RB; + return current = "]"; + case ',': + pos++; column++; + currentType = COMMA; + return current = ","; + case ';': + pos++; column++; + currentType = SEMIC; + return current = ";"; + case '=': + pos++; column++; + currentType = ASSIGN; + return current = "="; + default: + pos++; column++; + currentType = OTHER; + return current = m_formula.mid( pos-1, 1 ); + } + } +} + +void FormulaStringParser::readNumber() +{ + bool digitsBeforeDot = m_formula[pos] != '.'; + + readDigits(); + if ( pos < m_formula.length()-1 ) { + QChar ch = m_formula[pos]; + + // Look for a dot. + if ( ch == '.' ) { + pos++; + column++; + ch = m_formula[pos]; + if ( ch.isDigit() ) { + readDigits(); + } + else if ( !digitsBeforeDot ) { + error( QString( i18n( "A single '.' is not a number at %1:%2" ) ).arg( line ).arg( column ) ); + return; + } + } + + // there might as well be an exponent + if ( pos < m_formula.length()-1 ) { + ch = m_formula[pos]; + if ( ( ch == 'E' ) || ( ch == 'e' ) ) { + pos++; + column++; + ch = m_formula[pos]; + + // signs are allowed after the exponent + if ( ( ( ch == '+' ) || ( ch == '-' ) ) && + ( pos < m_formula.length()-1 ) ) { + pos++; + column++; + ch = m_formula[pos]; + if ( ch.isDigit() ) { + readDigits(); + } + else { + pos -= 2; + column -= 2; + return; + } + } + else if ( ch.isDigit() ) { + readDigits(); + } + else { + pos--; + column--; + } + } + } + } +} + + +void FormulaStringParser::readDigits() +{ + while ( !eol() && m_formula[pos].isDigit() ) { + pos++; + column++; + } +} + +void FormulaStringParser::error( QString err ) +{ + kdDebug( KFormula::DEBUGID ) << err << " (" << currentType << "; " << current << ")" << endl; + m_errorList.push_back( err ); +} |