Wallaroo  0.8
tokensource.h
Go to the documentation of this file.
1 /*******************************************************************************
2  * wallaroo - A library for configurable creation and wiring of C++ classes.
3  * Copyright (C) 2012 Daniele Pallastrelli
4  *
5  * This file is part of wallaroo.
6  * For more information, see http://wallaroolib.sourceforge.net/
7  *
8  * Boost Software License - Version 1.0 - August 17th, 2003
9  *
10  * Permission is hereby granted, free of charge, to any person or organization
11  * obtaining a copy of the software and accompanying documentation covered by
12  * this license (the "Software") to use, reproduce, display, distribute,
13  * execute, and transmit the Software, and to prepare derivative works of the
14  * Software, and to permit third-parties to whom the Software is furnished to
15  * do so, all subject to the following:
16  *
17  * The copyright notices in the Software and this entire statement, including
18  * the above license grant, this restriction and the following disclaimer,
19  * must be included in all copies of the Software, in whole or in part, and
20  * all derivative works of the Software, unless such copies or derivative
21  * works are solely in the form of machine-executable object code generated by
22  * a source language processor.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
27  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
28  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
29  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  ******************************************************************************/
32 
33 #ifndef WALLAROO_DETAIL_TOKENSOURCE_H_
34 #define WALLAROO_DETAIL_TOKENSOURCE_H_
35 
36 #include <string>
37 #include <sstream>
38 #include "wallaroo/exceptions.h"
39 
40 namespace wallaroo
41 {
42 namespace detail
43 {
44 
46 
47 // Represent a token when scanning a .wal configuration file
48 struct Token
49 {
50  // terminals
51  enum Type {
52  load, // @load
53  create, // new
54  open, // (
55  close, // )
56  stmtsep, // ;
57  attrsep, // ,
58  assign, // =
59  collsep, // .
60  id, // <id> [a-zA-Z_] [a-zA-Z0-9_:<>]*
61  value, // true | false | \'{char}\' | \"{char}*\" | [0-9+-]?[0-9]+\.[0-9]+
62  done // EOF
63  };
65  std::string lexem;
66  Token( Type t, const std::string& l = std::string() ) : type( t ), lexem( l ) {}
67  // return a string explaining the type of a token
68  static std::string Description( Type t )
69  {
70  switch ( t )
71  {
72  case load: return "@load"; break;
73  case create: return "new"; break;
74  case open: return "("; break;
75  case close: return ")"; break;
76  case stmtsep: return ";"; break;
77  case attrsep: return ","; break;
78  case assign: return "="; break;
79  case collsep: return "."; break;
80  case id: return "<id>"; break;
81  case value: return "<value>"; break;
82  case done: return "<EOF>"; break;
83  }
84  return "???"; // can't reach this point
85  }
86 };
87 
88 // Split an input stream into a sequence of token.
89 // Each call at Split::Next method returns the next token
90 // (or throws a LexicalError if the next token is unknown).
92 {
93 public:
94  explicit TokenSource( std::istream& in ) : input( in ), lineno( 1 ), column( 1 ) {}
95  // throw LexicalError
97  {
98  while ( true )
99  {
100  char c = input.peek();
101  switch ( c )
102  {
103  case ' ': case '\t': Consume(); break;
104  case '\n': NewLine(); Consume(); break;
105  case '(': Consume(); return Token( Token::open ); break;
106  case ')': Consume(); return Token( Token::close ); break;
107  case ';': Consume(); return Token( Token::stmtsep ); break;
108  case ',': Consume(); return Token( Token::attrsep ); break;
109  case '=': Consume(); return Token( Token::assign ); break;
110  case '.': Consume(); return Token( Token::collsep ); break;
111  case '\'':
112  {
113  Consume(); // '
114  c = input.peek();
115  // TODO manage quoted chars
116  Consume(); // char
117  if ( input.peek() == '\'' ) Consume(); // '
118  else throw LexicalError( "Missing terminating char closing", lineno, column );
119  return Token( Token::value, std::string( 1, c ) );
120  }
121  break;
122  case '"':
123  {
124  std::string value;
125  Consume();
126  c = input.peek();
127  while ( c != '"' && !input.eof() && c != '\n' )
128  {
129  value += c;
130  Consume();
131  c = input.peek();
132  }
133  if ( c == '"' ) Consume();
134  else throw LexicalError( "Missing terminating string closing", lineno, column );
135  return Token( Token::value, value );
136  }
137  break;
138  case '#':
139  {
140  while ( c != '\n' && !input.eof() )
141  {
142  Consume();
143  c = input.peek();
144  }
145  if ( input.eof() ) return Token( Token::done );
146  else
147  {
148  NewLine();
149  Consume();
150  }
151  }
152  break;
153  default:
154  {
155  if ( isalpha( c ) || c == '_' )
156  {
157  std::string id;
158  while ( isalnum( c ) || c == '_' || c == ':' || c == '<' || c == '>' )
159  {
160  id += c;
161  Consume();
162  c = input.peek(); // next char...
163  }
164  if ( id == "new" ) return Token( Token::create );
165  else if ( id == "true" || id == "false" ) return Token( Token::value, id );
166  else return Token( Token::id, id );
167  }
168  else if (c == '@')
169  {
170  std::string id;
171  while (isalnum(c) || c == '@')
172  {
173  id += c;
174  Consume();
175  c = input.peek(); // next char...
176  }
177  if (id == "@load") return Token(Token::load);
178  throw LexicalError("Invalid keyword:" + id, lineno, column);
179  }
180  else if ( input.eof() )
181  return Token( Token::done );
182  else if ( isdigit( c ) || c == '-' || c == '+' )
183  {
184  std::string num;
185  std::size_t sepcount = 0;
186 
187  num += c;
188  Consume();
189  c = input.peek(); // next char...
190 
191  while ( isdigit( c ) || c == '.' )
192  {
193  if ( c == '.' )
194  if ( ++sepcount > 1 )
195  throw LexicalError( "Floating point invalid (too many '.')", lineno, column );
196  num += c;
197  Consume();
198  c = input.peek(); // next char...
199  }
200  return Token( Token::value, num );
201  }
202  else
203  throw LexicalError( "Unrecognized character", lineno, column );
204  }
205  }
206  }
207  }
208 
209  std::size_t Line() const { return lineno; }
210  std::size_t Col() const { return column; }
211 
212 private:
213  void NewLine()
214  {
215  ++lineno;
216  column = 1;
217  }
218  void Consume()
219  {
220  input.get();
221  ++column;
222  }
223  std::istream& input;
224  std::size_t lineno;
225  std::size_t column;
226 };
227 
228 } // detail
229 } // namespace
230 
231 #endif // WALLAROO_DETAIL_TOKENSOURCE_H_
Definition: tokensource.h:57
std::size_t Line() const
Definition: tokensource.h:209
Definition: tokensource.h:48
Type type
Definition: tokensource.h:64
std::string lexem
Definition: tokensource.h:65
static std::string Description(Type t)
Definition: tokensource.h:68
Definition: tokensource.h:52
Definition: tokensource.h:62
Definition: exceptions.h:217
Definition: tokensource.h:55
Token(Type t, const std::string &l=std::string())
Definition: tokensource.h:66
TokenSource(std::istream &in)
Definition: tokensource.h:94
Definition: tokensource.h:59
Definition: tokensource.h:56
Definition: tokensource.h:91
Definition: attribute.h:45
Definition: tokensource.h:54
Definition: tokensource.h:61
std::size_t Col() const
Definition: tokensource.h:210
Token Next()
Definition: tokensource.h:96
Definition: tokensource.h:58
Definition: tokensource.h:60
Type
Definition: tokensource.h:51
Definition: tokensource.h:53