ENH: update lemon version and linkage directive (#1768)
- replace `%namespace` directive with simpler `%static` directive. We always encapsulate Lemon parser routines in an anonymous namespace, so a simpler static linkage directive suffices. This reduces the size of the Lemon patch (program and template).
This commit is contained in:
parent
a088bda4d2
commit
6365bab800
@ -7,7 +7,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -120,7 +120,8 @@ tmp_management()
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
%namespace {}
|
||||
// File-scope visibility for exposed Lemon parser routines
|
||||
%static
|
||||
|
||||
// Use extra argument for the return value
|
||||
%extra_context { Foam::expressions::fieldExpr::parseDriver* driver }
|
||||
|
@ -7,7 +7,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -66,7 +66,8 @@ tmp_management()
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
%namespace {}
|
||||
// File-scope visibility for exposed Lemon parser routines
|
||||
%static
|
||||
|
||||
// Use extra argument for the return value
|
||||
%extra_context { Foam::expressions::patchExpr::parseDriver* driver }
|
||||
|
@ -7,7 +7,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -99,7 +99,8 @@ dnl
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
%namespace {}
|
||||
// File-scope visibility for exposed Lemon parser routines
|
||||
%static
|
||||
|
||||
// Use extra argument for the return value
|
||||
%extra_context { Foam::expressions::volumeExpr::parseDriver* driver }
|
||||
|
@ -93,6 +93,12 @@
|
||||
/************* End control #defines *******************************************/
|
||||
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
|
||||
|
||||
/* Default linkage for exposed parser routines is global
|
||||
*/
|
||||
#ifndef YYFUNCAPI
|
||||
# define YYFUNCAPI
|
||||
#endif
|
||||
|
||||
/* Define the yytestcase() macro to be a no-op if is not already defined
|
||||
** otherwise.
|
||||
**
|
||||
@ -251,14 +257,13 @@ static char *yyTracePrompt = 0;
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
|
||||
yyTraceFILE = TraceFILE;
|
||||
yyTracePrompt = zTracePrompt;
|
||||
if( yyTraceFILE==0 ) yyTracePrompt = 0;
|
||||
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
|
||||
}
|
||||
%namespace_end
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#if defined(YYCOVERAGE) || !defined(NDEBUG)
|
||||
@ -322,7 +327,7 @@ static int yyGrowStack(yyParser *p){
|
||||
|
||||
/* Initialize a new parser that has already been allocated.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void ParseInit(void *yypRawParser ParseCTX_PDECL){
|
||||
yyParser *yypParser = (yyParser*)yypRawParser;
|
||||
ParseCTX_STORE
|
||||
@ -348,7 +353,6 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){
|
||||
yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
|
||||
#endif
|
||||
}
|
||||
%namespace_end
|
||||
|
||||
#ifndef Parse_ENGINEALWAYSONSTACK
|
||||
/*
|
||||
@ -363,7 +367,7 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){
|
||||
** A pointer to a parser. This pointer is used in subsequent calls
|
||||
** to Parse and ParseFree.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){
|
||||
yyParser *yypParser;
|
||||
yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
|
||||
@ -373,7 +377,6 @@ void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){
|
||||
}
|
||||
return (void*)yypParser;
|
||||
}
|
||||
%namespace_end
|
||||
#endif /* Parse_ENGINEALWAYSONSTACK */
|
||||
|
||||
|
||||
@ -433,7 +436,7 @@ static void yy_pop_parser_stack(yyParser *pParser){
|
||||
/*
|
||||
** Clear all secondary memory allocations from the parser
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void ParseFinalize(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
|
||||
@ -441,7 +444,6 @@ void ParseFinalize(void *p){
|
||||
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
|
||||
#endif
|
||||
}
|
||||
%namespace_end
|
||||
|
||||
#ifndef Parse_ENGINEALWAYSONSTACK
|
||||
/*
|
||||
@ -452,7 +454,7 @@ void ParseFinalize(void *p){
|
||||
** is defined in a %include section of the input grammar) then it is
|
||||
** assumed that the input pointer is never NULL.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void ParseFree(
|
||||
void *p, /* The parser to be deleted */
|
||||
void (*freeProc)(void*) /* Function used to reclaim memory */
|
||||
@ -463,19 +465,17 @@ void ParseFree(
|
||||
ParseFinalize(p);
|
||||
(*freeProc)(p);
|
||||
}
|
||||
%namespace_end
|
||||
#endif /* Parse_ENGINEALWAYSONSTACK */
|
||||
|
||||
/*
|
||||
** Return the peak depth of the stack for a parser.
|
||||
*/
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
int ParseStackPeak(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
return pParser->yyhwm;
|
||||
}
|
||||
%namespace_end
|
||||
#endif
|
||||
|
||||
/* This array of booleans keeps track of the parser statement
|
||||
@ -496,7 +496,7 @@ static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
|
||||
** Return the number of missed state/lookahead combinations.
|
||||
*/
|
||||
#if defined(YYCOVERAGE)
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
int ParseCoverage(FILE *out){
|
||||
int stateno, iLookAhead, i;
|
||||
int nMissed = 0;
|
||||
@ -514,7 +514,6 @@ int ParseCoverage(FILE *out){
|
||||
}
|
||||
return nMissed;
|
||||
}
|
||||
%namespace_end
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -905,7 +904,7 @@ static void yy_accept(
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
void Parse(
|
||||
void *yyp, /* The parser */
|
||||
int yymajor, /* The major token code number */
|
||||
@ -1075,13 +1074,12 @@ void Parse(
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
%namespace_end
|
||||
|
||||
/*
|
||||
** Return the fallback token corresponding to canonical token iToken, or
|
||||
** 0 if iToken has no fallback.
|
||||
*/
|
||||
%namespace_begin
|
||||
YYFUNCAPI
|
||||
int ParseFallback(int iToken){
|
||||
#ifdef YYFALLBACK
|
||||
assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
|
||||
@ -1091,4 +1089,3 @@ int ParseFallback(int iToken){
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
%namespace_end
|
||||
|
@ -1,136 +1,87 @@
|
||||
--- lempar.c.orig 2020-01-10 14:08:55.225662130 +0100
|
||||
+++ lempar.c 2020-01-10 14:31:25.891656998 +0100
|
||||
@@ -251,12 +251,14 @@
|
||||
--- lempar.c.orig 2020-07-09 14:55:42.000000000 +0200
|
||||
+++ lempar.c 2020-07-10 11:04:51.991472607 +0200
|
||||
@@ -93,6 +93,12 @@
|
||||
/************* End control #defines *******************************************/
|
||||
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
|
||||
|
||||
+/* Default linkage for exposed parser routines is global
|
||||
+*/
|
||||
+#ifndef YYFUNCAPI
|
||||
+# define YYFUNCAPI
|
||||
+#endif
|
||||
+
|
||||
/* Define the yytestcase() macro to be a no-op if is not already defined
|
||||
** otherwise.
|
||||
**
|
||||
@@ -251,6 +257,7 @@
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
|
||||
yyTraceFILE = TraceFILE;
|
||||
yyTracePrompt = zTracePrompt;
|
||||
if( yyTraceFILE==0 ) yyTracePrompt = 0;
|
||||
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
|
||||
}
|
||||
+%namespace_end
|
||||
#endif /* NDEBUG */
|
||||
|
||||
#if defined(YYCOVERAGE) || !defined(NDEBUG)
|
||||
@@ -320,6 +322,7 @@
|
||||
@@ -320,6 +327,7 @@
|
||||
|
||||
/* Initialize a new parser that has already been allocated.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void ParseInit(void *yypRawParser ParseCTX_PDECL){
|
||||
yyParser *yypParser = (yyParser*)yypRawParser;
|
||||
ParseCTX_STORE
|
||||
@@ -345,6 +348,7 @@
|
||||
yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
|
||||
#endif
|
||||
}
|
||||
+%namespace_end
|
||||
|
||||
#ifndef Parse_ENGINEALWAYSONSTACK
|
||||
/*
|
||||
@@ -359,6 +363,7 @@
|
||||
@@ -359,6 +367,7 @@
|
||||
** A pointer to a parser. This pointer is used in subsequent calls
|
||||
** to Parse and ParseFree.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){
|
||||
yyParser *yypParser;
|
||||
yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
|
||||
@@ -368,6 +373,7 @@
|
||||
}
|
||||
return (void*)yypParser;
|
||||
}
|
||||
+%namespace_end
|
||||
#endif /* Parse_ENGINEALWAYSONSTACK */
|
||||
|
||||
|
||||
@@ -427,6 +433,7 @@
|
||||
@@ -427,6 +436,7 @@
|
||||
/*
|
||||
** Clear all secondary memory allocations from the parser
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void ParseFinalize(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
|
||||
@@ -434,6 +441,7 @@
|
||||
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
|
||||
#endif
|
||||
}
|
||||
+%namespace_end
|
||||
|
||||
#ifndef Parse_ENGINEALWAYSONSTACK
|
||||
/*
|
||||
@@ -444,6 +452,7 @@
|
||||
@@ -444,6 +454,7 @@
|
||||
** is defined in a %include section of the input grammar) then it is
|
||||
** assumed that the input pointer is never NULL.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void ParseFree(
|
||||
void *p, /* The parser to be deleted */
|
||||
void (*freeProc)(void*) /* Function used to reclaim memory */
|
||||
@@ -454,16 +463,19 @@
|
||||
ParseFinalize(p);
|
||||
(*freeProc)(p);
|
||||
}
|
||||
+%namespace_end
|
||||
#endif /* Parse_ENGINEALWAYSONSTACK */
|
||||
|
||||
/*
|
||||
@@ -460,6 +471,7 @@
|
||||
** Return the peak depth of the stack for a parser.
|
||||
*/
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
int ParseStackPeak(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
return pParser->yyhwm;
|
||||
}
|
||||
+%namespace_end
|
||||
#endif
|
||||
|
||||
/* This array of booleans keeps track of the parser statement
|
||||
@@ -484,6 +496,7 @@
|
||||
** Return the number of missed state/lookahead combinations.
|
||||
*/
|
||||
#if defined(YYCOVERAGE)
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
int ParseCoverage(FILE *out){
|
||||
int stateno, iLookAhead, i;
|
||||
int nMissed = 0;
|
||||
@@ -501,6 +514,7 @@
|
||||
}
|
||||
return nMissed;
|
||||
}
|
||||
+%namespace_end
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -891,6 +905,7 @@
|
||||
@@ -891,6 +904,7 @@
|
||||
** Outputs:
|
||||
** None.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
void Parse(
|
||||
void *yyp, /* The parser */
|
||||
int yymajor, /* The major token code number */
|
||||
@@ -1060,11 +1075,13 @@
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
+%namespace_end
|
||||
|
||||
/*
|
||||
@@ -1065,6 +1079,7 @@
|
||||
** Return the fallback token corresponding to canonical token iToken, or
|
||||
** 0 if iToken has no fallback.
|
||||
*/
|
||||
+%namespace_begin
|
||||
+YYFUNCAPI
|
||||
int ParseFallback(int iToken){
|
||||
#ifdef YYFALLBACK
|
||||
assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
|
||||
@@ -1074,3 +1091,4 @@
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
+%namespace_end
|
||||
|
@ -1,23 +1,21 @@
|
||||
Minimal changes to lemon for C++ integration.
|
||||
|
||||
- New '-e' command line option to define the code extension.
|
||||
- Additional '-e' command line option to define the code extension.
|
||||
By default this is 'c', but with this option can define something
|
||||
like -ecxx etc for using a C++ compiler.
|
||||
like '-ecxx' etc for using a C++ compiler.
|
||||
|
||||
- New '%namespace' directive. This can be used to embed the 'Parse*'
|
||||
routines into a C++ namespace. The namespace can be anonymous or
|
||||
contain multiple nested namespaces. For example,
|
||||
- Additional '%static' Lemon directive, which is boolean-like:
|
||||
|
||||
%namespace {}
|
||||
%namespace {ns1::ns2::ns3}
|
||||
%static
|
||||
|
||||
|
||||
One simple means to encapsulate code is to use an anonymous
|
||||
namespace for the Lemon code and place all C++ interface code with
|
||||
the %code block in the same translation unit.
|
||||
This adds a 'static' qualifier to all of the 'Parse*' routines that
|
||||
would otherwise have global linkage, thus making them only visible
|
||||
in the same file-scope.
|
||||
Can subsequently place all of the C++ interface code within a %code
|
||||
block in the same translation unit.
|
||||
|
||||
This allows good encapsulation without fundamentally changing how
|
||||
Lemon works.
|
||||
|
||||
--
|
||||
2019-09-27
|
||||
2020-07-10
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Part of check-in [https://www.sqlite.org/src/info/fccfb8a9ed3c1df9]
|
||||
* artifact:
|
||||
* https://www.sqlite.org/src/raw/tool/lemon.c?name=a361b85fa230560b783006ac002a6a8bad214c3b9d7fa48980aecc2b691ddcad
|
||||
/* https://sqlite.org/src/artifact/600a58b9
|
||||
* Artifact 600a58b9d1b8ec5419373982428e927ca208826edacb91ca42ab94514d006039:
|
||||
* File tool/lemon.c part of check-in [951d22b7] at 2020-07-03
|
||||
*/
|
||||
/*
|
||||
** This file contains all sources (including headers) to the LEMON
|
||||
@ -406,7 +405,6 @@ struct lemon {
|
||||
struct symbol *errsym; /* The error symbol */
|
||||
struct symbol *wildcard; /* Token that matches anything */
|
||||
char *name; /* Name of the generated parser */
|
||||
char *namesp; /* Surrounding namespace for generated parser */
|
||||
char *arg; /* Declaration of the 3th argument to parser */
|
||||
char *ctx; /* Declaration of 2nd argument to constructor */
|
||||
char *tokentype; /* Type of terminal symbols in the parser stack */
|
||||
@ -429,8 +427,10 @@ struct lemon {
|
||||
int nlookaheadtab; /* Number of entries in yy_lookahead[] */
|
||||
int tablesize; /* Total table size of all tables in bytes */
|
||||
int basisflag; /* Print only basis configurations */
|
||||
int printPreprocessed; /* Show preprocessor output on stdout */
|
||||
int has_fallback; /* True if any %fallback is seen in the grammar */
|
||||
int nolinenosflag; /* True if #line statements should not be printed */
|
||||
int linkage; /* 1 if %static provided (use static linkage) */
|
||||
char *argv0; /* Name of the program */
|
||||
};
|
||||
|
||||
@ -1561,8 +1561,9 @@ static void handle_d_option(char *z){
|
||||
}
|
||||
|
||||
/* Remember the name of the code extension (automatically prefix '.')
|
||||
** default is "c" extension
|
||||
*/
|
||||
static char *code_ext = NULL;
|
||||
static char *code_ext = ".c";
|
||||
static void handle_e_option(char *z){
|
||||
code_ext = (char *) malloc( lemonStrlen(z)+2 );
|
||||
if( code_ext==0 ){
|
||||
@ -1659,6 +1660,7 @@ int main(int argc, char **argv)
|
||||
static int nolinenosflag = 0;
|
||||
static int noResort = 0;
|
||||
static int sqlFlag = 0;
|
||||
static int printPP = 0;
|
||||
|
||||
static struct s_options options[] = {
|
||||
{OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
|
||||
@ -1666,6 +1668,7 @@ int main(int argc, char **argv)
|
||||
{OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"},
|
||||
{OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
|
||||
{OPT_FSTR, "e", (char*)&handle_e_option, "Output code extension. Default 'c'"},
|
||||
{OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."},
|
||||
{OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
|
||||
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
|
||||
{OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
|
||||
@ -1710,11 +1713,12 @@ int main(int argc, char **argv)
|
||||
lem.filename = OptArg(0);
|
||||
lem.basisflag = basisflag;
|
||||
lem.nolinenosflag = nolinenosflag;
|
||||
lem.printPreprocessed = printPP;
|
||||
Symbol_new("$");
|
||||
|
||||
/* Parse the input file */
|
||||
Parse(&lem);
|
||||
if( lem.errorcnt ) exit(lem.errorcnt);
|
||||
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
|
||||
if( lem.nrule==0 ){
|
||||
fprintf(stderr,"Empty grammar.\n");
|
||||
exit(1);
|
||||
@ -2286,6 +2290,7 @@ static void parseonetoken(struct pstate *psp)
|
||||
psp->preccounter = 0;
|
||||
psp->firstrule = psp->lastrule = 0;
|
||||
psp->gp->nrule = 0;
|
||||
psp->gp->linkage = 0;
|
||||
/* Fall thru to next case */
|
||||
case WAITING_FOR_DECL_OR_RULE:
|
||||
if( x[0]=='%' ){
|
||||
@ -2509,9 +2514,6 @@ static void parseonetoken(struct pstate *psp)
|
||||
if( strcmp(x,"name")==0 ){
|
||||
psp->declargslot = &(psp->gp->name);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"namespace")==0 ){
|
||||
psp->declargslot = &(psp->gp->namesp);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"include")==0 ){
|
||||
psp->declargslot = &(psp->gp->include);
|
||||
}else if( strcmp(x,"code")==0 ){
|
||||
@ -2574,6 +2576,11 @@ static void parseonetoken(struct pstate *psp)
|
||||
psp->state = WAITING_FOR_WILDCARD_ID;
|
||||
}else if( strcmp(x,"token_class")==0 ){
|
||||
psp->state = WAITING_FOR_CLASS_ID;
|
||||
}else if( strcmp(x,"static")==0 ){
|
||||
/* %static is boolean-like */
|
||||
psp->gp->linkage = 1; /* 1 = static (True) */
|
||||
psp->insertLineMacro = 0;
|
||||
psp->state = WAITING_FOR_DECL_OR_RULE;
|
||||
}else{
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Unknown declaration keyword: \"%%%s\".",x);
|
||||
@ -2806,13 +2813,108 @@ static void parseonetoken(struct pstate *psp)
|
||||
}
|
||||
}
|
||||
|
||||
/* The text in the input is part of the argument to an %ifdef or %ifndef.
|
||||
** Evaluate the text as a boolean expression. Return true or false.
|
||||
*/
|
||||
static int eval_preprocessor_boolean(char *z, int lineno){
|
||||
int neg = 0;
|
||||
int res = 0;
|
||||
int okTerm = 1;
|
||||
int i;
|
||||
for(i=0; z[i]!=0; i++){
|
||||
if( ISSPACE(z[i]) ) continue;
|
||||
if( z[i]=='!' ){
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
neg = !neg;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='|' && z[i+1]=='|' ){
|
||||
if( okTerm ) goto pp_syntax_error;
|
||||
if( res ) return 1;
|
||||
i++;
|
||||
okTerm = 1;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='&' && z[i+1]=='&' ){
|
||||
if( okTerm ) goto pp_syntax_error;
|
||||
if( !res ) return 0;
|
||||
i++;
|
||||
okTerm = 1;
|
||||
continue;
|
||||
}
|
||||
if( z[i]=='(' ){
|
||||
int k;
|
||||
int n = 1;
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
for(k=i+1; z[k]; k++){
|
||||
if( z[k]==')' ){
|
||||
n--;
|
||||
if( n==0 ){
|
||||
z[k] = 0;
|
||||
res = eval_preprocessor_boolean(&z[i+1], -1);
|
||||
z[k] = ')';
|
||||
if( res<0 ){
|
||||
i = i-res;
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
i = k;
|
||||
break;
|
||||
}
|
||||
}else if( z[k]=='(' ){
|
||||
n++;
|
||||
}else if( z[k]==0 ){
|
||||
i = k;
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
}
|
||||
if( neg ){
|
||||
res = !res;
|
||||
neg = 0;
|
||||
}
|
||||
okTerm = 0;
|
||||
continue;
|
||||
}
|
||||
if( ISALPHA(z[i]) ){
|
||||
int j, k, n;
|
||||
if( !okTerm ) goto pp_syntax_error;
|
||||
for(k=i+1; ISALNUM(z[k]) || z[k]=='_'; k++){}
|
||||
n = k - i;
|
||||
res = 0;
|
||||
for(j=0; j<nDefine; j++){
|
||||
if( strncmp(azDefine[j],&z[i],n)==0 && azDefine[j][n]==0 ){
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = k-1;
|
||||
if( neg ){
|
||||
res = !res;
|
||||
neg = 0;
|
||||
}
|
||||
okTerm = 0;
|
||||
continue;
|
||||
}
|
||||
goto pp_syntax_error;
|
||||
}
|
||||
return res;
|
||||
|
||||
pp_syntax_error:
|
||||
if( lineno>0 ){
|
||||
fprintf(stderr, "%%if syntax error on line %d.\n", lineno);
|
||||
fprintf(stderr, " %.*s <-- syntax error here\n", i+1, z);
|
||||
exit(1);
|
||||
}else{
|
||||
return -(i+1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the preprocessor over the input file text. The global variables
|
||||
** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
|
||||
** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
|
||||
** comments them out. Text in between is also commented out as appropriate.
|
||||
*/
|
||||
static void preprocess_input(char *z){
|
||||
int i, j, k, n;
|
||||
int i, j, k;
|
||||
int exclude = 0;
|
||||
int start = 0;
|
||||
int lineno = 1;
|
||||
@ -2828,21 +2930,33 @@ static void preprocess_input(char *z){
|
||||
}
|
||||
}
|
||||
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
|
||||
}else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
|
||||
|| (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
|
||||
}else if( strncmp(&z[i],"%else",5)==0 && ISSPACE(z[i+5]) ){
|
||||
if( exclude==1){
|
||||
exclude = 0;
|
||||
for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
|
||||
}else if( exclude==0 ){
|
||||
exclude = 1;
|
||||
start = i;
|
||||
start_lineno = lineno;
|
||||
}
|
||||
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
|
||||
}else if( strncmp(&z[i],"%ifdef ",7)==0
|
||||
|| strncmp(&z[i],"%if ",4)==0
|
||||
|| strncmp(&z[i],"%ifndef ",8)==0 ){
|
||||
if( exclude ){
|
||||
exclude++;
|
||||
}else{
|
||||
for(j=i+7; ISSPACE(z[j]); j++){}
|
||||
for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
|
||||
exclude = 1;
|
||||
for(k=0; k<nDefine; k++){
|
||||
if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
|
||||
exclude = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( z[i+3]=='n' ) exclude = !exclude;
|
||||
int isNot;
|
||||
int iBool;
|
||||
for(j=i; z[j] && !ISSPACE(z[j]); j++){}
|
||||
iBool = j;
|
||||
isNot = (j==i+7);
|
||||
while( z[j] && z[j]!='\n' ){ j++; }
|
||||
k = z[j];
|
||||
z[j] = 0;
|
||||
exclude = eval_preprocessor_boolean(&z[iBool], lineno);
|
||||
z[j] = k;
|
||||
if( !isNot ) exclude = !exclude;
|
||||
if( exclude ){
|
||||
start = i;
|
||||
start_lineno = lineno;
|
||||
@ -2910,6 +3024,10 @@ void Parse(struct lemon *gp)
|
||||
|
||||
/* Make an initial pass through the file to handle %ifdef and %ifndef */
|
||||
preprocess_input(filebuf);
|
||||
if( gp->printPreprocessed ){
|
||||
printf("%s\n", filebuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now scan the text of the input file */
|
||||
lineno = 1;
|
||||
@ -3499,83 +3617,20 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
|
||||
#define LINESIZE 1000
|
||||
/* The next cluster of routines are for reading the template file
|
||||
** and writing the results to the generated parser */
|
||||
|
||||
/* Helper function to emit begin of namespace when namesp!=0
|
||||
** Converts "ns1::ns2" to "namespace ns1 { namespace ns2 {"
|
||||
*/
|
||||
PRIVATE void tplt_namespace_begin(char *namesp, FILE *out)
|
||||
{
|
||||
if(!namesp) return;
|
||||
while (ISSPACE(*namesp)) ++namesp;
|
||||
|
||||
char *cp = namesp;
|
||||
do {
|
||||
fprintf(out,"namespace ");
|
||||
cp = strchr(namesp, ':');
|
||||
if (cp) {
|
||||
while (namesp != cp) {
|
||||
fputc(*namesp,out);
|
||||
++namesp;
|
||||
}
|
||||
while(*namesp == ':') ++namesp;
|
||||
}
|
||||
else {
|
||||
while (*namesp && !ISSPACE(*namesp)) {
|
||||
fputc(*namesp,out);
|
||||
++namesp;
|
||||
}
|
||||
}
|
||||
fprintf(out, " {");
|
||||
} while (cp);
|
||||
fputc('\n',out);
|
||||
}
|
||||
|
||||
/* Helper function to emit end of namespace when namesp!=0
|
||||
** Converts "ns1::ns2" to "}} // End namespace"
|
||||
*/
|
||||
PRIVATE void tplt_namespace_end(char *namesp, FILE *out)
|
||||
{
|
||||
if(!namesp) return;
|
||||
while (ISSPACE(*namesp)) ++namesp;
|
||||
|
||||
char *cp = namesp;
|
||||
do {
|
||||
cp = strchr(cp, ':');
|
||||
if (cp) {
|
||||
while(*cp == ':') ++cp;
|
||||
}
|
||||
fputc('}',out);
|
||||
} while (cp);
|
||||
|
||||
fprintf(out," // End namespace %s\n", namesp);
|
||||
}
|
||||
|
||||
/* The first function transfers data from "in" to "out" until
|
||||
** a line is seen which begins with "%%". The line number is
|
||||
** tracked.
|
||||
**
|
||||
** if name!=0, then any word that begin with "Parse" is changed to
|
||||
** begin with *name instead.
|
||||
**
|
||||
** if namesp!=0, then replace %namespace_begin / %namespace_end
|
||||
*/
|
||||
PRIVATE void tplt_xfer(char *name, char *namesp, FILE *in, FILE *out, int *lineno)
|
||||
PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
|
||||
{
|
||||
int i, iStart;
|
||||
char line[LINESIZE];
|
||||
while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
|
||||
(*lineno)++;
|
||||
iStart = 0;
|
||||
if(line[0]=='%' && line[1]=='n'){
|
||||
if(strncmp(&line[1],"namespace_begin",15)==0){
|
||||
tplt_namespace_begin(namesp, out);
|
||||
continue;
|
||||
}else if(strncmp(&line[1],"namespace_end",13)==0){
|
||||
tplt_namespace_end(namesp, out);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( name ){
|
||||
for(i=0; line[i]; i++){
|
||||
if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
|
||||
@ -4272,8 +4327,7 @@ void ReportTable(
|
||||
|
||||
in = tplt_open(lemp);
|
||||
if( in==0 ) return;
|
||||
if(code_ext) out = file_open(lemp,code_ext,"wb");
|
||||
else out = file_open(lemp,".c","wb");
|
||||
out = file_open(lemp,code_ext,"wb");
|
||||
if( out==0 ){
|
||||
fclose(in);
|
||||
return;
|
||||
@ -4351,7 +4405,7 @@ void ReportTable(
|
||||
fprintf(sql, "COMMIT;\n");
|
||||
}
|
||||
lineno = 1;
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the include code, if any */
|
||||
tplt_print(out,lemp,lemp->include,&lineno);
|
||||
@ -4360,7 +4414,7 @@ void ReportTable(
|
||||
fprintf(out,"#include \"%s\"\n", incName); lineno++;
|
||||
free(incName);
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate #defines for all tokens */
|
||||
if( mhflag ){
|
||||
@ -4374,9 +4428,12 @@ void ReportTable(
|
||||
}
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the defines */
|
||||
if( lemp->linkage ){
|
||||
fprintf(out,"#define YYFUNCAPI static\n"); lineno++;
|
||||
}
|
||||
fprintf(out,"#define YYCODETYPE %s\n",
|
||||
minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++;
|
||||
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++;
|
||||
@ -4539,7 +4596,7 @@ void ReportTable(
|
||||
fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
|
||||
i = lemp->minReduce + lemp->nrule;
|
||||
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Now output the action table and its associates:
|
||||
**
|
||||
@ -4677,7 +4734,7 @@ void ReportTable(
|
||||
}
|
||||
}
|
||||
fprintf(out, "};\n"); lineno++;
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the table of fallback tokens.
|
||||
*/
|
||||
@ -4698,7 +4755,7 @@ void ReportTable(
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp, in, out, &lineno);
|
||||
tplt_xfer(lemp->name, in, out, &lineno);
|
||||
|
||||
/* Generate a table containing the symbolic name of every symbol
|
||||
*/
|
||||
@ -4706,7 +4763,7 @@ void ReportTable(
|
||||
lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
|
||||
fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate a table containing a text string that describes every
|
||||
** rule in the rule set of the grammar. This information is used
|
||||
@ -4718,7 +4775,7 @@ void ReportTable(
|
||||
writeRuleText(out, rp);
|
||||
fprintf(out,"\",\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes every time a symbol is popped from
|
||||
** the stack while processing errors or while destroying the parser.
|
||||
@ -4781,11 +4838,11 @@ void ReportTable(
|
||||
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes whenever the parser stack overflows */
|
||||
tplt_print(out,lemp,lemp->overflow,&lineno);
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the tables of rule information. yyRuleInfoLhs[] and
|
||||
** yyRuleInfoNRhs[].
|
||||
@ -4798,13 +4855,13 @@ void ReportTable(
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
|
||||
fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which execution during each REDUCE action */
|
||||
i = 0;
|
||||
@ -4857,19 +4914,19 @@ void ReportTable(
|
||||
}
|
||||
}
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes if a parse fails */
|
||||
tplt_print(out,lemp,lemp->failure,&lineno);
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes when a syntax error occurs */
|
||||
tplt_print(out,lemp,lemp->error,&lineno);
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes when the parser accepts its input */
|
||||
tplt_print(out,lemp,lemp->accept,&lineno);
|
||||
tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Append any addition code the user desires */
|
||||
tplt_print(out,lemp,lemp->extracode,&lineno);
|
||||
|
@ -1,20 +1,21 @@
|
||||
--- lemon.c.orig 2020-01-10 14:08:19.181711107 +0100
|
||||
+++ lemon.c 2020-01-10 14:12:00.621402133 +0100
|
||||
@@ -406,6 +406,7 @@
|
||||
struct symbol *errsym; /* The error symbol */
|
||||
struct symbol *wildcard; /* Token that matches anything */
|
||||
char *name; /* Name of the generated parser */
|
||||
+ char *namesp; /* Surrounding namespace for generated parser */
|
||||
char *arg; /* Declaration of the 3th argument to parser */
|
||||
char *ctx; /* Declaration of 2nd argument to constructor */
|
||||
char *tokentype; /* Type of terminal symbols in the parser stack */
|
||||
@@ -1559,6 +1560,23 @@
|
||||
--- lemon.c.orig 2020-07-09 14:54:53.871102972 +0200
|
||||
+++ lemon.c 2020-07-10 12:01:05.488791973 +0200
|
||||
@@ -426,6 +426,7 @@
|
||||
int printPreprocessed; /* Show preprocessor output on stdout */
|
||||
int has_fallback; /* True if any %fallback is seen in the grammar */
|
||||
int nolinenosflag; /* True if #line statements should not be printed */
|
||||
+ int linkage; /* 1 if %static provided (use static linkage) */
|
||||
char *argv0; /* Name of the program */
|
||||
};
|
||||
|
||||
@@ -1555,6 +1556,24 @@
|
||||
lemon_strcpy(outputDir, z);
|
||||
}
|
||||
|
||||
+/* Remember the name of the code extension (automatically prefix '.')
|
||||
+** default is "c" extension
|
||||
+*/
|
||||
+static char *code_ext = NULL;
|
||||
+static char *code_ext = ".c";
|
||||
+static void handle_e_option(char *z){
|
||||
+ code_ext = (char *) malloc( lemonStrlen(z)+2 );
|
||||
+ if( code_ext==0 ){
|
||||
@ -32,242 +33,50 @@
|
||||
static char *user_templatename = NULL;
|
||||
static void handle_T_option(char *z){
|
||||
user_templatename = (char *) malloc( lemonStrlen(z)+1 );
|
||||
@@ -1647,6 +1665,7 @@
|
||||
@@ -1644,6 +1663,7 @@
|
||||
{OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
|
||||
{OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"},
|
||||
{OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
|
||||
+ {OPT_FSTR, "e", (char*)&handle_e_option, "Output code extension. Default 'c'"},
|
||||
{OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."},
|
||||
{OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
|
||||
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
|
||||
{OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
|
||||
@@ -2490,6 +2509,9 @@
|
||||
if( strcmp(x,"name")==0 ){
|
||||
psp->declargslot = &(psp->gp->name);
|
||||
psp->insertLineMacro = 0;
|
||||
+ }else if( strcmp(x,"namespace")==0 ){
|
||||
+ psp->declargslot = &(psp->gp->namesp);
|
||||
@@ -2266,6 +2286,7 @@
|
||||
psp->preccounter = 0;
|
||||
psp->firstrule = psp->lastrule = 0;
|
||||
psp->gp->nrule = 0;
|
||||
+ psp->gp->linkage = 0;
|
||||
/* Fall thru to next case */
|
||||
case WAITING_FOR_DECL_OR_RULE:
|
||||
if( x[0]=='%' ){
|
||||
@@ -2551,6 +2572,11 @@
|
||||
psp->state = WAITING_FOR_WILDCARD_ID;
|
||||
}else if( strcmp(x,"token_class")==0 ){
|
||||
psp->state = WAITING_FOR_CLASS_ID;
|
||||
+ }else if( strcmp(x,"static")==0 ){
|
||||
+ /* %static is boolean-like */
|
||||
+ psp->gp->linkage = 1; /* 1 = static (True) */
|
||||
+ psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"include")==0 ){
|
||||
psp->declargslot = &(psp->gp->include);
|
||||
}else if( strcmp(x,"code")==0 ){
|
||||
@@ -3477,20 +3499,83 @@
|
||||
#define LINESIZE 1000
|
||||
/* The next cluster of routines are for reading the template file
|
||||
** and writing the results to the generated parser */
|
||||
+
|
||||
+/* Helper function to emit begin of namespace when namesp!=0
|
||||
+** Converts "ns1::ns2" to "namespace ns1 { namespace ns2 {"
|
||||
+*/
|
||||
+PRIVATE void tplt_namespace_begin(char *namesp, FILE *out)
|
||||
+{
|
||||
+ if(!namesp) return;
|
||||
+ while (ISSPACE(*namesp)) ++namesp;
|
||||
+
|
||||
+ char *cp = namesp;
|
||||
+ do {
|
||||
+ fprintf(out,"namespace ");
|
||||
+ cp = strchr(namesp, ':');
|
||||
+ if (cp) {
|
||||
+ while (namesp != cp) {
|
||||
+ fputc(*namesp,out);
|
||||
+ ++namesp;
|
||||
+ }
|
||||
+ while(*namesp == ':') ++namesp;
|
||||
+ }
|
||||
+ else {
|
||||
+ while (*namesp && !ISSPACE(*namesp)) {
|
||||
+ fputc(*namesp,out);
|
||||
+ ++namesp;
|
||||
+ }
|
||||
+ }
|
||||
+ fprintf(out, " {");
|
||||
+ } while (cp);
|
||||
+ fputc('\n',out);
|
||||
+}
|
||||
+
|
||||
+/* Helper function to emit end of namespace when namesp!=0
|
||||
+** Converts "ns1::ns2" to "}} // End namespace"
|
||||
+*/
|
||||
+PRIVATE void tplt_namespace_end(char *namesp, FILE *out)
|
||||
+{
|
||||
+ if(!namesp) return;
|
||||
+ while (ISSPACE(*namesp)) ++namesp;
|
||||
+
|
||||
+ char *cp = namesp;
|
||||
+ do {
|
||||
+ cp = strchr(cp, ':');
|
||||
+ if (cp) {
|
||||
+ while(*cp == ':') ++cp;
|
||||
+ }
|
||||
+ fputc('}',out);
|
||||
+ } while (cp);
|
||||
+
|
||||
+ fprintf(out," // End namespace %s\n", namesp);
|
||||
+}
|
||||
+
|
||||
/* The first function transfers data from "in" to "out" until
|
||||
** a line is seen which begins with "%%". The line number is
|
||||
** tracked.
|
||||
**
|
||||
** if name!=0, then any word that begin with "Parse" is changed to
|
||||
** begin with *name instead.
|
||||
+**
|
||||
+** if namesp!=0, then replace %namespace_begin / %namespace_end
|
||||
*/
|
||||
-PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
|
||||
+PRIVATE void tplt_xfer(char *name, char *namesp, FILE *in, FILE *out, int *lineno)
|
||||
{
|
||||
int i, iStart;
|
||||
char line[LINESIZE];
|
||||
while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
|
||||
(*lineno)++;
|
||||
iStart = 0;
|
||||
+ if(line[0]=='%' && line[1]=='n'){
|
||||
+ if(strncmp(&line[1],"namespace_begin",15)==0){
|
||||
+ tplt_namespace_begin(namesp, out);
|
||||
+ continue;
|
||||
+ }else if(strncmp(&line[1],"namespace_end",13)==0){
|
||||
+ tplt_namespace_end(namesp, out);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if( name ){
|
||||
for(i=0; line[i]; i++){
|
||||
if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
|
||||
@@ -4187,7 +4272,8 @@
|
||||
+ psp->state = WAITING_FOR_DECL_OR_RULE;
|
||||
}else{
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Unknown declaration keyword: \"%%%s\".",x);
|
||||
@@ -4297,7 +4323,7 @@
|
||||
|
||||
in = tplt_open(lemp);
|
||||
if( in==0 ) return;
|
||||
- out = file_open(lemp,".c","wb");
|
||||
+ if(code_ext) out = file_open(lemp,code_ext,"wb");
|
||||
+ else out = file_open(lemp,".c","wb");
|
||||
+ out = file_open(lemp,code_ext,"wb");
|
||||
if( out==0 ){
|
||||
fclose(in);
|
||||
return;
|
||||
@@ -4265,7 +4351,7 @@
|
||||
fprintf(sql, "COMMIT;\n");
|
||||
}
|
||||
lineno = 1;
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate the include code, if any */
|
||||
tplt_print(out,lemp,lemp->include,&lineno);
|
||||
@@ -4274,7 +4360,7 @@
|
||||
fprintf(out,"#include \"%s\"\n", incName); lineno++;
|
||||
free(incName);
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate #defines for all tokens */
|
||||
if( mhflag ){
|
||||
@@ -4288,7 +4374,7 @@
|
||||
}
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
@@ -4401,6 +4427,9 @@
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the defines */
|
||||
+ if( lemp->linkage ){
|
||||
+ fprintf(out,"#define YYFUNCAPI static\n"); lineno++;
|
||||
+ }
|
||||
fprintf(out,"#define YYCODETYPE %s\n",
|
||||
@@ -4453,7 +4539,7 @@
|
||||
fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
|
||||
i = lemp->minReduce + lemp->nrule;
|
||||
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Now output the action table and its associates:
|
||||
**
|
||||
@@ -4591,7 +4677,7 @@
|
||||
}
|
||||
}
|
||||
fprintf(out, "};\n"); lineno++;
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate the table of fallback tokens.
|
||||
*/
|
||||
@@ -4612,7 +4698,7 @@
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
- tplt_xfer(lemp->name, in, out, &lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp, in, out, &lineno);
|
||||
|
||||
/* Generate a table containing the symbolic name of every symbol
|
||||
*/
|
||||
@@ -4620,7 +4706,7 @@
|
||||
lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
|
||||
fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate a table containing a text string that describes every
|
||||
** rule in the rule set of the grammar. This information is used
|
||||
@@ -4632,7 +4718,7 @@
|
||||
writeRuleText(out, rp);
|
||||
fprintf(out,"\",\n"); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes every time a symbol is popped from
|
||||
** the stack while processing errors or while destroying the parser.
|
||||
@@ -4695,11 +4781,11 @@
|
||||
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes whenever the parser stack overflows */
|
||||
tplt_print(out,lemp,lemp->overflow,&lineno);
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate the tables of rule information. yyRuleInfoLhs[] and
|
||||
** yyRuleInfoNRhs[].
|
||||
@@ -4712,13 +4798,13 @@
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
|
||||
fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which execution during each REDUCE action */
|
||||
i = 0;
|
||||
@@ -4771,19 +4857,19 @@
|
||||
}
|
||||
}
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes if a parse fails */
|
||||
tplt_print(out,lemp,lemp->failure,&lineno);
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes when a syntax error occurs */
|
||||
tplt_print(out,lemp,lemp->error,&lineno);
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Generate code which executes when the parser accepts its input */
|
||||
tplt_print(out,lemp,lemp->accept,&lineno);
|
||||
- tplt_xfer(lemp->name,in,out,&lineno);
|
||||
+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno);
|
||||
|
||||
/* Append any addition code the user desires */
|
||||
tplt_print(out,lemp,lemp->extracode,&lineno);
|
||||
minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++;
|
||||
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++;
|
||||
|
Loading…
Reference in New Issue
Block a user