At Fri, 26 Feb 2016 10:38:22 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI
<[email protected]> wrote in
<[email protected]>
> Hello, Thanks for the new patch.
>
>
> At Fri, 26 Feb 2016 08:52:54 +0900, Masahiko Sawada <[email protected]>
> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers