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::BRACKET_OPEN:
111 case Tokenizer::Token::PARENTHESIS_OPEN:
112 case Tokenizer::Token::NUMBER:
113 case Tokenizer::Token::STRING:
114 case Tokenizer::Token::KEYWORD_FALSE:
115 case Tokenizer::Token::KEYWORD_TRUE:
116 case Tokenizer::Token::TYPE_NAME:
123 bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const {
124 return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
127 Definition *Parser::ParseDefinition() {
128 string typeName(ParseTypeName());
129 string identifier(ParseIdentifier());
131 Tokenizer::Token t(GetToken());
133 if (BeginOfPropertyList(t)) {
134 PropertyList *propertyList(ParsePropertyList());
135 Definition *dfn(new Definition(typeName, identifier));
136 dfn->SetValue(propertyList);
138 } else if (BeginningOfLiteral(t)) {
139 Literal *literal(ParseLiteral());
140 Definition *dfn(new Definition(typeName, identifier));
141 dfn->SetValue(literal);
144 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected property-list or literal");
148 string Parser::ParseIdentifier() {
149 Tokenizer::Token t(GetToken());
150 AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER);
154 string Parser::ParseTypeName() {
155 Tokenizer::Token t(GetToken());
156 AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME);
160 PropertyList *Parser::ParsePropertyList() {
161 Tokenizer::Token t(GetToken());
162 AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN);
164 auto_ptr<PropertyList> props(new PropertyList);
166 while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
167 Tokenizer::Token name(GetToken());
168 AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER);
171 AssertTokenType(t.type, Tokenizer::Token::COLON);
173 Value *value(ParseValue());
174 props->SetProperty(name.str, value);
177 if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
178 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }");
182 return props.release();
185 Value *Parser::ParseValue() {
186 Tokenizer::Token t(GetToken());
187 if (t.type == Tokenizer::Token::IDENTIFIER) {
188 return new Value(t.str);
189 } else if (BeginningOfLiteral(t)) {
191 Literal *literal(ParseLiteral());
192 return new Value(literal);
194 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected literal or identifier");
198 Literal *Parser::ParseLiteral() {
199 Tokenizer::Token t(GetToken());
200 if (t.type == Tokenizer::Token::TYPE_NAME) {
201 PropertyList *props(ParsePropertyList());
202 return new Literal(t.str, props);
203 } else if (BeginningOfLiteral(t)) {
205 case Tokenizer::Token::CHEVRON_OPEN:
207 return ParseVector();
208 case Tokenizer::Token::BRACKET_OPEN:
211 case Tokenizer::Token::PARENTHESIS_OPEN:
214 case Tokenizer::Token::NUMBER:
215 return new Literal(t.number);
216 case Tokenizer::Token::STRING:
217 return new Literal(t.str);
218 case Tokenizer::Token::KEYWORD_FALSE:
219 return new Literal(false);
220 case Tokenizer::Token::KEYWORD_TRUE:
221 return new Literal(true);
223 throw std::logic_error("literal switch reached impossible default branch oO");
226 throw new Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected type-name or primitive");
230 Literal *Parser::ParseArray() {
231 Tokenizer::Token t(GetToken());
232 AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN);
234 Tokenizer::Token probe(GetToken());
237 if (probe.type == Tokenizer::Token::ANGLE_BRACKET_OPEN) {
238 vector<PropertyList *> values;
239 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
240 PropertyList *value(ParsePropertyList());
241 values.push_back(value);
244 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
245 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
248 return new Literal(values);
250 vector<Value *> values;
251 while (t.type != Tokenizer::Token::BRACKET_CLOSE) {
252 Value *value(ParseValue());
253 values.push_back(value);
256 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
257 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
260 return new Literal(values);
264 Literal *Parser::ParseColor() {
265 string msg("error parsing color");
266 Tokenizer::Token t(GetToken());
267 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg);
269 Tokenizer::Token red(GetToken());
270 AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color");
273 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
275 Tokenizer::Token green(GetToken());
276 AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color");
279 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
281 Tokenizer::Token blue(GetToken());
282 AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color");
285 if (t.type == Tokenizer::Token::BRACKET_CLOSE) {
286 return new Literal(red.number, green.number, blue.number);
287 } else if (t.type != Tokenizer::Token::COMMA) {
288 Tokenizer::Token alpha(GetToken());
289 AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color");
292 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg);
294 return new Literal(red.number, green.number, blue.number, alpha.number);
296 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
300 Literal *Parser::ParseVector() {
301 std::string msg("error parsing vector");
302 Tokenizer::Token t(GetToken());
303 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg);
305 Tokenizer::Token x(GetToken());
306 AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector");
309 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
311 Tokenizer::Token y(GetToken());
312 AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector");
315 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg);
317 return new Literal(x.number, y.number);
320 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
321 if (expected != actual) {
322 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
326 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) {
327 if (expected != actual) {
328 throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));