At Fri, 26 Feb 2016 10:38:22 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI 
<horiguchi.kyot...@lab.ntt.co.jp> wrote in 
<20160226.103822.12680005.horiguchi.kyot...@lab.ntt.co.jp>
> Hello, Thanks for the new patch.
> 
> 
> At Fri, 26 Feb 2016 08:52:54 +0900, Masahiko Sawada <sawada.m...@gmail.com> 
> wrote in <CAD21AoAZKFVu8-MVhkJ3ywAiJmb=P-HSbJTGi=gk1la73kj...@mail.gmail.com>
> > Previous patch could not parse one character standby name correctly.
> > Attached latest patch.
> 
> I haven't looked it in detail but it won't work as you
> expected. flex compains as the following for v12 patch.
> 
> syncgroup_scanner.l:80: warning, rule cannot be matched
> syncgroup_scanner.l:84: warning, rule cannot be matched

Making it independent from postgres body then compile it with
-DYYDEBUG and set yydebug = 1 would give you valuable information
and make testing of the parser far easier.

| $ flex test2.l; bison -v test2.y; gcc -g -DYYDEBUG -o ltest2 test2.tab.c
| $ echo '1[aa,bb,cc]' | ./ltest2
| Starting parse
| Entering state 0
| Reading a token: Next token is token NAME ()
| Shifting token NAME ()
| ...
| Entering state 4
| Next token is token '[' ()
| syntax error at or near "[" in "(null)

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
%{
//#include "postgres.h"

/* No reason to constrain amount of data slurped */
#define YY_READ_BUF_SIZE 16777216

#define BUFSIZE 8192

/* Handles to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle;

/* Functions for handling double quoted string */
static void init_xd_string(void);
static void addlit_xd_string(char *ytext, int yleng);
static void addlitchar_xd_string(unsigned char ychar);

char  *scanbuf;
char *xd_string;
int     xd_size; /* actual size of xd_string */
int     xd_len; /* string length of xd_string  */
%}
%option 8bit
/* %option never-interactive*/
/* %option nounput*/
/* %option noinput*/
%option noyywrap
%option warn
/* %option prefix="syncgroup_yy" */

/*
 * <xd> delimited identifiers (double-quoted identifiers)
 */
%x xd

space           [ \t\n\r\f]
non_newline     [^\n\r]
whitespace      ({space}+)
self            [\[\]\,]
asterisk        \*

/*
 * Basically all ascii characteres except for {self} and {whitespace} are 
allowed
 * to be used for node name. These special charater could be used by 
double-quoted.
 */
 /* excluding ' ', '\"', '*', ',', '[', ']' */
node_name       [\x21\x23-\x29\x29-\x2b\x2d-\x5a\x5c\x5e-\x7e]
/* excluding '\"' */
dquoted_name    [\x20\x21\x23-\x7e]

/* Double-quoted string */
dquote          \"
xdstart         {dquote}
xddouble        {dquote}{dquote}
xdstop          {dquote}
xdinside        {dquoted_name}+

%%
{whitespace}    { /* ignore */ }

{xdstart} {
                                init_xd_string();
                                BEGIN(xd);
                }
<xd>{xddouble} {
                                addlitchar_xd_string('\"');
                }
<xd>{xdinside} {
                                addlit_xd_string(yytext, yyleng);
                }
<xd>{xdstop} {
                                xd_string[xd_len] = '\0';
                                yylval.str = xd_string;
                                BEGIN(INITIAL);
                                return NAME;
                }
{node_name}+ {
                                yylval.str = strdup(yytext);
                                return NAME;
                        }
[1-9][0-9]* {
                                yylval.str = yytext;
                                return NUM;
                }
{asterisk} {
                                yylval.str = strdup(yytext);
                                return AST;
                        }
{self} {
                                return yytext[0];
                }
. {
//                              ereport(ERROR,
//                                      (errcode(ERRCODE_SYNTAX_ERROR),
//                                              errmsg("syntax error: 
unexpected character \"%s\"", yytext)));
                                fprintf(stderr, "syntax error: unexpected 
character \"%s\"", yytext);
                        exit(1);
        }
%%

