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.
284 lines
8.4 KiB
284 lines
8.4 KiB
/***************************************************************************
|
|
mpformula.cpp
|
|
-------------------
|
|
begin : Sun Nov 18 2001
|
|
copyright : (C) 2001 by Kamil
|
|
email : kamil@localhost.localdomain
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "mpformula.h"
|
|
#include <iostream.h>
|
|
#include <qstring.h>
|
|
#include <qobject.h>
|
|
//
|
|
// TODO: i18n
|
|
// ? :
|
|
// AND OR XOR
|
|
// >=, <= ==
|
|
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
void yyerr( const char *, void *location_info_ptr, void *formula_ptr )
|
|
{
|
|
MPFormula *formula = (MPFormula *)formula_ptr;
|
|
YYLTYPE *location_info = (YYLTYPE *)location_info_ptr;
|
|
formula->m_error->setParseError( location_info->first_column, location_info->last_column );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
int yylex( MPParserSymbol *symbol_value, void *location_info_ptr, void *formula_ptr )
|
|
{
|
|
MPFormula *formula = (MPFormula *)formula_ptr;
|
|
YYLTYPE *location_info = (YYLTYPE *)location_info_ptr;
|
|
|
|
QString token;
|
|
QChar c = formula->curr_char();
|
|
// eat white spaces
|
|
while( c.isSpace() ) {
|
|
c = formula->m_formula[++formula->m_char];
|
|
}
|
|
|
|
location_info->first_column = formula->m_char;
|
|
|
|
// number
|
|
if ( c.isDigit() || c == '.' ) {
|
|
while ( c.isDigit() ) c = formula->apply_char( token );
|
|
if ( c == '.' ) c = formula->apply_char( token );
|
|
while ( c.isDigit() ) c = formula->apply_char( token );
|
|
if ( c == 'e' || c == 'E' ) {
|
|
c = formula->apply_char( token );
|
|
if ( c == '+' || c == '-' ) {
|
|
c = formula->apply_char( token );
|
|
while ( c.isDigit() ) c = formula->apply_char( token );
|
|
}
|
|
}
|
|
*symbol_value = token;
|
|
location_info->last_column = formula->m_char-1;
|
|
return NUMBER;
|
|
}
|
|
// identifier - function or variable
|
|
else if ( c.isLetter() || c == '_' ) {
|
|
while ( c.isLetterOrNumber() || c == '_' ) c = formula->apply_char( token );
|
|
location_info->last_column = formula->m_char-1;
|
|
MPSymbol *result = formula->get_symbol( token.latin1(), NULL, location_info->first_column, location_info->last_column );
|
|
if ( result && result->isVariable() ) {
|
|
*symbol_value = result;
|
|
return VAR;
|
|
}
|
|
else if ( result ) {
|
|
*symbol_value = result;
|
|
return FUNC;
|
|
}
|
|
else {
|
|
*symbol_value = token;
|
|
return ID;
|
|
}
|
|
}
|
|
else if ( c.isNull() ) {
|
|
location_info->last_column = formula->m_char-1;
|
|
*symbol_value = MPParserSymbol();
|
|
return END;
|
|
}
|
|
|
|
location_info->last_column = formula->m_char;
|
|
// make the next character the current one.
|
|
formula->m_char++;
|
|
*symbol_value = MPParserSymbol();
|
|
return c.latin1();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
MPFactoryList MPFormula::m_global_symbols;
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
MPFormula::MPFormula()
|
|
{
|
|
m_char = 0;
|
|
m_local_symbols = NULL;
|
|
m_root_sym = NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
MPFormula::~MPFormula()
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
MPSymbol *MPFormula::parse( const QString& formula, MPError& error, MPFactoryList *locals )
|
|
{
|
|
m_char = 0;
|
|
m_error = &error;
|
|
m_formula = formula;
|
|
m_root_sym = NULL;
|
|
m_local_symbols = locals;
|
|
|
|
yyparse( (void *)this );
|
|
|
|
if ( m_root_sym ) {
|
|
m_root_sym->checkArgs( error );
|
|
if ( error.hasError() ) {
|
|
delete m_root_sym;
|
|
m_root_sym = NULL;
|
|
}
|
|
}
|
|
return m_root_sym;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
QChar MPFormula::curr_char() const
|
|
{
|
|
return m_formula[m_char];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
QChar MPFormula::apply_char( QString& append_to )
|
|
{
|
|
append_to += m_formula[m_char++];
|
|
return m_formula[m_char];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
void MPFormula::addGlobalSymbols( MPSymbolFactory *factory )
|
|
{
|
|
m_global_symbols.prepend( factory );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
void MPFormula::delGlobalSymbols( MPSymbolFactory *factory )
|
|
{
|
|
m_global_symbols.remove( factory );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------//
|
|
|
|
MPSymbol *MPFormula::get_symbol( const QString &identifier, MPSymbolList *args, int colFrom, int colTo )
|
|
// sets undefined error in the case of error
|
|
{
|
|
// no support for unicode yet
|
|
const char *id = identifier.latin1();
|
|
|
|
MPSymbol *result = NULL;
|
|
|
|
// search through local symbols
|
|
if ( m_local_symbols )
|
|
for ( MPSymbolFactory *f=m_local_symbols->first(); ( f && !result ); f=m_local_symbols->next() ) {
|
|
result = f->create( id, args, colFrom, colTo );
|
|
}
|
|
// search through global symbols
|
|
for ( MPSymbolFactory *f=m_global_symbols.first(); ( f && !result ); f=m_global_symbols.next() ) {
|
|
result = f->create( id, args, colFrom, colTo );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
//--------------------------------------------------------------------------//
|
|
//--------------------------------------------------------------------------//
|
|
//--------------------------------------------------------------------------//
|
|
//--------------------------------------------------------------------------//
|
|
//--------------------------------------------------------------------------//
|
|
|
|
MPFormulaError::MPFormulaError()
|
|
:MPError()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
MPFormulaError::~MPFormulaError()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
void MPFormulaError::setWrongNumberOfArguments( int currArgs, int correctArgs, MPSymbol *expression )
|
|
{
|
|
if ( m_type == None ) {
|
|
MPError::setWrongNumberOfArguments( currArgs, correctArgs, expression );
|
|
m_msg = QObject::tr(" Wrong number of arguments ( is %1, sould be %2 ). \n" ).arg(currArgs).arg(correctArgs)+standard_message( expression );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
void MPFormulaError::setNonconformantArgument( int arg_nr, MPSymbol *expression, MPSymbol *sym )
|
|
{
|
|
if ( m_type == None ) {
|
|
MPError::setNonconformantArgument( arg_nr, expression, sym );
|
|
m_msg = QObject::tr( "Nonconformat argument %1 '%2' at columns %3-%4\n" )
|
|
.arg( arg_nr )
|
|
.arg( expression->identifier() )
|
|
.arg( expression->colFrom() )
|
|
.arg( expression->colTo() )
|
|
+standard_message( sym );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
void MPFormulaError::setError( const char *message, MPSymbol *expression )
|
|
{
|
|
if ( m_type == None ) {
|
|
MPError::setError( message, expression );
|
|
m_msg = QObject::tr(message)+"\n"+standard_message( expression );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
void MPFormulaError::setUndefinedSymbol( const char *symbol, int colFrom, int colTo )
|
|
{
|
|
if ( m_type == None ) {
|
|
MPError::setUndefinedSymbol( symbol, colFrom, colTo );
|
|
m_msg = QObject::tr(" Undefined symbol '%1' at columns %2-%3 ." ).arg( symbol ).arg( colFrom ).arg( colTo );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
void MPFormulaError::setParseError( int colFrom, int colTo )
|
|
{
|
|
if ( m_type == None ) {
|
|
MPError::setParseError( colFrom, colTo );
|
|
m_msg = QObject::tr(" Parse error at columns %2-%3 ." ).arg( colFrom ).arg( colTo );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------//
|
|
|
|
QString MPFormulaError::standard_message( MPSymbol *expression )
|
|
{
|
|
return QObject::tr(" Evaluating '%1' at columns %2-%3 . " )
|
|
.arg( expression->identifier() )
|
|
.arg( expression->colFrom() )
|
|
.arg( expression->colTo() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|