123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /*
- Parser functions and class implementations for malio interpreter
- For details on specifications of the Malio language, please see:
- https://notabug.org/Malio
- Copyright 2015 - Malio dev team
-
- This file is part of malio-cpp
- malio-cpp is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- malio-cpp is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <fstream>
- #include <vector>
- #include <algorithm>
- #include <map>
- #include "parser.h"
- #include "builtins.h"
- // reserved keywords:
- std::vector<std::string> keywords {
- "print",
- "program",
- "int",
- "char",
- "dec",
- "string",
- "boolean",
- "end",
- "writef",
- "copyf",
- "#",
- "null"
- };
- // -- Exceptions class definitions:
- malio::Exception::Exception(std::string err):
- errortype(err)
- {
- std::cout << errortype << ": ";
- }
- malio::SyntaxError::SyntaxError(std::string what):
- Exception("SyntaxError"), explanation(what)
- {
- std::cout << explanation << std::endl;
- }
- malio::NameError::NameError(std::string what):
- Exception("NameError"), explanation(what)
- {
- std::cout << explanation << " is not defined." << std::endl;
- }
- // -- Parser functions:
- int malio::read(std::string filename)
- {
- std::string program_name;
- std::tuple<std::string, std::string> action;
- std::ifstream file(filename);
- if (file.is_open()) {
- std::string buffer;
- while(std::getline(file, buffer)) {
- // Process the line as needed:
- action = malio::parse(buffer);
- if (std::get<0>(action) == "comment")
- continue;
- else if (std::get<0>(action) == "program") {
- program_name = std::get<1>(action);
- continue;
- }
- else if (std::get<0>(action) == "end") {
- // std::cout << "Program exit OK.\n";
- break;
- }
- else if (std::get<0>(action) == "print")
- malio::print(std::get<1>(action));
- else if (std::get<0>(action) == "writef")
- malio::writef(std::get<1>(action), "testwf.txt");
- }
- file.close();
- return 0;
- }
- else {
- std::cerr << "Failed to open file " << filename << std::endl;
- return 1;
- }
- }
- // take a full line of code and parse it, return the action to perform by
- // the interpreter:
- std::tuple<std::string, std::string>
- malio::parse(std::string line)
- {
- std::stringstream ss(line);
- std::string buffer;
- std::tuple<std::string, std::string> action;
- bool ignore_names(false);
- // When we enter this loop, we need to consider the order of evaluation
- // of things:
- // 1. Is it a comment? Then ignore the rest of the line.
- // 2. Is it a program directive? Then fetch the program information
- // 3. Is it a print statement? Then print the rest of the line. Ignore
- // names never seen before.
- // 4. Everything else; first come, first served.
- while(ss >> buffer) {
- if (buffer.at(0) == '#') {
- std::get<0>(action) = "comment"; // tuple syntax is horrible!
- std::get<1>(action) = "";
- break;
- }
- else if (buffer == "program") {
- std::get<0>(action) = "program";
- ignore_names = true;
- continue;
- }
- else if (buffer == "end") {
- std::get<0>(action) = "end";
- std::get<1>(action) = "";
- break;
- }
- else if (buffer == "print") {
- std::get<0>(action) = "print";
- ignore_names = true;
- continue; // fill in the buffer with the remainder of the line.
- }
- else if (buffer == "writef") {
- std::get<0>(action) = "writef";
- ignore_names = true;
- continue;
- }
- else if (
- std::find(
- keywords.begin(), keywords.end(), buffer
- ) == keywords.end() && !ignore_names
- ) {
- // Not in the name database? GTFO!
- throw malio::NameError(buffer);
- }
- else {
- std::get<1>(action).append(buffer);
- std::get<1>(action).append(" ");
- }
- }
- return action;
- }
|