4 * Created on: Aug 26, 2012
20 void Parser::Parse() {
21 while (tok.HasMore()) {
26 void Parser::ParseStatement() {
27 Tokenizer::Token t(GetToken());
29 case Tokenizer::Token::KEYWORD_EXPORT:
30 ParseExportDirective();
32 case Tokenizer::Token::KEYWORD_INCLUDE:
33 ParseIncludeDirective();
35 case Tokenizer::Token::TYPE_NAME:
38 Declaration *decl(ProbeDefinition());
39 product.AddDeclaration(decl);
43 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type));
47 Tokenizer::Token Parser::GetToken() try {
49 } catch (Tokenizer::LexerError &e) {
50 throw Error(file, e.Line(), e.what());
53 void Parser::ParseExportDirective() {
54 Tokenizer::Token t(GetToken());
55 if (t.type != Tokenizer::Token::IDENTIFIER) {
57 Declaration *decl(ProbeDefinition());
58 product.ExportDeclaration(decl);
60 product.ExportIdentifier(t.str);
64 void Parser::ParseIncludeDirective() {
65 Tokenizer::Token t(GetToken());
66 AssertTokenType(t.type, Tokenizer::Token::STRING);
67 Parser sub(t.str.c_str(), product); // TODO: resolve path name
71 Declaration *Parser::ProbeDefinition() {
72 string typeName(ParseTypeName());
73 string identifier(ParseIdentifier());
75 Tokenizer::Token t(GetToken());
77 if (BeginOfPropertyList(t)) {
78 auto_ptr<PropertyList> propertyList(ParsePropertyList());
79 auto_ptr<Definition> dfn(new Definition(typeName, identifier));
80 dfn->SetValue(propertyList.release());
81 product.AddDefinition(dfn.get());
83 } else if (BeginningOfLiteral(t)) {
84 auto_ptr<Literal> literal(ParseLiteral());
85 auto_ptr<Definition> dfn(new Definition(typeName, identifier));
86 dfn->SetValue(literal.release());
87 product.AddDefinition(dfn.get());
90 return new Declaration(typeName, identifier);
94 bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const {
96 case Tokenizer::Token::CHEVRON_OPEN:
97 case Tokenizer::Token::BRACKET_OPEN:
98 case Tokenizer::Token::PARENTHESIS_OPEN:
99 case Tokenizer::Token::NUMBER:
100 case Tokenizer::Token::STRING:
101 case Tokenizer::Token::KEYWORD_FALSE:
102 case Tokenizer::Token::KEYWORD_TRUE:
103 case Tokenizer::Token::TYPE_NAME:
110 bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const {
111 return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
114 Definition *Parser::ParseDefinition() {
115 string typeName(ParseTypeName());
116 string identifier(ParseIdentifier());
118 Tokenizer::Token t(GetToken());
120 if (BeginOfPropertyList(t)) {
121 PropertyList *propertyList(ParsePropertyList());
122 Definition *dfn(new Definition(typeName, identifier));
123 dfn->SetValue(propertyList);
125 } else if (BeginningOfLiteral(t)) {
126 Literal *literal(ParseLiteral());
127 Definition *dfn(new Definition(typeName, identifier));
128 dfn->SetValue(literal);
131 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected property-list or literal");
135 string Parser::ParseIdentifier() {
136 Tokenizer::Token t(GetToken());
137 AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER);
141 string Parser::ParseTypeName() {
142 Tokenizer::Token t(GetToken());
143 AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME);
147 PropertyList *Parser::ParsePropertyList() {
148 Tokenizer::Token t(GetToken());
149 AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN);
151 auto_ptr<PropertyList> props(new PropertyList);
153 while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
154 Tokenizer::Token name(GetToken());
155 AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER);
158 AssertTokenType(t.type, Tokenizer::Token::COLON);
160 Value *value(ParseValue());
161 props->SetProperty(name.str, value);
164 if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
165 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }");
169 return props.release();
172 Value *Parser::ParseValue() {
173 Tokenizer::Token t(GetToken());
174 if (t.type == Tokenizer::Token::IDENTIFIER) {
175 return new Value(t.str);
176 } else if (BeginningOfLiteral(t)) {
178 Literal *literal(ParseLiteral());
179 return new Value(literal);
181 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected literal or identifier");
185 Literal *Parser::ParseLiteral() {
186 Tokenizer::Token t(GetToken());
187 if (t.type == Tokenizer::Token::TYPE_NAME) {
188 PropertyList *props(ParsePropertyList());
189 return new Literal(t.str, props);
190 } else if (BeginningOfLiteral(t)) {
192 case Tokenizer::Token::CHEVRON_OPEN:
194 return ParseVector();
195 case Tokenizer::Token::BRACKET_OPEN:
198 case Tokenizer::Token::PARENTHESIS_OPEN:
201 case Tokenizer::Token::NUMBER:
202 return new Literal(t.number);
203 case Tokenizer::Token::STRING:
204 return new Literal(t.str);
205 case Tokenizer::Token::KEYWORD_FALSE:
206 return new Literal(false);
207 case Tokenizer::Token::KEYWORD_TRUE:
208 return new Literal(true);
210 throw std::logic_error("literal switch reached impossible default branch oO");
213 throw new Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected type-name or primitive");
217 Literal *Parser::ParseArray() {
218 Tokenizer::Token t(GetToken());
219 AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN);
221 Tokenizer::Token probe(GetToken());
224 if (probe.type == Tokenizer::Token::ANGLE_BRACKET_OPEN) {
225 vector<PropertyList *> values;
226 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
227 PropertyList *value(ParsePropertyList());
228 values.push_back(value);
231 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
232 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
235 return new Literal(values);
237 vector<Value *> values;
238 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
239 Value *value(ParseValue());
240 values.push_back(value);
243 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
244 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
247 return new Literal(values);
251 Literal *Parser::ParseColor() {
252 string msg("error parsing color");
253 Tokenizer::Token t(GetToken());
254 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg);
256 Tokenizer::Token red(GetToken());
257 AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color");
260 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
262 Tokenizer::Token green(GetToken());
263 AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color");
266 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
268 Tokenizer::Token blue(GetToken());
269 AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color");
272 if (t.type == Tokenizer::Token::BRACKET_CLOSE) {
273 return new Literal(red.number, green.number, blue.number);
274 } else if (t.type != Tokenizer::Token::COMMA) {
275 Tokenizer::Token alpha(GetToken());
276 AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color");
279 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg);
281 return new Literal(red.number, green.number, blue.number, alpha.number);
283 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
287 Literal *Parser::ParseVector() {
288 std::string msg("error parsing vector");
289 Tokenizer::Token t(GetToken());
290 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg);
292 Tokenizer::Token x(GetToken());
293 AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector");
296 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
298 Tokenizer::Token y(GetToken());
299 AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector");
302 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg);
304 return new Literal(x.number, y.number);
307 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
308 if (expected != actual) {
309 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
313 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) {
314 if (expected != actual) {
315 throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));