it may help if you developed your code on a laptop once verified, it can be moved to the Arduino with it's keypad and LCD.
confused why there's no "equals pressed" in your wiki.
i get the following output from a laptop version of your code (with some other changes).
i provide "12.3+5.6=" input
> 12.3+5.6=
lcdPrint: 1
lcdPrint: 2
lcdPrint: .
lcdPrint: 3
lcdPrint: +
lcdPrint: 5
lcdPrint: .
lcdPrint: 6
evaluate:
tokenize:
shuntingYard:
evaluateRPN:
evaluateRPN: 11.000000 15.000000 +
evaluate: 26.00
lcdPrint: 26.000000>
#if 0
#include <math.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
// -------------------------------------
enum { OUTPUT, INPUT, INPUT_PULLUP };
enum { LOW, HIGH };
void pinMode (int p, int mode) { }
struct hd44780_I2Cexp {
void begin (int x, int y) { }
void blink () { }
void clear () { }
void setCursor (int x, int y) { }
void print (int i) { printf ("\nlcdPrint: %d", i); }
void print (char c) { printf ("\nlcdPrint: %c", c); }
void print (float f) { printf ("\nlcdPrint: %f", f); }
};
// -------------------------------------
void delay (long) { }
int digitalRead (int p) { return 1; }
void digitalWrite (int p, int val) { }
bool isDigit (char c) { return isdigit (c); }
int pow (float c, int p) { return 1; }
// -------------------------------------
struct HW {
void begin (int bps) { }
void println (int i) { printf ("%d\n", i); }
void println (const char *s) { printf ("%s\n", s); }
} Serial;
// -------------------------------------
void setup ();
void loop ();
int main () {
setup ();
while (1)
loop ();
}
#endif
// -----------------------------------------------------------------------------
hd44780_I2Cexp lcd;
//--------------------DATA--------------------------------------------------
const int ROW_COUNT = 4;
const int COL_COUNT = 5;
int rowPins[ROW_COUNT] = {2, 3, 4, 5};
int colPins[COL_COUNT] = {8, 9, 10, 11, 12};
bool buttonStates[ROW_COUNT][COL_COUNT] = {false};
bool prevButtonStates[ROW_COUNT][COL_COUNT] = {false};
char buttonVals[ROW_COUNT][COL_COUNT] = {
{'7', '8', '9', 'D', 'C'},
{'4', '5', '6', '*', '/'},
{'1', '2', '3', '+', '-'},
{'0', '.', 'E', 'a', '='},
};
const int MAX_INPUT_SIZE = 100;
const int MAX_MEMORY_SIZE = 8;
const int MAX_STACK_SIZE = 100;
struct Input{
char data[MAX_INPUT_SIZE];
int len;
};
Input userInput = {};
struct Token{
char type;
union{
float val;
char op;
};
};
enum ErrorCodes{
SUCCESS,
MULTIPLE_DECIMAL_POINTS,
};
struct TokenExpression{
int tokenCount;
ErrorCodes status;
Token data[MAX_INPUT_SIZE];
};
struct Stack{
int top;
Token data[MAX_STACK_SIZE];
void POP () {
top--;
};
void PUSH (Token input) {
top++;
data[top] = input;
};
Token PEEK () {
return data[top];
};
};
struct Memory{
float ans[MAX_MEMORY_SIZE];
char expr[MAX_INPUT_SIZE];
};
Memory memory = {};
struct Cursor{
int x;
int y;
};
Cursor cursor = {};
//-----------------------------------------------FUNCTIONS------------------------------------------------
bool isOperator (char input) {
const int OPERATOR_COUNT = 4;
char operatorArray[OPERATOR_COUNT] = {'+', '-', '*', '/'};
for (int i = 0; i < OPERATOR_COUNT; i++) {
if (input == operatorArray[i]) {
return true;
}
}
return false;
}
// -----------------------------------------------------------------------------
TokenExpression tokenize (Input input)
{
printf (" %s:\n", __func__);
TokenExpression infixExpression = {};
int i = 0;
while (i < input.len) {
if (isDigit(input.data[i]) || input.data[i] == '.') {
float num = 0;
bool seenDecimal = false;
int digitsAD = 0;
while (i < input.len && (isDigit(input.data[i]) || input.data[i] == '.')) {
if (input.data[i] == '.') {
if (seenDecimal) {
infixExpression.status = MULTIPLE_DECIMAL_POINTS;
return infixExpression;
};
seenDecimal = true;
i++;
continue;
};
if (isDigit(input.data[i]) && !seenDecimal) {
num = num * 10 + (input.data[i] - '0');
i++;
continue;
};
if (isDigit(input.data[i]) && seenDecimal) {
digitsAD++;
num = num + (input.data[i] - '0') * pow(0.1, digitsAD);
i++;
continue;
};
}
infixExpression.data[infixExpression.tokenCount].type = 'n';
infixExpression.data[infixExpression.tokenCount].val = num;
infixExpression.tokenCount++;
}
if (i < input.len && isOperator(input.data[i])) {
infixExpression.data[infixExpression.tokenCount].type = 'o';
infixExpression.data[infixExpression.tokenCount].op = input.data[i];
i++;
infixExpression.tokenCount++;
}
}
infixExpression.status = SUCCESS;
return infixExpression;
}
// -----------------------------------------------------------------------------
int precedence (char op) {
printf ("\n%s:\n", __func__);
if (op == '+' || op == '-') {
return 1;
}
else if (op == '*' || op == '/') {
return 2;
}
return 0;
}
// -----------------------------------------------------------------------------
TokenExpression shuntingYard (TokenExpression infixExpression) {
printf (" %s:\n", __func__);
TokenExpression RPNExpression = {};
int RPNLen = 0;
Stack opStack = {
.top = -1
};
for (int i = 0; i < infixExpression.tokenCount; i++) {
if (infixExpression.data[i].type == 'n') {
RPNExpression.data[RPNLen].type = 'n';
RPNExpression.data[RPNLen].val = infixExpression.data[i].val;
RPNLen++;
}else if (infixExpression.data[i].type == 'o') {
RPNExpression.data[RPNLen].type = 'o';
if (opStack.top > -1) {
while (precedence(opStack.PEEK().op) >= precedence(infixExpression.data[i].op)) {
RPNExpression.data[RPNLen] = opStack.PEEK ();
RPNLen++;
opStack.POP ();
continue;
}
};
opStack.PUSH (infixExpression.data[i]);
};
}
for (int i = 0; opStack.top > -1; i++) {
RPNExpression.data[RPNLen] = opStack.PEEK ();
opStack.POP ();
RPNLen++;
}
RPNExpression.tokenCount = RPNLen;
RPNExpression.status = SUCCESS;
return RPNExpression;
}
// -----------------------------------------------------------------------------
float evaluateRPN (TokenExpression RPNExpression) {
printf (" %s:\n", __func__);
Stack numberStack = {
.top = -1
};
for (int i = 0; i < RPNExpression.tokenCount; i++) {
if (RPNExpression.data[i].type == 'n') {
numberStack.PUSH (RPNExpression.data[i]);
}
else if (RPNExpression.data[i].type == 'o') {
float num1 = numberStack.PEEK ().val;
numberStack.POP ();
float num2 = numberStack.PEEK ().val;
numberStack.POP ();
Token ans = {
.type = 'n'
};
printf (" %s: %f %f %c\n",
__func__, num1, num2, RPNExpression.data[i].op);
if (RPNExpression.data[i].op == '+') {
ans.val = num2 + num1;
}
else if (RPNExpression.data[i].op == '-') {
ans.val = num2 - num1;
}
else if (RPNExpression.data[i].op == '*') {
ans.val = num2 * num1;
}
else if (RPNExpression.data[i].op == '/') {
ans.val = num2 / num1;
};
numberStack.PUSH (ans);
};
}
return numberStack.data[numberStack.top].val;
}
// -----------------------------------------------------------------------------
float evaluate (Input input) {
printf ("\n%s:\n", __func__);
// Serial.println (1);
TokenExpression infixExpression = tokenize (input);
// Serial.println (2);
TokenExpression RPNExpression = shuntingYard (infixExpression);
// Serial.println (3);
float ans = evaluateRPN (RPNExpression);
// Serial.println (4);
printf (" %s: %.2f\n", __func__, ans);
return ans;
}
// -----------------------------------------------------------------------------
void clearInput () {
printf ("%s:\n", __func__);
for (int i = 0; i < userInput.len; i++) {
userInput.data[i] = '\0';
}
userInput.len = 0;
lcd.clear ();
cursor.x = 0;
cursor.y = 0;
lcd.setCursor (cursor.x, cursor.y);
}
// -----------------------------------------------------------------------------
void deleteChar () {
printf ("%s:\n", __func__);
userInput.len--;
userInput.data[userInput.len] = '\0';
cursor.x--;
lcd.setCursor (cursor.x, cursor.y);
lcd.print (' ');
lcd.setCursor (cursor.x, cursor.y);
}
void printChar (char input) {
// printf ("%s: %c\n", __func__, input);
userInput.data[userInput.len] = input;
userInput.len++;
lcd.print (input);
cursor.x++;
lcd.setCursor (cursor.x, cursor.y);
}
//---------------------------------------------SETUP AND LOOP---------------------------------------------
void setup () {
for (int row = 0; row < ROW_COUNT; row++) {
pinMode (rowPins[row], OUTPUT);
}
for (int col = 0; col < COL_COUNT; col++) {
pinMode (colPins[col], INPUT_PULLUP);
}
lcd.begin (20, 4);
lcd.setCursor (cursor.x, cursor.y);
lcd.blink ();
Serial.begin (9600);
printf ("> ");
}
// -----------------------------------------------------------------------------
void scan () {
printf ("%s:\n", __func__);
//SCAN
for (int cR = 0; cR < ROW_COUNT; cR++) {
for (int row = 0; row < ROW_COUNT; row++) {
digitalWrite (rowPins[row], HIGH);
}
digitalWrite (rowPins[cR], LOW);
for (int cC = 0; cC < COL_COUNT; cC++) {
prevButtonStates[cR][cC] = buttonStates[cR][cC];
buttonStates[cR][cC] = ! digitalRead (colPins[cC]);
}
}
//OUTPUT
for (int cR = 0; cR < ROW_COUNT; cR++) {
for (int cC = 0; cC < COL_COUNT; cC++) {
if (buttonStates[cR][cC] && !prevButtonStates[cR][cC]) {
char val = buttonVals[cR][cC];
if (val == '=') {
Serial.println ("equals pressed");
float ans = evaluate (userInput);
cursor.x = 3;
cursor.y = 3;
lcd.setCursor (cursor.x, cursor.y);
lcd.print (ans);
}
else if (val == 'C') {
clearInput ();
}
else if (val == 'D') {
deleteChar ();
}
else{
printChar (val);
}
}
}
}
delay (15);
}
// -----------------------------------------------------------------------------
void loop ()
{
char c = getchar ();
// printf ("%c", c);
switch (c) {
case '=':
// Serial.println ("equals pressed");
lcd.print ( evaluate (userInput) );
printf ("> ");
break;
case 'C':
clearInput ();
break;
case 'D':
deleteChar ();
break;
case '\n':
break;
case 'q':
exit (0);
break;
default:
printChar (c);
break;
}
}