diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index 140760e9f8902ee6ef2884c36f3ce98aded89b62..0b54e93f02a108d73b2675f8f810399a5357870f 100644
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -19,36 +19,28 @@
 #include "libknot_la-cf-parse.h" /* Automake generated header. */
 
 /* Imported symbols. */
-#define yylex cf_lex
+#define cf_lval (*yylval)
 extern void cf_error(const char *msg);
 extern int (*cf_read_hook)(char *buf, size_t nbytes);
-
-#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
-
-/*! \warning Free yy buffers until reentrant parser is made. */
-void __attribute__ ((destructor)) yy_deinit()
+void switch_input(const char *str, void *scanner)
 {
-#ifdef YY_CURRENT_BUFFER_LVALUE
-	/* Pop the buffer stack, destroying each element. */
-	while (YY_CURRENT_BUFFER) {
-		yy_delete_buffer(YY_CURRENT_BUFFER);
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	yyfree(yy_buffer_stack);
-	yy_buffer_stack = NULL;
-#endif
+	yy_scan_string(str, scanner);
 }
 
+//#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
+#define YY_NO_UNPUT
+
 %}
 
+%option reentrant
+%option bison-bridge
 %option noyywrap
 %option noinput
 %option nounput
 %option noreject
 %option yylineno
+%option prefix = "cf_"
+%option outfile = "lex.yy.c"
 
 ALPHA [a-zA-Z_]
 DIGIT [0-9]
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 4b47d70537b7cf38b8a27cc14f2ae90f949a21e8..f8a63fd3d7172d2d7018f09fa774744134a8fde7 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -12,9 +12,10 @@
 #include <stdlib.h>
 #include "dnslib/dname.h"
 #include "knot/conf/conf.h"
+#include "libknot_la-cf-parse.h" /* Automake generated header. */
 
-extern int yylex (void);
-extern void cf_error(const char *msg);
+extern int cf_lex (YYSTYPE *lvalp, void *scanner);
+extern void cf_error(const char *msg, void *scanner);
 extern conf_t *new_config;
 static conf_iface_t *this_iface = 0;
 static conf_iface_t *this_remote = 0;
@@ -26,7 +27,9 @@ static conf_log_map_t *this_logmap = 0;
 
 %}
 
