Code:
#include <stdio.h>
#include <iostream>
#include <vector>
#include <QString>
#include <QVariant>
#include <QVector>
#include <QMessageBox>
#include <QRegExp>
#include <QDebug>
int line_no = 1;
int file_eof = 0;
int last_op = 0;
const int cmd_invalid = 0;
const int cmd_assign = 1; // var = 12
const int cmd_assign_plus = 2; // var = 12 + 44
const int cmd_assign_new = 3; // var = new ...
enum SymbolType_ {
NoError,
NumberError,
EndOfText
};
SymbolType_ SymbolType;
// -------------------
// our AST struct ...
// -------------------
struct MyNode {
public:
int command;
QVariant value;
MyNode * lhs;
MyNode * rhs;
};
QVector<MyNode> eval_ast;
QString newnum;
QString number, ident;
int pos = -1; // buffer position
bool in_comment = false;
bool end_of_file = false;
int SkipWhitespaces(char *buffer)
{
int c = 0;
while (1) {
c = buffer[pos++];
if (isspace(c))
continue;
break;
}
return c;
}
QString GetIdent(char *buffer)
{
int c = 0;
while (1) {
c = buffer[pos++];
if (isalpha(c)) {
ident += c;
continue;
} break;
}
return ident;
}
QString GetNumber(char *buffer)
{
int c = 0;
while (1) {
c = buffer[pos];
if (isdigit(c)) {
number += c;
++pos;
continue;
}
else if (c == '.') {
number += '.';
++pos;
continue;
}
else if (c == '+' || c == '-'
|| c == '*' || c == '/') {
last_op = c;
return number;
}
else if (c == EOF || c == 0) {
last_op = c;
return number;
}
else if (isspace(c)) {
return number;
}
else {
throw QString("number expected, wrong type: >>%1<<").arg(c);
break;
}
}
return number;
}
int Match(char *buffer, char expected)
{
if (SkipWhitespaces(buffer) == expected)
return expected;
throw QString("Expected token '%1' at position: %2")
.arg(expected)
.arg(pos);
}
// --------------------------
// execute collected data ...
// --------------------------
bool evaluate(void)
{
MyNode ptr;
int c = 0;
while (!eval_ast.isEmpty()) {
ptr = eval_ast.at(c++);
if (ptr.value == QChar('+')) {
double lv = ptr.lhs->value.toDouble();
double rv = ptr.rhs->value.toDouble();
double sv = lv + rv;
qDebug() << "res: " << sv;
}
if (c+1 >= eval_ast.size())
break;
}
/*
MyNode ptr1, ptr2, ptr3;
double val1, val2, res;
while (!eval_stack.isEmpty()) {
ptr1 = eval_stack.pop(); qDebug() << ptr1.oper;
ptr2 = eval_stack.pop(); qDebug() << ptr2.value;
ptr3 = eval_stack.pop(); qDebug() << ptr3.value;
val1 = ptr2.value.toDouble();
val2 = ptr3.value.toDouble();
if (ptr1.oper == '+')
res = val1 + val2;
ptr1.oper = 'N';
ptr2.value = res;
qDebug() << ":= " << res;
if (eval_stack.isEmpty())
break;
ptr1 = eval_stack.pop/
eval_stack.push(ptr1);
eval_stack.push(ptr2);
eval_stack.push(ptr3);
}*/
return true;
}
bool parseText(char *buffer)
{
int flag = 0;
double res1;
ident .clear();
number.clear();
eval_ast.clear();
MyNode ptr;
int c;
while (1) {
c = SkipWhitespaces(buffer);
if (c == 0) {
if (SymbolType == EndOfText)
break;
}
else if ((c >= 'a') && (c <= 'z')) {
--pos;
ident = GetIdent(buffer);
Match(buffer,'=');
while (1) {
c = SkipWhitespaces(buffer);
if (isdigit(c)) {
number += c;
number = GetNumber (buffer); okk:
c = SkipWhitespaces(buffer);
if (c == '+') { nextp:
QString num = number;
double val1;
double val2;
number.clear();
c = SkipWhitespaces(buffer);
if (isdigit(c)) {
number += c;
number = GetNumber(buffer);
}
else
throw QString("number or ident expected.");
val1 = number.toDouble();
val2 = num .toDouble();
res1 = val1 + val2;
//ptr = new MyNode;
ptr.rhs = new MyNode;
ptr.lhs = new MyNode;
ptr.value = '+';
if (val1 < val2) {
ptr.rhs->value = val2;
ptr.lhs->value = val1;
}
else {
ptr.lhs->value = val2;
ptr.rhs->value = val1;
}
eval_ast.append(ptr);
c = SkipWhitespaces(buffer);
if (c == '+') {
number.clear();
c = SkipWhitespaces(buffer);
if (isdigit(c)) {
number += c;
number = GetNumber(buffer);
qDebug() << number;
val1 = number.toDouble();
double re = val1 + res1;
qDebug() << "re: " << re;
goto okk;
}
else {
if (c == EOF || c == 0)
break;
}
} else {
if (c == EOF || c == 0)
break;
}
}
if (c == EOF || c == 0) {
if (flag == 0)
break;
}
}
else if (c == '+' || c == '-'
|| c == '*' || c == '/') {
goto nextp;
}
else if (c == EOF || c == 0) {
if (flag > 0)
break;
throw QString("number or ident expected.");
}
}
}
if (flag > 0 || c == 0 || c == EOF)
break;
} return evaluate();
}
bool parseText(QString str)
{
char buffer[str.size()+1];
bool r = false;
try {
line_no = 1;
pos = 0;
file_eof = 0;
ident .clear();
number.clear();
strcpy(buffer,str.toLatin1().data());
std::cout << buffer << "\n";
r = parseText((char*)buffer);
if (r == false) {
QMessageBox::critical(0,"Error",
QString("Syntax Error in line: %1").arg(line_no));
return false;
}
QMessageBox::information(0,"Info","SUCCESS");
//evaluate();
return true;
}
catch (QString &e) {
QMessageBox::critical(0,"Error",
QString("Error in line: %1\n%2")
.arg(line_no)
.arg(e));
}
catch (int &e) {
if (e > 0) {
if (e == 2)
QMessageBox::critical(0,"Error",
QString("Error in line: %1").arg(line_no));
r = false;
}
}
return r;
}