2 This file is part of libmspparser
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
8 #include <msp/streams/format.h>
10 #include "statement.h"
20 Parser::Parser(istream &i, const string &s):
26 Statement Parser::parse()
29 throw Exception("Parser is not good");
35 catch(const Exception &e)
42 Statement Parser::parse_(const Token *t)
59 if(result.keyword.empty())
63 else if(token.type!=Token::IDENTIFIER)
64 throw DataError(get_location()+format(": Syntax error at token '%S' (expected an identifier)", &token.str).str());
65 result.keyword=token.str;
68 result.line=in.get_line_number();
79 Statement ss=parse_(&token);
80 result.sub.push_back(ss);
86 throw DataError(get_location()+format(": Syntax error at token '%S' (Expected a ';')", &token.str).str());
89 else if(token.str=="{")
91 else if(token.str==";")
93 else if(token.type==Token::INTEGER)
94 result.args.push_back(Value(Value::INTEGER, token.str));
95 else if(token.type==Token::FLOAT)
96 result.args.push_back(Value(Value::FLOAT, token.str));
97 else if(token.type==Token::STRING)
98 result.args.push_back(Value(Value::STRING, token.str));
99 else if(token.type==Token::IDENTIFIER)
101 //result.args.push_back(resolve_identifiertoken.str);
103 else if(token.str=="")
104 throw DataError(src+": Unexcepted EOF");
106 throw DataError(get_location()+": Syntax error");
112 Token Parser::parse_token()
121 //cout<<c<<' '<<next<<'\n';
123 if(c=='/' && next=='/')
125 else if(c=='/' && next=='*')
127 else if(c=='\n' && comment==1)
129 else if(c=='*' && next=='/' && comment==2)
131 else if(comment==3) // Skip the second character of block comment end
133 else if(!isspace(c) && !comment)
137 throw DataError(src+": Unfinished comment");
153 static Token::Type token_type[]=
167 ParseState state=INIT;
190 else if(c=='{' || c=='}' || c==';')
191 return Token(Token::SPECIAL, string(1, c));
197 parse_error(c, state);
208 parse_error(c, state);
219 parse_error(c, state);
226 parse_error(c, state);
231 parse_error(c, state);
236 parse_error(c, state);
241 parse_error(c, state);
247 else if(c=='"' && !escape)
248 return Token(Token::STRING, unescape_string(buf));
254 if(!isalpha(c) && !isdigit(c) && c!='_')
255 parse_error(c, state);
259 throw Exception(get_location()+": Internal error (bad state)");
262 if(is_delimiter(next) && state>=ACCEPT)
263 return Token(token_type[state], buf);
266 return Token(Token::SPECIAL, "");
269 bool Parser::is_delimiter(int c)
271 return (isspace(c) || c=='{' || c=='}' || c==';' || c=='/');
274 bool Parser::isodigit(int c)
276 return (c>='0' && c<='7');
279 string Parser::unescape_string(const string &str)
284 for(string::const_iterator i=str.begin()+1; i!=str.end()-1; ++i)
299 throw DataError("Invalid escape");
305 if(*i>='0' && *i<='9')
307 else if(*i>='a' && *i<='f')
309 else if(*i>='A' && *i<='F')
312 throw DataError("Invalid hex digit");
314 hexcape=(hexcape<<4)|digit;
317 result+=hexcape&0xFF;
330 string Parser::get_location()
333 ss<<src<<':'<<in.get_line_number();
337 void Parser::parse_error(int c, int state)
339 throw DataError(get_location()+format(": Parse error at '%c' (state %d)", c, state).str());
342 } // namespace Parser