implement enough of a lexer to get through Olden/health/Output/health.llc.s

without errors.

llvm-svn: 73855
This commit is contained in:
Chris Lattner 2009-06-21 19:21:25 +00:00
parent 99b57fb987
commit d0765617d2
3 changed files with 184 additions and 10 deletions

View File

@ -14,6 +14,7 @@
#include "AsmLexer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cerrno>
using namespace llvm;
AsmLexer::AsmLexer(SourceMgr &SM) : SrcMgr(SM) {
@ -23,6 +24,10 @@ AsmLexer::AsmLexer(SourceMgr &SM) : SrcMgr(SM) {
TokStart = 0;
}
SMLoc AsmLexer::getLoc() const {
return SMLoc::getFromPointer(TokStart);
}
void AsmLexer::PrintError(const char *Loc, const std::string &Msg) const {
SrcMgr.PrintError(SMLoc::getFromPointer(Loc), Msg);
}
@ -31,6 +36,13 @@ void AsmLexer::PrintError(SMLoc Loc, const std::string &Msg) const {
SrcMgr.PrintError(Loc, Msg);
}
/// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return asmtok::Error.
asmtok::TokKind AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
PrintError(Loc, Msg);
return asmtok::Error;
}
int AsmLexer::getNextChar() {
char CurChar = *CurPtr++;
switch (CurChar) {
@ -59,6 +71,129 @@ int AsmLexer::getNextChar() {
}
}
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
asmtok::TokKind AsmLexer::LexIdentifier() {
while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
*CurPtr == '.' || *CurPtr == '@')
++CurPtr;
CurStrVal.assign(TokStart, CurPtr); // Skip %
return asmtok::Identifier;
}
/// LexPercent: Register: %[a-zA-Z0-9]+
asmtok::TokKind AsmLexer::LexPercent() {
if (!isalnum(*CurPtr))
return asmtok::Error; // Must have at least one character.
while (isalnum(*CurPtr))
++CurPtr;
CurStrVal.assign(TokStart, CurPtr); // Skip %
return asmtok::Register;
}
/// LexSlash: Slash: /
/// C-Style Comment: /* ... */
asmtok::TokKind AsmLexer::LexSlash() {
if (*CurPtr != '*')
return asmtok::Slash;
// C Style comment.
++CurPtr; // skip the star.
while (1) {
int CurChar = getNextChar();
switch (CurChar) {
case EOF:
PrintError(TokStart, "Unterminated comment!");
return asmtok::Error;
case '*':
// End of the comment?
if (CurPtr[0] != '/') break;
++CurPtr; // End the */.
return LexToken();
}
}
}
/// LexHash: Comment: #[^\n]*
asmtok::TokKind AsmLexer::LexHash() {
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF)
CurChar = getNextChar();
if (CurChar == EOF)
return asmtok::Eof;
return asmtok::EndOfStatement;
}
/// LexDigit: First character is [0-9].
/// Local Label: [0-9][:]
/// Forward/Backward Label: [0-9][fb]
/// Binary integer: 0b[01]+
/// Octal integer: 0[0-7]+
/// Hex integer: 0x[0-9a-fA-F]+
/// Decimal integer: [1-9][0-9]*
/// TODO: FP literal.
asmtok::TokKind AsmLexer::LexDigit() {
if (*CurPtr == ':')
return asmtok::Error; // FIXME LOCAL LABEL.
if (*CurPtr == 'f' || *CurPtr == 'b')
return asmtok::Error; // FIXME FORWARD/BACKWARD LABEL.
// Decimal integer: [1-9][0-9]*
if (CurPtr[-1] != '0') {
while (isdigit(*CurPtr))
++CurPtr;
CurIntVal = strtoll(TokStart, 0, 10);
return asmtok::IntVal;
}
if (*CurPtr == 'b') {
++CurPtr;
const char *NumStart = CurPtr;
while (CurPtr[0] == '0' || CurPtr[0] == '1')
++CurPtr;
// Requires at least one binary digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "Invalid binary number");
CurIntVal = strtoll(NumStart, 0, 2);
return asmtok::IntVal;
}
if (*CurPtr == 'x') {
++CurPtr;
const char *NumStart = CurPtr;
while (isxdigit(CurPtr[0]))
++CurPtr;
// Requires at least one hex digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
errno = 0;
CurIntVal = strtoll(NumStart, 0, 16);
if (errno == EINVAL)
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
if (errno == ERANGE) {
errno = 0;
CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
if (errno == EINVAL)
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
if (errno == ERANGE)
return ReturnError(CurPtr-2, "Hexadecimal number out of range");
}
return asmtok::IntVal;
}
// Must be an octal number, it starts with 0.
while (*CurPtr >= '0' && *CurPtr <= '7')
++CurPtr;
CurIntVal = strtoll(TokStart, 0, 8);
return asmtok::IntVal;
}
asmtok::TokKind AsmLexer::LexToken() {
TokStart = CurPtr;
// This always consumes at least one character.
@ -66,9 +201,9 @@ asmtok::TokKind AsmLexer::LexToken() {
switch (CurChar) {
default:
// Handle letters: [a-zA-Z_]
// if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
// return LexIdentifier();
// Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
return LexIdentifier();
// Unknown character, emit an error.
return asmtok::Error;
@ -76,12 +211,29 @@ asmtok::TokKind AsmLexer::LexToken() {
case 0:
case ' ':
case '\t':
case '\n':
case '\r':
// Ignore whitespace.
return LexToken();
case '\n': // FALL THROUGH.
case '\r': // FALL THROUGH.
case ';': return asmtok::EndOfStatement;
case ':': return asmtok::Colon;
case '+': return asmtok::Plus;
case '-': return asmtok::Minus;
case '(': return asmtok::LParen;
case ')': return asmtok::RParen;
case '*': return asmtok::Star;
case ',': return asmtok::Comma;
case '$': return asmtok::Dollar;
case '%': return LexPercent();
case '/': return LexSlash();
case '#': return LexHash();
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return LexDigit();
// TODO: Quoted identifiers (objc methods etc)
// local labels: [0-9][:]
// Forward/backward labels: [0-9][fb]
// Integers, fp constants, character constants.
}
}

View File

@ -29,12 +29,16 @@ namespace asmtok {
Eof, Error,
Identifier,
Register,
IntVal,
EndOfStatement,
Colon,
Plus,
Minus
Minus,
Slash, // '/'
LParen, RParen,
Star, Comma, Dollar
};
}
@ -66,7 +70,7 @@ public:
asmtok::TokKind getKind() const { return CurKind; }
const std::string &getCurStrVal() const {
assert(CurKind == asmtok::Identifier &&
assert((CurKind == asmtok::Identifier || CurKind == asmtok::Register) &&
"This token doesn't have a string value");
return CurStrVal;
}
@ -82,9 +86,15 @@ public:
private:
int getNextChar();
asmtok::TokKind ReturnError(const char *Loc, const std::string &Msg);
/// LexToken - Read the next token and return its code.
asmtok::TokKind LexToken();
asmtok::TokKind LexIdentifier();
asmtok::TokKind LexPercent();
asmtok::TokKind LexSlash();
asmtok::TokKind LexHash();
asmtok::TokKind LexDigit();
};
} // end namespace llvm

