Re: [sqlite] (Lemon) (Patch) adding a -f option to Lemon to emit function prototypes

2013-01-09 Thread Tiago Rodrigues
I see; well, that's unfortunate.  At any rate, parsing lempar.c will
probably be much more complex than the code I have now, which solves a
simple (but common) case.  Maybe I'll look into parsing lempar.c, but since
this solves my use case, I probably won't be in a hurry to do it.  I
apologise to everyone this doesn't help, then.

Cheers,

  -Tiago


On Mon, Jan 7, 2013 at 9:13 PM, Richard Hipp  wrote:

> On Mon, Jan 7, 2013 at 4:18 PM, Tiago Rodrigues  wrote:
>
> > Oops, Dominique alerted me to the fact that the patch I included was
> > stripped by the listserver...  I'm including it inline, then.
> >
>
>
> This patch does not work in the general case.  I don't doubt that it works
> for your use case, but in general it does not.  The reason:  The function
> prototypes depend on the "lempar.c" template file.  Some applications (ex:
> SQLite) change the lempar.c parser template in ways that could change the
> function signatures.  (The function signatures for SQLite are unchanged,
> but that doesn't exclude the possibility that they might in the future.)
>
> For this to really work in general, I suppose you would have to somehow
> extract the function signatures from the lempar.c template file.  Or maybe
> have a separate lempar.h template that contains the header.  Or something.
>
>
>
> >
> > (Begin patch)
> >
> > --- lemon.c2013-01-04 20:39:20 +
> > +++ lemon-new.c2013-01-04 23:09:59 +
> > @@ -109,7 +109,7 @@
> >  void Reprint(struct lemon *);
> >  void ReportOutput(struct lemon *);
> >  void ReportTable(struct lemon *, int);
> > -void ReportHeader(struct lemon *);
> > +void ReportHeader(struct lemon *, int);
> >  void CompressTables(struct lemon *);
> >  void ResortStates(struct lemon *);
> >
> > @@ -1393,11 +1393,13 @@
> >static int mhflag = 0;
> >static int nolinenosflag = 0;
> >static int noResort = 0;
> > +  static int fpflag = 0;
> >static struct s_options options[] = {
> >  {OPT_FLAG, "b", (char*), "Print only the basis in
> report."},
> >  {OPT_FLAG, "c", (char*), "Don't compress the action
> table."},
> >  {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
> >  {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
> > +{OPT_FLAG, "f", (char*), "Generate function prototypes in
> > header."},
> >  {OPT_FLAG, "g", (char*), "Print grammar without actions."},
> >  {OPT_FLAG, "m", (char*), "Output a makeheaders compatible
> > file."},
> >  {OPT_FLAG, "l", (char*), "Do not print #line
> > statements."},
> > @@ -1502,7 +1504,7 @@
> >  /* Produce a header file for use by the scanner.  (This step is
> >  ** omitted if the "-m" option is used because makeheaders will
> >  ** generate the file for us.) */
> > -if( !mhflag ) ReportHeader();
> > +if( !mhflag ) ReportHeader(, fpflag);
> >}
> >if( statistics ){
> >  printf("Parser statistics: %d terminals, %d nonterminals, %d
> rules\n",
> > @@ -4009,16 +4011,20 @@
> >  }
> >
> >  /* Generate a header file for the parser */
> > -void ReportHeader(struct lemon *lemp)
> > +void ReportHeader(struct lemon *lemp, int fpflag)
> >  {
> >FILE *out, *in;
> > +  const char *name;
> >const char *prefix;
> >char line[LINESIZE];
> >char pattern[LINESIZE];
> >int i;
> > +  int protok = 1;
> >
> >if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
> >elseprefix = "";
> > +  if( lemp->name ) name = lemp->name;
> > +  else name = "Parse";
> >in = file_open(lemp,".h","rb");
> >if( in ){
> >  int nextChar;
> > @@ -4026,9 +4032,24 @@
> >sprintf(pattern,"#define %s%-30s
> > %2d\n",prefix,lemp->symbols[i]->name,i);
> >if( strcmp(line,pattern) ) break;
> >  }
> > +if( fpflag ){
> > +sprintf(pattern,"void *%sAlloc(void *(*)(size_t));\n",name);
> > +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> > 0; goto after; }
> > +
> > +if( lemp->arg ){
> > +sprintf(pattern,"void %s(void
> > *,int,%s,%s);\n",name,lemp->tokentype,lemp->arg);
> > +}else{
> > +sprintf(pattern,"void %s(void
> > *,int,%s);\n",name,lemp->tokentype);
> > +}
> > +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> > 0; goto after; }
> > +
> > +sprintf(pattern,"void *%sFree(void *,void (*)(void
> *));\n",name);
> > +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> > 0; goto after; }
> > +}
> > +after:
> >  nextChar = fgetc(in);
> >  fclose(in);
> > -if( i==lemp->nterminal && nextChar==EOF ){
> > +if( i==lemp->nterminal && protok && nextChar==EOF ){
> >/* No change in the file.  Don't rewrite it. */
> >return;
> >  }
> > @@ -4038,6 +4059,16 @@
> >  for(i=1; interminal; i++){
> >fprintf(out,"#define %s%-30s
> > %2d\n",prefix,lemp->symbols[i]->name,i);
> >  }
> > +

Re: [sqlite] (Lemon) (Patch) adding a -f option to Lemon to emit function prototypes

2013-01-07 Thread Richard Hipp
On Mon, Jan 7, 2013 at 4:18 PM, Tiago Rodrigues  wrote:

> Oops, Dominique alerted me to the fact that the patch I included was
> stripped by the listserver...  I'm including it inline, then.
>


This patch does not work in the general case.  I don't doubt that it works
for your use case, but in general it does not.  The reason:  The function
prototypes depend on the "lempar.c" template file.  Some applications (ex:
SQLite) change the lempar.c parser template in ways that could change the
function signatures.  (The function signatures for SQLite are unchanged,
but that doesn't exclude the possibility that they might in the future.)

For this to really work in general, I suppose you would have to somehow
extract the function signatures from the lempar.c template file.  Or maybe
have a separate lempar.h template that contains the header.  Or something.



>
> (Begin patch)
>
> --- lemon.c2013-01-04 20:39:20 +
> +++ lemon-new.c2013-01-04 23:09:59 +
> @@ -109,7 +109,7 @@
>  void Reprint(struct lemon *);
>  void ReportOutput(struct lemon *);
>  void ReportTable(struct lemon *, int);
> -void ReportHeader(struct lemon *);
> +void ReportHeader(struct lemon *, int);
>  void CompressTables(struct lemon *);
>  void ResortStates(struct lemon *);
>
> @@ -1393,11 +1393,13 @@
>static int mhflag = 0;
>static int nolinenosflag = 0;
>static int noResort = 0;
> +  static int fpflag = 0;
>static struct s_options options[] = {
>  {OPT_FLAG, "b", (char*), "Print only the basis in report."},
>  {OPT_FLAG, "c", (char*), "Don't compress the action table."},
>  {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
>  {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
> +{OPT_FLAG, "f", (char*), "Generate function prototypes in
> header."},
>  {OPT_FLAG, "g", (char*), "Print grammar without actions."},
>  {OPT_FLAG, "m", (char*), "Output a makeheaders compatible
> file."},
>  {OPT_FLAG, "l", (char*), "Do not print #line
> statements."},
> @@ -1502,7 +1504,7 @@
>  /* Produce a header file for use by the scanner.  (This step is
>  ** omitted if the "-m" option is used because makeheaders will
>  ** generate the file for us.) */
> -if( !mhflag ) ReportHeader();
> +if( !mhflag ) ReportHeader(, fpflag);
>}
>if( statistics ){
>  printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
> @@ -4009,16 +4011,20 @@
>  }
>
>  /* Generate a header file for the parser */
> -void ReportHeader(struct lemon *lemp)
> +void ReportHeader(struct lemon *lemp, int fpflag)
>  {
>FILE *out, *in;
> +  const char *name;
>const char *prefix;
>char line[LINESIZE];
>char pattern[LINESIZE];
>int i;
> +  int protok = 1;
>
>if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
>elseprefix = "";
> +  if( lemp->name ) name = lemp->name;
> +  else name = "Parse";
>in = file_open(lemp,".h","rb");
>if( in ){
>  int nextChar;
> @@ -4026,9 +4032,24 @@
>sprintf(pattern,"#define %s%-30s
> %2d\n",prefix,lemp->symbols[i]->name,i);
>if( strcmp(line,pattern) ) break;
>  }
> +if( fpflag ){
> +sprintf(pattern,"void *%sAlloc(void *(*)(size_t));\n",name);
> +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> 0; goto after; }
> +
> +if( lemp->arg ){
> +sprintf(pattern,"void %s(void
> *,int,%s,%s);\n",name,lemp->tokentype,lemp->arg);
> +}else{
> +sprintf(pattern,"void %s(void
> *,int,%s);\n",name,lemp->tokentype);
> +}
> +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> 0; goto after; }
> +
> +sprintf(pattern,"void *%sFree(void *,void (*)(void *));\n",name);
> +if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
> 0; goto after; }
> +}
> +after:
>  nextChar = fgetc(in);
>  fclose(in);
> -if( i==lemp->nterminal && nextChar==EOF ){
> +if( i==lemp->nterminal && protok && nextChar==EOF ){
>/* No change in the file.  Don't rewrite it. */
>return;
>  }
> @@ -4038,6 +4059,16 @@
>  for(i=1; interminal; i++){
>fprintf(out,"#define %s%-30s
> %2d\n",prefix,lemp->symbols[i]->name,i);
>  }
> +if( fpflag ){
> +/* emit function prototypes */
> +fprintf(out,"void *%sAlloc(void *(*)(size_t));\n",name);
> +if( lemp->arg ){
> +fprintf(out,"void %s(void
> *,int,%s,%s);\n",name,lemp->tokentype,lemp->arg);
> +}else{
> +fprintf(out,"void %s(void *,int,%s);\n",name,lemp->tokentype);
> +}
> +fprintf(out,"void *%sFree(void *,void (*)(void *));\n",name);
> +}
>  fclose(out);
>}
>return;
>
> (End patch)
>
> Thanks,
>
>   -Tiago
>
>
> On Mon, Jan 7, 2013 at 6:15 AM, Dominique Devienne  >wrote:
>
> > On Sat, Jan 5, 2013 at 6:22 PM, Tiago Rodrigues 

Re: [sqlite] (Lemon) (Patch) adding a -f option to Lemon to emit function prototypes

2013-01-07 Thread Tiago Rodrigues
Oops, Dominique alerted me to the fact that the patch I included was
stripped by the listserver...  I'm including it inline, then.

(Begin patch)

--- lemon.c2013-01-04 20:39:20 +
+++ lemon-new.c2013-01-04 23:09:59 +
@@ -109,7 +109,7 @@
 void Reprint(struct lemon *);
 void ReportOutput(struct lemon *);
 void ReportTable(struct lemon *, int);
-void ReportHeader(struct lemon *);
+void ReportHeader(struct lemon *, int);
 void CompressTables(struct lemon *);
 void ResortStates(struct lemon *);

@@ -1393,11 +1393,13 @@
   static int mhflag = 0;
   static int nolinenosflag = 0;
   static int noResort = 0;
+  static int fpflag = 0;
   static struct s_options options[] = {
 {OPT_FLAG, "b", (char*), "Print only the basis in report."},
 {OPT_FLAG, "c", (char*), "Don't compress the action table."},
 {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
 {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
+{OPT_FLAG, "f", (char*), "Generate function prototypes in
header."},
 {OPT_FLAG, "g", (char*), "Print grammar without actions."},
 {OPT_FLAG, "m", (char*), "Output a makeheaders compatible
file."},
 {OPT_FLAG, "l", (char*), "Do not print #line
statements."},
@@ -1502,7 +1504,7 @@
 /* Produce a header file for use by the scanner.  (This step is
 ** omitted if the "-m" option is used because makeheaders will
 ** generate the file for us.) */
-if( !mhflag ) ReportHeader();
+if( !mhflag ) ReportHeader(, fpflag);
   }
   if( statistics ){
 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
@@ -4009,16 +4011,20 @@
 }

 /* Generate a header file for the parser */
-void ReportHeader(struct lemon *lemp)
+void ReportHeader(struct lemon *lemp, int fpflag)
 {
   FILE *out, *in;
+  const char *name;
   const char *prefix;
   char line[LINESIZE];
   char pattern[LINESIZE];
   int i;
+  int protok = 1;

   if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
   elseprefix = "";
+  if( lemp->name ) name = lemp->name;
+  else name = "Parse";
   in = file_open(lemp,".h","rb");
   if( in ){
 int nextChar;
@@ -4026,9 +4032,24 @@
   sprintf(pattern,"#define %s%-30s
%2d\n",prefix,lemp->symbols[i]->name,i);
   if( strcmp(line,pattern) ) break;
 }
+if( fpflag ){
+sprintf(pattern,"void *%sAlloc(void *(*)(size_t));\n",name);
+if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
0; goto after; }
+
+if( lemp->arg ){
+sprintf(pattern,"void %s(void
*,int,%s,%s);\n",name,lemp->tokentype,lemp->arg);
+}else{
+sprintf(pattern,"void %s(void
*,int,%s);\n",name,lemp->tokentype);
+}
+if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
0; goto after; }
+
+sprintf(pattern,"void *%sFree(void *,void (*)(void *));\n",name);
+if( !fgets(line,LINESIZE,in) || strcmp(line,pattern) ){ protok =
0; goto after; }
+}
+after:
 nextChar = fgetc(in);
 fclose(in);
-if( i==lemp->nterminal && nextChar==EOF ){
+if( i==lemp->nterminal && protok && nextChar==EOF ){
   /* No change in the file.  Don't rewrite it. */
   return;
 }
@@ -4038,6 +4059,16 @@
 for(i=1; interminal; i++){
   fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
 }
+if( fpflag ){
+/* emit function prototypes */
+fprintf(out,"void *%sAlloc(void *(*)(size_t));\n",name);
+if( lemp->arg ){
+fprintf(out,"void %s(void
*,int,%s,%s);\n",name,lemp->tokentype,lemp->arg);
+}else{
+fprintf(out,"void %s(void *,int,%s);\n",name,lemp->tokentype);
+}
+fprintf(out,"void *%sFree(void *,void (*)(void *));\n",name);
+}
 fclose(out);
   }
   return;

(End patch)

Thanks,

  -Tiago


On Mon, Jan 7, 2013 at 6:15 AM, Dominique Devienne wrote:

> On Sat, Jan 5, 2013 at 6:22 PM, Tiago Rodrigues  wrote:
> > [...]
> > This patch works against the current version of lemon.c, as linked to by
> > the Lemon page.  This is probably not correct, as the file is amalgamated
> > from other sources, but still might be useful to somebody.
>
> Hi Tiago. Looks like the patch was stripped by the mailing list.
> Perhaps you should include it inline to your message. Thanks, --DD
>



-- 
In those days, in those distant days, in those nights, in those remote
nights, in those years, in those distant years...
  - Gilgamesh, Enkidu and the Underworld
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users