// Arguments // [NAME] INPUTFILE STRINGTOTEST OUTPUTFILE int main (int argc, char *argv[]) { if (argc < 3) { cerr << "ERROR: Please provide at least 2 arguments. The file and a string to test. Example: TuringMachine TM.XML somestring" << endl; return 1; } Parser p = Parser(); TuringMachine tm = p.TMFromXML(argv[1]); if (argc > 3) { TMGrapher tmg = TMGrapher(tm); std::ofstream file; file.open(argv[3]); file << tmg.toDot(); } tm.currentTape = Tape(tm.blank, argv[2]); tm.run(); cout << tm.accepted(); return 0; }
int main(int argc, char** argv) { /* * Main container of states and rules. */ TuringMachine machine; /// Variables for options. OptionsContainer options; /// Printing messages. Printer printer(&options); options.interactive = true; options.echoMode = false; options.printLines = false; options.verbose = false; options.onlyBoard = false; options.printInitialTape = false; options.noSpaces = false; options.printHead = false; options.hideSteps = false; machine.setOptions(&options); machine.setPrinter(&printer); /* * Program arguments handling */ string _fileName; bool sourceLoaded = false; if (argc > 1) { string argument; for (int i=1; i<argc; ++i) { argument = argv[i]; // Version printing. if ( argument.compare("-n") == 0 || argument.compare("--version") == 0 ) { cout << VERSION << '\n'; return 0; // Echo mode - source code printing. } else if ( argument.compare("-e") == 0 || argument.compare("--echo") == 0 ) { options.echoMode = true; // Echo with lines numbers. } else if ( argument.compare("-l") == 0 || argument.compare("--echo-lines") == 0 ) { options.echoMode = true; options.printLines = true; // Be verbose. } else if (argument.compare("-v") == 0 || argument.compare("--verbose") == 0) { options.verbose = true; // Print the table and end the program. } else if (argument.compare("-b") == 0 || argument.compare("--board") == 0) { options.onlyBoard = true; // Print the intial tape. } else if (argument.compare("-i") == 0 || argument.compare("--print-initial-tape") == 0) { options.printInitialTape = true; // Print the tape without spaces. } else if (argument.compare("-s") == 0 || argument.compare("--no-spaces") == 0) { options.noSpaces = true; // Print help. } else if (argument.compare("-h") == 0 || argument.compare("--help") == 0) { printHelp(); return 0; // Hide step-by-step print. } else if (argument.compare("-d") == 0 || argument.compare("--head") == 0) { options.printHead = true; // Hide step-by-step print. } else if (argument.compare("-x") == 0 || argument.compare("--hide-steps") == 0) { options.hideSteps = true; // Unknown option - source file. } else if (not sourceLoaded) { // Try to open the file int source = open(argument.c_str(), ios::in); if (source < 0) { cout << "[E] No such source file or directory: '" << argument << "'.\n"; return 1; // Redirect standard input to file } else if ( dup2(source,0) < 0) { cout << "[E] Error reading source file '" << argument << "'.\n"; return 2; } // Done opening options.interactive = false; _fileName = argument; sourceLoaded = true; // If source loaded - tape file. } else { if (options.verbose) { printer.verbosePrint("Loading tape from file '" + argument + "'."); } machine.loadTape( argument ); } } } if (options.printInitialTape) machine.printTape(); /* * Interpreter startup - welcome message if interactive. */ if (options.interactive) { cout << "STuring " << VERSION << " - Simple Turing Machine interpreter.\n"; cout << _prompt; } /* * INTERPRETER */ string line; int _lineNumber = 1; string word; int found; int length; // Auxiliary variables string currentState = ""; // 0 - no state. 1 - first state set in while. int currentStateIndex = 0; string currentCharacter = ""; int currentCharacterIndex = 0; string currentWrite = ""; int currentWriteIndex = 0; string currentDirectionWord = ""; direction currentDirection = NONE; string currentJump = ""; int currentJumpIndex = 0; // Starting with first state interpretation: machineMode currentMode = STATE; int i; // Interpreting every line. while (getline(cin,line) && line.compare("\\exit") && line.compare("\\go") && line.compare("\\GO")) { // Before interpreting. if (options.echoMode) { if (options.printLines) { cout << _lineNumber << ": "; } cout << line << "\n"; } // Begin interpreting. // Every word in line. line += ' '; found = -1; length = 0; for (i = 0; i < line.size(); ++i) { if (found > -1) { if (isspace(line[i])) { word = line.substr(found,length); // If its a comment. if ( word[0] == '/' && word[1] == '/') { continue; } // Else, interpreting word. switch (currentMode) { // State definition. case STATE: if (word[length-1] == ':' ) { currentState = word.substr(0,length-1); currentStateIndex = machine.declareState(currentState); currentMode = MEETING; if (options.verbose) { printer.verbosePrint( "[NEW STATE DEF] Starting a new definition of the state '" + currentState + "'."); } } else { printer.printError(_fileName, _lineNumber, "Expected state definition beginning. Missing ':' symbol?"); } break; // Encounter of a character. case MEETING: currentCharacter = word; // Next state definition started. if ( word[length-1] == ':') { //TODO: No characters to encounter are given in state definition // and next state definition started - syntax error? currentState = word.substr(0,length-1); currentStateIndex = machine.declareState(currentState); currentMode = MEETING; if (options.verbose) { printer.verbosePrint( "[NEW STATE DEF] Starting a new definition of the state '" + currentState + "'."); } } else { // Check the index of character, or - if not exist - add to alphabet. currentCharacterIndex = machine.declareCharacter(currentCharacter); currentMode = WRITE; if (options.verbose) { printer.verbosePrint( "[MEETING] Starting a new rule with meeting the character '" + currentCharacter + "'."); } } break; case WRITE: currentWrite = word; if ( word.compare("\\=") == 0) { currentWriteIndex = -1; } else if ( word.compare("\\tape" ) == 0) { currentWriteIndex = 0; } else { currentWriteIndex = machine.declareCharacter(word); } currentMode = MOVE; if (options.verbose) { printer.verbosePrint("[WRITE] Setting to write a character '" + currentWrite + "' within this rule."); } break; case MOVE: currentDirectionWord = word; if ( word[0] == '>' || word[0] == 'P' || word[0] == 'p' || word[0] == 'R' || word[0] == 'r' || word.compare("\\right") == 0) { currentDirection = RIGHT; currentMode = JUMP; if (options.verbose) { printer.verbosePrint("[MOVE] Setting to move machine head right within this rule."); } } else if ( word[0] == '<' || word[0] == 'L' || word[0] == 'l' || word.compare("\\left") == 0) { currentDirection = LEFT; currentMode = JUMP; if (options.verbose) { printer.verbosePrint("[MOVE] Setting to move machine head left within this rule."); } } else if ( word[0] == '=' || word[0] == 'S' || word[0] == 's' || word.compare("\\stay") == 0) { currentDirection = STAY; currentMode = JUMP; if (options.verbose) { printer.verbosePrint("[MOVE] Setting to not move machine head within this rule."); } } break; case JUMP: currentJump = word; // Turn off machine. if ( word[0] == '^' || word[0] == ';' || word.compare("\\done") == 0) { currentJumpIndex = -1; if (options.verbose) { printer.verbosePrint("[JUMP] Setting to end the machine process within this rule."); } // Jump to the state. } else { currentJumpIndex = machine.declareState(currentJump); if (options.verbose) { printer.verbosePrint( "[JUMP] Setting to jump to the state '" + machine.getState(currentJumpIndex) + "' within this rule."); } } TuringStateRule newRule; newRule.write = currentWriteIndex; newRule.move = currentDirection; newRule.jump = currentJumpIndex; machine[ currentStateIndex ][ currentCharacterIndex ] = newRule; currentMode = MEETING; break; } // Word interpreted found = -1; length = 0; } else { ++length; } } else if (!isspace(line[i])) { found = i; ++length; } } // End interpreting // After interpreting if (options.interactive) { cout << _prompt; } ++_lineNumber; } // EOF or 'exit' command. if (options.onlyBoard) { machine.printBoard(); return 0; } if (!line.compare("\\exit")) { return 0; } // In this place everything indicates that we want to run our machine. if (machine.numberOfStates() > 0) { machine.run(); machine.printTape(); } return 0; }