예제 #1
0
	bool parser::parse_number(context& ctx, number_type& value, IteratorType& ch, IteratorType end)
	{
		ctx.clear();

		// Check if the number is negative
		if (ch != end)
		{
			if (*ch == '-')
			{
				ctx.push_char(*ch);
				++ch;
			}
		}

		if (ch == end)
		{
			return false;
		}

		switch (*ch)
		{
			case '0':
				ctx.push_char(*ch);
				++ch;
				break;

			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				ctx.push_char(*ch);
				++ch;

				while ((ch != end) && std::isdigit(*ch))
				{
					ctx.push_char(*ch);
					++ch;
				}

				break;
		}

		// Check for a period
		if (ch != end)
		{
			if (*ch == '.')
			{
				ctx.push_char(*ch);
				++ch;

				while ((ch != end) && std::isdigit(*ch))
				{
					ctx.push_char(*ch);
					++ch;
				}
			}
		}

		// Check for an exponent
		if (ch != end)
		{
			if ((*ch == 'e') || (*ch == 'E'))
			{
				ctx.push_char(*ch);
				++ch;

				if (ch == end)
				{
					return false;
				}

				switch (*ch)
				{
					case '-':
						ctx.push_char(*ch);
						++ch;
						break;

					case '+':
						ctx.push_char(*ch);
						++ch;
						break;
				}

				if (ch == end)
				{
					return false;
				}

				while ((ch != end) && std::isdigit(*ch))
				{
					ctx.push_char(*ch);
					++ch;
				}
			}
		}

		if (!ctx.get_number(value))
		{
			return false;
		}

		return true;
	}
예제 #2
0
	bool parser::parse_string(context& ctx, string_type& value, IteratorType& ch, IteratorType end)
	{
		ctx.clear();

		if (!check_char(ctx, '"', ch, end))
		{
			return false;
		}

		while (ch != end)
		{
			if (std::iscntrl(*ch))
			{
				return false;
			}

			switch (*ch)
			{
				case '"':
					{
						// The string ends.
						++ch;

						value = ctx.str();

						return true;
					}

				case '\\':
					{
						// An escape character was provided.
						++ch;

						if (ch == end)
						{
							return false;
						}

						switch (*ch)
						{
							case '"':
								ctx.push_char('"');
								++ch;
								break;

							case '\\':
								ctx.push_char('\\');
								++ch;
								break;

							case '/':
								ctx.push_char('/');
								++ch;
								break;

							case 'b':
								ctx.push_char('\b');
								++ch;
								break;

							case 'n':
								ctx.push_char('\n');
								++ch;
								break;

							case 'f':
								ctx.push_char('\f');
								++ch;
								break;

							case 'r':
								ctx.push_char('\r');
								++ch;
								break;

							case 't':
								ctx.push_char('\t');
								++ch;
								break;

							case 'u':
								{
									++ch;

									uint16_t codepoint = 0x0000;

									for (size_t i = 0; i < 4; ++i)
									{
										if (ch == end)
										{
											return false;
										}

										if (!std::isxdigit(*ch))
										{
											return false;
										}

										codepoint *= 16;
										codepoint += xdigit_to_int(*ch);

										++ch;
									}

									ctx.push_codepoint(codepoint);

									break;
								}

							default:
								return false;
						}

						break;
					}

				default:
					{
						ctx.push_char(*ch);

						++ch;
					}
			}
		}

		return false;
	}