1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// file : tests/build/lexer/driver.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license : MIT; see accompanying LICENSE file
#include <string>
#include <vector>
#include <cassert>
#include <sstream>
#include <iostream>
#include <build/token>
#include <build/lexer>
using namespace std;
using namespace build;
typedef vector<string> tokens;
static tokens
lex (const char*);
int
main ()
{
// Whitespaces.
//
assert (lex ("") == tokens ({""}));
assert (lex ("\n") == tokens ({""}));
assert (lex ("\n\n") == tokens ({""}));
assert (lex (" \t \n") == tokens ({""}));
assert (lex ("#comment") == tokens ({""}));
assert (lex (" #comment") == tokens ({""}));
assert (lex ("#comment\n") == tokens ({""}));
assert (lex ("#comment\\\n") == tokens ({""}));
assert (lex ("#comment 1\n#comment2") == tokens ({""}));
// Punctuation.
//
assert (lex (": \n { }") == tokens ({":", "\n", "{", "}", ""}));
// Names.
//
assert (lex ("foo") == tokens ({"foo", ""}));
assert (lex ("foo.bar") == tokens ({"foo.bar", ""}));
// Escaping.
//
assert (lex (" \\\n") == tokens ({""}));
assert (lex ("\\\nfoo") == tokens ({"foo", ""}));
assert (lex (" \\ foo") == tokens ({" foo", ""}));
assert (lex ("fo\\ o\\:") == tokens ({"fo o:", ""}));
assert (lex ("foo\\\nbar") == tokens ({"foo\nbar", ""}));
assert (lex ("foo \\\nbar") == tokens ({"foo", "bar", ""}));
assert (lex (" \\") == tokens ({"<lexer error>"}));
assert (lex (" foo\\") == tokens ({"<lexer error>"}));
// Combinations.
//
assert (lex ("foo: bar") == tokens ({"foo", ":", "bar", ""}));
assert (lex ("\n \nfoo: bar") == tokens ({"foo", ":", "bar", ""}));
assert (lex ("foo: bar\n") == tokens ({"foo", ":", "bar", "\n", ""}));
assert (lex ("foo: bar#comment") == tokens ({"foo", ":", "bar", ""}));
assert (lex ("exe{foo}: obj{bar}") ==
tokens ({"exe", "{", "foo", "}", ":", "obj", "{", "bar", "}", ""}));
assert (lex ("foo: bar\nbaz: biz") ==
tokens ({"foo", ":", "bar", "\n", "baz", ":", "biz", ""}));
assert (lex ("foo: bar#comment\nbaz: biz") ==
tokens ({"foo", ":", "bar", "\n", "baz", ":", "biz", ""}));
assert (lex ("foo:#comment \\\nbar") ==
tokens ({"foo", ":", "\n", "bar", ""}));
}
static tokens
lex (const char* s)
{
tokens r;
istringstream is (s);
is.exceptions (istream::failbit | istream::badbit);
lexer l (is, "");
try
{
for (token t (l.next ());; t = l.next ())
{
const char* v (nullptr);
switch (t.type ())
{
case token_type::eos: v= ""; break;
case token_type::punctuation:
{
switch (t.punctuation ())
{
case token_punctuation::newline: v = "\n"; break;
case token_punctuation::colon: v = ":"; break;
case token_punctuation::lcbrace: v = "{"; break;
case token_punctuation::rcbrace: v = "}"; break;
}
break;
}
case token_type::name: v = t.name ().c_str (); break;
}
// cerr << t.line () << ':' << t.column () << ':' << v << endl;
r.push_back (v);
if (t.type () == token_type::eos)
break;
}
}
catch (const lexer_error&)
{
r.push_back ("<lexer error>");
}
catch (const std::ios_base::failure&)
{
r.push_back ("<io error>");
}
return r;
}
|