← index
cplusplus2x.Examples/C++20/MasterX/src/apps/ats/code_func.cpp
Source: cplusplus2x.Examples/C++20/MasterX/src/apps/ats/code_func.cpp
#include "code.hpp"

namespace interp {

    bool saveLineSource(const std::string &text) {
        std::fstream file;
        file.open(text, std::ios::out);
        if (!file.is_open())
            return false;
        for (unsigned int i = 0; i < lines.size(); ++i) {
            file << lines[i].index << " " << lines[i].text << "\r\n";
        }
        file.close();
        return true;
    }

    std::string eatComment(std::string src) {
        std::string text;
        for (unsigned int i = 0; i < src.length(); ++i) {
            if (src[i] == ';')
                return text;
            else
                text += src[i];
        }
        return text;
    }

    bool openLineSource(const std::string &text) {
        std::fstream file;
        file.open(text, std::ios::in);
        if (!file.is_open())
            return false;
        if (!lines.empty()) {
            lines.erase(lines.begin(), lines.end());
        }
        while (!file.eof() && file) {
            std::string in, orig;
            std::getline(file, orig);
            in = eatComment(orig);
            if (in.length() == 0)
                continue;

            std::vector<lex::Token> tokens;
            std::istringstream stream(in);
            lex::Scanner scan(stream);
            while (scan.valid()) {
                lex::Token token;
                scan >> token;
                if (token.getTokenType() != lex::TOKEN_EOF)
                    tokens.push_back(token);
            }

            inputText(tokens, in);
        }
        file.close();
        return true;
    }

    void insertText(std::vector<lex::Token> &tokens, const TextLine &in) {
        for (unsigned int i = 0; i < lines.size(); ++i) {
            if (lines[i].index == in.index) {
                if (checkInstruction(tokens, in)) {
                    lines[i].text = in.text;
                    return;
                } else
                    return;
            }
        }
        if (checkInstruction(tokens, in)) {
            lines.push_back(in);
            std::sort(lines.begin(), lines.end());
        }
    }

    void inputText(std::vector<lex::Token> &tokens, std::string input_line) {
        if (tokens.size() >= 2 && input_line.length() > 0) {
            lex::Token_type num = tokens[0].getTokenType();
            if (num != lex::TOKEN_DIGIT) {
                stream << "Requires line number before code.\r\n";
                return;
            }
            int value = atoi(tokens[0].getToken().c_str());
            std::string codetext;
            codetext = input_line.substr(input_line.find(tokens[0].getToken()) + tokens[0].getToken().length() + 1, input_line.length());
            TextLine in(value, codetext);
            insertText(tokens, in);
        } else {
            stream << "Error invalid input.\r\n";
            return;
        }
    }

    // should have used recursive functions
    // will do for translating
    bool checkInstruction(std::vector<lex::Token> &tokens, const TextLine &text) {
        if (tokens.size() <= 1) {
            stream << "Error: Statement requires instruction.\r\n";
            return false;
        }
        static unsigned int inc_offset = 0;
        if (tokens.size() >= 2) {
            icode::opc op = icode::strtoInc(tokens[1].getToken());
            if (op == icode::opc::NOTINC) {
                if (tokens[1].getTokenType() != lex::TOKEN_CHAR) {
                    stream << "Syntax Error: After line number requires either Label or instruction.\r\n";
                    return false;
                }
                inc_offset = 1;
                op = icode::strtoInc(tokens[1 + inc_offset].getToken());
                if (op == icode::opc::NOTINC) {
                    stream << "Syntax Error: After Label requires Instruction.\r\n";
                    return false;
                }
            } else {
                // check operands
                if (tokens.size() >= 3 + inc_offset) {
                    if (tokens[2 + inc_offset].getToken() == "#") {
                        if (tokens.size() >= 4 + inc_offset) {
                            if (tokens[3 + inc_offset].getTokenType() == lex::TOKEN_DIGIT) {
                            } else if (tokens[3 + inc_offset].getTokenType() != lex::TOKEN_DIGIT && tokens[3 + inc_offset].getTokenType() != lex::TOKEN_HEX) {
                                stream << "Syntax Error: requires either digit or $.\r\n";
                                return false;

                            } else if (tokens[3 + inc_offset].getTokenType() != lex::TOKEN_HEX) {
                                stream << "Syntax Error: $ is followed by a Hex value\r\n";
                                return false;
                            }

                            if (tokens.size() >= 5 + inc_offset && tokens[4 + inc_offset].getToken() == ",") {
                                if (tokens.size() >= 6 + inc_offset && tokens[5 + inc_offset].getTokenType() == lex::TOKEN_CHAR) {
                                    // check if register
                                }
                            } else if (tokens.size() >= 5 + inc_offset && tokens[4 + inc_offset].getToken() != ",") {
                                stream << "Syntax Error: Expecting comma instead I found: " << tokens[4].getToken() << "\r\n";
                                return false;
                            }

                        } else {
                            stream << "Syntax Error: Missing value after #\r\n";
                            return false;
                        }
                    }
                } else {
                    return true; // check if inc requires no operand
                }
            }
        }
        return true;
    }

    bool procLine(const TextLine &text, Code &code) {
        std::istringstream input(text.text);
        lex::Scanner scan(input);
        std::vector<lex::Token> tokens;
        while (scan.valid()) {
            lex::Token token;
            scan >> token;
            if (token.getTokenType() != lex::TOKEN_EOF)
                tokens.push_back(token);
        }
        // for now output each token
        stream << "Code Line: [" << text.index << "] - [" << text.text << "] = {\r\n";
        for (unsigned int i = 0; i < tokens.size(); ++i) {
            stream << tokens[i] << "\r\n";
        }
        stream << "}\r\n\r\n";
        return true;
    }
} // namespace interp