#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define F_MAX_LENGTH 8192
#define GLOBAL_VARS_N_MAX 8192+1
#define VAR_STR_MAX_LENGTH 128
#define E_TO_FEW_PROGRAM_ARGUMENTS -1
#define E_CANT_OPEN_FILE -2
#define E_SOURCE_FILE_EXCEEDED -3
#define E_SYNTAX_ERROR -4
#define E_NOT_ENOUGH_MEMORY -5
float global_vars [8192];
char lexstream [F_MAX_LENGTH];
char *lexstreamptr = lexstream;
int loopcount = 0;
int hash (char *);
float numexpr ();
float numexpr2 ();
float term ();
float term2 ();
float factor ();
char *arrayname ();
int boolexpr ();
int block ();
int block_do_not_execute ();
int loop () ;
int statement () ;
void stmt () ;
int ech () ;
int assignment ();
int cnd ();
int main (int argc, char *argv []) {
FILE *fp;
int ch;
char *p;
int i;
char lexstreamtmp [F_MAX_LENGTH];
char *p1, *p2;
if (argc != 2) {
perror ("Too few arguments for program");
return E_TO_FEW_PROGRAM_ARGUMENTS;
}
if ((fp = fopen (argv [1], "r")) == NULL) {
perror ("Can't open file");
return E_CANT_OPEN_FILE;
}
i = 0;
p = lexstream;
while (!feof(fp)) {
ch = fgetc (fp);
if (i > 8129) {
perror ("Source File to long");
return E_SOURCE_FILE_EXCEEDED;
}
i++;
*p = ch;
p++;
}
*p = 0;
lexstreamptr = lexstream;
for (p1 = lexstream, p2 = lexstreamtmp; (*p1) != 0; p1++, p2++) {
if ((*p1) == '\n')
(*p2) = ' ';
else if ((*p1) == '\t')
(*p2) = ' ';
else if ((*p1) == '\r')
(*p2) = ' ';
else
(*p2) = (*p1);
}
(*p2) = 0;
for (p1 = lexstream, p2 = lexstreamtmp; (*p2) != 0; p2++) {
(*p1) = (*p2);
if (!(((*p2) == ' ') && ((*(p2+1)) == ' ')))
p1++;
}
(*p1) = 0;
statement ();
return 0;
}
int hash (char *v) {
int h;
for (h = 0; *v != 0; v++)
h = (128*h+*v) % GLOBAL_VARS_N_MAX;
return h;
}
float numexpr () {
float x;
float y;
x = term ();
y = numexpr2 ();
return x+y;
}
float numexpr2 () {
char *ptrtmp;
float x, y;
ptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '+') {
lexstreamptr++;
x = term ();
y = numexpr2 ();
return x+y;
}
if ((*lexstreamptr) == '-') {
lexstreamptr++;
x = term ();
y = numexpr2 ();
return -x+y;
}
lexstreamptr = ptrtmp;
return 0;
}
float term () {
int x, y;
x = factor ();
y = term2 ();
return x*y;
}
float term2 () {
float x, y;
char *ptrtmp;
ptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '*') {
lexstreamptr++;
x = factor ();
y = term2 ();
return x*y;
}
if ((*lexstreamptr) == '/') {
lexstreamptr++;
x = factor ();
y = term2 ();
return y/x;
}
lexstreamptr = ptrtmp;
return 1;
}
float factor () {
float floatret;
char floatstrtmp [VAR_STR_MAX_LENGTH];
float retval;
char *ptr;
char varname [VAR_STR_MAX_LENGTH];
char *arraynamestr;
char buf [128];
if ((*lexstreamptr) == ' ')
lexstreamptr++;
floatret = strtof (lexstreamptr, NULL);
if (((*lexstreamptr) != '0') && (floatret != 0)) {
sprintf (floatstrtmp, "%.2f", floatret);
lexstreamptr += strlen (floatstrtmp);
return floatret;
}
else if ((*lexstreamptr) == '0') {
sprintf (floatstrtmp, "%.2f", floatret);
lexstreamptr += strlen (floatstrtmp);
return floatret;
}
else if ((*lexstreamptr) == '(') {
lexstreamptr ++;
retval = numexpr ();
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) != ')') {
perror ("Forget round bracket in arithmetic expression");
return E_SYNTAX_ERROR;
}
lexstreamptr ++;
return retval;
}
else if ((*lexstreamptr) == '$') {
lexstreamptr++;
if (!((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z'))) {
perror ("bad variable name");
return E_SYNTAX_ERROR;
}
ptr = varname;
while ((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z')) {
*ptr = *lexstreamptr;
ptr++;
lexstreamptr++;
}
*ptr = 0;
arraynamestr = arrayname ();
if (arraynamestr != NULL)
strcat (varname, arraynamestr);
return global_vars [hash (varname)];
}
else {
perror ("error in arithmetic expression");
return E_SYNTAX_ERROR;
}
}
char *arrayname () {
char *lexstreamptrtmp = lexstreamptr;
char *lexstreamptrtmp2;
char *arrayindexstr;
char *arraynamestrpost;
if ((arrayindexstr = (char *) malloc (VAR_STR_MAX_LENGTH)) == NULL) {
perror ("Not enough memory");
exit( E_NOT_ENOUGH_MEMORY );
}
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '[') {
lexstreamptr++;
sprintf (arrayindexstr, "%i", (int) numexpr());
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) != ']') {
perror ("Forgot closing array bracket");
exit ( E_SYNTAX_ERROR );
}
lexstreamptr++;
lexstreamptrtmp2 = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '[') {
lexstreamptr = lexstreamptrtmp2;
arraynamestrpost = arrayname ();
if (arraynamestrpost != NULL)
strcat (arrayindexstr, arraynamestrpost);
}
else
lexstreamptr = lexstreamptrtmp2;
return arrayindexstr;
}
else {
free (arrayindexstr);
lexstreamptr = lexstreamptrtmp;
return NULL;
}
}
int boolexpr () {
float x, y;
x = numexpr ();
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '<') {
lexstreamptr++;
y = numexpr ();
return (x < y);
}
else if ((*lexstreamptr) == '>') {
lexstreamptr++;
y = numexpr ();
return (x > y);
}
else if (((*lexstreamptr) == '<') && (*(lexstreamptr+1) == '=')) {
lexstreamptr+=2;
y = numexpr ();
return (x <= y);
}
else if (((*lexstreamptr) == '>') && (*(lexstreamptr+1) == '=')) {
lexstreamptr+=2;
y = numexpr ();
return (x >= y);
}
else if (((*lexstreamptr) == '=') && (*(lexstreamptr+1) == '=')) {
lexstreamptr+=2;
y = numexpr ();
return (x == y);
}
else if (((*lexstreamptr) == '!') && (*(lexstreamptr+1) == '=')) {
lexstreamptr+=2;
y = numexpr ();
return (x != y);
}
else {
perror ("Wrong compare operator in boolesche expression");
exit ( E_SYNTAX_ERROR );
}
}
int block () {
char *lexstreamptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
lexstreamptr += strlen ("begin");
statement ();
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "end", strlen ("end")) == 0)
lexstreamptr += strlen ("end");
else {
perror ("forgot end in block");
exit ( E_SYNTAX_ERROR );
}
}
else {
perror ("forgot begin in block");
exit ( E_SYNTAX_ERROR );
}
}
int block_do_not_execute () {
int count = 1;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
lexstreamptr += strlen ("begin");
while ((*lexstreamptr) != 0) {
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "end", strlen ("end")) == 0) {
lexstreamptr += strlen ("end");
count--;
}
else if (count == 0)
break;
else if (strncmp (lexstreamptr, "begin", strlen ("begin")) == 0) {
lexstreamptr += strlen ("begin");
count++;
}
else
lexstreamptr ++;
}
if (count != 0) {
perror ("code ends before block cloesd");
exit ( E_SYNTAX_ERROR );
}
}
else {
perror ("forgot begin in block");
exit ( E_SYNTAX_ERROR );
}
}
int loop () {
char *lexstreamptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "while", strlen ("while")) == 0) {
lexstreamptr += strlen ("while");
if (boolexpr ()) {
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "do", strlen ("do")) == 0) {
lexstreamptr += strlen ("do");
block ();
lexstreamptr = lexstreamptrtmp;
loop ();
return 1;
}
else {
perror ("Forgot do in while statement");
exit ( E_SYNTAX_ERROR );
}
}
else {
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "do", strlen ("do")) == 0) {
lexstreamptr += strlen ("do");
block_do_not_execute ();
return 1;
}
else {
perror ("Forgot do in while statement");
exit ( E_SYNTAX_ERROR );
}
}
}
else {
lexstreamptr = lexstreamptrtmp;
return 0;
}
}
int statement () {
char *lexstreamptrtmp = lexstreamptr;
char *lexstreamptrtmp2;
stmt ();
lexstreamptrtmp2 = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == ';') {
lexstreamptr++;
statement ();
}
else
lexstreamptr = lexstreamptrtmp2;
}
void stmt () {
if (loop ());
else if (assignment ());
else if (cnd ());
else if (ech ());
}
int ech () {
char *lexstreamptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "echo", strlen ("echo")) == 0) {
lexstreamptr += strlen ("echo");
if ((*lexstreamptr) == ' ')
lexstreamptr++;
printf ("%.2f\n", numexpr ());
return 1;
}
else {
lexstreamptr = lexstreamptrtmp;
return 0;
}
}
int assignment () {
char *lexstreamptrtmp = lexstreamptr;
char *arraynamestr;
char varname [VAR_STR_MAX_LENGTH];
char *ptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*lexstreamptr) == '$') {
lexstreamptr++;
if (!((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z'))) {
perror ("bad variable name");
exit ( E_SYNTAX_ERROR );
}
ptr = varname;
while ((*lexstreamptr >= 'a') && (*lexstreamptr <= 'z')) {
*ptr = *lexstreamptr;
ptr++;
lexstreamptr++;
}
*ptr = 0;
arraynamestr = arrayname ();
if (arraynamestr != NULL)
strcat (varname, arraynamestr);
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if ((*(lexstreamptr) == ':') && (*(lexstreamptr+1) == '=')) {
lexstreamptr += 2;
global_vars [hash (varname)] = numexpr ();
return 1;
}
else {
lexstreamptr = lexstreamptrtmp;
return 0;
}
}
else {
lexstreamptr = lexstreamptrtmp;
return 0;
}
}
int cnd () {
char *lexstreamptrtmp = lexstreamptr;
char *lexstreamptrtmp2;
int flag;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "if", strlen ("if")) == 0) {
lexstreamptr += strlen ("if");
flag = boolexpr ();
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "then", strlen ("then")) == 0) {
lexstreamptr += strlen ("then");
if (flag) {
block ();
lexstreamptrtmp2 = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "else", strlen ("else")) == 0) {
lexstreamptr += strlen ("else");
block_do_not_execute ();
}
else
lexstreamptr = lexstreamptrtmp2;
return 1;
}
else {
block_do_not_execute ();
lexstreamptrtmp = lexstreamptr;
if ((*lexstreamptr) == ' ')
lexstreamptr++;
if (strncmp (lexstreamptr, "else", strlen ("else")) == 0) {
lexstreamptr += strlen ("else");
block ();
}
else
lexstreamptr = lexstreamptrtmp2;
return 1;
}
}
else {
perror ("Forget then in if-Statement");
exit (E_SYNTAX_ERROR);
}
}
else {
lexstreamptr = lexstreamptrtmp;
return 0;
}
}