Skip to content

Commit

Permalink
first upload
Browse files Browse the repository at this point in the history
  • Loading branch information
promisivia committed Dec 20, 2019
1 parent d3a622b commit c475402
Show file tree
Hide file tree
Showing 16 changed files with 1,578 additions and 0 deletions.
49 changes: 49 additions & 0 deletions Basic.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-11-10T23:30:15
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Basic
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
evaluation.cpp \
expression.cpp \
main.cpp \
parser.cpp \
program.cpp\
basic.cpp \
statement.cpp \
tokenizer.cpp

HEADERS += \
evaluation.h \
expression.h \
parser.h \
program.h\
basic.h \
statement.h \
tokenizer.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
182 changes: 182 additions & 0 deletions basic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include "basic.h"

#include <QKeyEvent>
#include <QTextLine>
#include <QTextCursor>
#include <QDebug>
#include <QFont>

Basic::Basic(QWidget *parent) : QTextEdit(parent)
{
program = new Program;
tokenizer = new Tokenizer;
parser = new Parser;
eval = new Evaluation();
this->setFont(QFont("Consolas",14));
this->write("MINIMAL BASIC -- Type HELP for help.\n");
resize(800,600);
}

void Basic::write(QString string)
{
this->append(string);
}

QString Basic::getInputValue()
{
if (runtimeInput == "")
return "";
tokenizer->scanLine(runtimeInput);
QString token = tokenizer->getNextToken();
token = tokenizer->getNextToken();
QString value = tokenizer->getNextToken();
if(tokenizer->getTokenType(value)!= NUMBER || tokenizer->hasMoreTokens()){
return "INVALID";
}
return value;
}

void Basic::inputGotten(){
runtimeInput = "";
}

void Basic::processLine(QString line)
{
tokenizer->scanLine(line);
if (state == RUNNING){
runtimeInput = line;
}else{
QString firstTerm = tokenizer->getNextToken();
if(tokenizer->getTokenType(firstTerm) != NUMBER)
processCommand(firstTerm);
else
processCode(firstTerm.toInt(),line);
}

}

void Basic::processCode(int lineNum, QString line)
{
if (lineNum <= 0)
throw QString("Line number should be greater than 0!");
if (tokenizer->hasMoreTokens()){
program->insertLine(lineNum, line);
parser->parseStatement(tokenizer,this);
} else {
if(program->map.contains(lineNum))
program->removeLine(lineNum);
else throw QString("No such line to remove!");
}
}

void Basic::processCommand(QString cmd)
{
QString CMD = cmd.toUpper();
if(CMD == "RUN") {
run();
}else if(CMD == "LIST") {
listProgram();
} else if(CMD == "CLEAR") {
clear();
} else if(CMD == "HELP") {
printHelpMsg();
} else if(CMD == "QUIT") {
exit(0);
} else if(CMD == "PRINT") {
tokenizer->trackback();
parser->parseStatement(tokenizer,this);
} else {
throw "Invalid COMMAND: " + CMD + ". Type HELP for help.";
}
}

void Basic::run()
{
state = RUNNING;
int index = program->getFirstLineNum();
while(index != -1){
try{
program->getParsedStatement(index)->execute(eval);
}catch(int){
break;
}catch(const QString error) {
this->write(error);
break;
}
if (eval->getNextLineNum() != -1){
index = eval->getNextLineNum();
}else {
index = program->getNextLineNum(index);
}
}
state = NOTRUNNING;
}

void Basic::listProgram()
{
for (int i = 0; i < program->list.size(); ++i) {
if(program->list.at(i)->stm)
this->write(program->list.at(i)->statement);
}
}

void Basic::clear()
{
program->clear();
eval->clear();
}


