Expression Parser Project

I've been working on making an Arduino based calculator, but have ran into some issues. To start with I downloaded a C-based expression-parser library from the listed site: James' Blog: Mathematical Expression Parser in C. I've tested it in a c++ console application and decided that it worked well enough for me to upload it to my Arduino Mega 2560. Now when I tried this on the Mega, I ran into some errors. The output to serial was "nan" (not a number). When I looked further into the library's code, I realized that it was throwing some sort of error at me by outputting "sqrt(-1.0)". I've kept trying to figure this out, but I finally decided that one of you guys at the forum would know better than I. This is my first post, so I hope I gave you all the info you needed!

Help is greatly appreciated, thanks in advance!

sqrt(-1.0) is like dividing by 0 - it generates a result that is not a real number. i.e. -NaN. So you've proven sqrt works correctly....

Regards,
Ray L.

The code you've linked to will not run as-is on an Arduino. Post the code that you uploaded to the Mega (in code tags).

Pete

#include <expression_parser.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print(parse_expression("1+2"));
}

void loop() {
  // put your main code here, to run repeatedly:
  
}

As mentioned before the result on the serial is "nan".

In the expression parser, the function parse_expression_with_callbacks has two printf statements. On the Teensy 3.0 I am using these cause the code to hang. I changed them to Serial.printf. Now your test code prints this:

Error: Failed to read real number
Expression '1+2' failed to parse, returning nan

I don't have time to dig any further right now, but maybe after the long weekend.

Pete

Okay! I've sort of got somewhere with this. For whatever reason, it doesn't go into the if statement with setjmp(). I have no idea what this function does, as I'm really not the greatest programmer in the world, but this is clearly where the issue is.

(This is code in the expression_parser.cpp file of the library)

double parser_parse( parser_data *pd ){
    double result = 0.0;
	// set the jump position and launch the parser
        // FOR WHAT EVER REASON ARDUINO ENDS UP IN THE ELSE SECTION OF THE IF STATEMENT BELOW.  THIS IS THE ERROR PART CLEARLY AS IT RETURNS A NAN
	if( !setjmp( pd->err_jmp_buf ) ){
#if !defined(PARSER_EXCLUDE_BOOLEAN_OPS)
		result = parser_read_boolean_or( pd );
#else
		result = parser_read_expr( pd );
#endif
        parser_eat_whitespace( pd );
        if( pd->pos < pd->len-1 ){
            parser_error( pd, "Failed to reach end of input expression, likely malformed input" );
        } else return result;
	} else {
		// error was returned, output a nan silently
		return sqrt( -1.0 );
	}
    return sqrt(-1.0);
}

Inspiration struck me :slight_smile:
The parser_read_double function uses sscanf to read the floating point constants in an expression. This function, like the floating point version of printf, is not available by default.
On the Teensy 3 it is easy to add them by including these two statements at the beginning of the setup() function:

 asm(".global _printf_float");
  asm(".global _scanf_float");

With those, your test code now prints "3.00".
I don't know how, or if, there is an easy way to get sscanf included with an Arduino.

Pete

Thanks so much for the solution... Though I've been tearing my hair out trying to figure out sscanf in Arduino (I just deleted the not as important printf part). I'm getting close, but I just thought I'd drop a reply...

A temporary work-around would be to replace the sscanf with atof. atof doesn't do exactly what sscanf does but as long as the input is correct, this will work for now.
Try this:

  // check that a double-precision was read, otherwise throw an error
  // comment the sscanf
  if ( pos == 0 /*|| sscanf( token, "%lf", &val ) != 1*/ )
    parser_error( pd, "Failed to read real number" );
  // add a call to atof
  val = atof(token);

This still requires the ability to print floating point numbers.

Pete

Thanks so much for helping me out! :slight_smile:

I have tested the code and it works perfectly! I really appreciate your assistance and I can finally finish my calculator!