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 in.peek();
66
67 while (true)
68 {
69 if (in.lookahead == EOF)
70 return TOK_NONE;
71 if (!std::isspace(in.lookahead))
72 break;
73 in.advance();
74 }
75
76 switch (in.lookahead)
77 {
78
79 case '"':
80 {
81 in.advance();
82 while (static_cast<char>(in.lookahead) != '"')
83 {
84 if (in.lookahead == EOF)
85 in.err("input stream ended in string");
86 if (static_cast<char>(in.lookahead) == '\\')
87 {
88 // possible escape: we understand escaped quotes
89 // and escaped backslashes. nothing else.
90 in.advance();
91 if (!(static_cast<char>(in.lookahead) == '"'
92 || static_cast<char>(in.lookahead) == '\\'))
93 {
94 in.err("unrecognized character escape");
95 }
96 }
97 in.advance();
98 val += in.c;
99 }
100
101 if (static_cast<char>(in.lookahead) != '"')
102 in.err("string did not end with '\"'");
103 in.eat();
104
105 return basic_io::TOK_STRING;
106 }
107
108 case '[':
109 {
110 in.advance();
111 while (static_cast<char>(in.lookahead) != ']')
112 {
113 if (in.lookahead == EOF)
114 in.err("input stream ended in hex string");
115 if (!std::isxdigit(in.lookahead))
116 in.err("non-hex character in hex string");
117 in.advance();
118 val += in.c;
119 }
120
121 if (static_cast<char>(in.lookahead) != ']')
122 in.err("hex string did not end with ']'");
123 in.eat();
124
125 return basic_io::TOK_HEX;
126 }
127 default:
128 if (std::isalpha(in.lookahead))
129 {
130 while (std::isalnum(in.lookahead) || in.lookahead == '_')
131 {
132 in.advance();
133 val += in.c;
134 }
135 return basic_io::TOK_SYMBOL;
136 }
137 }
138 return basic_io::TOK_NONE;
139 }
140 void err(std::string const & s);
141 };
142
143 struct
144 stanza
145 {
146 stanza();
147 size_t indent;
148 std::vector<std::pair<std::string, std::string> > entries;
149 void push_hex_pair(std::string const & k, std::string const & v);
150 void push_str_pair(std::string const & k, std::string const & v);
151 };
152
153 struct
154 printer
155 {
156 bool empty_output;
157 std::ostream & out;
158 printer(std::ostream & ost);
159 void print_stanza(stanza const & st);
160 };
161
162 struct
163 parser
164 {
165 tokenizer & tok;
166 parser(tokenizer & t) : tok(t)
167 {
168 advance();
169 }
170
171 std::string token;
172 token_type ttype;
173
174 void err(std::string const & s);
175 std::string tt2str(token_type tt);
176
177 inline void advance()
178 {
179 ttype = tok.get_token(token);
180 }
181
182 inline void eat(token_type want)
183 {
184 if (ttype != want)
185 err("wanted "
186 + tt2str(want)
187 + ", got "
188 + tt2str(ttype)
189 + (token.empty()
190 ? std::string("")
191 : (std::string(" with value ") + token)));
192 advance();
193 }
194
195 inline void str() { eat(basic_io::TOK_STRING); }
196 inline void sym() { eat(basic_io::TOK_SYMBOL); }
197 inline void hex() { eat(basic_io::TOK_HEX); }
198
199 inline void str(std::string & v) { v = token; str(); }
200 inline void sym(std::string & v) { v = token; sym(); }
201 inline void hex(std::string & v) { v = token; hex(); }
202 inline bool symp() { return ttype == basic_io::TOK_SYMBOL; }
203 inline bool symp(std::string const & val)
204 {
205 return ttype == basic_io::TOK_SYMBOL && token == val;
206 }
207 inline void esym(std::string const & val)
208 {
209 if (!(ttype == basic_io::TOK_SYMBOL && token == val))
210 err("wanted symbol '"
211 + val +
212 + "', got "
213 + tt2str(ttype)
214 + (token.empty()
215 ? std::string("")
216 : (std::string(" with value ") + token)));
217 advance();
218 }
219 };
220
221}
222
223#endif // __BASIC_IO_HH__

Archive Download this file

Branches

Tags

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