void
yyerror(const char *message)
{
//      ereport(ERROR,
//              (errcode(ERRCODE_SYNTAX_ERROR),
//                      errmsg("%s at or near \"%s\" in \"%s\"", message,
//                             yytext, scanbuf)));
        fprintf(stderr, "%s at or near \"%s\" in \"%s\"", message, yytext, 
scanbuf);
        exit(1);
}

void
syncgroup_scanner_init(const char *str)
{
        Size            slen = strlen(str);

        /*
         * Might be left over after ereport()
         */
        if (YY_CURRENT_BUFFER)
                yy_delete_buffer(YY_CURRENT_BUFFER);

        /*
         * Make a scan buffer with special termination needed by flex.
         */
        scanbuf = (char *) palloc(slen + 2);
        memcpy(scanbuf, str, slen);
        scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
        scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
}

void
syncgroup_scanner_finish(void)
{
        yy_delete_buffer(scanbufhandle);
        scanbufhandle = NULL;
}

static void
init_xd_string()
{
        xd_string = palloc(sizeof(char) * BUFSIZE);
        xd_size = BUFSIZE;
        xd_len = 0;
}

static void
addlit_xd_string(char *ytext, int yleng)
{
        /* enlarge buffer if needed */
        if ((xd_len + yleng) > xd_size)
                xd_string = repalloc(xd_string, xd_size + BUFSIZE);

        memcpy(xd_string + xd_len, ytext, yleng);
        xd_len += yleng;
}

static void
addlitchar_xd_string(unsigned char ychar)
{
        /* enlarge buffer if needed */
        if ((xd_len + 1) > xd_size)
                xd_string = repalloc(xd_string, xd_size + BUFSIZE);

        xd_string[xd_len] = ychar;
        xd_len += 1;
}
%{
/*-------------------------------------------------------------------------
 *
 * syncgroup_gram.y                             - Parser for synchronous 
replication group
 *
 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *        src/backend/replication/syncgroup_gram.y
 *
 *-------------------------------------------------------------------------
 */

//#include "postgres.h"

//#include "replication/syncrep.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define palloc malloc
#define repalloc realloc
#define pfree free

#define SYNC_REP_GROUP_MAIN                     0x01
#define SYNC_REP_GROUP_NAME                     0x02
#define SYNC_REP_GROUP_GROUP            0x04

#define SYNC_REP_METHOD_PRIORITY        0

struct SyncGroupNode;
typedef struct SyncGroupNode SyncGroupNode;

struct  SyncGroupNode
{
        /* Common information */
        int             type;
        char    *name;
        SyncGroupNode   *next; /* Same group, next name node */

        /* For group ndoe */
        int sync_method; /* priority */
        int     wait_num;
        SyncGroupNode   *members; /* member of its group */
};

static SyncGroupNode *create_name_node(char *name);
static SyncGroupNode *add_node(SyncGroupNode *node_list, SyncGroupNode *node);
static SyncGroupNode *create_group_node(char *wait_num, SyncGroupNode 
*node_list);
static void yyerror(const char *message);
 typedef int Size;

/*
 * Bison doesn't allocate anything that needs to live across parser calls,
 * so we can easily have it use palloc instead of malloc.  This prevents
 * memory leaks if we error out during parsing.  Note this only works with
 * bison >= 2.0.  However, in bison 1.875 the default is to use alloca()
 * if possible, so there's not really much problem anyhow, at least if
 * you're building with gcc.
 */
#define YYMALLOC palloc
#define YYFREE   pfree
 SyncGroupNode *SyncRepStandbys;
%}

%expect 0
 /*%name-prefix="syncgroup_yy"*/

%union
{
        char       *str;
        SyncGroupNode  *expr;
}

%token <str> NAME NUM
%token <str> AST

%type <expr> result sync_list sync_list_ast sync_element sync_element_ast
                         sync_node_group sync_group_old sync_group

%start result

