From 5533ca87a4f3c3e7bae2e13532ba6def1de840cb Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Mon, 30 Nov 2020 01:36:28 +0100 Subject: [PATCH] updated parselabel.l to allow more generic node names and/or spaces: these are now valid "a a,bb[3 : 0] , ccc", "1,2,3" and various other improvemenst and "ugly" code removals --- src/parselabel.l | 231 +++++++++++++++++++++++++++-------------------- src/scheduler.c | 8 ++ src/xschem.h | 1 + 3 files changed, 144 insertions(+), 96 deletions(-) diff --git a/src/parselabel.l b/src/parselabel.l index 8a0cbb4c..09642c63 100644 --- a/src/parselabel.l +++ b/src/parselabel.l @@ -32,7 +32,7 @@ #define CAD_SPICE_NETLIST 1 -int dbg_var = 0; +int dbg_var = 3; extern int netlist_type; extern int has_x; extern FILE *errfp; @@ -57,9 +57,9 @@ typedef struct /* used in expandlabel.y */ Stringptr dest_string={NULL,0}; /*19102004; */ -static int bracket=0; extern int yyparse(void) ; extern int yyparse_error; +extern int yylex(); void clear_expandlabel_data(void) { @@ -79,6 +79,16 @@ void strreplace(char s[], char chr, char repl_chr) } } +void parse(const char *s) +{ + YY_BUFFER_STATE buf; + buf=yy_scan_string(s); + while(yylex()){ + fprintf(errfp, "token:|%s|\n", yytext); + } + yy_delete_buffer(buf); +} + const char *expandlabel(const char *s, int *m) { YY_BUFFER_STATE buf; @@ -86,7 +96,6 @@ const char *expandlabel(const char *s, int *m) if(dbg_var >= 3) fprintf(errfp, "expandlabel(): entering\n"); buf=yy_scan_string(s); - bracket=0; yyparse(); yy_delete_buffer(buf); if(yyparse_error==1) { @@ -125,131 +134,161 @@ const char *expandlabel(const char *s, int *m) Lexical analyzer */ -%x net_label -%x next_to_alias -%x rest +%x index +%x mult - -ID [-#+_\\/=a-zA-Z0-9]*[-#@+_\\/=a-zA-Z]+[-#@+_\\/=a-zA-Z0-9]* -ID_NUM [-#+_\\/=a-zA-Z0-9]+ - -ID_EXT ([-~#+/=_a-zA-Z][-~#@\\/ :.=_+a-zA-Z0-9]*)|([-~#+/.=_a-zA-Z][-~#@\\/ :=_+a-zA-Z0-9]*) -ID_EXT_PARENTHESIS [-~#+/=_a-zA-Z][-#@\\/:.=_+a-zA-Z0-9]*\([-#@\\/:.=_+a-zA-Z0-9]*\) +SP [ \t]* +INT [0-9]+ +DDOT {SP}".."{SP} +CLN {SP}":"{SP} +LAB [-a-zA-Z_%$~#/\\<>] + /* includes numbers */ +LAB_NUM [-a-zA-Z_%$~#/\\<>0-9] + /* includes numbers and space and *+(). */ +IDX_LAB_NUM_SP [-a-zA-Z_%$~#/\\<> \t0-9*+().] + /* identifier, may start with a number */ +IDX_ID_NUM ({LAB_NUM}+({IDX_LAB_NUM_SP}*{LAB_NUM})*) + /* identifier, not starting with a number */ +IDX_ID (("("|{LAB})+{IDX_LAB_NUM_SP}*) + /* includes numbers and space and +(). */ +LAB_NUM_SP [-a-zA-Z_%$~#/\\<> \t0-9+().] + /* identifier, may start with a number */ +ID_NUM ({LAB_NUM}+({LAB_NUM_SP}*{LAB_NUM})*) + /* identifier, not starting with a number */ +ID (("("|{LAB})+{LAB_NUM_SP}*) + /* ~#diUV=9_(\#-hgvUY=) */ +ID_EXT_PARENTHESIS ([-~#+/=_a-zA-Z][-#@\\/:.=_+a-zA-Z0-9]*\([-#@\\/:.=_+a-zA-Z0-9]*\)) %% -^(alias|ipin|iopin|opin)[+ \n]+[^+\n ]+/[\n +]+ { - yylval.ptr.str=NULL; /*19102004 */ - /* these things are freed after use in expandlabel.y */ - my_strdup(298, &yylval.ptr.str, yytext); - BEGIN(next_to_alias); - if(dbg_var >= 3) fprintf(errfp, "yylex(): alias, yytext = %s\n", yytext); - return B_LINE; - } -[\n +]+ { /* get all white space and return a single separator */ - BEGIN(net_label); - if(dbg_var >= 3) fprintf(errfp, "yylex(): next_to_alias, yytext = %s\n", yytext); - yylval.val=yytext[0]; - return B_CAR; - } -^[^*] { + /* this action resets initial condition at start of line. This is extremely useful if previously lexer + * bailed out in the middle of some non INITIAL start condition due to yyparse() syntax errors */ +^. { if(dbg_var >= 3) fprintf(errfp, "yylex(): matched: ^[^*] |%s|, push back\n",yytext); yyless(0); /* push entire token back to input */ - BEGIN(net_label); /* we know that a label follows. */ - /* so go and process it. */ - } -^\*.* { /* a comment, return as LINE token */ - yylval.ptr.str=NULL; /*19102004 */ - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_LINE: %s\n",yytext); - my_strdup(299, &yylval.ptr.str, yytext); /* freed after use in expandlabel.y */ - return B_LINE; - } -{ + BEGIN(INITIAL); /* reset parser */ + } -[ \n]+ { /* this ends the start condition */ - BEGIN(rest); - yylval.val=yytext[0]; - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_CAR: %s\n",yytext); - return B_CAR; +{ + /* postfix multiplier */ +{INT} { + sscanf(yytext, "%d",&yylval.val); + if(dbg_var >= 3) fprintf(errfp, "yylex(): postmult B_NUM: |%s|\n", yytext); + BEGIN(INITIAL); + return B_NUM; } -\.\. { - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_DOUBLEDOT: %s\n", yytext); +} /* end */ + + /* node indexes: "3:2" "5:1:2" "5..1" "7..1..2" "b:a" "c:b:a" .... */ +{ +{INT} { + sscanf(yytext, "%d",&yylval.val); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_IDXNUM: |%s|\n", yytext); + return B_IDXNUM; + } +{SP}\.\.{SP} { + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_DOUBLEDOT: |%s|\n", yytext); return B_DOUBLEDOT; } -[0-9]+{ID_EXT} { - yylval.ptr.str=NULL; - my_strdup(452, &yylval.ptr.str, yytext); - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME 3: %s\n", yytext); - return B_NAME; + /* end vector node index "...]" */ +\] { + if(dbg_var >= 3) fprintf(errfp, "yylex(): close bracket: %s\n", yytext); + BEGIN(INITIAL); + return yytext[0]; + } +[^ ] { + if(dbg_var >= 3) fprintf(errfp, "yylex(): idx character: |%s|\n", yytext); + return yytext[0]; } - /* recognize AA[aa:bb:33] or AA[33:cc:dd] or AA[aa..bb..11] .... */ -({ID}\.\.{ID_NUM}\.\.{ID_NUM})|({ID_NUM}\.\.{ID}\.\.{ID_NUM})|({ID_NUM}\.\.{ID_NUM}\.\.{ID}) { +({IDX_ID}{DDOT}{IDX_ID_NUM}{DDOT}{IDX_ID_NUM})|({IDX_ID_NUM}{DDOT}{IDX_ID}{DDOT}{IDX_ID_NUM})|({IDX_ID_NUM}{DDOT}{IDX_ID_NUM}{DDOT}{IDX_ID}) { yylval.ptr.str=NULL; my_strdup(428, &yylval.ptr.str, yytext); - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME 2: %s\n", yytext); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME3: |%s|\n", yytext); return B_NAME; } -({ID}:{ID_NUM}:{ID_NUM})|({ID_NUM}:{ID}:{ID_NUM})|({ID_NUM}:{ID_NUM}:{ID}) { +({IDX_ID}{CLN}{IDX_ID_NUM}{CLN}{IDX_ID_NUM})|({IDX_ID_NUM}{CLN}{IDX_ID}{CLN}{IDX_ID_NUM})|({IDX_ID_NUM}{CLN}{IDX_ID_NUM}{CLN}{IDX_ID}) { yylval.ptr.str=NULL; my_strdup(430, &yylval.ptr.str, yytext); - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME 2: %s\n", yytext); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME2: |%s|\n", yytext); return B_NAME; } /* recognize AA[width-1:0], AA[0:width-1], AA[width-1..4], AA[3..width+3], AA[aa:bb] AA[aa..bb] */ -({ID}:{ID_NUM})|({ID_NUM}:{ID})|({ID}\.\.{ID_NUM})|({ID_NUM}\.\.{ID}) { +({IDX_ID}{CLN}{IDX_ID_NUM})|({IDX_ID_NUM}{CLN}{IDX_ID})|({IDX_ID}{DDOT}{IDX_ID_NUM})|({IDX_ID_NUM}{DDOT}{IDX_ID}) { yylval.ptr.str=NULL; my_strdup(92, &yylval.ptr.str, yytext); - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME 1: %s\n", yytext); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME1: |%s|\n", yytext); return B_NAME; } +} /* end */ -[0-9]+ { - sscanf(yytext, "%d",&yylval.val); - if(bracket) { - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_IDXNUM: %s\n", yytext); - return B_IDXNUM; - } - else { - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NUM: %s\n", yytext); - return B_NUM; - } - } - - /* recognize the most esotheric identifiers */ -{ID_EXT}|{ID_EXT_PARENTHESIS} { - yylval.ptr.str=NULL;/*19102004 */ - my_strdup(300, &yylval.ptr.str, yytext); /* freed after use in expandlabel.y */ - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME: %s\n", yytext); - return B_NAME; - } -\[ { - bracket++; - if(dbg_var >= 3) fprintf(errfp, "yylex(): open bracket: %s\n", yytext); - return yytext[0]; - } -\] { - bracket--; - if(dbg_var >= 3) fprintf(errfp, "yylex(): close bracket: %s\n", yytext); - return yytext[0]; - } -[^ ] { - if(dbg_var >= 3) fprintf(errfp, "yylex(): returning character: %s\n", yytext); - return yytext[0]; - } -} /* end */ - -{ /* treat rest of line as a single LINE token */ -(.|\n)* { + /* a comment, return as LINE token */ +^\*.* { yylval.ptr.str=NULL; /*19102004 */ - my_strdup(301, &yylval.ptr.str, yytext); /* freed after use in expandlabel.y */ - if(dbg_var >= 3) fprintf(errfp, "yylex(): B_LINE: %s\n",yytext); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_LINE: |%s|\n",yytext); + my_strdup(299, &yylval.ptr.str, yytext); /* freed after use in expandlabel.y */ BEGIN(INITIAL); return B_LINE; } + /* prefix multiplier */ +{INT}/{SP}\*{SP} { + sscanf(yytext, "%d",&yylval.val); + if(dbg_var >= 3) fprintf(errfp, "yylex(): premult B_NUM: |%s|\n", yytext); + BEGIN(INITIAL); + return B_NUM; + } + /* a number: if not a multiplier nor a node index return as a node name */ +{INT} { + yylval.ptr.str=NULL; + my_strdup(120, &yylval.ptr.str, yytext); + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME4: |%s|\n", yytext); + BEGIN(INITIAL); + return B_NAME; + } +{SP} { + if(dbg_var >= 3) fprintf(errfp, "yylex(): skipping: |%s|\n", yytext); + } + /* comma separator between nodes: chop spaces "a,b , c" */ +{SP},{SP} { + yylval.val=','; + if(dbg_var >= 3) fprintf(errfp, "yylex(): comma: |%s|\n", yytext); + BEGIN(INITIAL); + return ','; + } + + /* recognize the most esotheric identifiers */ +{ID_NUM}|{ID_EXT_PARENTHESIS} { + yylval.ptr.str=NULL;/*19102004 */ + my_strdup(300, &yylval.ptr.str, yytext); /* freed after use in expandlabel.y */ + if(dbg_var >= 3) fprintf(errfp, "yylex(): B_NAME0: |%s|\n", yytext); + BEGIN(INITIAL); + return B_NAME; + } + /* start vector node index: "aa[" */ +\[ { + if(dbg_var >= 3) fprintf(errfp, "yylex(): open bracket: %s\n", yytext); + BEGIN(index); + return yytext[0]; + } + /* "*(aa,bb,cc)" or "*aaa" prefix multiplication*/ +{SP}\*{SP}/({ID}|[(]) { + if(dbg_var >= 3) fprintf(errfp, "yylex(): pre *: |%s|\n", yytext); + BEGIN(INITIAL); + return '*'; + } + /* "*16" postfix multiplication */ +{SP}\*{SP}/{INT} { + if(dbg_var >= 3) fprintf(errfp, "yylex(): post *: |%s|\n", yytext); + BEGIN(mult); + return '*'; + } +[^ ] { + if(dbg_var >= 3) fprintf(errfp, "yylex(): character: |%s|\n", yytext); + BEGIN(INITIAL); + return yytext[0]; + } -} /* end rest */ <*><> { BEGIN(INITIAL); return 0; diff --git a/src/scheduler.c b/src/scheduler.c index 9534bdcb..8c2e302d 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -22,6 +22,11 @@ #include "xschem.h" +extern char yytext[]; +extern int yylex (void); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); + void statusmsg(char str[],int n) { static char s[2048]; @@ -1740,6 +1745,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } } + else if(argc == 3 && !strcmp(argv[1],"parselabel")) { + parse( argv[2]); + } else if(argc == 3 && !strcmp(argv[1],"expandlabel")) { int tmp, llen; char *result=NULL; diff --git a/src/xschem.h b/src/xschem.h index a2d6f76d..9f4be380 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1016,6 +1016,7 @@ extern void check_arc_storage(int c); extern void check_line_storage(int c); extern void check_polygon_storage(int c); extern const char *expandlabel(const char *s, int *m); +extern void parse(const char *s); extern void clear_expandlabel_data(void); extern void merge_inst(int k, FILE *fd); extern void merge_file(int selection_load, const char ext[]);