View File

@ -72,17 +72,29 @@ static int AssembleInput(const char *ProgName) {
asmtok::TokKind Tok = Lexer.Lex();
while (Tok != asmtok::Eof) {
switch (Tok) {
default: outs() << "<<unknown token>>\n"; break;
case asmtok::Error: outs() << "<<error>>\n"; break;
default: Lexer.PrintError(Lexer.getLoc(), "driver: unknown token"); break;
case asmtok::Error:
Lexer.PrintError(Lexer.getLoc(), "error, bad token");
break;
case asmtok::Identifier:
outs() << "identifier: " << Lexer.getCurStrVal() << '\n';
break;
case asmtok::Register:
outs() << "register: " << Lexer.getCurStrVal() << '\n';
break;
case asmtok::IntVal:
outs() << "int: " << Lexer.getCurIntVal() << '\n';
break;
case asmtok::EndOfStatement: outs() << "EndOfStatement\n"; break;
case asmtok::Colon: outs() << "Colon\n"; break;
case asmtok::Plus: outs() << "Plus\n"; break;
case asmtok::Minus: outs() << "Minus\n"; break;
case asmtok::Slash: outs() << "Slash\n"; break;
case asmtok::LParen: outs() << "LParen\n"; break;
case asmtok::RParen: outs() << "RParen\n"; break;
case asmtok::Star: outs() << "Star\n"; break;
case asmtok::Comma: outs() << "Comma\n"; break;
case asmtok::Dollar: outs() << "Dollar\n"; break;
}
Tok = Lexer.Lex();