api.location.type: support it in C

Reported by Balázs Scheidler.

* data/skeletons/c.m4 (b4_location_type_define): Use api.location.type
if defined.
* doc/bison.texi: Document it.
* tests/local.at (AT_C_IF, AT_LANG_CASE): New.
Support Span in C.
* tests/calc.at (Span): Convert it to be usable in C and C++.
Check api.location.type with yacc.c and glr.c.
This commit is contained in:
Akim Demaille
2019-04-22 19:24:11 +02:00
parent 971e72514f
commit 9260e5ca4f
7 changed files with 58 additions and 22 deletions

9
NEWS
View File

@@ -86,6 +86,15 @@ GNU Bison NEWS
%define api.header.include {<parser/parse.h>} %define api.header.include {<parser/parse.h>}
*** api.location.type is now supported in C (yacc.c, glr.c)
The %define variable api.location.type defines the name of the type to use
for locations. When defined, Bison no longer defines YYLTYPE.
This can be used in programs with several parsers to factor their
definition of locations: let one of them generate them, and the others
just use them.
** Documentation ** Documentation
A new example in C shows an simple infix calculator with a hand-written A new example in C shows an simple infix calculator with a hand-written

View File

@@ -1078,10 +1078,10 @@ m4_define_default([b4_location_initial_line], [1])
## Sanity checks. ## ## Sanity checks. ##
## --------------- ## ## --------------- ##
# api.location.prefix={...} (Java and C++). # api.location.type={...} (C, C++ and Java).
b4_percent_define_check_kind([api.location.type], [code], [deprecated]) b4_percent_define_check_kind([api.location.type], [code], [deprecated])
# api.position.prefix={...} (Java). # api.position.type={...} (Java).
b4_percent_define_check_kind([api.position.type], [code], [deprecated]) b4_percent_define_check_kind([api.position.type], [code], [deprecated])
# api.prefix >< %name-prefix. # api.prefix >< %name-prefix.

View File

