bool Parser::parseIdentifier (Lexer& lexer, string* output) { if (lexer.getType () != Lexer::IDENTIFIER) return this->fail (lexer, "expected column identifier"); *output = lexer.getCurrent (); lexer.next (); return true; }
bool Parser::parseValue (Lexer& lexer, Lookup& lookup, Int32u* slot, const Extractor** output) { const Extractor* argument; Extractors arguments; const Constant* constant; const Function* function; string name; Float64 number; switch (lexer.getType ()) { case Lexer::IDENTIFIER: name = lexer.getCurrent (); lexer.next (); if (lexer.getType () == Lexer::PARENTHESIS_BEGIN) { function = 0; for (Int32u i = 0; Function::functions[i].name; ++i) { if (Function::functions[i].name == name) { function = &Function::functions[i]; break; } } if (!function) return this->fail (lexer, string ("unknown function name '") + lexer.getCurrent () + "'"); lexer.next (); while (lexer.getType () != Lexer::PARENTHESIS_END) { if (arguments.size () > 0 && !this->parseType (lexer, Lexer::COMMA, "argument separator")) return false; if (!this->parseExpression (lexer, lookup, slot, &argument)) return false; arguments.push_back (argument); } lexer.next (); if (arguments.size () < function->min || (function->max > 0 && arguments.size () > function->max)) return this->fail (lexer, "wrong number of arguments"); *output = function->builder (arguments, slot); } else { constant = 0; for (Int32u i = 0; Constant::constants[i].name; ++i) { if (Constant::constants[i].name == name) { constant = &Constant::constants[i]; break; } } if (constant) *output = new ConstantExtractor (constant->value); else *output = new FieldExtractor (lookup.store (name)); } break; case Lexer::NUMBER: if (!Convert::toFloat (&number, lexer.getCurrent ().data (), lexer.getCurrent ().length ())) return this->fail (lexer, "invalid number"); *output = new ConstantExtractor (Variant (number)); lexer.next (); break; case Lexer::STRING: *output = new ConstantExtractor (Variant (lexer.getCurrent ())); lexer.next (); break; default: this->fail (lexer, "unexpected character"); return false; } this->extractors.push_back (*output); return true; }