void Basic::printHelpMsg()
{
this->write("The following commands are accepted by the interpreter:");
this->write("RUN - Runs the stored program.");
this->write("LIST - Lists the stored program.");
this->write("CLEAR - Deletes the stored program.");
this->write("HELP - Displays help information.");
this->write("QUIT - Exits the interpreter.\n");

this->write("The following statements are accepted by the interpreter:");
this->write("The LET, PRINT, and INPUT statements can be executed directly by typing them without a line number.");
this->write("Following commands cannot be part of a program and must therefore be entered without a line number. ");
this->write("[Usage: REM exp]: This statement is used for comments. Any text on the line after the keyword REM is ignored.");
this->write("[Usage: LET var = exp]: Assignment statement. Assigns the value of the expression to the variable, replacing any previous value.");
this->write("[Usage: PRINT exp]: Prints value of the expression to the console.");
this->write("[Usage: INPUT var]: Reads in a variable from the user. Prompts the user by printing \" ? \", and assigns the input value to the variable");
this->write("[Usage: GOTO n]: Forces program to execute line n instead of the next stored line.");
this->write("[Usage: IF exp1 op exp2 THEN n]*: Conditional operator op accepts =, <, and > to compare exp1 and exp2. If condition holds, executes line n. If not, program executes the next stored line.");
this->write("[Usage: END]: Halts program execution.\n");

this->write("Functions are supported with the following statements.");
this->write("[Usage: SUB function_name, Statements, End Sub ]: the function can use variables defined outside the function, and variables defined inside the function can also be accessed in other parts of the code.");
this->write("[Usage: CALL function_name]: invoked the function.\n");
}

void Basic::keyPressEvent(QKeyEvent *event)
{
QTextCursor cursor = this->textCursor();
cursor.movePosition(QTextCursor::End);
this->setTextCursor(cursor);
ensureCursorVisible();

if (event->key() == Qt::Key_Backspace){
cursor.deletePreviousChar();
return;
}
if (event->key() == Qt::Key_Delete){
cursor.deleteChar();
return;
}
if (this->textCursor().hasSelection())
return;
if (event->key() == Qt::Key_Return) {
cursor.select(QTextCursor::LineUnderCursor);
QString Line = cursor.selectedText();
try{
processLine(Line);
}catch (const QString error) {
this->write(error);
}
}
QTextEdit::keyPressEvent(event);
}
120 changes: 120 additions & 0 deletions basic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* File: Basic.h
* -------------------
* Export a QTextEdit class to implement a console to interact
* with the user.Process the command and print information.
*
*/

#ifndef BASIC_H
#define BASIC_H

#include <QObject>
#include <QTextEdit>
#include <QWidget>

#include "program.h"
#include "tokenizer.h"
#include "parser.h"

/* Mark wheter the program is running */
enum State{RUNNING,NOTRUNNING};

class Basic : public QTextEdit
{
Q_OBJECT

public:
Program* program;
Tokenizer* tokenizer;
Parser* parser;
Evaluation *eval;

private:
QString runtimeInput;
State state;

public:
explicit Basic(QWidget *parent = nullptr);

/*
* Function: write
* Usage: basic->write(QString);
* -----------------------------------------
* Print the string on the widget.
*/
void write(QString string);

/*
* Function: processLine
* -----------------------------------------
* Get a single line entered by the user and decide if it
* is a command or a line of code. Process accordingly.
*/
void processLine(QString line);

/*
* Function: processCode
* -----------------------------------------
* Process the line with a line number with the help of parser.
* Store it in the program.
* If line only has a line number, delete it if this line already
* exsits, or print that this line does not exists.
*/
void processCode(int lineNum, QString line);

/*
* Function: processCommand
* -----------------------------------------
* Get a single command and checks its validity.
* If valid, carries out the corresponding operation.
*/
void processCommand(QString cmd);

/*
* Function: getInputValue
* -----------------------------------------
* Get the user input during the running of the program.
*/
QString getInputValue();

/*
* Function: inputGotten
* -----------------------------------------
* Mark that the input is gotten by the evaluation.
*/
void inputGotten();

/*
* Function: run
* -----------------------------------------
* Start executing the program.
*/
void run();

/*
* Function: listProgram
* -----------------------------------------------
* Print the line stored in program out on the window.
*/
void listProgram();

/*
* Function: clear
* -----------------------------------------------
* Delete all the previous information.
*/
void clear();

/*
* Function: printHelpMsg
* -----------------------------------------------
* Support the PRINT command. Print all the help information.
*/
void printHelpMsg();
protected:
virtual void keyPressEvent(QKeyEvent *event) override;
};


#endif // BASIC_H
Loading

0 comments on commit c475402

Please sign in to comment.