/* SI 413 Fall 2021
* This is a hand-coded scanner for the simple calculator
* language in the slides. It is based explicitly on the
* finite automaton.
*/
#include <iostream>
using namespace std;
#include "bisoncalc.tab.hpp" // Header file generated by bison
/* This is the scanner. It reads in characters and returns
* the type of the token, as an integer code.
*/
int yylex()
{
int state = 0; // this is the start state.
char opsym; // this is the operation ('*' or '/') when we OMP.
bool negative; // true for a negative NUM
int intval; // this is the integer value when we end in an NUM.
while(true) {
char c = cin.get();
switch(state) {
case 0:
switch(c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
intval = c - '0';
negative = false;
state = 1;
break;
case '-':
state = 2; break;
case '+':
state = 3; break;
case '*': case '/':
opsym = c; state = 4; break;
case '(': state = 5; break;
case ')': state = 6; break;
case ';': state = 7; break;
case ' ': case '\t': case '\n':
break; // stay in state 0
case EOF:
return YYEOF;
default:
cerr << "scanner error: token cannot start with '"
<< c << "'" << endl;
cin.putback(c);
return YYerror;
}
break;
case 1:
switch(c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
intval = intval * 10 + (c - '0');
break; // stay in state 1
default:
cin.putback(c);
// finished! set yylval.val to return the number to the parser
if (negative) yylval.val = -intval;
else yylval.val = intval;
return NUM;
}
break;
case 2:
switch(c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
intval = c - '0';
negative = true;
state = 1;
break;
default:
cin.putback(c);
yylval.sym = '-';
return OPA;
}
break;
case 3:
cin.putback(c);
yylval.sym = '+';
return OPA;
case 4:
cin.putback(c);
yylval.sym = opsym;
return OPM;
break;
case 5:
cin.putback(c);
return LP;
case 6:
cin.putback(c);
return RP;
case 7:
cin.putback(c);
return STOP;
} // end switch(state)
} // end while
// this should be unreachable
}