4 * Created on: Aug 26, 2012
22 Parser::Parser(const string &file, ParsedSource &product)
24 , dirname(Dirname(file))
25 , in(this->file.c_str())
29 throw Error(file, 0, "unable to read file");
33 void Parser::Parse() {
34 while (tok.HasMore()) {
39 void Parser::ParseStatement() {
40 Tokenizer::Token t(GetToken());
42 case Tokenizer::Token::KEYWORD_EXPORT:
43 ParseExportDirective();
45 case Tokenizer::Token::KEYWORD_INCLUDE:
46 ParseIncludeDirective();
48 case Tokenizer::Token::TYPE_NAME:
51 Declaration *decl(ProbeDefinition());
52 product.AddDeclaration(decl);
56 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type));
60 Tokenizer::Token Parser::GetToken() try {
62 } catch (Tokenizer::LexerError &e) {
63 throw Error(file, e.Line(), e.what());
66 void Parser::ParseExportDirective() {
67 Tokenizer::Token t(GetToken());
68 if (t.type != Tokenizer::Token::IDENTIFIER) {
70 Declaration *decl(ProbeDefinition());
71 product.ExportDeclaration(decl);
73 product.ExportIdentifier(t.str);
77 void Parser::ParseIncludeDirective() {
78 Tokenizer::Token t(GetToken());
79 AssertTokenType(t.type, Tokenizer::Token::STRING);
80 Parser sub(CatPath(dirname, t.str), product);
84 Declaration *Parser::ProbeDefinition() {
85 string typeName(ParseTypeName());
86 string identifier(ParseIdentifier());
88 Tokenizer::Token t(GetToken());
90 if (BeginOfPropertyList(t)) {
91 auto_ptr<PropertyList> propertyList(ParsePropertyList());
92 auto_ptr<Definition> dfn(new Definition(typeName, identifier));
93 dfn->SetValue(propertyList.release());
94 product.AddDefinition(dfn.get());
96 } else if (BeginningOfLiteral(t)) {
97 auto_ptr<Literal> literal(ParseLiteral());
98 auto_ptr<Definition> dfn(new Definition(typeName, identifier));
99 dfn->SetValue(literal.release());
100 product.AddDefinition(dfn.get());
101 return dfn.release();
103 return new Declaration(typeName, identifier);
107 bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const {
109 case Tokenizer::Token::CHEVRON_OPEN:
110 case Tokenizer::Token::COLON:
111 case Tokenizer::Token::BRACKET_OPEN:
112 case Tokenizer::Token::PARENTHESIS_OPEN:
113 case Tokenizer::Token::NUMBER:
114 case Tokenizer::Token::STRING:
115 case Tokenizer::Token::KEYWORD_FALSE:
116 case Tokenizer::Token::KEYWORD_TRUE:
117 case Tokenizer::Token::TYPE_NAME:
124 bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const {
125 return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
128 Definition *Parser::ParseDefinition() {
129 string typeName(ParseTypeName());
130 string identifier(ParseIdentifier());
132 Tokenizer::Token t(GetToken());
134 if (BeginOfPropertyList(t)) {
135 PropertyList *propertyList(ParsePropertyList());
136 Definition *dfn(new Definition(typeName, identifier));
137 dfn->SetValue(propertyList);
139 } else if (BeginningOfLiteral(t)) {
140 Literal *literal(ParseLiteral());
141 Definition *dfn(new Definition(typeName, identifier));
142 dfn->SetValue(literal);
145 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected property-list or literal");
149 string Parser::ParseIdentifier() {
150 Tokenizer::Token t(GetToken());
151 AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER);
155 string Parser::ParseTypeName() {
156 Tokenizer::Token t(GetToken());
157 AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME);
161 PropertyList *Parser::ParsePropertyList() {
162 Tokenizer::Token t(GetToken());
163 AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN);
165 auto_ptr<PropertyList> props(new PropertyList);
167 while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
168 Tokenizer::Token name(GetToken());
169 AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER);
172 AssertTokenType(t.type, Tokenizer::Token::COLON);
174 Value *value(ParseValue());
175 props->SetProperty(name.str, value);
178 if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
179 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }");
183 return props.release();
186 Value *Parser::ParseValue() {
187 Tokenizer::Token t(GetToken());
188 if (t.type == Tokenizer::Token::IDENTIFIER) {
189 return new Value(t.str);
190 } else if (BeginningOfLiteral(t)) {
192 Literal *literal(ParseLiteral());
193 return new Value(literal);
195 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected literal or identifier");
199 Literal *Parser::ParseLiteral() {
200 Tokenizer::Token t(GetToken());
201 if (t.type == Tokenizer::Token::TYPE_NAME) {
202 PropertyList *props(ParsePropertyList());
203 return new Literal(t.str, props);
204 } else if (BeginningOfLiteral(t)) {
206 case Tokenizer::Token::CHEVRON_OPEN:
208 return ParseVector();
209 case Tokenizer::Token::COLON:
211 AssertTokenType(t.type, Tokenizer::Token::STRING);
212 return new Literal(dirname, t.str);
213 case Tokenizer::Token::BRACKET_OPEN:
216 case Tokenizer::Token::PARENTHESIS_OPEN:
219 case Tokenizer::Token::NUMBER:
220 return new Literal(t.number);
221 case Tokenizer::Token::STRING:
222 return new Literal(t.str);
223 case Tokenizer::Token::KEYWORD_FALSE:
224 return new Literal(false);
225 case Tokenizer::Token::KEYWORD_TRUE:
226 return new Literal(true);
228 throw std::logic_error("literal switch reached impossible default branch oO");
231 throw new Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected type-name or primitive");
235 Literal *Parser::ParseArray() {
236 Tokenizer::Token t(GetToken());
237 AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN);
239 Tokenizer::Token probe(GetToken());
242 if (probe.type == Tokenizer::Token::ANGLE_BRACKET_OPEN) {
243 vector<PropertyList *> values;
244 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
245 PropertyList *value(ParsePropertyList());
246 values.push_back(value);
249 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
250 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
253 return new Literal(values);
255 vector<Value *> values;
256 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
257 Value *value(ParseValue());
258 values.push_back(value);
261 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
262 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
265 return new Literal(values);
269 Literal *Parser::ParseColor() {
270 string msg("error parsing color");
271 Tokenizer::Token t(GetToken());
272 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg);
274 Tokenizer::Token red(GetToken());
275 AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color");
278 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
280 Tokenizer::Token green(GetToken());
281 AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color");
284 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
286 Tokenizer::Token blue(GetToken());
287 AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color");
290 if (t.type == Tokenizer::Token::BRACKET_CLOSE) {
291 return new Literal(red.number, green.number, blue.number);
292 } else if (t.type != Tokenizer::Token::COMMA) {
293 Tokenizer::Token alpha(GetToken());
294 AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color");
297 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg);
299 return new Literal(red.number, green.number, blue.number, alpha.number);
301 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
305 Literal *Parser::ParseVector() {
306 std::string msg("error parsing vector");
307 Tokenizer::Token t(GetToken());
308 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg);
310 Tokenizer::Token x(GetToken());
311 AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector");
314 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
316 Tokenizer::Token y(GetToken());
317 AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector");
320 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg);
322 return new Literal(x.number, y.number);
325 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
326 if (expected != actual) {
327 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
331 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) {
332 if (expected != actual) {
333 throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));