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

Archive Download this file

Branches

Tags

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