 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
87.1% |
122 / 140 |
| Generated: |
2009-05-17 22:47 |
|
Branches Executed: |
100.0% |
140 / 140 |
| |
|
Line Coverage: |
93.2% |
138 / 148 |
| |
 |
|
 |
1 : //===- Lexer.cpp - --*- C++ -*-===//
2 :
3 : #include "expr/Lexer.h"
4 :
5 : #include "llvm/Support/MemoryBuffer.h"
6 : #include "llvm/Support/Streams.h"
7 :
8 : #include <iomanip>
9 : #include <iostream>
10 : #include <string.h>
11 :
12 : using namespace llvm;
13 : using namespace klee;
14 : using namespace klee::expr;
15 :
16 : ///
17 :
18 65: const char *Token::getKindName() const {
0: branch 0 not taken
1: branch 1 taken
1: branch 2 taken
1: branch 3 taken
1: branch 4 taken
36: branch 5 taken
1: branch 6 taken
1: branch 7 taken
1: branch 8 taken
1: branch 9 taken
1: branch 10 taken
7: branch 11 taken
1: branch 12 taken
0: branch 13 not taken
1: branch 14 taken
1: branch 15 taken
1: branch 16 taken
5: branch 17 taken
1: branch 18 taken
1: branch 19 taken
1: branch 20 taken
1: branch 21 taken
19 65: switch (kind) {
20 : default:
21 0: case Unknown: return "Unknown";
22 1: case Arrow: return "Arrow";
23 1: case At: return "At";
24 1: case Colon: return "Colon";
25 1: case Comma: return "Comma";
26 36: case Comment: return "Comment";
27 1: case EndOfFile: return "EndOfFile";
28 1: case Equals: return "Equals";
29 1: case Identifier: return "Identifier";
30 1: case KWFalse: return "KWFalse";
31 1: case KWQuery: return "KWQuery";
32 7: case KWReserved: return "KWReserved";
33 1: case KWTrue: return "KWTrue";
34 0: case KWWidth: return "KWWidth";
35 1: case LBrace: return "LBrace";
36 1: case LParen: return "LParen";
37 1: case LSquare: return "LSquare";
38 5: case Number: return "Number";
39 1: case RBrace: return "RBrace";
40 1: case RParen: return "RParen";
41 1: case RSquare: return "RSquare";
42 1: case Semicolon: return "Semicolon";
43 : }
44 : }
45 :
46 0: void Token::dump() {
47 : llvm::cerr << "(Token \"" << getKindName() << "\" "
48 : << (void*) start << " " << length << " "
49 0: << line << " " << column << ")";
50 0: }
51 :
52 : ///
53 :
54 : static inline bool isInternalIdentifierChar(int Char) {
1487: branch 1 taken
3881: branch 2 taken
1: branch 3 taken
1486: branch 4 taken
55 5368: return isalnum(Char) || Char == '_' || Char == '.';
56 : }
57 :
58 3: Lexer::Lexer(const llvm::MemoryBuffer *MB)
59 : : BufferPos(MB->getBufferStart()), BufferEnd(MB->getBufferEnd()),
60 6: LineNumber(1), ColumnNumber(0) {
61 3: }
62 :
63 3: Lexer::~Lexer() {
64 3: }
65 :
66 22756: int Lexer::PeekNextChar() {
3: branch 0 taken
22753: branch 1 taken
67 22756: if (BufferPos == BufferEnd)
68 3: return -1;
69 22753: return *BufferPos;
70 : }
71 :
72 22915: int Lexer::GetNextChar() {
3: branch 0 taken
22912: branch 1 taken
73 22915: if (BufferPos == BufferEnd)
74 3: return -1;
75 :
76 : // Handle DOS/Mac newlines here, by stripping duplicates and by
77 : // returning '\n' for both.
78 22912: char Result = *BufferPos++;
509: branch 0 taken
22403: branch 1 taken
79 22912: if (Result == '\n' || Result == '\r') {
506: branch 0 taken
3: branch 1 taken
0: branch 2 not taken
506: branch 3 taken
80 509: if (BufferPos != BufferEnd && *BufferPos == ('\n' + '\r' - Result))
81 0: ++BufferPos;
82 509: Result = '\n';
83 : }
84 :
509: branch 0 taken
22403: branch 1 taken
85 22912: if (Result == '\n') {
86 509: ++LineNumber;
87 509: ColumnNumber = 0;
88 : } else {
89 22403: ++ColumnNumber;
90 : }
91 :
92 22912: return Result;
93 : }
94 :
95 4537: Token &Lexer::SetTokenKind(Token &Result, Token::Kind k) {
96 4537: Result.kind = k;
97 4537: Result.length = BufferPos - Result.start;
98 4537: return Result;
99 : }
100 :
101 : static bool isReservedKW(const char *Str, unsigned N) {
102 : unsigned i;
103 :
104 : // Check for i[0-9]+
1458: branch 0 taken
0: branch 1 not taken
1: branch 2 taken
1457: branch 3 taken
105 1458: if (N>1 && Str[0] == 'i') {
2: branch 0 taken
1: branch 1 taken
106 3: for (i=1; i<N; ++i)
2: branch 0 taken
0: branch 1 not taken
107 2: if (!isdigit(Str[i]))
108 : break;
1: branch 0 taken
0: branch 1 not taken
109 1: if (i==N)
110 1: return true;
111 : }
112 :
113 : // Check for fp[0-9]+([.].*)?$
567: branch 0 taken
890: branch 1 taken
1: branch 2 taken
566: branch 3 taken
1: branch 4 taken
0: branch 5 not taken
1: branch 6 taken
0: branch 7 not taken
114 1457: if (N>3 && Str[0]=='f' && Str[1]=='p' && isdigit(Str[2])) {
2: branch 0 taken
0: branch 1 not taken
115 2: for (i=3; i<N; ++i)
1: branch 0 taken
1: branch 1 taken
116 2: if (!isdigit(Str[i]))
117 : break;
1: branch 0 taken
0: branch 1 not taken
1: branch 2 taken
0: branch 3 not taken
118 1: if (i==N || Str[i]=='.')
119 1: return true;
120 : }
121 :
122 1456: return false;
123 : }
124 : static bool isWidthKW(const char *Str, unsigned N) {
1456: branch 0 taken
0: branch 1 not taken
1011: branch 2 taken
445: branch 3 taken
125 1456: if (N<2 || Str[0] != 'w')
126 1011: return false;
702: branch 0 taken
445: branch 1 taken
127 1147: for (unsigned i=1; i<N; ++i)
0: branch 0 not taken
702: branch 1 taken
128 702: if (!isdigit(Str[i]))
129 0: return false;
130 445: return true;
131 : }
132 1486: Token &Lexer::SetIdentifierTokenKind(Token &Result) {
133 1486: unsigned Length = BufferPos - Result.start;
443: branch 0 taken
160: branch 1 taken
199: branch 2 taken
139: branch 3 taken
94: branch 4 taken
451: branch 5 taken
134 1486: switch (Length) {
135 : case 3:
1: branch 1 taken
442: branch 2 taken
136 443: if (memcmp("def", Result.start, 3) == 0)
137 1: return SetTokenKind(Result, Token::KWReserved);
1: branch 1 taken
441: branch 2 taken
138 442: if (memcmp("var", Result.start, 3) == 0)
139 1: return SetTokenKind(Result, Token::KWReserved);
140 : break;
141 :
142 : case 4:
1: branch 1 taken
159: branch 2 taken
143 160: if (memcmp("true", Result.start, 4) == 0)
144 1: return SetTokenKind(Result, Token::KWTrue);
145 : break;
146 :
147 : case 5:
1: branch 1 taken
198: branch 2 taken
148 199: if (memcmp("array", Result.start, 5) == 0)
149 1: return SetTokenKind(Result, Token::KWReserved);
3: branch 1 taken
195: branch 2 taken
150 198: if (memcmp("false", Result.start, 5) == 0)
151 3: return SetTokenKind(Result, Token::KWFalse);
19: branch 1 taken
176: branch 2 taken
152 195: if (memcmp("query", Result.start, 5) == 0)
153 19: return SetTokenKind(Result, Token::KWQuery);
154 : break;
155 :
156 : case 6:
1: branch 1 taken
138: branch 2 taken
157 139: if (memcmp("define", Result.start, 6) == 0)
158 1: return SetTokenKind(Result, Token::KWReserved);
159 : break;
160 :
161 : case 7:
1: branch 1 taken
93: branch 2 taken
162 94: if (memcmp("declare", Result.start, 7) == 0)
163 1: return SetTokenKind(Result, Token::KWReserved);
164 : break;
165 : }
166 :
2: branch 0 taken
1456: branch 1 taken
167 2916: if (isReservedKW(Result.start, Length))
168 2: return SetTokenKind(Result, Token::KWReserved);
445: branch 0 taken
1011: branch 1 taken
169 2912: if (isWidthKW(Result.start, Length))
170 445: return SetTokenKind(Result, Token::KWWidth);
171 :
172 1011: return SetTokenKind(Result, Token::Identifier);
173 : }
174 :
175 3497: void Lexer::SkipToEndOfLine() {
176 : for (;;) {
177 3497: int Char = GetNextChar();
3402: branch 0 taken
95: branch 1 taken
178 3497: if (Char == -1 || Char =='\n')
179 95: break;
180 : }
181 95: }
182 :
183 924: Token &Lexer::LexNumber(Token &Result) {
926: branch 2 taken
424: branch 3 taken
2: branch 5 taken
924: branch 6 taken
426: branch 7 taken
924: branch 8 taken
184 2274: while (isalnum(PeekNextChar()) || PeekNextChar()=='_')
185 426: GetNextChar();
186 924: return SetTokenKind(Result, Token::Number);
187 : }
188 :
189 1486: Token &Lexer::LexIdentifier(Token &Result) {
3882: branch 1 taken
1486: branch 2 taken
190 12222: while (isInternalIdentifierChar(PeekNextChar()))
191 3882: GetNextChar();
192 :
193 : // Recognize keywords specially.
194 1486: return SetIdentifierTokenKind(Result);
195 : }
196 :
197 4537: Token &Lexer::Lex(Token &Result) {
198 4537: Result.kind = Token::Unknown;
199 4537: Result.length = 0;
200 4537: Result.start = BufferPos;
201 :
202 : // Skip whitespace.
10572: branch 2 taken
4537: branch 3 taken
203 19646: while (isspace(PeekNextChar()))
204 10572: GetNextChar();
205 :
206 4537: Result.start = BufferPos;
207 4537: Result.line = LineNumber;
208 4537: Result.column = ColumnNumber;
209 4537: int Char = GetNextChar();
3: branch 0 taken
648: branch 1 taken
648: branch 2 taken
288: branch 3 taken
66: branch 4 taken
1: branch 5 taken
301: branch 6 taken
10: branch 7 taken
32: branch 8 taken
32: branch 9 taken
1: branch 10 taken
1: branch 11 taken
95: branch 12 taken
1: branch 13 taken
2: branch 14 taken
2408: branch 15 taken
210 4537: switch (Char) {
211 3: case -1: return SetTokenKind(Result, Token::EndOfFile);
212 :
213 648: case '(': return SetTokenKind(Result, Token::LParen);
214 648: case ')': return SetTokenKind(Result, Token::RParen);
215 288: case ',': return SetTokenKind(Result, Token::Comma);
216 66: case ':': return SetTokenKind(Result, Token::Colon);
217 1: case ';': return SetTokenKind(Result, Token::Semicolon);
218 301: case '=': return SetTokenKind(Result, Token::Equals);
219 10: case '@': return SetTokenKind(Result, Token::At);
220 32: case '[': return SetTokenKind(Result, Token::LSquare);
221 32: case ']': return SetTokenKind(Result, Token::RSquare);
222 1: case '{': return SetTokenKind(Result, Token::LBrace);
223 1: case '}': return SetTokenKind(Result, Token::RBrace);
224 :
225 : case '#':
226 95: SkipToEndOfLine();
227 95: return SetTokenKind(Result, Token::Comment);
228 :
229 : case '+': {
1: branch 1 taken
0: branch 2 not taken
230 1: if (isdigit(PeekNextChar()))
231 1: return LexNumber(Result);
232 : else
233 0: return SetTokenKind(Result, Token::Unknown);
234 : }
235 :
236 : case '-': {
237 2: int Next = PeekNextChar();
1: branch 0 taken
1: branch 1 taken
238 2: if (Next == '>')
239 1: return GetNextChar(), SetTokenKind(Result, Token::Arrow);
1: branch 0 taken
0: branch 1 not taken
240 1: else if (isdigit(Next))
241 1: return LexNumber(Result);
242 : else
243 0: return SetTokenKind(Result, Token::Unknown);
244 : break;
245 : }
246 :
247 : default:
922: branch 0 taken
1486: branch 1 taken
248 2408: if (isdigit(Char))
249 922: return LexNumber(Result);
1486: branch 1 taken
0: branch 2 not taken
250 1486: else if (isalpha(Char) || Char == '_')
251 1486: return LexIdentifier(Result);
252 0: return SetTokenKind(Result, Token::Unknown);
253 : }
5: branch 0 taken
0: branch 1 not taken
5: branch 2 taken
0: branch 3 not taken
254 10: }
Generated: 2009-05-17 22:47 by zcov