lexer keeps skiping the final token

时间:2017-04-10 01:23:43

标签: c++ assembly lexer chip-8

So no I'm creating a lexer for Chip-8 assembly using C++ ,but it always skips the third token.

E.G.(My function reads one line of assembly)

ADD V1,V2

It only finds ADD , V1 as a token,skips V2; same

DRW V3,V4,2

It only finds DRW,V3,V4 where am I wrong?

#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <exception>
#include <iostream>
#include <iterator>
static std::string C8InsTable[] = {"ADD", "SUB",  "SUBN", "AND", "OR", "XOR",
     "SE",  "SNE",  "SYS",  "JP",  "LD", "DRW",
     "SKP", "CALL", "CLS",  "RET"}; //Instruction Table
static const std::string C88BitReg[] = {"V1", "V2", "V3", "V4", "V5",
          "V6", "V7", "V8", "V9", "VA",
          "VB", "VC", "VD", "VE", "VF"}; //Name of Regsiters
//Define Exceptions
class LexEmptyExc : public std::runtime_error {
public:
    LexEmptyExc() : runtime_error("Empty Line."){};
    virtual const char* what() const throw() { return runtime_error::what();}
} LexEE;
class LexErrorVar : public std::runtime_error {
public:
    LexErrorVar()
    : runtime_error("Error var type.Out of range or not a valid var."){};
    virtual const char* what() const throw() { 
      return runtime_error::what();}}LexEV;

class LexErrorToken : public std::runtime_error {
public:
  LexErrorToken() : runtime_error("Error Token."){};
  virtual const char* what() const throw() { return runtime_error::what(); }
  } LexET;
//To write Log (Test purpose)
bool LexerLogWriter(std::string LogLine, std::ofstream& LexerLogFile) {
  if (!LexerLogFile.good())
    return false;
  else {
    LexerLogFile << LogLine;
    return true;
  }
 };
//It returns Tokens into a string vector
std::vector<std::string> lexer(std::string ProgLine,
 std::ofstream& LexerLogFile) {
  try {
  if (ProgLine.length() == 0) throw LexEE;
  bool IsVar = false;
  bool Is8BitReg = false;
  bool IsIns = false;
  std::stringstream LogStream;
  std::string Token("");
  std::string Var("");
  std::vector<std::string> TokenList;
  std::string param("");
  for (auto& x : ProgLine) {
    std::string LogType;
    if ((x != ',' && x != ' ')){ //Skip spaces and commas
      Token += x;
      std::cout << "Now Token is " << Token << "(lexing)" << std::endl;
    } else{
      if (find(std::begin(C8InsTable), std::end(C8InsTable), Token) !=std::end(C8InsTable)) {  //Find Instruction
        LogType = "Instruction";
    } else if (find(std::begin(C88BitReg), std::end(C88BitReg), Token) !=std::end(C88BitReg)) {
        LogType = "8 Bit Register";
    } else if (Token == "DT") {
        LogType = "Delay Timer";
    } else if (Token == "ST") {
      LogType = "Sound Timer";
    } else if (Token == "I") {
    LogType = "Address Register";
    } else {
        if (Token.length() <= 4) { //4~16bitvar
        LogType = "Var";
        } else { //Var bigger than 16bit-max
          LogStream << "Error:Invalid var exist." << std::endl;
          throw LexEE;
          }
      }
      std::cout << "Now Token is " << Token << "(not lexing)" << std::endl;
      if (!LogType.empty()) { //Is correct token
      LogStream << LogType << " found: " << Token << std::endl;
      LogType = "";
      std::cout << "Pushing " << Token << "..." << std::endl;
      TokenList.push_back(Token);
      Token = ""; //clear the string to store next one
    }
  }
}
  if (!LogStream.str().empty() && LexerLogFile.good())
    LexerLogWriter(LogStream.str(), LexerLogFile); //Write logs
    return TokenList;
  } catch (std::exception& e) {
    std::cerr << "Error occured!Error info: " << e.what() << std::endl;
  }
  }
//Test Main Func
int main() {
std::ofstream a("Test.log"); //Output log file
std::ifstream b("test.asm"); //Infile
for (std::string s; getline(b, s, '\n');)
for (auto x : lexer(s, a)) std::cout << x << std::endl;
  return 0;
}

Thanks!

1 个答案:

答案 0 :(得分:1)

事实上,在我改变分支后

if ((x == ',' && x == ' ')) 

if ((x == ',' || x == ' ' || &x == &ProgLine.back()))

然后它有效。