# I need my NSTextFields be able to evaluate formulas...

24/07/03 18:55

It would be very nice for my customers to enter math formulas in text fields, how to achieve this in Cocoa ? |

-(BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor; to know if editing could be ended: you could design such a delegate that will parse the text and replace it by the result (or an error message is something goes wrong).

But how fo you evaluate a formula would you ask ?

This is a parsing problem and the solution depends on the complexity of the formula language you want to offer to your users. If you limit yourself to +,-,*,/ operations without parenthensis, it's quite easy to parse the string token by token to calculate the result.

If you want something more sophisticated you can use /usr/bin/yacc to generate the code of the parser from a grammar definition. Here is an example supporting some basic math function like tan, sqrt and exponentiation operator ^.

%{

#include

#include

int yyparse(void);

void yyerror(char *);

int yylex(void);

#define YYTRACE

#define YYSTYPE double

#define kPI (3.1415926535897932384626433832795)

#define YYACCEPT { yyresult = yyval ; return(0); }

extern YYSTYPE yyresult ;

int last=0;

%}

%left '+' '-'

%left '*' '/'

%left '^'

%nonassoc UMINUS

%nonassoc UPLUS

%token NUMBER, SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2, POW, PI, SQRT

%%

start : /* Nothing */

{ $$ = 0.0; }

| expr

{ $$ = $1; }

;

expr : NUMBER { $$ = $1 }

| function_call { $$ = $1 }

| PI { $$ = kPI }

| '(' expr ')' { $$ = $2 }

| expr '+' expr { $$ = $1 + $3 }

| expr '-' expr { $$ = $1 - $3 }

| expr '*' expr { $$ = $1 * $3 }

| expr '/' expr { $$ = $1 / $3 }

| expr '^' expr { $$ = pow ($1, $3) }

| '-' expr %prec UMINUS { $$ = -$2 }

| '+' expr %prec UPLUS { $$ = $2 }

;

function_call : SIN '(' expr ')'

{ $$ = sin( $3 ) }

| COS '(' expr ')'

{ $$ = cos( $3 ) }

| TAN '(' expr ')'

{ $$ = tan( $3 ) }

| ASIN '(' expr ')'

{ $$ = asin( $3 ) }

| ACOS '(' expr ')'

{ $$ = acos( $3 ) }

| ATAN '(' expr ')'

{ $$ = atan( $3 ) }

| ATAN2 '(' expr ',' expr ')'

{ $$ = atan2($3,$5) }

| POW '(' expr ',' expr ')'

{ $$ = pow($3,$5) }

| SQRT '(' expr ')'

{ $$ = sqrt($3) }

;

%%

But how fo you evaluate a formula would you ask ?

This is a parsing problem and the solution depends on the complexity of the formula language you want to offer to your users. If you limit yourself to +,-,*,/ operations without parenthensis, it's quite easy to parse the string token by token to calculate the result.

If you want something more sophisticated you can use /usr/bin/yacc to generate the code of the parser from a grammar definition. Here is an example supporting some basic math function like tan, sqrt and exponentiation operator ^.

%{

#include

#include

int yyparse(void);

void yyerror(char *);

int yylex(void);

#define YYTRACE

#define YYSTYPE double

#define kPI (3.1415926535897932384626433832795)

#define YYACCEPT { yyresult = yyval ; return(0); }

extern YYSTYPE yyresult ;

int last=0;

%}

%left '+' '-'

%left '*' '/'

%left '^'

%nonassoc UMINUS

%nonassoc UPLUS

%token NUMBER, SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2, POW, PI, SQRT

%%

start : /* Nothing */

{ $$ = 0.0; }

| expr

{ $$ = $1; }

;

expr : NUMBER { $$ = $1 }

| function_call { $$ = $1 }

| PI { $$ = kPI }

| '(' expr ')' { $$ = $2 }

| expr '+' expr { $$ = $1 + $3 }

| expr '-' expr { $$ = $1 - $3 }

| expr '*' expr { $$ = $1 * $3 }

| expr '/' expr { $$ = $1 / $3 }

| expr '^' expr { $$ = pow ($1, $3) }

| '-' expr %prec UMINUS { $$ = -$2 }

| '+' expr %prec UPLUS { $$ = $2 }

;

function_call : SIN '(' expr ')'

{ $$ = sin( $3 ) }

| COS '(' expr ')'

{ $$ = cos( $3 ) }

| TAN '(' expr ')'

{ $$ = tan( $3 ) }

| ASIN '(' expr ')'

{ $$ = asin( $3 ) }

| ACOS '(' expr ')'

{ $$ = acos( $3 ) }

| ATAN '(' expr ')'

{ $$ = atan( $3 ) }

| ATAN2 '(' expr ',' expr ')'

{ $$ = atan2($3,$5) }

| POW '(' expr ',' expr ')'

{ $$ = pow($3,$5) }

| SQRT '(' expr ')'

{ $$ = sqrt($3) }

;

%%

There are several solutions: - NSTextField are validated and formated by NSFormater objects: to make your NSTextField accept math formulas, you may write a NSFormater subclass that will evaluate the formula and returns the value as the object value. - NSTextField calls its delegate's method |