diff --git a/Makefile.cfg b/Makefile.cfg
index e7c841fda7eb1853361fdc4cd81f0bd5df693786..e745ab5e34be4322367023506149c1747d23054e 100644
--- a/Makefile.cfg
+++ b/Makefile.cfg
@@ -54,6 +54,9 @@ PATH := ${PATH}:${TTCN3_DIR}/bin
 # Set it to 'yes' for developing or 'no' for release.
 DEBUG := no
 
+# Set it to 'yes' to display debug information for parsers (very spammy)
+PARSER_DEBUG := no
+
 # Set it to 'yes' to generate coverage data (requires DEBUG=yes)
 COVERAGE := no
 
@@ -152,6 +155,10 @@ else
   CPPFLAGS += -DNDEBUG
 endif
 
+ifeq ($(PARSER_DEBUG), yes)
+  CPPFLAGS += -DPARSER_DEBUG
+endif
+
 # MingW flags need to be passed to the preprocessor during ctags configure
 CPPFLAGS += $(MINGW)
 
@@ -216,6 +223,10 @@ ifeq ($(DEBUG), yes)
   BISONFLAGS += -t -v
 endif
 
+ifeq ($(PARSER_DEBUG), yes)
+  BISONFLAGS += --debug --verbose
+endif
+
 ifeq ($(COVERAGE), yes)
   CPPFLAGS += -DCOVERAGE_BUILD
   COMPILERFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/common/config_preproc_p.y b/common/config_preproc_p.y
