2 This file is part of libmspparser
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
10 #include "statement.h"
18 Parser::Parser(istream &i, const string &s):
24 Statement Parser::parse()
27 throw Exception("Parser is not good");
33 catch(const Exception &e)
40 Statement Parser::parse_(const Token *t)
57 if(result.keyword.empty())
61 else if(token.type!=Token::IDENTIFIER)
62 throw DataError(get_location()+": Syntax error at token '"+token.str+"' (expected an identifier)");
63 result.keyword=token.str;
66 result.line=in.get_line_number();
77 Statement ss=parse_(&token);
78 result.sub.push_back(ss);
84 throw DataError(get_location()+": Syntax error at token '"+token.str+"' (Expected a ';')");
87 else if(token.str=="{")
89 else if(token.str==";")
91 else if(token.type==Token::INTEGER)
92 result.args.push_back(Value(Value::INTEGER, token.str));
93 else if(token.type==Token::FLOAT)
94 result.args.push_back(Value(Value::FLOAT, token.str));
95 else if(token.type==Token::STRING)
96 result.args.push_back(Value(Value::STRING, token.str));
97 else if(token.type==Token::IDENTIFIER)
100 result.args.push_back(Value(Value::BOOLEAN, "1"));
101 else if(token.str=="false")
102 result.args.push_back(Value(Value::BOOLEAN, "0"));
104 result.args.push_back(Value(Value::ENUM, token.str));
105 //result.args.push_back(resolve_identifiertoken.str);
107 else if(token.str=="")
108 throw DataError(src+": Unexcepted EOF");
110 throw DataError(get_location()+": Syntax error");
116 Token Parser::parse_token()
125 //cout<<c<<' '<<next<<'\n';
127 if(c=='/' && next=='/')
129 else if(c=='/' && next=='*')
131 else if(c=='\n' && comment==1)
133 else if(c=='*' && next=='/' && comment==2)
135 else if(comment==3) // Skip the second character of block comment end
137 else if(!isspace(c) && !comment)
141 throw DataError(src+": Unfinished comment");
157 static Token::Type token_type[]=
171 ParseState state=INIT;
194 else if(c=='{' || c=='}' || c==';')
195 return Token(Token::SPECIAL, string(1, c));
201 parse_error(c, state);
212 parse_error(c, state);
223 parse_error(c, state);
230 parse_error(c, state);
235 parse_error(c, state);
240 parse_error(c, state);
245 parse_error(c, state);
251 else if(c=='"' && !escape)
252 return Token(Token::STRING, unescape_string(buf));
258 if(!isalpha(c) && !isdigit(c) && c!='_')
259 parse_error(c, state);
263 throw Exception(get_location()+": Internal error (bad state)");
266 if(is_delimiter(next) && state>=ACCEPT)
267 return Token(token_type[state], buf);
270 return Token(Token::SPECIAL, "");
273 bool Parser::is_delimiter(int c)
275 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
278 bool Parser::isodigit(int c)
280 return (c>='0' && c<='7');
283 string Parser::unescape_string(const string &str)
288 for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i)
303 throw DataError("Invalid escape");
309 if(*i>='0' && *i<='9')
311 else if(*i>='a' && *i<='f')
313 else if(*i>='A' && *i<='F')
316 throw DataError("Invalid hex digit");
318 hexcape=(hexcape<<4)|digit;
321 result+=hexcape&0xFF;
334 string Parser::get_location()
337 ss<<src<<':'<<in.get_line_number();
341 void Parser::parse_error(int c, int state)
344 ss<<get_location()<<": Parse error at '"<<c<<"' (state "<<state<<')';
345 throw DataError(ss.str());
348 } // namespace Parser