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!
答案 0 :(得分:1)
事实上,在我改变分支后
if ((x == ',' && x == ' '))
到
if ((x == ',' || x == ' ' || &x == &ProgLine.back()))
然后它有效。