monotone

monotone Mtn Source Tree

Root/basic_io.hh

1#ifndef __BASIC_IO_HH__
2#define __BASIC_IO_HH__
3
4// copyright (C) 2004 graydon hoare <graydon@pobox.com>
5// all rights reserved.
6// licensed to the public under the terms of the GNU GPL (>= 2)
7// see the file COPYING for details
8
9// this file provides parsing and printing primitives used by the higher
10// level parser and printer routines for the two datatypes change_set and
11// revision_set. every revision_set contains a number of change_sets, so
12// their i/o routines are somewhat related.
13
14#include <iosfwd>
15#include <string>
16#include <vector>
17#include <map>
18
19namespace basic_io
20{
21
22 typedef enum
23 {
24 TOK_SYMBOL,
25 TOK_STRING,
26 TOK_HEX,
27 TOK_NONE,
28 } token_type;
29
30 struct
31 input_source
32 {
33 size_t line, col;
34 std::istream & in;
35 std::string name;
36 int lookahead;
37 char c;
38 input_source(std::istream & i, std::string const & nm)
39 : line(1), col(1), in(i), name(nm), lookahead(0), c('\0')
40 {}
41 inline void peek() { lookahead = in.peek(); }
42 inline void eat()
43 {
44 in.get(c);
45 ++col;
46 if (c == '\n')
47 {
48 col = 1;
49 ++line;
50 }
51 }
52 inline void advance() { eat(); peek(); }
53 void err(std::string const & s);
54 };
55
56 struct
57 tokenizer
58 {
59 input_source & in;
60 tokenizer(input_source & i) : in(i) {}
61
62 inline token_type get_token(std::string & val)
63 {
64 val.clear();
65 val.reserve(80);
66 in.peek();
67
68 while (true)
69 {
70 if (in.lookahead == EOF)
71 return TOK_NONE;
72 if (!std::isspace(in.lookahead))
73 break;
74 in.advance();
75 }
76
77 switch (in.lookahead)
78 {
79
80 case '"':
81 {
82 in.advance();
83 while (static_cast<char>(in.lookahead) != '"')
84 {
85 if (in.lookahead == EOF)
86 in.err("input stream ended in string");
87 if (static_cast<char>(in.lookahead) == '\\')
88 {
89 // possible escape: we understand escaped quotes
90 // and escaped backslashes. nothing else.
91 in.advance();
92 if (!(static_cast<char>(in.lookahead) == '"'
93 || static_cast<char>(in.lookahead) == '\\'))
94 {
95 in.err("unrecognized character escape");
96 }
97 }
98 in.advance();
99 val += in.c;
100 }
101
102 if (static_cast<char>(in.lookahead) != '"')
103 in.err("string did not end with '\"'");
104 in.eat();
105
106 return basic_io::TOK_STRING;
107 }
108
109 case '[':
110 {
111 in.advance();
112 while (static_cast<char>(in.lookahead) != ']')
113 {
114 if (in.lookahead == EOF)
115 in.err("input stream ended in hex string");
116 if (!std::isxdigit(in.lookahead))
117 in.err("non-hex character in hex string");
118 in.advance();
119 val += in.c;
120 }
121
122 if (static_cast<char>(in.lookahead) != ']')
123 in.err("hex string did not end with ']'");
124 in.eat();
125
126 return basic_io::TOK_HEX;
127 }
128 default:
129 if (std::isalpha(in.lookahead))
130 {
131 while (std::isalnum(in.lookahead) || in.lookahead == '_')
132 {
133 in.advance();
134 val += in.c;
135 }
136 return basic_io::TOK_SYMBOL;
137 }
138 }
139 return basic_io::TOK_NONE;
140 }
141 void err(std::string const & s);
142 };
143
144 std::string escape(std::string const & s);
145
146 struct
147 stanza
148 {
149 stanza();
150 size_t indent;
151 std::vector<std::pair<std::string, std::string> > entries;
152 void push_hex_pair(std::string const & k, std::string const & v);
153 void push_str_pair(std::string const & k, std::string const & v);
154 };
155
156 struct
157 printer
158 {
159 bool empty_output;
160 std::ostream & out;
161 printer(std::ostream & ost);
162 void print_stanza(stanza const & st);
163 };
164
165 struct
166 parser
167 {
168 tokenizer & tok;
169 parser(tokenizer & t) : tok(t)
170 {
171 advance();
172 }
173
174 std::string token;
175 token_type ttype;
176
177 void err(std::string const & s);
178 std::string tt2str(token_type tt);
179
180 inline void advance()
181 {
182 ttype = tok.get_token(token);
183 }
184
185 inline void eat(token_type want)
186 {
187 if (ttype != want)
188 err("wanted "
189 + tt2str(want)
190 + ", got "
191 + tt2str(ttype)
192 + (token.empty()
193 ? std::string("")
194 : (std::string(" with value ") + token)));
195 advance();
196 }
197
198 inline void str() { eat(basic_io::TOK_STRING); }
199 inline void sym() { eat(basic_io::TOK_SYMBOL); }
200 inline void hex() { eat(basic_io::TOK_HEX); }
201
202 inline void str(std::string & v) { v = token; str(); }
203 inline void sym(std::string & v) { v = token; sym(); }
204 inline void hex(std::string & v) { v = token; hex(); }
205 inline bool symp() { return ttype == basic_io::TOK_SYMBOL; }
206 inline bool symp(std::string const & val)
207 {
208 return ttype == basic_io::TOK_SYMBOL && token == val;
209 }
210 inline void esym(std::string const & val)
211 {
212 if (!(ttype == basic_io::TOK_SYMBOL && token == val))
213 err("wanted symbol '"
214 + val +
215 + "', got "
216 + tt2str(ttype)
217 + (token.empty()
218 ? std::string("")
219 : (std::string(" with value ") + token)));
220 advance();
221 }
222 };
223
224}
225
226#endif // __BASIC_IO_HH__

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status