@@ -730,7 +730,10 @@ typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
# ----------------------- # -----------------------
m4_define([b4_location_type_define], m4_define([b4_location_type_define],
[[/* Location type. */ [[/* Location type. */
#if ! defined ]b4_api_PREFIX[LTYPE && ! defined ]b4_api_PREFIX[LTYPE_IS_DECLARED ]b4_percent_define_ifdef([[api.location.type]],
[[typedef ]b4_percent_define_get([[api.location.type]])[ ]b4_api_PREFIX[LTYPE;
]],
[[#if ! defined ]b4_api_PREFIX[LTYPE && ! defined ]b4_api_PREFIX[LTYPE_IS_DECLARED
typedef struct ]b4_api_PREFIX[LTYPE ]b4_api_PREFIX[LTYPE; typedef struct ]b4_api_PREFIX[LTYPE ]b4_api_PREFIX[LTYPE;
struct ]b4_api_PREFIX[LTYPE struct ]b4_api_PREFIX[LTYPE
{ {
@@ -742,7 +745,7 @@ struct ]b4_api_PREFIX[LTYPE
# define ]b4_api_PREFIX[LTYPE_IS_DECLARED 1 # define ]b4_api_PREFIX[LTYPE_IS_DECLARED 1
# define ]b4_api_PREFIX[LTYPE_IS_TRIVIAL 1 # define ]b4_api_PREFIX[LTYPE_IS_TRIVIAL 1
#endif #endif
]]) ]])])
# b4_declare_yylstype # b4_declare_yylstype

View File

@@ -5975,7 +5975,7 @@ Introduced in Bison 3.2.
@deffn {Directive} {%define api.location.type} @{@var{type}@} @deffn {Directive} {%define api.location.type} @{@var{type}@}
@itemize @bullet @itemize @bullet
@item Language(s): C++, Java @item Language(s): C, C++, Java
@item Purpose: Define the location type. @item Purpose: Define the location type.
@xref{User Defined Location Type}. @xref{User Defined Location Type}.
@@ -5985,8 +5985,7 @@ Introduced in Bison 3.2.
@item Default Value: none @item Default Value: none
@item History: @item History:
Introduced in Bison 2.7 for C, C++ and Java. Introduced under the name Introduced in Bison 2.7 for C++ and Java, in Bison 3.4 for C.
@code{location_type} for C++ in Bison 2.5 and for Java in Bison 2.4.
@end itemize @end itemize
@end deffn @end deffn

View File

@@ -289,18 +289,17 @@ AT_DATA_GRAMMAR([calc.y],
%code requires %code requires
{ {
]AT_LOCATION_TYPE_SPAN_IF([[ ]AT_LOCATION_TYPE_SPAN_IF([[
# include <iostream> typedef struct
struct Point
{ {
int l; int l;
int c; int c;
}; } Point;
struct Span typedef struct
{ {
Point first; Point first;
Point last; Point last;
}; } Span;
# define YYLLOC_DEFAULT(Current, Rhs, N) \ # define YYLLOC_DEFAULT(Current, Rhs, N) \
do \ do \
@@ -313,7 +312,13 @@ AT_DATA_GRAMMAR([calc.y],
{ \ { \
(Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \ (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
} \ } \
while (false) while (0)
]AT_C_IF(
[[#include <stdio.h>
void location_print (FILE *o, Span s);
#define LOCATION_PRINT location_print
]])[
]])[ ]])[
/* Exercise pre-prologue dependency to %union. */ /* Exercise pre-prologue dependency to %union. */
@@ -416,7 +421,8 @@ power (int base, int exponent)
return res; return res;
} }
]AT_LOCATION_TYPE_SPAN_IF([[ ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
#include <iostream>
namespace namespace
{ {
std::ostream& std::ostream&
@@ -430,7 +436,17 @@ namespace
return o; return o;
} }
} }
]])[ ]], [[
void
location_print (FILE *o, Span s)
{
fprintf (o, "%d.%d", s.first.l, s.first.c);
if (s.first.l != s.last.l)
fprintf (o, "-%d.%d", s.last.l, s.last.c - 1);
else if (s.first.c != s.last.c - 1)
fprintf (o, "-%d", s.last.c - 1);
}
]])])[
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_DEFINES_IF([], ]AT_DEFINES_IF([],
[AT_CALC_LEX [AT_CALC_LEX
@@ -684,6 +700,7 @@ AT_CHECK_CALC_LALR()
AT_CHECK_CALC_LALR([%defines]) AT_CHECK_CALC_LALR([%defines])
AT_CHECK_CALC_LALR([%locations]) AT_CHECK_CALC_LALR([%locations])
AT_CHECK_CALC_LALR([%locations %define api.location.type {Span}])
AT_CHECK_CALC_LALR([%name-prefix "calc"]) AT_CHECK_CALC_LALR([%name-prefix "calc"])
AT_CHECK_CALC_LALR([%verbose]) AT_CHECK_CALC_LALR([%verbose])
@@ -726,6 +743,7 @@ AT_CHECK_CALC_GLR()
AT_CHECK_CALC_GLR([%defines]) AT_CHECK_CALC_GLR([%defines])
AT_CHECK_CALC_GLR([%locations]) AT_CHECK_CALC_GLR([%locations])
AT_CHECK_CALC_GLR([%locations %define api.location.type {Span}])
AT_CHECK_CALC_GLR([%name-prefix "calc"]) AT_CHECK_CALC_GLR([%name-prefix "calc"])
AT_CHECK_CALC_GLR([%define api.prefix {calc}]) AT_CHECK_CALC_GLR([%define api.prefix {calc}])
AT_CHECK_CALC_GLR([%verbose]) AT_CHECK_CALC_GLR([%verbose])

View File

@@ -65,7 +65,6 @@ AT_TEST_CPP_GUARD_H([9foo], [%glr-parser])
## export YYLTYPE. ## ## export YYLTYPE. ##
## ---------------- ## ## ---------------- ##
AT_SETUP([export YYLTYPE]) AT_SETUP([export YYLTYPE])
AT_BISON_OPTION_PUSHDEFS([%name-prefix "my_"]) AT_BISON_OPTION_PUSHDEFS([%name-prefix "my_"])

View File

@@ -157,6 +157,8 @@ m4_pushdef([AT_LANG],
[AT_CXX_IF([c++], [AT_CXX_IF([c++],
[AT_D_IF([d], [AT_D_IF([d],
[c])])])]) [c])])])])
m4_pushdef([AT_C_IF],
[m4_if(AT_LANG, [c], [$1], [$2])])
m4_pushdef([AT_GLR_IF], m4_pushdef([AT_GLR_IF],
[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])]) [m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])])
m4_pushdef([AT_LALR1_CC_IF], m4_pushdef([AT_LALR1_CC_IF],
@@ -288,13 +290,12 @@ AT_TOKEN_CTOR_IF(
m4_pushdef([AT_YYLEX_PRE_ARGS], []) m4_pushdef([AT_YYLEX_PRE_ARGS], [])
])]) ])])
# Handle the different types of location components.
AT_CXX_IF( # Handle the different types of location components.
[AT_LOCATION_TYPE_SPAN_IF( AT_LOCATION_TYPE_SPAN_IF(
[AT_LOC_PUSHDEF([first.l], [first.c], [last.l], [last.c])], [AT_LOC_PUSHDEF([first.l], [first.c], [last.l], [last.c])],
[AT_LOC_PUSHDEF([begin.line], [begin.column], [end.line], [end.column])])], [AT_CXX_IF([AT_LOC_PUSHDEF([begin.line], [begin.column], [end.line], [end.column])],
[AT_LOC_PUSHDEF([first_line], [first_column], [last_line], [last_column])]) [AT_LOC_PUSHDEF([first_line], [first_column], [last_line], [last_column])])])
AT_GLR_IF([AT_KEYWORDS([glr])]) AT_GLR_IF([AT_KEYWORDS([glr])])
@@ -334,6 +335,7 @@ m4_popdef([AT_LEXPARAM_IF])
m4_popdef([AT_YACC_IF]) m4_popdef([AT_YACC_IF])
m4_popdef([AT_GLR_IF]) m4_popdef([AT_GLR_IF])
m4_popdef([AT_CXX_IF]) m4_popdef([AT_CXX_IF])
m4_popdef([AT_C_IF])
m4_popdef([AT_LANG]) m4_popdef([AT_LANG])
m4_popdef([AT_JAVA_IF]) m4_popdef([AT_JAVA_IF])
m4_popdef([AT_GLR_CC_IF]) m4_popdef([AT_GLR_CC_IF])
@@ -349,6 +351,12 @@ AT_LOC_POPDEF])dnl
## Generating Grammar Files. ## ## Generating Grammar Files. ##
## -------------------------- ## ## -------------------------- ##
# AT_LANG_CASE(LANG1, IF-LANG1, LANG2, IF-LANG2, ..., DEFAULT)
# ------------------------------------------------------------
m4_define([AT_LANG_CASE],
[m4_case(AT_LANG, $@)])
# _AT_LANG_DISPATCH(LANG, MACRO, ARGS) # _AT_LANG_DISPATCH(LANG, MACRO, ARGS)
# ------------------------------------ # ------------------------------------
# Call the specialization of MACRO for LANG with ARGS. Complain if # Call the specialization of MACRO for LANG with ARGS. Complain if
@@ -990,7 +998,7 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
# AT_LANG_FOR_EACH_STD(BODY) # AT_LANG_FOR_EACH_STD(BODY)
# ------------------------------- # --------------------------
m4_define([AT_LANG_FOR_EACH_STD], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_LANG_FOR_EACH_STD], [AT_LANG_DISPATCH([$0], $@)])