bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: c++: provide control over the stack.hh file name


From: Akim Demaille
Subject: RFC: c++: provide control over the stack.hh file name
Date: Mon, 24 Sep 2018 22:36:39 +0200

Frank’s skeleton adds support to prefix all the files, not
just foo.tab.cc and foo.tab.hh, but also location.hh, position.hh
and stack.hh.

We need this and we will have it.

However, I think we also need to be able to not have these files.
Instead of generating these files, we could just generate their
content into foo.tab.hh (or foo.tab.cc when there no foo.tab.hh).

It was really stupid to generate stack.hh: it’s absolutely useless
except in the parser itself.

It’s different in the case of location.hh and position.hh.  I have
several parsers that generate ASTs tagged with source locations,
using Bison’s generated location.hh and position.hh, so I really
want to be able to use these files independently of the parser’s
foo.tab.hh.

So I think we need to be able to specify that we don’t want these
files, or be able to specify their name.

This is an initial stab at this: the user can decide not to generate
stack.hh, or to change the output file name.  There’s one thing I
don’t know how to handle: if the user specifies the location of
these files _with_ a directory component, I’m not sure what
#include I should generate.

Below, I’m using some weak approach: the user is expected to
define api.stack.file as a filename without directory, and it’s
output in the same directory as the output file.  So if she
wrote ‘%define api.stack.file "mystack.hh"’, and passed
-o foo/bar/parser.cc, we generate foo/bar/mystack.hh, and use
#include "mystack.hh" in parser.cc.

In the case of stack.hh, I think we don’t care.  In fact, I expect
people to ‘%define api.stack.file none’ to not generate this file.
But in the case of location.hh/position.hh, it might be important
to generate them in foo/ast while the parser is in foo/parse.
But then, what should the #include look like?  Maybe we cannot
just invent it, and should also introduce api.stack.include to
specify it.

Just thinking aloud.  But I’d be happy to not be alone doing so :)


PS/  Not sure api.* is the appropriate prefix for file names.

commit d3c59fc9587f17e85d888884d57ff8d18fd9f9ef
Author: Akim Demaille <address@hidden>
Date:   Sun Sep 23 17:59:46 2018 +0200

    WIP: c++: provide control over the stack.hh file name
    
    It was not a good idea to generate the file stack.hh.  It never was.
    But now we have to deal with backward compatibility: if we stop
    generating it, the build system of some build system will probably
    break.
    
    So offer the user a means to (i) decide what the name of the output
    file should be, and (ii) not generate this file at all (its content
    will be inline where the parser is defined).
    
    * data/c++.m4 (api.stack.file): Defaults to stack.hh.
    * data/stack.hh: Generate the file only if api.stack.file is not
    empty.
    In that case, use it as file name.
    * data/lalr1.cc: Adjust to include the right file, or to include
    the definition of stack.
    * tests/calc.at, tests/output.at: Exercise api.stack.file.

diff --git a/data/bison.m4 b/data/bison.m4
index 7ff30c4c..2757edd3 100644
--- a/data/bison.m4
+++ b/data/bison.m4
@@ -863,6 +863,21 @@ m4_define([b4_percent_define_check_kind],
 ])
 
 
+# b4_percent_define_check_kind(VARIABLE, KIND, [DIAGNOSTIC = complain])
+# ---------------------------------------------------------------------
+m4_define([b4_percent_define_check_kind],
+[_b4_percent_define_ifdef([$1],
+  [m4_if(b4_percent_define_get_kind([$1]), [$2], [],
+    [b4_error([m4_default([$3], [complain])],
+              b4_percent_define_get_loc([$1]),
+              [m4_case([$2],
+                 [code],    [[%%define variable '%s' requires '{...}' values]],
+                 [keyword], [[%%define variable '%s' requires keyword values]],
+                 [string],  [[%%define variable '%s' requires '"..."' 
values]])],
+              [$1])])])dnl
+])
+
+
 # b4_percent_define_check_values(VALUES)
 # --------------------------------------
 # Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 47a76a05..42eacb2e 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -20,6 +20,21 @@ m4_include(b4_pkgdatadir/[c++.m4])
 # api.value.type=variant is valid.
 m4_define([b4_value_type_setup_variant])
 
+m4_define([_b4_check_stack_file],
+[b4_percent_define_ifdef([api.stack.file],
+  [m4_if(b4_percent_define_get_kind([api.stack.file]),
+    [string],
+        [m4_define([b4_stack_file],
+                   b4_percent_define_get([[api.stack.file]]))],
+    [keyword],
+         [],
+    [b4_warn_at(b4_percent_define_get_loc([$1]),
+                [[%%define variable '%s' requires keyword or '"..."' 
values]])],
+              [api.stack.file])])
+])
+_b4_check_stack_file
+
+
 # b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
 # --------------------------------------------------------------
 # Declare "parser::yy<TABLE-NAME>_" whose contents is CONTENT.