index 43a746d16048ffb0fca15b94763b4aca9f3db13a..8f2c85d1c74ae3560b784698b1e01b94ad317057 100644
--- a/common/config_preproc_p.y
+++ b/common/config_preproc_p.y
@@ -298,6 +298,9 @@ extern int add_include_file(const std::string& filename)
 extern int preproc_parse_file(const char *filename, string_chain_t **filenames,
                               string_map_t **defines)
 {
+#ifdef PARSER_DEBUG
+  config_preproc_yydebug = 1;
+#endif
   int error_flag = 0;
   config_preproc_filenames=NULL;
   config_preproc_defines=string_map_new();
diff --git a/common/pattern_p.y b/common/pattern_p.y
index e9d6c331f0e89a0c77398ea55aac1b13d7028ae1..eb24a558e96fb76a13045c6265a72f331068d86d 100644
--- a/common/pattern_p.y
+++ b/common/pattern_p.y
@@ -636,6 +636,9 @@ RE_Quadruple:
 
 char* TTCN_pattern_to_regexp(const char* p_pattern, bool utf8)
 {
+#ifdef PARSER_DEBUG
+  pattern_yydebug = 1;
+#endif
   /* if you want to debug */
   //pattern_yydebug=1;
 
diff --git a/common/pattern_uni.y b/common/pattern_uni.y
index 3fcc479d86da41afb9684f896369ee2d2447d10b..e2351f7751e9123c015b59db05a9fb351931d7e6 100644
--- a/common/pattern_uni.y
+++ b/common/pattern_uni.y
@@ -589,8 +589,9 @@ RE_Quadruple:
 
 char* TTCN_pattern_to_regexp_uni(const char* p_pattern, bool p_nocase, int** groups)
 {
-  /* if you want to debug */
-  //pattern_unidebug=1;
+#ifdef PARSER_DEBUG
+  pattern_unidebug = 1;
+#endif
 
   ret_val=NULL;
   user_groups = 0;
diff --git a/compiler2/asn1/asn1p.y b/compiler2/asn1/asn1p.y
index 53c62f8e430c67d631150345ba428ef835202e4f..3d537f2ae3e765a273948b986c58ae0bd533d72f 100644
--- a/compiler2/asn1/asn1p.y
+++ b/compiler2/asn1/asn1p.y
@@ -3946,6 +3946,9 @@ LowerRef:
 
 int asn1_parse_file(const char* filename, boolean generate_code)
 {
+#ifdef PARSER_DEBUG
+  yydebug = 1;
+#endif
   asn1_yy_parse_internal=false;
   int retval=0;
   asn1la_newfile(filename);
@@ -3976,6 +3979,9 @@ int asn1_parse_file(const char* filename, boolean generate_code)
  */
 int asn1_parse_string(const char* p_str)
 {
+#ifdef PARSER_DEBUG
+  yydebug = 1;
+#endif
   unsigned verb_level_backup=verb_level;
   verb_level=0; // be vewy, vewy quiet
   asn1la_newfile("<internal>");
diff --git a/compiler2/ttcn3/coding_attrib_p.y b/compiler2/ttcn3/coding_attrib_p.y
index 77e2ea829f3acb282057d524c3825d43738ae938..65f8bdbe5c9e2f8f91c129696fa3114ab5ee95d0 100644
--- a/compiler2/ttcn3/coding_attrib_p.y
+++ b/compiler2/ttcn3/coding_attrib_p.y
@@ -881,6 +881,9 @@ static void yyerror(const char *str)
 /** Parse all extension attributes in a "with" statement */
 ExtensionAttributes * parse_extattributes(WithAttribPath *w_attrib_path)
 {
+#ifdef PARSER_DEBUG
+  yydebug = 1;
+#endif
   extatrs = 0;
   if (!w_attrib_path) FATAL_ERROR("parse_extattributes(): NULL pointer");
   // Collect attributes from outer scopes
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index 10fe18cfb73e95c9db09f4e20f9a38b75975efcb..fd0af25e993b80ca3570f3a07a89897e5ed3a075 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -11017,6 +11017,9 @@ static void ttcn3_error(const char *str)
 
 int ttcn3_parse_file(const char* filename, boolean generate_code)
 {
+#ifdef PARSER_DEBUG
+  ttcn3_debug = 1;
+#endif
   anytype_access = false;
   ttcn3_in = fopen(filename, "r");
   if (ttcn3_in == NULL) {
diff --git a/compiler2/ttcn3/rawAST.l b/compiler2/ttcn3/rawAST.l
index e4ed0d7b037e3cff8ea87490a0320d682313369a..e120213142c03a5eab36116189e98f626575491b 100644
--- a/compiler2/ttcn3/rawAST.l
+++ b/compiler2/ttcn3/rawAST.l
@@ -678,6 +678,9 @@ int parse_rawAST(RawAST *par, TextAST *textpar, XerAttributes *xerpar,
     bool &xer_found, bool &ber_found, bool &json_found,
     Common::Type::MessageEncodingType_t par_codec /* = Common::Type::CT_UNDEF */)
 {
+#ifdef PARSER_DEBUG
+    rawAST_debug = 1;
+#endif
     rawstruct=par;
     textstruct=textpar;
     xerstruct = xerpar;
diff --git a/core/config_process.y b/core/config_process.y
index ad726a43341ccbf8e80248aff7eacbb460e2acb3..33068a811e2d99a8606219c6d9b5678bd7b54bf5 100644
--- a/core/config_process.y
+++ b/core/config_process.y
@@ -2286,6 +2286,9 @@ static void reset_configuration_options()
 
 Module_Param* process_config_string2ttcn(const char* mp_str, boolean is_component)
 {
+#ifdef PARSER_DEBUG
+  config_process_debug = 1;
+#endif
   if (parsed_module_param!=NULL || parsing_error_messages!=NULL) TTCN_error("Internal error: previously parsed ttcn string was not cleared.");
   // add the hidden keyword
   std::string mp_string = (is_component) ? std::string("$#&&&(#TTCNSTRINGPARSING_COMPONENT$#&&^#% ") + mp_str
@@ -2323,6 +2326,9 @@ Module_Param* process_config_string2ttcn(const char* mp_str, boolean is_componen
 
 Module_Param* process_config_debugger_value(const char* mp_str)
 {
+#ifdef PARSER_DEBUG
+  config_process_debug = 1;
+#endif
   if (parsed_module_param != NULL || parsing_error_messages != NULL) {
     ttcn3_debugger.print(DRET_NOTIFICATION,
       "Internal error: previously parsed TTCN string was not cleared.");
@@ -2376,6 +2382,9 @@ Module_Param* process_config_debugger_value(const char* mp_str)
 
 boolean process_config_string(const char *config_string, int string_len)
 {
+#ifdef PARSER_DEBUG
+  config_process_debug = 1;
+#endif
   error_flag = FALSE;
 
   struct yy_buffer_state *flex_buffer =
@@ -2405,6 +2414,9 @@ boolean process_config_string(const char *config_string, int string_len)
 
 boolean process_config_file(const char *file_name)
 {
+#ifdef PARSER_DEBUG
+  config_process_debug = 1;
+#endif
   error_flag = FALSE;
   string_chain_t *filenames=NULL;
 
diff --git a/mctr2/cli/config_read.y b/mctr2/cli/config_read.y
index 3f7cba868048777719012bb3ec646b2c6bc1b0c1..08d8daa2672b26f42ba74689a7fcbe7e1d55eaec 100644
--- a/mctr2/cli/config_read.y
+++ b/mctr2/cli/config_read.y
@@ -1086,6 +1086,9 @@ optSemiColon:
 
 int process_config_read_file(const char *file_name, config_data *pcfg)
 {
+#ifdef PARSER_DEBUG
+  config_read_debug = 1;
+#endif
   // reset "locals"
   local_addr_set = FALSE;
   tcp_listen_port_set = FALSE;