1 #include <msp/strings/format.h>
2 #include <msp/strings/utils.h>
5 #include "textparser.h"
13 TextParser::TextParser(Input &i, const string &s):
17 Statement TextParser::parse()
19 return parse_statement(0);
22 Statement TextParser::parse_statement(const Token *t)
36 token = parse_token();
38 if(result.keyword.empty())
42 else if(token.type!=Token::IDENTIFIER)
43 throw syntax_error(token.str);
44 result.keyword = token.str;
47 result.line = in.get_line_number();
55 Statement ss = parse_statement(&token);
56 result.sub.push_back(ss);
62 throw syntax_error(token.str);
65 else if(token.str=="{")
67 else if(token.str==";")
69 else if(token.type!=Token::SPECIAL)
70 result.append_from_token(token);
72 throw syntax_error(token.str);
78 Token TextParser::parse_token()
83 // Skip over comments and whitespace
84 while(in && comment>=0)
89 if(c=='/' && next=='/' && !comment)
91 else if(c=='/' && next=='*' && !comment)
93 else if(c=='\n' && comment==1)
95 else if(c=='*' && next=='/' && comment==2)
97 else if(comment==3) // Skip the second character of block comment end
99 else if(c!=-1 && !isspace(c) && !comment)
103 if(comment>0) // EOF while in comment
104 throw parse_error(string());
105 else if(comment==0) // Didn't hit any non-whitespace
106 return Token(Token::SPECIAL, "");
127 static Token::Type token_type[]=
146 ParseState state = INIT;
149 while(in || state==INIT)
153 int next = in.peek();
162 else if(c=='-' || c=='+')
168 else if(c=='{' || c=='}' || c==';')
169 return Token(Token::SPECIAL, string(1, c));
172 else if(isalpha(c) || c=='_' || c=='\\')
175 throw parse_error(buf);
186 throw parse_error(buf);
197 throw parse_error(buf);
203 else if(c=='e' || c=='E')
204 state = FLOATEXPINIT;
206 throw parse_error(buf);
211 throw parse_error(buf);
216 throw parse_error(buf);
221 state = FLOATEXPINIT;
223 throw parse_error(buf);
228 state = FLOATEXPSIGN;
232 throw parse_error(buf);
239 throw parse_error(buf);
244 throw parse_error(buf);
249 state = STRING_ESCAPE;
259 if(!isalpha(c) && !isdigit(c) && c!='_' && c!='-' && c!='/')
260 throw parse_error(buf);
264 throw parse_error(buf);
267 throw logic_error("bad parser state");
270 if(is_delimiter(next) && state>=ACCEPT)
272 if(state==IDENTIFIER && buf[0]=='\\')
273 return Token(Token::IDENTIFIER, buf.substr(1));
274 else if(state==STRING_END)
275 return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
277 return Token(token_type[state], buf);
281 return Token(Token::SPECIAL, "");
284 bool TextParser::is_delimiter(int c)
286 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
289 bool TextParser::isodigit(int c)
291 return (c>='0' && c<='7');
294 } // namespace DataFile