@@ -161,8 +176,9 @@ m4_define([b4_shared_declarations],
 # include <vector>
 
 ]b4_cxx_portability[
+]m4_ifdef([b4_stack_file],
+          [[# include "]b4_stack_file["]])[
 ]b4_defines_if([[
-# include "stack.hh"
 ]b4_bison_locations_if([[# include "location.hh"]])])[
 ]b4_variant_if([b4_variant_includes])[
 
@@ -173,9 +189,9 @@ m4_define([b4_shared_declarations],
 
 ]b4_namespace_open[
 
+]m4_ifdef([b4_stack_file], [], [b4_stack_define])[
 ]b4_defines_if([],
-[b4_stack_define
-b4_bison_locations_if([b4_position_define
+[b4_bison_locations_if([b4_position_define
 b4_location_define])])[
 
 ]b4_variant_if([b4_variant_define])[
diff --git a/data/stack.hh b/data/stack.hh
index 0ee2208b..5b921d25 100644
--- a/data/stack.hh
+++ b/data/stack.hh
@@ -129,16 +129,16 @@ m4_define([b4_stack_define],
   };
 ]])
 
-b4_defines_if(
-[b4_output_begin([b4_dir_prefix[]stack.hh])
-b4_copyright([Stack handling for Bison parsers in C++])[
+m4_ifdef([b4_stack_file],
+[b4_output_begin([b4_dir_prefix[]b4_stack_file])[
+]b4_copyright([Stack handling for Bison parsers in C++])[
 
 /**
- ** \file ]b4_dir_prefix[stack.hh
+ ** \file ]b4_dir_prefix[]b4_stack_file[
  ** Define the ]b4_namespace_ref[::stack class.
  */
 
-]b4_cpp_guard_open([b4_dir_prefix[]stack.hh])[
+]b4_cpp_guard_open([b4_dir_prefix[]b4_stack_file])[
 
 # include <vector>
 
@@ -148,7 +148,7 @@ b4_copyright([Stack handling for Bison parsers in C++])[
 ]b4_stack_define[
 ]b4_namespace_close[
 
-]b4_cpp_guard_close([b4_dir_prefix[]stack.hh])[
+]b4_cpp_guard_close([b4_dir_prefix[]b4_stack_file])[
 ]b4_output_end])
 
 m4_popdef([b4_copyright_years])
diff --git a/tests/calc.at b/tests/calc.at
index a75a1bc6..4f20dbd7 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -696,6 +696,9 @@ AT_CHECK_CALC_LALR1_CC([%defines %locations %define 
parse.error verbose %debug %
 AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix 
{calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int 
*count}])
 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug 
%define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} 
%parse-param {int *count}])
 
+AT_CHECK_CALC_LALR1_CC([%locations %define api.stack.file "my-stack.hh"])
+AT_CHECK_CALC_LALR1_CC([%locations %defines %define api.stack.file none])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %define api.stack.file 
"my-stack.hh"])
 
 
 # --------------------------- #
diff --git a/tests/output.at b/tests/output.at
index 6bee3147..7a3fb11d 100644
--- a/tests/output.at
+++ b/tests/output.at
@@ -145,6 +145,9 @@ AT_CHECK([grep 'include .subdir/' $1.cc], 1, [])
 AT_CHECK([grep 'include .subdir/' $1.hh], 1, [])
 ])
 
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc"], [],
+                [foo.tab.cc])
+
 AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %verbose], [],
                 [foo.output foo.tab.cc])
 
@@ -176,6 +179,22 @@ AT_CHECK_OUTPUT([gram_dir/foo.yy],
                 [],
                 [output_dir/foo.output output_dir/foo.tab.cc 
output_dir/foo.tab.hh output_dir/location.hh output_dir/position.hh 
output_dir/stack.hh])
 
+# api.stack.file.
+AT_CHECK_OUTPUT([foo.yy],
+                [%skeleton "lalr1.cc" %define api.stack.file "my-stack.hh"],
+                [],
+                [foo.tab.cc my-stack.hh])
+
+AT_CHECK_OUTPUT([foo.yy],
+                [%skeleton "lalr1.cc" %defines %define api.stack.file none],
+                [],
+                [foo.tab.cc foo.tab.hh])
+
+AT_CHECK_OUTPUT([gram_dir/foo.yy],
+                [%skeleton "lalr1.cc" %verbose %defines %define api.stack.file 
"my-stack.hh" %file-prefix "output_dir/foo"],
+                [],
+                [output_dir/foo.output output_dir/foo.tab.cc 
output_dir/foo.tab.hh output_dir/my-stack.hh])
+
 
 # AT_CHECK_CONFLICTING_OUTPUT(INPUT-FILE, DIRECTIVES, FLAGS, STDERR,
 #                             [EXIT-STATUS])




reply via email to

[Prev in Thread] Current Thread [Next in Thread]