
#ifndef EL_DOM_SGML_PARSER_H
#define EL_DOM_SGML_PARSER_H

#include "dom/node.h"
#include "dom/stack.h"
#include "dom/sgml/sgml.h"
#include "dom/scanner.h"

struct sgml_parser;
struct string;
struct uri;

/** enum:[sgml_parser_type]: SGML parser type
 *
 * There are two kinds of parser types: One that optimises one-time access to
 * the DOM tree and one that creates a persistent DOM tree. */
enum sgml_parser_type {
	/** id:[SGML_PARSER_TREE]:: The first one is a DOM tree builder. */
	SGML_PARSER_TREE,
	/** id:[SGML_PARSER_TREE]::
	 * The second one will simply push nodes on the stack, not building a
	 * DOM tree. This interface is similar to that of SAX (Simple API for
	 * XML) where events are fired when nodes are entered and exited. It is
	 * useful when you are not actually interested in the DOM tree, but can
	 * do all processing in a stream-like manner, such as when highlighting
	 * HTML code. */
	SGML_PARSER_STREAM,
};

enum sgml_parser_flag {
	SGML_PARSER_COUNT_LINES	= 1,
	SGML_PARSER_COMPLETE = 2,
	SGML_PARSER_INCREMENTAL = 4,
	SGML_PARSER_DETECT_ERRORS = 8,
};

struct sgml_parser_state {
	/* Info about the properties of the node contained by state.
	 * This is only meaningful to element and attribute nodes. For
	 * unknown nodes it points to the common 'unknown node' info. */
	struct sgml_node_info *info;
	/* This is used by the DOM source renderer for highlighting the
	 * end-tag of an element. */
	struct dom_scanner_token end_token;
};

/** enum:[sgml_parser_code]: (Error) codes for the SGML parser
 *
 * These enum values are used
 *
 */
enum sgml_parser_code {
	SGML_PARSER_CODE_OK,		/*:: The parsing was successful */
	SGML_PARSER_CODE_INCOMPLETE,	/*:: The parsing could not be completed */
	SGML_PARSER_CODE_MEM_ALLOC,	/*:: Failed to allocate memory */

	/** id:[SGML_PARSER_CODE_ERROR]::
	 * FIXME: For when we will add support for requiring stricter parsing
	 * or even a validator. */
	SGML_PARSER_CODE_ERROR,
};

/** callback:[sgml_error_T]: SGML error callback
 *
 * Called by the SGML parser when a parsing error has occurred.
 *
 * If the return code is not ref:[SGML_PARSER_CODE_OK] the parsing will be
 * ended and that code will be returned. */
typedef enum sgml_parser_code
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);

/** struct:[sgml_parser]
 *
 * ...
 *
 * NOTE: ...
 **/
struct sgml_parser {
	enum sgml_parser_type type;	/* Stream or tree */
	enum sgml_parser_flag flags;	/* Flags that control the behaviour */

	struct sgml_info *info;		/* Backend dependent info */

	struct dom_string uri;		/* The URI of the DOM document */
	struct dom_node *root;		/* The document root node */

	sgml_error_T error_func;

	struct dom_stack stack;		/* A stack for tracking parsed nodes */
	struct dom_stack parsing;	/* Used for tracking parsing states */
};


/** func:[init_sgml_parser]: Initialise an SGML parser
 *
 * Initialise an SGML parser with the given properties.
 *
 * type::	Stream or tree; one-time or persistant.
 * doctype::	The document type, this affects what sub type nodes are given.
 * uri::	The URI of the document root.
 * flags::	Flags controlling the behaviour of the parser.
 */
struct sgml_parser *
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
		 struct dom_string *uri, enum sgml_parser_flag flags);

/** func:[done_sgml_parser]: Release an SGML parser
 *
 * Deallocates all resources, _expect_ the root node.
 *
 * parser::	The parser being released.
 */
void done_sgml_parser(struct sgml_parser *parser);

enum sgml_parser_code
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete);

unsigned int get_sgml_parser_line_number(struct sgml_parser *parser);

#endif