%%
result:
                sync_node_group                                         { 
SyncRepStandbys = $1; }
;
sync_node_group:
                sync_group_old                                          { $$ = 
$1; }
                | sync_group                                            { $$ = 
$1; }
;
sync_group_old:
                sync_list                                                       
{ $$ = create_group_node("1", $1); }
                | sync_list_ast                                         { $$ = 
create_group_node("1", $1); }
;
sync_group:
                NUM '[' sync_list ']'                           { $$ = 
create_group_node($1, $3); }
                | NUM '[' sync_list_ast ']'                     { $$ = 
create_group_node($1, $3); }
;
sync_list:
                sync_element                                            { $$ = 
$1;}
                | sync_list ',' sync_element            { $$ = add_node($1, 
$3);}
;
sync_list_ast:
                sync_element_ast                                        { $$ = 
$1;}
                | sync_list ',' sync_element_ast        { $$ = add_node($1, 
$3);}
;
sync_element:
                NAME                                                            
{ $$ = create_name_node($1); }
                | NUM                                                           
{ $$ = create_name_node($1); }
;
sync_element_ast:
                AST                                                             
        { $$ = create_name_node($1); }
;
%%

static SyncGroupNode *
create_name_node(char *name)
{
        SyncGroupNode *name_node = (SyncGroupNode 
*)malloc(sizeof(SyncGroupNode));

        /* Common information */
        name_node->type = SYNC_REP_GROUP_NAME;
        name_node->name = strdup(name);
        name_node->next = NULL;

        /* For GROUP node */
        name_node->sync_method = 0;
        name_node->wait_num = 0;
        name_node->members = NULL;
        //      name_node->SyncRepGetSyncedLsnsFn = NULL;
        //      name_node->SyncRepGetSyncStandbysFn = NULL;

        return name_node;
}

static SyncGroupNode *
create_group_node(char *wait_num, SyncGroupNode *node_list)
{
        SyncGroupNode *group_node = (SyncGroupNode 
*)malloc(sizeof(SyncGroupNode));

        /* For NAME node */
        group_node->type = SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN;
        group_node->name = "main";
        group_node->next = NULL;

        /* For GROUP node */
        group_node->sync_method = SYNC_REP_METHOD_PRIORITY;
        group_node->wait_num = atoi(wait_num);
        group_node->members = node_list;
        //      group_node->SyncRepGetSyncedLsnsFn = 
SyncRepGetSyncedLsnsUsingPriority;
        //      group_node->SyncRepGetSyncStandbysFn = 
SyncRepGetSyncStandbysUsingPriority;

        return group_node;
}

static SyncGroupNode *
add_node(SyncGroupNode *node_list, SyncGroupNode *node)
{
        SyncGroupNode *tmp = node_list;

        /* Add node to tailing of node_list */
        while(tmp->next != NULL) tmp = tmp->next;

        tmp->next = node;
        return node_list;
}

void
indent(int level)
{
  int i;

  for (i = 0 ; i < level * 2 ; i++)
          putc(' ', stdout);
}

static void
dump_syncgroupnode(SyncGroupNode *def, int level)
{
  char *typelabel[] = {"MAIN", "NAME", "GROUP"};
  SyncGroupNode *p;

  if (def == NULL)
          return;

  switch(def->type)
  {
  case SYNC_REP_GROUP_NAME:
    indent(level);
    puts("{");
    indent(level+1);
    printf("NODE_TYPE: SYNC_REP_GROUP_NAME\n");
    indent(level+1);
    printf("NAME: %s\n", def->name);
    indent(level);
    puts("}");
    if (def->next)
      dump_syncgroupnode(def->next, level);
    break;
  case SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN:
    indent(level);
    puts("{");
    indent(level+1);
    printf("NODE_TYPE: SYNC_REP_GROUP_GROUP | SYNC_REP_GROUP_MAIN\n");
    indent(level+1);
    printf("NAME: %s\n", def->name);
    indent(level+1);
    printf("SYNC_METHOD: PRIORITY\n");
    indent(level+1);
    printf("WAIT_NUM: %d\n", def->wait_num);
    indent(level+1);
    if (def->members)
      dump_syncgroupnode(def->members, level+1);
    indent(level);
    puts("}");
    if (def->next)
      dump_syncgroupnode(def->next, level);
    break;
  default:
    fprintf(stderr, "ERR\n");
    exit(1);
  }    
  level--;
}

int main(void)
{
  yydebug = 1;
  yyparse();
  dump_syncgroupnode(SyncRepStandbys, 0);
}

//#include "syncgroup_scanner.c"
#include "lex.yy.c"

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to