This commit is contained in:
mrexodia 2016-11-22 09:37:09 +01:00
parent 87003fef8d
commit c8ca8305e2
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
4 changed files with 149 additions and 136 deletions

View File

@ -11,7 +11,7 @@ namespace AST
using uptr = unique_ptr<T>; using uptr = unique_ptr<T>;
template <class T, class... Args> template <class T, class... Args>
static typename enable_if<!is_array<T>::value, unique_ptr<T>>::type make_uptr(Args &&... args) static typename enable_if < !is_array<T>::value, unique_ptr<T >>::type make_uptr(Args && ... args)
{ {
return uptr<T>(new T(std::forward<Args>(args)...)); return uptr<T>(new T(std::forward<Args>(args)...));
} }

View File

@ -25,11 +25,11 @@ static const char* convertNumber(const char* str, uint64_t & result, int radix)
errno = 0; errno = 0;
char* end; char* end;
result = strtoull(str, &end, radix); result = strtoull(str, &end, radix);
if (!result && end == str) if(!result && end == str)
return "not a number"; return "not a number";
if (result == ULLONG_MAX && errno) if(result == ULLONG_MAX && errno)
return "does not fit"; return "does not fit";
if (*end) if(*end)
return "str not completely consumed"; return "str not completely consumed";
return nullptr; return nullptr;
} }
@ -54,17 +54,17 @@ void Lexer::SetInputData(const std::string & data)
bool Lexer::DoLexing(std::vector<TokenState> & tokens, std::string & error) bool Lexer::DoLexing(std::vector<TokenState> & tokens, std::string & error)
{ {
while (true) while(true)
{ {
auto token = getToken(); auto token = getToken();
mState.Token = token; mState.Token = token;
if (token == tok_error) if(token == tok_error)
{ {
error = StringUtils::sprintf("line %d, col %d: %s", mState.CurLine + 1, mState.LineIndex, mError.c_str()); error = StringUtils::sprintf("line %d, col %d: %s", mState.CurLine + 1, mState.LineIndex, mError.c_str());
return false; return false;
} }
tokens.push_back(mState); tokens.push_back(mState);
if (token == tok_eof) if(token == tok_eof)
break; break;
} }
return true; return true;
@ -73,7 +73,7 @@ bool Lexer::DoLexing(std::vector<TokenState> & tokens, std::string & error)
bool Lexer::Test(const std::function<void(const std::string & line)> & lexEnum, bool output) bool Lexer::Test(const std::function<void(const std::string & line)> & lexEnum, bool output)
{ {
size_t line = 0; size_t line = 0;
if (output) if(output)
lexEnum("1: "); lexEnum("1: ");
Token tok; Token tok;
std::string toks; std::string toks;
@ -82,10 +82,10 @@ bool Lexer::Test(const std::function<void(const std::string & line)> & lexEnum,
do do
{ {
tok = getToken(); tok = getToken();
if (!output) if(!output)
continue; continue;
toks.clear(); toks.clear();
while (line < mState.CurLine) while(line < mState.CurLine)
{ {
line++; line++;
sprintf_s(newlineText, "\n%d: ", line + 1); sprintf_s(newlineText, "\n%d: ", line + 1);
@ -94,11 +94,12 @@ bool Lexer::Test(const std::function<void(const std::string & line)> & lexEnum,
toks.append(TokString(tok)); toks.append(TokString(tok));
appendCh(toks, ' '); appendCh(toks, ' ');
lexEnum(toks); lexEnum(toks);
} while (tok != tok_eof && tok != tok_error); }
if (tok != tok_error && tok != tok_eof) while(tok != tok_eof && tok != tok_error);
if(tok != tok_error && tok != tok_eof)
tok = reportError("lexer did not finish at the end of the file"); tok = reportError("lexer did not finish at the end of the file");
for (const auto& warning : mWarnings) for(const auto & warning : mWarnings)
if (output) if(output)
lexEnum("\nwarning: " + warning); lexEnum("\nwarning: " + warning);
return tok != tok_error; return tok != tok_error;
} }
@ -106,76 +107,76 @@ bool Lexer::Test(const std::function<void(const std::string & line)> & lexEnum,
Lexer::Token Lexer::getToken() Lexer::Token Lexer::getToken()
{ {
//skip whitespace //skip whitespace
while (isspace(mLastChar)) while(isspace(mLastChar))
{ {
if (mLastChar == '\n') if(mLastChar == '\n')
signalNewLine(); signalNewLine();
nextChar(); nextChar();
} }
//skip \\[\r\n] //skip \\[\r\n]
if (mLastChar == '\\' && (peekChar() == '\r' || peekChar() == '\n')) if(mLastChar == '\\' && (peekChar() == '\r' || peekChar() == '\n'))
{ {
nextChar(); nextChar();
return getToken(); return getToken();
} }
//character literal //character literal
if (mLastChar == '\'') if(mLastChar == '\'')
{ {
std::string charLit; std::string charLit;
while (true) while(true)
{ {
nextChar(); nextChar();
if (mLastChar == EOF) //end of file if(mLastChar == EOF) //end of file
return reportError("unexpected end of file in character literal (1)"); return reportError("unexpected end of file in character literal (1)");
if (mLastChar == '\r' || mLastChar == '\n') if(mLastChar == '\r' || mLastChar == '\n')
return reportError("unexpected newline in character literal (1)"); return reportError("unexpected newline in character literal (1)");
if (mLastChar == '\'') //end of character literal if(mLastChar == '\'') //end of character literal
{ {
if (charLit.length() != 1) if(charLit.length() != 1)
return reportError(StringUtils::sprintf("invalid character literal '%s'", charLit.c_str())); return reportError(StringUtils::sprintf("invalid character literal '%s'", charLit.c_str()));
mState.CharLit = charLit[0]; mState.CharLit = charLit[0];
nextChar(); nextChar();
return tok_charlit; return tok_charlit;
} }
if (mLastChar == '\\') //escape sequence if(mLastChar == '\\') //escape sequence
{ {
nextChar(); nextChar();
if (mLastChar == EOF) if(mLastChar == EOF)
return reportError("unexpected end of file in character literal (2)"); return reportError("unexpected end of file in character literal (2)");
if (mLastChar == '\r' || mLastChar == '\n') if(mLastChar == '\r' || mLastChar == '\n')
return reportError("unexpected newline in character literal (2)"); return reportError("unexpected newline in character literal (2)");
if (mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\') if(mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\')
mLastChar = mLastChar; mLastChar = mLastChar;
else if (mLastChar == 'a') else if(mLastChar == 'a')
mLastChar = '\a'; mLastChar = '\a';
else if (mLastChar == 'b') else if(mLastChar == 'b')
mLastChar = '\b'; mLastChar = '\b';
else if (mLastChar == 'f') else if(mLastChar == 'f')
mLastChar = '\f'; mLastChar = '\f';
else if (mLastChar == 'n') else if(mLastChar == 'n')
mLastChar = '\n'; mLastChar = '\n';
else if (mLastChar == 'r') else if(mLastChar == 'r')
mLastChar = '\r'; mLastChar = '\r';
else if (mLastChar == 't') else if(mLastChar == 't')
mLastChar = '\t'; mLastChar = '\t';
else if (mLastChar == 'v') else if(mLastChar == 'v')
mLastChar = '\v'; mLastChar = '\v';
else if (mLastChar == '0') else if(mLastChar == '0')
mLastChar = '\0'; mLastChar = '\0';
else if (mLastChar == 'x') //\xHH else if(mLastChar == 'x') //\xHH
{ {
auto ch1 = nextChar(); auto ch1 = nextChar();
auto ch2 = nextChar(); auto ch2 = nextChar();
if (isxdigit(ch1) && isxdigit(ch2)) if(isxdigit(ch1) && isxdigit(ch2))
{ {
char byteStr[3] = ""; char byteStr[3] = "";
byteStr[0] = ch1; byteStr[0] = ch1;
byteStr[1] = ch2; byteStr[1] = ch2;
uint64_t hexData; uint64_t hexData;
auto error = convertNumber(byteStr, hexData, 16); auto error = convertNumber(byteStr, hexData, 16);
if (error) if(error)
return reportError(StringUtils::sprintf("convertNumber failed (%s) for hex sequence \"\\x%c%c\" in character literal", error, ch1, ch2)); return reportError(StringUtils::sprintf("convertNumber failed (%s) for hex sequence \"\\x%c%c\" in character literal", error, ch1, ch2));
mLastChar = hexData & 0xFF; mLastChar = hexData & 0xFF;
} }
@ -190,58 +191,58 @@ Lexer::Token Lexer::getToken()
} }
//string literal //string literal
if (mLastChar == '\"') if(mLastChar == '\"')
{ {
mState.StringLit.clear(); mState.StringLit.clear();
while (true) while(true)
{ {
nextChar(); nextChar();
if (mLastChar == EOF) //end of file if(mLastChar == EOF) //end of file
return reportError("unexpected end of file in string literal (1)"); return reportError("unexpected end of file in string literal (1)");
if (mLastChar == '\r' || mLastChar == '\n') if(mLastChar == '\r' || mLastChar == '\n')
return reportError("unexpected newline in string literal (1)"); return reportError("unexpected newline in string literal (1)");
if (mLastChar == '\"') //end of string literal if(mLastChar == '\"') //end of string literal
{ {
nextChar(); nextChar();
return tok_stringlit; return tok_stringlit;
} }
if (mLastChar == '\\') //escape sequence if(mLastChar == '\\') //escape sequence
{ {
nextChar(); nextChar();
if (mLastChar == EOF) if(mLastChar == EOF)
return reportError("unexpected end of file in string literal (2)"); return reportError("unexpected end of file in string literal (2)");
if (mLastChar == '\r' || mLastChar == '\n') if(mLastChar == '\r' || mLastChar == '\n')
return reportError("unexpected newline in string literal (2)"); return reportError("unexpected newline in string literal (2)");
if (mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\') if(mLastChar == '\'' || mLastChar == '\"' || mLastChar == '?' || mLastChar == '\\')
mLastChar = mLastChar; mLastChar = mLastChar;
else if (mLastChar == 'a') else if(mLastChar == 'a')
mLastChar = '\a'; mLastChar = '\a';
else if (mLastChar == 'b') else if(mLastChar == 'b')
mLastChar = '\b'; mLastChar = '\b';
else if (mLastChar == 'f') else if(mLastChar == 'f')
mLastChar = '\f'; mLastChar = '\f';
else if (mLastChar == 'n') else if(mLastChar == 'n')
mLastChar = '\n'; mLastChar = '\n';
else if (mLastChar == 'r') else if(mLastChar == 'r')
mLastChar = '\r'; mLastChar = '\r';
else if (mLastChar == 't') else if(mLastChar == 't')
mLastChar = '\t'; mLastChar = '\t';
else if (mLastChar == 'v') else if(mLastChar == 'v')
mLastChar = '\v'; mLastChar = '\v';
else if (mLastChar == '0') else if(mLastChar == '0')
mLastChar = '\0'; mLastChar = '\0';
else if (mLastChar == 'x') //\xHH else if(mLastChar == 'x') //\xHH
{ {
auto ch1 = nextChar(); auto ch1 = nextChar();
auto ch2 = nextChar(); auto ch2 = nextChar();
if (isxdigit(ch1) && isxdigit(ch2)) if(isxdigit(ch1) && isxdigit(ch2))
{ {
char byteStr[3] = ""; char byteStr[3] = "";
byteStr[0] = ch1; byteStr[0] = ch1;
byteStr[1] = ch2; byteStr[1] = ch2;
uint64_t hexData; uint64_t hexData;
auto error = convertNumber(byteStr, hexData, 16); auto error = convertNumber(byteStr, hexData, 16);
if (error) if(error)
return reportError(StringUtils::sprintf("convertNumber failed (%s) for hex sequence \"\\x%c%c\" in string literal", error, ch1, ch2)); return reportError(StringUtils::sprintf("convertNumber failed (%s) for hex sequence \"\\x%c%c\" in string literal", error, ch1, ch2));
mLastChar = hexData & 0xFF; mLastChar = hexData & 0xFF;
} }
@ -256,11 +257,11 @@ Lexer::Token Lexer::getToken()
} }
//identifier/keyword //identifier/keyword
if (isalpha(mLastChar) || mLastChar == '_') //[a-zA-Z_] if(isalpha(mLastChar) || mLastChar == '_') //[a-zA-Z_]
{ {
mState.IdentifierStr = mLastChar; mState.IdentifierStr = mLastChar;
nextChar(); nextChar();
while (isalnum(mLastChar) || mLastChar == '_') //[0-9a-zA-Z_] while(isalnum(mLastChar) || mLastChar == '_') //[0-9a-zA-Z_]
{ {
appendCh(mState.IdentifierStr, mLastChar); appendCh(mState.IdentifierStr, mLastChar);
nextChar(); nextChar();
@ -268,66 +269,68 @@ Lexer::Token Lexer::getToken()
//keywords //keywords
auto found = mKeywordMap.find(mState.IdentifierStr); auto found = mKeywordMap.find(mState.IdentifierStr);
if (found != mKeywordMap.end()) if(found != mKeywordMap.end())
return found->second; return found->second;
return tok_identifier; return tok_identifier;
} }
//hex numbers //hex numbers
if (mLastChar == '0' && peekChar() == 'x') //0x if(mLastChar == '0' && peekChar() == 'x') //0x
{ {
nextChar(); //consume the 'x' nextChar(); //consume the 'x'
mNumStr.clear(); mNumStr.clear();
while (isxdigit(nextChar())) //[0-9a-fA-F]* while(isxdigit(nextChar())) //[0-9a-fA-F]*
appendCh(mNumStr, mLastChar); appendCh(mNumStr, mLastChar);
if (!mNumStr.length()) //check for error condition if(!mNumStr.length()) //check for error condition
return reportError("no hex digits after \"0x\" prefix"); return reportError("no hex digits after \"0x\" prefix");
auto error = convertNumber(mNumStr.c_str(), mState.NumberVal, 16); auto error = convertNumber(mNumStr.c_str(), mState.NumberVal, 16);
if (error) if(error)
return reportError(StringUtils::sprintf("convertNumber failed (%s) on hexadecimal number", error)); return reportError(StringUtils::sprintf("convertNumber failed (%s) on hexadecimal number", error));
mIsHexNumberVal = true; mIsHexNumberVal = true;
return tok_number; return tok_number;
} }
if (isdigit(mLastChar)) //[0-9] if(isdigit(mLastChar)) //[0-9]
{ {
mNumStr = mLastChar; mNumStr = mLastChar;
while (isdigit(nextChar())) //[0-9]* while(isdigit(nextChar())) //[0-9]*
mNumStr += mLastChar; mNumStr += mLastChar;
auto error = convertNumber(mNumStr.c_str(), mState.NumberVal, 10); auto error = convertNumber(mNumStr.c_str(), mState.NumberVal, 10);
if (error) if(error)
return reportError(StringUtils::sprintf("convertNumber failed (%s) on decimal number", error)); return reportError(StringUtils::sprintf("convertNumber failed (%s) on decimal number", error));
mIsHexNumberVal = false; mIsHexNumberVal = false;
return tok_number; return tok_number;
} }
//comments //comments
if (mLastChar == '/' && peekChar() == '/') //line comment if(mLastChar == '/' && peekChar() == '/') //line comment
{ {
do do
{ {
if (mLastChar == '\n') if(mLastChar == '\n')
signalNewLine(); signalNewLine();
nextChar(); nextChar();
} while (!(mLastChar == EOF || mLastChar == '\n')); }
while(!(mLastChar == EOF || mLastChar == '\n'));
return getToken(); //interpret the next line return getToken(); //interpret the next line
} }
if (mLastChar == '/' && peekChar() == '*') //block comment if(mLastChar == '/' && peekChar() == '*') //block comment
{ {
do do
{ {
if (mLastChar == '\n') if(mLastChar == '\n')
signalNewLine(); signalNewLine();
nextChar(); nextChar();
} while (!(mLastChar == EOF || mLastChar == '*' && peekChar() == '/')); }
while(!(mLastChar == EOF || mLastChar == '*' && peekChar() == '/'));
if (mLastChar == EOF) //unexpected end of file if(mLastChar == EOF) //unexpected end of file
{ {
mState.LineIndex++; mState.LineIndex++;
return reportError("unexpected end of file in block comment"); return reportError("unexpected end of file in block comment");
@ -340,7 +343,7 @@ Lexer::Token Lexer::getToken()
//operators //operators
auto opFound = mOpTripleMap.find(MAKE_OP_TRIPLE(mLastChar, peekChar(), peekChar(1))); auto opFound = mOpTripleMap.find(MAKE_OP_TRIPLE(mLastChar, peekChar(), peekChar(1)));
if (opFound != mOpTripleMap.end()) if(opFound != mOpTripleMap.end())
{ {
nextChar(); nextChar();
nextChar(); nextChar();
@ -348,21 +351,21 @@ Lexer::Token Lexer::getToken()
return opFound->second; return opFound->second;
} }
opFound = mOpDoubleMap.find(MAKE_OP_DOUBLE(mLastChar, peekChar())); opFound = mOpDoubleMap.find(MAKE_OP_DOUBLE(mLastChar, peekChar()));
if (opFound != mOpDoubleMap.end()) if(opFound != mOpDoubleMap.end())
{ {
nextChar(); nextChar();
nextChar(); nextChar();
return opFound->second; return opFound->second;
} }
opFound = mOpSingleMap.find(MAKE_OP_SINGLE(mLastChar)); opFound = mOpSingleMap.find(MAKE_OP_SINGLE(mLastChar));
if (opFound != mOpSingleMap.end()) if(opFound != mOpSingleMap.end())
{ {
nextChar(); nextChar();
return opFound->second; return opFound->second;
} }
//end of file //end of file
if (mLastChar == EOF) if(mLastChar == EOF)
return tok_eof; return tok_eof;
//unknown character //unknown character
@ -437,11 +440,16 @@ std::string Lexer::TokString(const TokenState & ts)
{ {
switch(ts.Token) switch(ts.Token)
{ {
case tok_eof: return "tok_eof"; case tok_eof:
case tok_error: return StringUtils::sprintf("error(line %d, col %d, \"%s\")", ts.CurLine + 1, ts.LineIndex, mError.c_str()); return "tok_eof";
case tok_identifier: return ts.IdentifierStr; case tok_error:
case tok_number: return StringUtils::sprintf(mIsHexNumberVal ? "0x%llX" : "%llu", ts.NumberVal); return StringUtils::sprintf("error(line %d, col %d, \"%s\")", ts.CurLine + 1, ts.LineIndex, mError.c_str());
case tok_stringlit: return StringUtils::sprintf("\"%s\"", StringUtils::Escape(ts.StringLit).c_str()); case tok_identifier:
return ts.IdentifierStr;
case tok_number:
return StringUtils::sprintf(mIsHexNumberVal ? "0x%llX" : "%llu", ts.NumberVal);
case tok_stringlit:
return StringUtils::sprintf("\"%s\"", StringUtils::Escape(ts.StringLit).c_str());
case tok_charlit: case tok_charlit:
{ {
std::string s; std::string s;
@ -460,13 +468,18 @@ std::string Lexer::TokString(const TokenState & ts)
std::string Lexer::TokString(Token tok) std::string Lexer::TokString(Token tok)
{ {
switch (tok) switch(tok)
{ {
case tok_eof: return "tok_eof"; case tok_eof:
case tok_error: return StringUtils::sprintf("error(line %d, col %d, \"%s\")", mState.CurLine + 1, mState.LineIndex, mError.c_str()); return "tok_eof";
case tok_identifier: return mState.IdentifierStr; case tok_error:
case tok_number: return StringUtils::sprintf(mIsHexNumberVal ? "0x%llX" : "%llu", mState.NumberVal); return StringUtils::sprintf("error(line %d, col %d, \"%s\")", mState.CurLine + 1, mState.LineIndex, mError.c_str());
case tok_stringlit: return StringUtils::sprintf("\"%s\"", StringUtils::Escape(mState.StringLit).c_str()); case tok_identifier:
return mState.IdentifierStr;
case tok_number:
return StringUtils::sprintf(mIsHexNumberVal ? "0x%llX" : "%llu", mState.NumberVal);
case tok_stringlit:
return StringUtils::sprintf("\"%s\"", StringUtils::Escape(mState.StringLit).c_str());
case tok_charlit: case tok_charlit:
{ {
std::string s; std::string s;
@ -476,7 +489,7 @@ std::string Lexer::TokString(Token tok)
default: default:
{ {
auto found = mReverseTokenMap.find(Token(tok)); auto found = mReverseTokenMap.find(Token(tok));
if (found != mReverseTokenMap.end()) if(found != mReverseTokenMap.end())
return found->second; return found->second;
return "<UNKNOWN TOKEN>"; return "<UNKNOWN TOKEN>";
} }
@ -485,10 +498,10 @@ std::string Lexer::TokString(Token tok)
int Lexer::peekChar(size_t distance) int Lexer::peekChar(size_t distance)
{ {
if (mIndex + distance >= mInput.size()) if(mIndex + distance >= mInput.size())
return EOF; return EOF;
auto ch = mInput[mIndex + distance]; auto ch = mInput[mIndex + distance];
if (ch == '\0') if(ch == '\0')
{ {
reportWarning(StringUtils::sprintf("\\0 character in file data")); reportWarning(StringUtils::sprintf("\\0 character in file data"));
return peekChar(distance + 1); return peekChar(distance + 1);
@ -498,11 +511,11 @@ int Lexer::peekChar(size_t distance)
int Lexer::readChar() int Lexer::readChar()
{ {
if (mIndex == mInput.size()) if(mIndex == mInput.size())
return EOF; return EOF;
auto ch = mInput[mIndex++]; auto ch = mInput[mIndex++];
mState.LineIndex++; mState.LineIndex++;
if (ch == '\0') if(ch == '\0')
{ {
reportWarning(StringUtils::sprintf("\\0 character in file data")); reportWarning(StringUtils::sprintf("\\0 character in file data"));
return readChar(); return readChar();
@ -512,12 +525,12 @@ int Lexer::readChar()
bool Lexer::checkString(const std::string & expected) bool Lexer::checkString(const std::string & expected)
{ {
for (size_t i = 0; i < expected.size(); i++) for(size_t i = 0; i < expected.size(); i++)
{ {
auto ch = peekChar(i); auto ch = peekChar(i);
if (ch == EOF) if(ch == EOF)
return false; return false;
if (ch != uint8_t(expected[i])) if(ch != uint8_t(expected[i]))
return false; return false;
} }
mIndex += expected.size(); mIndex += expected.size();

View File

@ -7,7 +7,7 @@
bool TestLexer(Lexer & lexer, const std::string & filename) bool TestLexer(Lexer & lexer, const std::string & filename)
{ {
if (!lexer.ReadInputFile("tests\\" + filename)) if(!lexer.ReadInputFile("tests\\" + filename))
{ {
printf("failed to read \"%s\"\n", filename.c_str()); printf("failed to read \"%s\"\n", filename.c_str());
return false; return false;
@ -19,12 +19,12 @@ bool TestLexer(Lexer & lexer, const std::string & filename)
actual.append(line); actual.append(line);
}); });
std::string expected; std::string expected;
if (FileHelper::ReadAllText("tests\\exp_lex\\" + filename, expected) && expected == actual) if(FileHelper::ReadAllText("tests\\exp_lex\\" + filename, expected) && expected == actual)
{ {
printf("lexer test for \"%s\" success!\n", filename.c_str()); printf("lexer test for \"%s\" success!\n", filename.c_str());
return true; return true;
} }
if (success) if(success)
return true; return true;
printf("lexer test for \"%s\" failed...\n", filename.c_str()); printf("lexer test for \"%s\" failed...\n", filename.c_str());
FileHelper::WriteAllText("expected.out", expected); FileHelper::WriteAllText("expected.out", expected);
@ -34,7 +34,7 @@ bool TestLexer(Lexer & lexer, const std::string & filename)
bool DebugLexer(Lexer & lexer, const std::string & filename, bool output) bool DebugLexer(Lexer & lexer, const std::string & filename, bool output)
{ {
if (!lexer.ReadInputFile("tests\\" + filename)) if(!lexer.ReadInputFile("tests\\" + filename))
{ {
printf("failed to read \"%s\"\n", filename.c_str()); printf("failed to read \"%s\"\n", filename.c_str());
return false; return false;
@ -43,14 +43,14 @@ bool DebugLexer(Lexer & lexer, const std::string & filename, bool output)
{ {
printf("%s", line.c_str()); printf("%s", line.c_str());
}, output); }, output);
if (output) if(output)
puts(""); puts("");
return success; return success;
} }
void GenerateExpected(Lexer & lexer, const std::string & filename) void GenerateExpected(Lexer & lexer, const std::string & filename)
{ {
if (!lexer.ReadInputFile("tests\\" + filename)) if(!lexer.ReadInputFile("tests\\" + filename))
{ {
printf("failed to read \"%s\"\n", filename.c_str()); printf("failed to read \"%s\"\n", filename.c_str());
return; return;
@ -67,21 +67,21 @@ void GenerateExpected(Lexer & lexer, const std::string & filename)
void GenerateExpectedTests() void GenerateExpectedTests()
{ {
Lexer lexer; Lexer lexer;
for (auto file : testFiles) for(auto file : testFiles)
GenerateExpected(lexer, file); GenerateExpected(lexer, file);
} }
void RunLexerTests() void RunLexerTests()
{ {
Lexer lexer; Lexer lexer;
for (auto file : testFiles) for(auto file : testFiles)
TestLexer(lexer, file); TestLexer(lexer, file);
} }
void DebugLexerTests(bool output = true) void DebugLexerTests(bool output = true)
{ {
Lexer lexer; Lexer lexer;
for (auto file : testFiles) for(auto file : testFiles)
DebugLexer(lexer, file, output); DebugLexer(lexer, file, output);
} }

View File

@ -9,12 +9,12 @@ Parser::Parser()
bool Parser::ParseFile(const string & filename, string & error) bool Parser::ParseFile(const string & filename, string & error)
{ {
if (!mLexer.ReadInputFile(filename)) if(!mLexer.ReadInputFile(filename))
{ {
error = "failed to read input file"; error = "failed to read input file";
return false; return false;
} }
if (!mLexer.DoLexing(mTokens, error)) if(!mLexer.DoLexing(mTokens, error))
return false; return false;
CurToken = mTokens[0]; CurToken = mTokens[0];
mBinaryTemplate = ParseBinaryTemplate(); mBinaryTemplate = ParseBinaryTemplate();
@ -23,7 +23,7 @@ bool Parser::ParseFile(const string & filename, string & error)
void Parser::NextToken() void Parser::NextToken()
{ {
if (mIndex < mTokens.size() - 1) if(mIndex < mTokens.size() - 1)
{ {
mIndex++; mIndex++;
CurToken = mTokens[mIndex]; CurToken = mTokens[mIndex];
@ -38,30 +38,30 @@ void Parser::ReportError(const std::string & error)
uptr<Block> Parser::ParseBinaryTemplate() uptr<Block> Parser::ParseBinaryTemplate()
{ {
vector<uptr<StatDecl>> statDecls; vector<uptr<StatDecl>> statDecls;
while (true) while(true)
{ {
auto statDecl = ParseStatDecl(); auto statDecl = ParseStatDecl();
if (!statDecl) if(!statDecl)
break; break;
statDecls.push_back(move(statDecl)); statDecls.push_back(move(statDecl));
} }
auto binaryTemplate = make_uptr<Block>(move(statDecls)); auto binaryTemplate = make_uptr<Block>(move(statDecls));
if (CurToken.Token != Lexer::tok_eof) if(CurToken.Token != Lexer::tok_eof)
{ {
ReportError("last token is not EOF"); ReportError("last token is not EOF");
return nullptr; return nullptr;
} }
return move(binaryTemplate); return move(binaryTemplate);
} }
uptr<StatDecl> Parser::ParseStatDecl() uptr<StatDecl> Parser::ParseStatDecl()
{ {
auto decl = ParseDecl(); auto decl = ParseDecl();
if (decl) if(decl)
return move(decl); return move(decl);
auto stat = ParseStat(); auto stat = ParseStat();
if (stat) if(stat)
return move(stat); return move(stat);
ReportError("failed to parse StatDecl"); ReportError("failed to parse StatDecl");
@ -71,15 +71,15 @@ uptr<StatDecl> Parser::ParseStatDecl()
uptr<Stat> Parser::ParseStat() uptr<Stat> Parser::ParseStat()
{ {
auto block = ParseBlock(); auto block = ParseBlock();
if (block) if(block)
return move(block); return move(block);
auto expr = ParseExpr(); auto expr = ParseExpr();
if (expr) if(expr)
return move(expr); return move(expr);
auto ret = ParseReturn(); auto ret = ParseReturn();
if (ret) if(ret)
return move(ret); return move(ret);
ReportError("failed to parse Stat"); ReportError("failed to parse Stat");
@ -88,13 +88,13 @@ uptr<Stat> Parser::ParseStat()
uptr<Block> Parser::ParseBlock() uptr<Block> Parser::ParseBlock()
{ {
if (CurToken.Token != Lexer::tok_bropen) //'{' if(CurToken.Token != Lexer::tok_bropen) //'{'
return nullptr; return nullptr;
NextToken(); NextToken();
vector<uptr<StatDecl>> statDecls; vector<uptr<StatDecl>> statDecls;
if (CurToken.Token == Lexer::tok_brclose) //'}' if(CurToken.Token == Lexer::tok_brclose) //'}'
{ {
NextToken(); NextToken();
return make_uptr<Block>(move(statDecls)); return make_uptr<Block>(move(statDecls));
@ -111,11 +111,11 @@ uptr<Expr> Parser::ParseExpr()
uptr<Return> Parser::ParseReturn() uptr<Return> Parser::ParseReturn()
{ {
if (CurToken.Token == Lexer::tok_return) if(CurToken.Token == Lexer::tok_return)
{ {
NextToken(); NextToken();
auto expr = ParseExpr(); auto expr = ParseExpr();
if (!expr) if(!expr)
{ {
ReportError("failed to parse Return (ParseExpr failed)"); ReportError("failed to parse Return (ParseExpr failed)");
return nullptr; return nullptr;
@ -128,28 +128,28 @@ uptr<Return> Parser::ParseReturn()
uptr<Decl> Parser::ParseDecl() uptr<Decl> Parser::ParseDecl()
{ {
auto builtin = ParseBuiltinVar(); auto builtin = ParseBuiltinVar();
if (builtin) if(builtin)
return move(builtin); return move(builtin);
auto stru = ParseStruct(); auto stru = ParseStruct();
if (stru) if(stru)
return move(stru); return move(stru);
return nullptr; return nullptr;
} }
uptr<BuiltinVar> Parser::ParseBuiltinVar() uptr<BuiltinVar> Parser::ParseBuiltinVar()
{ {
if (CurToken.Token == Lexer::tok_uint) //TODO: properly handle types if(CurToken.Token == Lexer::tok_uint) //TODO: properly handle types
{ {
auto type = CurToken.Token; auto type = CurToken.Token;
NextToken(); NextToken();
if (CurToken.Token != Lexer::tok_identifier) if(CurToken.Token != Lexer::tok_identifier)
{ {
ReportError("failed to parse BuiltinVar (no identifier)"); ReportError("failed to parse BuiltinVar (no identifier)");
return nullptr; return nullptr;
} }
auto id = CurToken.IdentifierStr; auto id = CurToken.IdentifierStr;
NextToken(); NextToken();
if (CurToken.Token != Lexer::tok_semic) if(CurToken.Token != Lexer::tok_semic)
{ {
ReportError("failed to parse BuiltinVar (no semicolon)"); ReportError("failed to parse BuiltinVar (no semicolon)");
return nullptr; return nullptr;
@ -162,17 +162,17 @@ uptr<BuiltinVar> Parser::ParseBuiltinVar()
uptr<Struct> Parser::ParseStruct() uptr<Struct> Parser::ParseStruct()
{ {
if (CurToken.Token == Lexer::tok_struct) if(CurToken.Token == Lexer::tok_struct)
{ {
NextToken(); NextToken();
string id; string id;
if (CurToken.Token == Lexer::tok_identifier) if(CurToken.Token == Lexer::tok_identifier)
{ {
id = CurToken.IdentifierStr; id = CurToken.IdentifierStr;
NextToken(); NextToken();
} }
auto block = ParseBlock(); auto block = ParseBlock();
if (!block) if(!block)
{ {
ReportError("failed to parse Struct (ParseBlock)"); ReportError("failed to parse Struct (ParseBlock)");
return nullptr; return nullptr;