-%locations
+%pure-parser
+%parse-param{void *scanner}
+%lex-param{void *scanner}
 
 %union {
     char *t;
@@ -193,11 +196,11 @@ zone_acl_item:
      if (!found) {
         char buf[256];
         snprintf(buf, sizeof(buf), "remote '%s' is not defined", $1);
-        cf_error(buf);
+        cf_error(buf, scanner);
      } else {
         conf_remote_t *remote = malloc(sizeof(conf_remote_t));
         if (!remote) {
-           cf_error("out of memory");
+           cf_error("out of memory", scanner);
         } else {
            remote->remote = found;
            add_tail(this_list, &remote->n);
@@ -231,11 +234,11 @@ zone_acl:
       if (!found) {
 	 char buf[256];
 	 snprintf(buf, sizeof(buf), "remote '%s' is not defined", $2);
-	 cf_error(buf);
+	 cf_error(buf, scanner);
       } else {
 	 conf_remote_t *remote = malloc(sizeof(conf_remote_t));
 	 if (!remote) {
-	    cf_error("out of memory");
+	    cf_error("out of memory", scanner);
 	 } else {
 	    remote->remote = found;
 	    add_tail(this_list, &remote->n);
@@ -271,7 +274,7 @@ zone_start: TEXT {
    if (dn == 0) {
      free(this_zone->name);
      free(this_zone);
-     cf_error("invalid zone origin");
+     cf_error("invalid zone origin", scanner);
    } else {
      dnslib_dname_free(&dn);
      add_tail(&new_config->zones, &this_zone->n);
@@ -282,7 +285,7 @@ zone_start: TEXT {
      init_list(&this_zone->acl.xfr_out);
      init_list(&this_zone->acl.notify_in);
      init_list(&this_zone->acl.notify_out);
-   }  
+   }
  }
  ;
 
@@ -300,14 +303,14 @@ zone:
  | zone IXFR_FSLIMIT NUM 'G' ';' { this_zone->ixfr_fslimit = $3 * 1073741824; } // GB
  | zone NOTIFY_RETRIES NUM ';' {
        if ($3 < 1) {
-	   cf_error("notify retries must be positive integer");
+	   cf_error("notify retries must be positive integer", scanner);
        } else {
 	   this_zone->notify_retries = $3;
        }
    }
  | zone NOTIFY_TIMEOUT NUM ';' {
 	if ($3 < 1) {
-	   cf_error("notify timeout must be positive integer");
+	   cf_error("notify timeout must be positive integer", scanner);
        } else {
 	   this_zone->notify_timeout = $3;
        }
@@ -320,21 +323,21 @@ zones:
  | zones SEMANTIC_CHECKS BOOL ';' { new_config->zone_checks = $3; }
  | zones NOTIFY_RETRIES NUM ';' {
        if ($3 < 1) {
-	   cf_error("notify retries must be positive integer");
+	   cf_error("notify retries must be positive integer", scanner);
        } else {
 	   new_config->notify_retries = $3;
        }
    }
  | zones NOTIFY_TIMEOUT NUM ';' {
 	if ($3 < 1) {
-	   cf_error("notify timeout must be positive integer");
+	   cf_error("notify timeout must be positive integer", scanner);
        } else {
 	   new_config->notify_timeout = $3;
        }
    }
  | zones DBSYNC_TIMEOUT NUM ';' {
 	if ($3 < 1) {
-	   cf_error("zonefile sync timeout must be positive integer");
+	   cf_error("zonefile sync timeout must be positive integer", scanner);
        } else {
 	   new_config->dbsync_timeout = $3;
        }
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 6b09da50b2717c72dcafd9a4fcdf0d220a574c5a..b75cc4a3ad8f111e483608eebe304578bd7e14a0 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -50,75 +50,25 @@ static int rmkdir(char *path, int mode)
 }
 
 /* Prototypes for cf-parse.y */
-extern char* yytext;
-extern int yylineno;
-extern int cf_parse();
+extern int cf_parse(void *scanner);
+extern int cf_get_lineno(void *scanner);
+extern char *cf_get_text(void *scanner);
+extern int cf_lex_init(void *scanner);
+extern void cf_set_in(FILE *f, void *scanner);
+extern void cf_lex_destroy(void *scanner);
+extern void switch_input(const char *str, void *scanner);
 
-/*
- * Parser instance globals.
- * \todo: Use pure reentrant parser to get rid of the globals.
- */
 conf_t *new_config = 0; /*!< \brief Currently parsed config. */
 static volatile int _parser_res = 0; /*!< \brief Parser result. */
-static void *_parser_src = 0; /*!< \brief Parser data source. */
-static ssize_t _parser_remaining = -1; /*!< \brief Parser remaining bytes. */
 static pthread_mutex_t _parser_lock = PTHREAD_MUTEX_INITIALIZER;
-int (*cf_read_hook)(char *buf, size_t nbytes) = 0;
-
-/*!
- * \brief Config file read hook.
- *
- * Wrapper for fread().
- *
- * \retval number of read bytes on success.
- * \retval <0 on error.
- */
-int cf_read_file(char *buf, size_t nbytes) {
-	if (_parser_src == 0) {
-		return -1;
-	}
-
-	// Read a maximum of nbytes
-	return fread(buf, 1, nbytes, (FILE*)_parser_src);
-}
-
-/*!
- * \brief Config file read hook (from memory).
- * \retval number of read bytes on success.
- * \retval <0 on error.
- */
-int cf_read_mem(char *buf, size_t nbytes) {
-	if (_parser_src == 0 || _parser_remaining < 0) {
-		return -1;
-	}
-
-	// Assert remaining bytes
-	if ((size_t)_parser_remaining < nbytes) {
-		nbytes = (size_t)_parser_remaining;
-	}
-
-	// Check remaining
-	if (nbytes == 0) {
-		return 0;
-	}
-
-	// Read a maximum of nbytes
-	void* dst = memcpy(buf, (const char*)_parser_src, nbytes);
-	if (dst != 0) {
-		_parser_remaining -= nbytes;
-		_parser_src = (char*)_parser_src + nbytes;
-		return nbytes;
-	}
-
-	return -1;
-}
 
 /*! \brief Config error report. */
-void cf_error(const char *msg)
+void cf_error(const char *msg, void *scanner)
 {
 	fprintf(stderr, "config error\n");
 	log_server_error("Config '%s' - %s on line %d (current token '%s').\n",
-	                 new_config->filename, msg, yylineno, yytext);
+	                 new_config->filename, msg, cf_get_lineno(scanner),
+	                 (char *)cf_get_text(scanner));
 
 	_parser_res = KNOT_EPARSEFAIL;
 }
@@ -356,20 +306,22 @@ static int conf_fparser(conf_t *conf)
 	// {
 	// Hook new configuration
 	new_config = conf;
-	_parser_src = fopen(conf->filename, "r");
-	_parser_remaining = -1;
-	if (_parser_src == 0) {
+	FILE *f = fopen(conf->filename, "r");
+	if (f == 0) {
 		pthread_mutex_unlock(&_parser_lock);
 		return KNOT_ENOENT;
 	}
 
 	// Parse config
 	_parser_res = KNOT_EOK;
-	cf_read_hook = cf_read_file;
-	cf_parse();
+	new_config->filename = conf->filename;
+	void *scanner = NULL;
+	cf_lex_init(&scanner);
+	cf_set_in(f, scanner);
+	cf_parse(scanner);
+	cf_lex_destroy(scanner);
 	ret = _parser_res;
-	fclose((FILE*)_parser_src);
-	_parser_src = 0;
+	fclose(f);
 	// }
 	pthread_mutex_unlock(&_parser_lock);
 	return ret;
@@ -389,25 +341,22 @@ static int conf_strparser(conf_t *conf, const char *src)
 	// {
 	// Hook new configuration
 	new_config = conf;
-	_parser_src = (char*)src;
-	_parser_remaining = strlen(src);
-	if (_parser_src == 0) {
-		_parser_src = 0;
-		_parser_remaining = -1;
+	if (src == 0) {
 		pthread_mutex_unlock(&_parser_lock);
 		return KNOT_ENOENT;
 	}
 
 	// Parse config
 	_parser_res = KNOT_EOK;
-	cf_read_hook = cf_read_mem;
 	char *oldfn = new_config->filename;
 	new_config->filename = "(stdin)";
-	cf_parse();
+	void *scanner = NULL;
+	cf_lex_init(&scanner);
+	switch_input(src, scanner);
+	cf_parse(scanner);
+	cf_lex_destroy(scanner);
 	new_config->filename = oldfn;
 	ret = _parser_res;
-	_parser_src = 0;
-	_parser_remaining = -1;
 	// }
 	pthread_mutex_unlock(&_parser_lock);
 	return ret;
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index cfec1132a040d251dda3e902cbd035a7f4aa01ff..0764f0e51cc531df1c4fceaa4e747e7ee4e9197f 100644
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -428,9 +428,7 @@ dnslib_lookup_table_t dns_certificate_types[] = {
 
 /* Imported from lexer. */
 extern int hexdigit_to_int(char ch);
-
-
-
+extern FILE *zp_get_in(void *scanner);
 
 /* Some global flags... */
 static int vflag = 0;
@@ -1423,14 +1421,21 @@ void parse_unknown_rdata(uint16_t type, uint16_t *wireformat)
  *
  */
 static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
-	  dnslib_node_t *origin)
+	  dnslib_node_t *origin, void *scanner)
 {
 	/* Open the zone file... */
 	if (strcmp(filename, "-") == 0) {
-		yyin = stdin;
+		zp_set_in(stdin, scanner);
 		filename = "<stdin>";
-	} else if (!(yyin = fopen(filename, "r"))) {
-		return 0;
+	} else {
+		FILE *f = fopen(filename, "r");
+		if (f == NULL) {
+			return 0;
+		}
+		zp_set_in(f, scanner);
+		if (zp_get_in(scanner) == 0) {
+			return 0;
+		}
 	}
 
 	zparser_init(filename, ttl, rclass, origin);
@@ -1826,24 +1831,30 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
 
 	assert(dnslib_node_parent(origin_node, 0) == NULL);
 
-	if (!zone_open(zonefile, 3600, DNSLIB_CLASS_IN, origin_node)) {
-		strerror_r(errno, ebuf, sizeof(ebuf));
+	void *scanner = NULL;
+	zp_lex_init(&scanner);
+	if (scanner == NULL) {
+		return KNOT_ZCOMPILE_ENOMEM;
+	}
+
+	if (!zone_open(zonefile, 3600, DNSLIB_CLASS_IN, origin_node, scanner)) {
 		fprintf(stderr, "Cannot open '%s': %s.",
 			zonefile, ebuf);
-		fclose(yyin);
 		zparser_free();
 		return KNOT_ZCOMPILE_EZONEINVAL;
 	}
 
-	if (yyparse() != 0) {
-		fclose(yyin);
-		zparser_free();
+	if (zp_parse(scanner) != 0) {
 		return KNOT_ZCOMPILE_ESYNT;
 	}
 	
 	dnslib_zone_contents_t *contents =
 			dnslib_zone_get_contents(parser->current_zone);
 
+	FILE *in_file = (FILE *)zp_get_in(scanner);
+	fclose(in_file);
+	zp_lex_destroy(scanner);
+
 	if (parser->last_node && parser->node_rrsigs != NULL) {
 		/* assign rrsigs to last node in the zone*/
 		process_rrsigs_in_node(contents,
@@ -1853,19 +1864,19 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
 
 	debug_zp("zone parsed\n");
 
+	find_rrsets_orphans(parser->current_zone->contents,
+	                    parser->rrsig_orphans);
 	if (!(parser->current_zone &&
 	      dnslib_node_rrset(parser->current_zone->contents->apex,
 	                        DNSLIB_RRTYPE_SOA))) {
 		fprintf(stderr, "Zone file does not contain SOA record!\n");
 		dnslib_zone_deep_free(&parser->current_zone, 0);
-		fclose(yyin);
 		zparser_free();
 		return KNOT_ZCOMPILE_EZONEINVAL;
 	}
 
 
 	uint found_orphans;
-
 	found_orphans = find_rrsets_orphans(contents,
 					    parser->rrsig_orphans);
 
@@ -1887,12 +1898,8 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
 //	printf("apex: %s\n", zone->apex->owner->name);
 
 
-	fclose(yyin);
-
 	fflush(stdout);
-
 	totalerrors += parser->errors;
-
 	zparser_free();
 
 	return totalerrors;
diff --git a/src/zcompile/zcompile.h b/src/zcompile/zcompile.h
index 2f6d2385b8de6489d6a3d6c9a2dcca4115fad6d7..20cb049a04ed5d7e3dc88baa39c2678a8ca29251 100644
--- a/src/zcompile/zcompile.h
+++ b/src/zcompile/zcompile.h
@@ -56,7 +56,11 @@ struct lex_data {
 
 #define DEFAULT_TTL 3600
 
-int yylex_destroy();
+int yylex_destroy(void *scanner);
+int zp_parse(void *scanner);
+void zp_set_in(FILE *f, void *scanner);
+int zp_lex_init(void **scanner);
+int zp_lex_destroy(void *scanner);
 
 /*! \todo Implement ZoneDB. */
 typedef void namedb_type;
@@ -111,13 +115,6 @@ typedef struct zparser zparser_type;
 extern zparser_type *parser;
 
 /* used in zonec.lex */
-extern FILE *yyin;
-
-int yyparse(void);
-
-int yylex(void);
-
-void yyrestart(FILE *);
 
 /*!
  * \brief Does all the processing of RR - saves to zone, assigns RRSIGs etc.
diff --git a/src/zcompile/zlexer.l b/src/zcompile/zlexer.l
index 75a62aab9b06e24d475e067693460e064131d99a..43d8bff937b8000d20e5393f642694b12f89ecb7 100644
--- a/src/zcompile/zlexer.l
+++ b/src/zcompile/zlexer.l
@@ -81,6 +81,9 @@ extern uint32_t strtottl(const char *nptr, const char **endptr);
 #define YY_NO_UNPUT
 #define MAXINCLUDES 10
 
+#define scanner yyscanner
+extern int zp_lex(YYSTYPE *lvalp, void *scanner);
+
 #if 0
 #define LEXOUT(s)  printf s /* used ONLY when debugging */
 #else
@@ -94,41 +97,18 @@ enum lexer_state {
 	PARSING_RDATA
 };
 
-static int parse_token(int token, char *yytext, enum lexer_state *lexer_state);
-
 static YY_BUFFER_STATE include_stack[MAXINCLUDES];
 static zparser_type zparser_stack[MAXINCLUDES];
 static int include_stack_ptr = 0;
 
-/*
- * Saves the file specific variables on the include stack.
- */
-static void
-push_parser_state(FILE *input)
-{
-	zparser_stack[include_stack_ptr].filename = parser->filename;
-	zparser_stack[include_stack_ptr].line = parser->line;
-	zparser_stack[include_stack_ptr].origin = parser->origin;
-	include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
-	yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
-	++include_stack_ptr;
-}
+static void pop_parser_state(void *scanner);
+static void push_parser_state(FILE *input, void *scanner);
+static int parse_token(void *scanner, int token, char *in_str,
+                       enum lexer_state *lexer_state);
 
-/*
- * Restores the file specific variables from the include stack.
- */
-static void
-pop_parser_state(void)
-{
-	--include_stack_ptr;
-	parser->filename = zparser_stack[include_stack_ptr].filename;
-	parser->line = zparser_stack[include_stack_ptr].line;
-	parser->origin = zparser_stack[include_stack_ptr].origin;
-	yy_delete_buffer(YY_CURRENT_BUFFER);
-	yy_switch_to_buffer(include_stack[include_stack_ptr]);
-}
 
-#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */
+/*!< \todo does not compile */
+#ifndef yy_set_bol // compat definition, for flex 2.4.6
 #define yy_set_bol(at_bol) \
 { \
 	if (!yy_current_buffer ) \
@@ -140,6 +120,9 @@ pop_parser_state(void)
 %}
 
 %option nounput
+%option reentrant bison-bridge
+%option prefix = "zp_"
+%option outfile = "lex.yy.c"
 
 SPACE   [ \t]
 LETTER  [a-zA-Z]
@@ -180,7 +163,7 @@ ANY     [^\"\n\\]|\\.
 <incl>.+ 		{
 	char *tmp;
 	/*! \todo pointer to origin. */
-	void *origin = 0;
+	void *origin = parser->origin;
 	/* domain_type *origin = parser->origin; */
 	int error_occurred = parser->error_occurred;
 
@@ -234,7 +217,7 @@ ANY     [^\"\n\\]|\\.
 		} else {
 			/* Initialize parser for include file.  */
 			char *filename = strdup(yytext);
-			push_parser_state(input); /* Destroys yytext.  */
+			push_parser_state(input, scanner); /* Destroys yytext.  */
 			parser->filename = filename;
 			parser->line = 1;
 			parser->origin = origin;
@@ -257,21 +240,21 @@ ANY     [^\"\n\\]|\\.
 		}
 	} else {
 		fclose(yyin);
-		pop_parser_state();
+		pop_parser_state(scanner);
 	}
 }
 ^{DOLLAR}{LETTER}+	{ zc_warning("Unknown directive: %s", yytext); }
 {DOT}	{
 	LEXOUT((". "));
-	return parse_token('.', yytext, &lexer_state);
+	return parse_token(scanner, '.', yytext, &lexer_state);
 }
 @	{
 	LEXOUT(("@ "));
-	return parse_token('@', yytext, &lexer_state);
+	return parse_token(scanner, '@', yytext, &lexer_state);
 }
 \\#	{
 	LEXOUT(("\\# "));
-	return parse_token(URR, yytext, &lexer_state);
+	return parse_token(scanner, URR, yytext, &lexer_state);
 }
 {NEWLINE}	{
 	++parser->line;
@@ -326,7 +309,7 @@ ANY     [^\"\n\\]|\\.
 <bitlabel>\]		{
 	BEGIN(INITIAL);
 	yytext[yyleng - 1] = '\0';
-	return parse_token(BITLAB, yytext, &lexer_state);
+	return parse_token(scanner, BITLAB, yytext, &lexer_state);
 }
 
 	/* Quoted strings.  Strip leading and ending quotes.  */
@@ -341,12 +324,12 @@ ANY     [^\"\n\\]|\\.
 	LEXOUT(("\" "));
 	BEGIN(INITIAL);
 	yytext[yyleng - 1] = '\0';
-	return parse_token(STR, yytext, &lexer_state);
+	return parse_token(scanner, STR, yytext, &lexer_state);
 }
 
 ({ZONESTR}|\\.|\\\n)+ {
 	/* Any allowed word.  */
-	return parse_token(STR, yytext, &lexer_state);
+	return parse_token(scanner, STR, yytext, &lexer_state);
 }
 . {
 	zc_error("unknown character '%c' (\\%03d) seen - is this a zonefile?",
@@ -420,11 +403,13 @@ zoctet(char *text)
 	return p - text;
 }
 
-static int
-parse_token(int token, char *yytext, enum lexer_state *lexer_state)
+static int parse_token(void *scanner, int token, char *in_str,
+                       enum lexer_state *lexer_state)
 {
-	size_t len;
-	char *str;
+	size_t len = 0;
+	char *str = NULL;
+
+	struct yyguts_t *yyg = (struct yyguts_t *)scanner;
 
 	if (*lexer_state == EXPECT_OWNER) {
 		*lexer_state = PARSING_OWNER;
@@ -434,46 +419,75 @@ parse_token(int token, char *yytext, enum lexer_state *lexer_state)
 		uint16_t rrclass;
 
 		/* type */
-		token = rrtype_to_token(yytext, &yylval.type);
+		token = rrtype_to_token(in_str, &yylval->type);
 		if (token != 0) {
 			*lexer_state = PARSING_RDATA;
-			LEXOUT(("%d[%s] ", token, yytext));
+			LEXOUT(("%d[%s] ", token, in_str));
 			return token;
 		}
 
 		/* class */
-		rrclass = parser_rrclass_from_string(yytext);
+		rrclass = parser_rrclass_from_string(in_str);
 		if (rrclass != 0) {
-			yylval.rclass = rrclass;
+			yylval->rclass = rrclass;
 			LEXOUT(("CLASS "));
 			return T_RRCLASS;
 		}
 
 		/* ttl */
-		yylval.ttl = strtottl(yytext, &t);
+		yylval->ttl = strtottl(in_str, &t);
 		if (*t == '\0') {
 			LEXOUT(("TTL "));
 			return T_TTL;
 		}
 	}
 
-	str = strdup(yytext);
+	str = strdup(in_str);
 	len = zoctet(str);
 
-	yylval.data.str = str;
-	yylval.data.len = len;
+	yylval->data.str = str;
+	yylval->data.len = len;
 
-	if (strcmp(yytext, ".") == 0) {
+	if (strcmp(str, ".") == 0) {
 		free(str);
-		yylval.data.str=".";
-	} else if (strcmp(yytext, "@") == 0) {
+		yylval->data.str=".";
+	} else if (strcmp(str, "@") == 0) {
 		free(str);
-		yylval.data.str="@";
-	} else if (strcmp(yytext, "\\#") == 0) {
+		yylval->data.str="@";
+	} else if (strcmp(str, "\\#") == 0) {
 		free(str);
-		yylval.data.str="\\#";
+		yylval->data.str="\\#";
 	}
 
-	LEXOUT(("%d[%s] ", token, yytext));
+	LEXOUT(("%d[%s] ", token, in_str));
 	return token;
 }
+
+/*
+ * Saves the file specific variables on the include stack.
+ */
+static void push_parser_state(FILE *input, void *scanner)
+{
+	struct yyguts_t *yyg = (struct yyguts_t *)scanner;
+	zparser_stack[include_stack_ptr].filename = parser->filename;
+	zparser_stack[include_stack_ptr].line = parser->line;
+	zparser_stack[include_stack_ptr].origin = parser->origin;
+	include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+	yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE, scanner),
+	                    scanner);
+	++include_stack_ptr;
+}
+
+/*
+ * Restores the file specific variables from the include stack.
+ */
+void pop_parser_state(void *scanner)
+{
+	struct yyguts_t *yyg = (struct yyguts_t *)scanner;
+	--include_stack_ptr;
+	parser->filename = zparser_stack[include_stack_ptr].filename;
+	parser->line = zparser_stack[include_stack_ptr].line;
+	parser->origin = zparser_stack[include_stack_ptr].origin;
+	yy_delete_buffer(YY_CURRENT_BUFFER, scanner);
+	yy_switch_to_buffer(include_stack[include_stack_ptr], scanner);
+}
diff --git a/src/zcompile/zparser.y b/src/zcompile/zparser.y
index 059427df2b0138e514ff3b1d0f250f97ae75ba40..abbf12e7af77b8b906c9b3b8145c0705510dddfe 100644
--- a/src/zcompile/zparser.y
+++ b/src/zcompile/zparser.y
@@ -27,6 +27,7 @@
 #include "zcompile/zcompile.h"
 #include "zcompile/parser-descriptor.h"
 #include "zcompile/zcompile-error.h"
+#include "zparser.h"
 
 /* these need to be global, otherwise they cannot be used inside yacc */
 zparser_type *parser;
@@ -34,7 +35,7 @@ zparser_type *parser;
 #ifdef __cplusplus
 extern "C"
 #endif /* __cplusplus */
-int yywrap(void);
+int zp_wrap(void);
 
 /* this hold the nxt bits */
 static uint8_t nxtbits[16];
@@ -47,7 +48,8 @@ static uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
 /* hold the highest rcode seen in a NSEC rdata , BUG #106 */
 uint16_t nsec_highest_rcode;
 
-void yyerror(const char *message);
+void zp_error(void *scanner, const char *message);
+int zp_lex(YYSTYPE *lvalp, void *scanner);
 
 /* helper functions */
 void zc_error(const char *fmt, ...);
@@ -77,6 +79,11 @@ dnslib_dname_t *error_domain;
 	uint16_t             *unknown;
 }
 
+%pure-parser
+%parse-param {void *scanner}
+%lex-param {void *scanner}
+%name-prefix = "zp_"
+
 /*
  * Tokens to represent the known RR types of DNS.
  */
@@ -1386,9 +1393,7 @@ rdata_unknown:	URR sp STR sp str_sp_seq trail
     ;
 %%
 
-/* ??? */
-int
-yywrap(void)
+int zp_wrap(void)
 {
 	return 1;
 }
@@ -1465,13 +1470,12 @@ void zparser_free()
 	dnslib_dname_free(&(parser->root_domain));
 	free(parser->temporary_items);
 	dnslib_rrset_free(&(parser->current_rrset));
-	dnslib_dname_free(&parser->prev_dname);
-	yylex_destroy();
+	dnslib_dname_free(&(parser->prev_dname));
 	free(parser);
 }
 
 void
-yyerror(const char *message)
+yyerror(void *scanner, const char *message)
 {
 	zc_error("%s", message);
 }