00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef COMMA_PARSER_LEXER_HDR_GUARD
00010 #define COMMA_PARSER_LEXER_HDR_GUARD
00011
00012 #include "comma/basic/Diagnostic.h"
00013 #include "comma/basic/TextProvider.h"
00014 #include <iosfwd>
00015 #include <string>
00016
00017 namespace comma {
00018
00019 class Lexer {
00020
00021 public:
00022 Lexer(TextProvider &txtProvider, Diagnostic &diag);
00023
00024
00025
00026
00027
00028
00029
00030 enum Code {
00031 UNUSED_ID,
00032
00033 #define KEYWORD(NAME, STRING) TKN_ ## NAME,
00034 #define GLYPH(NAME, STRING) TKN_ ## NAME,
00035 #define TOKEN(NAME) TKN_ ## NAME,
00036 #include "comma/parser/Tokens.def"
00037 #undef KEYWORD
00038 #undef GLYPH
00039 #undef TOKEN
00040
00041 NUMTOKEN_CODES
00042 };
00043
00044
00045
00046
00047
00048
00049 class Token {
00050
00051 public:
00052 Token() : code(Lexer::UNUSED_ID) { }
00053
00054 Lexer::Code getCode() const { return code; }
00055
00056 Location getLocation() const { return location; }
00057
00058 const char *getRep() const { return string; }
00059
00060 unsigned getLength() const { return length; }
00061
00062
00063
00064 const char *getString() const;
00065
00066 private:
00067 Lexer::Code code : 8;
00068 unsigned length : 24;
00069 Location location;
00070 const char *string;
00071
00072
00073
00074 friend class Lexer;
00075
00076 Token(Lexer::Code code,
00077 Location location,
00078 const char *string,
00079 unsigned length)
00080 : code(code),
00081 length(length),
00082 location(location),
00083 string(string) { }
00084 };
00085
00086
00087
00088
00089 void scan(Lexer::Token &tkn);
00090
00091
00092 bool seenError() const { return errorDetected; }
00093
00094
00095
00096 static bool isFunctionGlyph(const Lexer::Token &tkn) {
00097 switch (tkn.getCode()) {
00098 case TKN_EQUAL:
00099 case TKN_MINUS:
00100 case TKN_NEQUAL:
00101 case TKN_STAR:
00102 case TKN_PLUS:
00103 case TKN_TILDE:
00104 return true;
00105 default:
00106 return false;
00107 }
00108 }
00109
00110
00111
00112 static const char *tokenString(Code code);
00113
00114
00115
00116 static const char *tokenString(const Token &tkn);
00117
00118 private:
00119 bool eatWhitespace();
00120
00121 bool eatComment();
00122
00123 bool scanWord();
00124
00125 bool scanGlyph();
00126
00127 bool scanString();
00128
00129 bool scanNumeric();
00130
00131 bool scanEscape();
00132
00133 static bool isAlphabetic(unsigned c);
00134
00135 static bool isInitialIdentifierChar(unsigned c);
00136
00137 static bool isInnerIdentifierChar(unsigned c);
00138
00139 static bool isWhitespace(unsigned c);
00140
00141 static bool isDecimalDigit(unsigned c);
00142
00143 Location currentLocation() const;
00144
00145
00146
00147
00148
00149
00150 unsigned readStream();
00151 unsigned peekStream();
00152 void ungetStream();
00153 void ignoreStream();
00154
00155
00156
00157
00158
00159 Code getTokenCode(TextIterator &start, TextIterator &end) const;
00160
00161 void emitToken(Code code,
00162 const TextIterator &start, const TextIterator &end);
00163
00164
00165
00166 void emitToken(Code code, Location loc);
00167
00168 void emitStringToken(const TextIterator &start, const TextIterator &end);
00169
00170 void emitIntegerToken(const TextIterator &start, const TextIterator &end);
00171
00172 void emitIdentifierToken(const TextIterator &start,
00173 const TextIterator &end);
00174
00175 DiagnosticStream &report(Location loc, diag::Kind kind) {
00176 SourceLocation sloc = txtProvider.getSourceLocation(loc);
00177 return diagnostic.report(sloc, kind);
00178 }
00179
00180 DiagnosticStream &report(SourceLocation sloc, diag::Kind kind) {
00181 return diagnostic.report(sloc, kind);
00182 }
00183
00184 DiagnosticStream &report(diag::Kind kind) {
00185 SourceLocation sloc = txtProvider.getSourceLocation(currentLocation());
00186 return diagnostic.report(sloc, kind);
00187 }
00188
00189
00190 TextProvider &txtProvider;
00191
00192
00193 Diagnostic &diagnostic;
00194
00195
00196 TextIterator currentIter;
00197
00198
00199 bool errorDetected;
00200
00201
00202
00203 Token *targetToken;
00204 };
00205
00206 }
00207
00208 #endif