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 PropertyList *propertyList(ParsePropertyList());
79 Definition *dfn(new Definition(typeName, identifier));
80 dfn->SetValue(propertyList);
82 } else if (BeginningOfLiteral(t)) {
83 Literal *literal(ParseLiteral());
84 Definition *dfn(new Definition(typeName, identifier));
85 dfn->SetValue(literal);
88 return new Declaration(typeName, identifier);
92 bool Parser::BeginningOfLiteral(const Tokenizer::Token &t) const {
94 case Tokenizer::Token::CHEVRON_OPEN:
95 case Tokenizer::Token::BRACKET_OPEN:
96 case Tokenizer::Token::PARENTHESIS_OPEN:
97 case Tokenizer::Token::NUMBER:
98 case Tokenizer::Token::STRING:
99 case Tokenizer::Token::KEYWORD_FALSE:
100 case Tokenizer::Token::KEYWORD_TRUE:
101 case Tokenizer::Token::TYPE_NAME:
108 bool Parser::BeginOfPropertyList(const Tokenizer::Token &t) const {
109 return t.type == Tokenizer::Token::ANGLE_BRACKET_OPEN;
112 Definition *Parser::ParseDefinition() {
113 string typeName(ParseTypeName());
114 string identifier(ParseIdentifier());
116 Tokenizer::Token t(GetToken());
118 if (BeginOfPropertyList(t)) {
119 PropertyList *propertyList(ParsePropertyList());
120 Definition *dfn(new Definition(typeName, identifier));
121 dfn->SetValue(propertyList);
123 } else if (BeginningOfLiteral(t)) {
124 Literal *literal(ParseLiteral());
125 Definition *dfn(new Definition(typeName, identifier));
126 dfn->SetValue(literal);
129 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected property-list or literal");
133 string Parser::ParseIdentifier() {
134 Tokenizer::Token t(GetToken());
135 AssertTokenType(t.type, Tokenizer::Token::IDENTIFIER);
139 string Parser::ParseTypeName() {
140 Tokenizer::Token t(GetToken());
141 AssertTokenType(t.type, Tokenizer::Token::TYPE_NAME);
145 PropertyList *Parser::ParsePropertyList() {
146 Tokenizer::Token t(GetToken());
147 AssertTokenType(t.type, Tokenizer::Token::ANGLE_BRACKET_OPEN);
149 auto_ptr<PropertyList> props(new PropertyList);
151 while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
152 Tokenizer::Token name(GetToken());
153 AssertTokenType(name.type, Tokenizer::Token::IDENTIFIER);
156 AssertTokenType(t.type, Tokenizer::Token::COLON);
158 Value *value(ParseValue());
159 props->SetProperty(name.str, value);
162 if (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
163 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or }");
167 return props.release();
170 Value *Parser::ParseValue() {
171 Tokenizer::Token t(GetToken());
172 if (t.type == Tokenizer::Token::IDENTIFIER) {
173 return new Value(t.str);
174 } else if (BeginningOfLiteral(t)) {
176 Literal *literal(ParseLiteral());
177 return new Value(literal);
179 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected literal or identifier");
183 Literal *Parser::ParseLiteral() {
184 Tokenizer::Token t(GetToken());
185 if (t.type == Tokenizer::Token::TYPE_NAME) {
186 PropertyList *props(ParsePropertyList());
187 return new Literal(t.str, props);
188 } else if (BeginningOfLiteral(t)) {
190 case Tokenizer::Token::CHEVRON_OPEN:
192 return ParseVector();
193 case Tokenizer::Token::BRACKET_OPEN:
196 case Tokenizer::Token::PARENTHESIS_OPEN:
199 case Tokenizer::Token::NUMBER:
200 return new Literal(t.number);
201 case Tokenizer::Token::STRING:
202 return new Literal(t.str);
203 case Tokenizer::Token::KEYWORD_FALSE:
204 return new Literal(false);
205 case Tokenizer::Token::KEYWORD_TRUE:
206 return new Literal(true);
208 throw std::logic_error("literal switch reached impossible default branch oO");
211 throw new Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected type-name or primitive");
215 Literal *Parser::ParseArray() {
216 Tokenizer::Token t(GetToken());
217 AssertTokenType(t.type, Tokenizer::Token::BRACKET_OPEN);
219 vector<Value *> values;
221 while (t.type != Tokenizer::Token::ANGLE_BRACKET_CLOSE) {
222 Value *value(ParseValue());
223 values.push_back(value);
226 if (t.type != Tokenizer::Token::BRACKET_CLOSE && t.type != Tokenizer::Token::COMMA) {
227 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
231 return new Literal(values);
234 Literal *Parser::ParseColor() {
235 string msg("error parsing color");
236 Tokenizer::Token t(GetToken());
237 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_OPEN, msg);
239 Tokenizer::Token red(GetToken());
240 AssertTokenType(red.type, Tokenizer::Token::NUMBER, "error parsing red component of color");
243 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
245 Tokenizer::Token green(GetToken());
246 AssertTokenType(green.type, Tokenizer::Token::NUMBER, "error parsing green component of color");
249 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
251 Tokenizer::Token blue(GetToken());
252 AssertTokenType(blue.type, Tokenizer::Token::NUMBER, "error parsing blue component of color");
255 if (t.type == Tokenizer::Token::BRACKET_CLOSE) {
256 return new Literal(red.number, green.number, blue.number);
257 } else if (t.type != Tokenizer::Token::COMMA) {
258 Tokenizer::Token alpha(GetToken());
259 AssertTokenType(alpha.type, Tokenizer::Token::NUMBER, "error parsing alpha component of color");
262 AssertTokenType(t.type, Tokenizer::Token::PARENTHESIS_CLOSE, msg);
264 return new Literal(red.number, green.number, blue.number, alpha.number);
266 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]");
270 Literal *Parser::ParseVector() {
271 std::string msg("error parsing vector");
272 Tokenizer::Token t(GetToken());
273 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_OPEN, msg);
275 Tokenizer::Token x(GetToken());
276 AssertTokenType(x.type, Tokenizer::Token::NUMBER, "error parsing x component of vector");
279 AssertTokenType(t.type, Tokenizer::Token::COMMA, msg);
281 Tokenizer::Token y(GetToken());
282 AssertTokenType(y.type, Tokenizer::Token::NUMBER, "error parsing y component of vector");
285 AssertTokenType(t.type, Tokenizer::Token::CHEVRON_CLOSE, msg);
287 return new Literal(x.number, y.number);
290 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected) {
291 if (expected != actual) {
292 throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));
296 void Parser::AssertTokenType(Tokenizer::Token::Type actual, Tokenizer::Token::Type expected, const string &msg) {
297 if (expected != actual) {
298 throw Error(file, tok.Line(), msg + ": unexpected token " + TokenTypeToString(actual) + ", expected " + TokenTypeToString(expected));