Move most of the parsing to yacc instead of lexer

This commit is contained in:
Dave Davenport 2017-05-10 12:41:06 +02:00
parent 00e297c5ca
commit f5b1e4b3d4
2 changed files with 201 additions and 177 deletions

View File

@ -83,39 +83,6 @@ GQueue *queue = NULL;
ParseObject *current = NULL;
static char * rofi_theme_parse_prepare_file ( const char *file, const char *parent_file );
#define IN_RANGE(index,low,high) ( ( (index) > (low) )? ( ( (index) < (high) )? (index):(high) ) : ( low ) )
static double hue2rgb(double p, double q, double t){
t += (t<0)?1:0;
t -= (t>1)?1:0;
if( t < (1/6.0) ) {
return p + (q - p) * 6 * t;
}
if( t < (1/2.0) ) {
return q;
}
if( t < (2/3.0) ) {
return p + (q - p) * (2/3.0 - t) * 6;
}
return p;
}
static ThemeColor hsl_to_rgb ( double h, double s, double l )
{
ThemeColor colour;
if(s < 0.001 && s > -0.001){
colour.red = colour.green = colour.blue = l; // achromatic
}else{
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
colour.red = hue2rgb(p, q, h + 1/3.0);
colour.green = hue2rgb(p, q, h);
colour.blue = hue2rgb(p, q, h - 1/3.0);
}
return colour;
}
%}
%{
@ -191,16 +158,30 @@ PERCENT (\%)
ASTERIX \*
/* Position */
CENTER "center"
NORTH "north"
SOUTH "south"
EAST "east"
WEST "west"
NONE "none"
BOLD "bold"
UNDERLINE "underline"
ITALIC "italic"
/* Line Style */
NONE "none"
BOLD "bold"
UNDERLINE "underline"
ITALIC "italic"
/* Color schema */
ARGB "argb"
RGBA "rgba"
RGB "rgb"
HWB "hwb"
CMYK "cmyk"
HSL "hsl"
PARENT_LEFT \(
PARENT_RIGHT \)
COMMA ,
LS_DASH "dash"
LS_SOLID "solid"
@ -375,71 +356,27 @@ if ( queue == NULL ){
<INITIAL,SECTION>{WHITESPACE}+ ; // ignore all whitespace
<PROPERTIES>{WHITESPACE}+ ; // ignore all whitespace
<SECTION>":" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES); return PSEP; }
<PROPERTIES>";" { BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); return PCLOSE;}
<SECTION>":" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES); return PSEP; }
<PROPERTIES>";" { BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); return PCLOSE;}
<PROPERTIES>(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;}
<PROPERTIES>{PNNUMBER} { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;}
<PROPERTIES>{PNNUMBER}\.{NUMBER}+ { yylval->fval = g_ascii_strtod(yytext, NULL); return T_DOUBLE;}
<PROPERTIES>{PNNUMBER} { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;}
<PROPERTIES>\"{STRING}\" { yytext[yyleng-1] = '\0'; yylval->sval = g_strdup(&yytext[1]); return T_STRING;}
<PROPERTIES>@{WORD} {
yylval->sval = g_strdup(yytext);
return T_LINK;
}
<PROPERTIES>{REAL}{EM} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_EM;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{PNNUMBER}{PX} {
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
yylval->distance.type = PW_PX;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{PNNUMBER}{PX}{WHITESPACE}{LS_DASH} {
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
yylval->distance.type = PW_PX;
yylval->distance.style = DASH;
return T_PIXEL;
}
<PROPERTIES>{REAL}{EM}{WHITESPACE}{LS_DASH} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_EM;
yylval->distance.style = DASH;
return T_PIXEL;
}
<PROPERTIES>{PNNUMBER}{PX}{WHITESPACE}{LS_SOLID} {
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
yylval->distance.type = PW_PX;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{REAL}{EM}{WHITESPACE}{LS_SOLID} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_EM;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{REAL}{PERCENT} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_PERCENT;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{REAL}{PERCENT}{WHITESPACE}{LS_SOLID} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_PERCENT;
yylval->distance.style = SOLID;
return T_PIXEL;
}
<PROPERTIES>{REAL}{PERCENT}{WHITESPACE}{LS_DASH} {
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
yylval->distance.type = PW_PERCENT;
yylval->distance.style = DASH;
return T_PIXEL;
}
<PROPERTIES>{EM} { return T_UNIT_EM; }
<PROPERTIES>{PX} { return T_UNIT_PX; }
<PROPERTIES>{PERCENT} { return PERCENT; }
<PROPERTIES>{LS_SOLID} { return T_SOLID; }
<PROPERTIES>{LS_DASH} { return T_DASH; }
/**
* Color parsing. It is easier to do this at lexer level.
* Other schemes are done at yacc level.
*/
<PROPERTIES>#{HEX}{8} {
union { unsigned int val; struct { unsigned char b,g,r,a;};} val;
val.val = (unsigned int)strtoull ( &yytext[1], NULL, 16);
@ -467,68 +404,6 @@ if ( queue == NULL ){
yylval->colorval.blue = val.b/15.0;
return T_COLOR;
}
<PROPERTIES>rgba\({WSO}{NUMBER}{1,3},{WSO}{NUMBER}{1,3},{WSO}{NUMBER}{1,3},{WSO}[01](\.{NUMBER}+)?\) {
char *endptr = &yytext[5];
yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10)/255.0;
yylval->colorval.green= g_ascii_strtoull ( endptr+1, &endptr, 10)/255.0;
yylval->colorval.blue= g_ascii_strtoull ( endptr+1, &endptr, 10)/255.0;
yylval->colorval.alpha= g_ascii_strtod ( endptr+1, NULL);
return T_COLOR;
}
<PROPERTIES>rgb\({WSO}{NUMBER}{1,3},{WSO}{NUMBER}{1,3},{WSO}{NUMBER}{1,3}\) {
char *endptr = &yytext[4];
yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10)/255.0;
yylval->colorval.green = g_ascii_strtoull ( endptr+1, &endptr, 10)/255.0;
yylval->colorval.blue = g_ascii_strtoull ( endptr+1, &endptr, 10)/255.0;
yylval->colorval.alpha = 1.0;
return T_COLOR;
}
<PROPERTIES>hsl\({WSO}{NUMBER}{1,3},{WSO}[1]?{NUMBER}{1,2}{PERCENT},{WSO}[1]?{NUMBER}{1,2}{PERCENT}\) {
char *endptr = &yytext[4];
gint64 hi= g_ascii_strtoll ( endptr, &endptr, 10);
gint64 si= g_ascii_strtoll ( endptr+1, &endptr, 10);
gint64 li= g_ascii_strtoll ( endptr+2, &endptr, 10);
gdouble h = IN_RANGE(hi, 0, 359);
gdouble s = IN_RANGE(si, 0, 100);
gdouble l = IN_RANGE(li, 0, 100);
yylval->colorval = hsl_to_rgb ( h/360.0, s/100.0, l/100.0 );
yylval->colorval.alpha = 1.0;
return T_COLOR;
}
<PROPERTIES>cmyk\({WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT},{WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT},{WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT},{WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT}\) {
char *endptr = &yytext[5];
gint64 ci = g_ascii_strtoll ( endptr, &endptr, 10);
gint64 mi = g_ascii_strtoll ( endptr+2, &endptr, 10);
gint64 my = g_ascii_strtoll ( endptr+2, &endptr, 10);
gint64 mk = g_ascii_strtoll ( endptr+2, &endptr, 10);
double c= IN_RANGE(ci, 0, 100)/100.0;
double m= IN_RANGE(mi, 0, 100)/100.0;
double y= IN_RANGE(my, 0, 100)/100.0;
double k= IN_RANGE(mk, 0, 100)/100.0;
yylval->colorval.red = (1.0-c)*(1.0-k);
yylval->colorval.green = (1.0-m)*(1.0-k);
yylval->colorval.blue = (1.0-y)*(1.0-k);
yylval->colorval.alpha = 1.0;
return T_COLOR;
}
<PROPERTIES>hwb\({WHITESPACE}{NUMBER}{1,3},{WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT},{WHITESPACE}[1]?{NUMBER}{1,2}{PERCENT}\) {
char *endptr = &yytext[4];
gint64 hi = g_ascii_strtoll ( endptr, &endptr, 10);
gint64 hw = g_ascii_strtoll ( endptr+1, &endptr, 10);
gint64 hb = g_ascii_strtoll ( endptr+2, &endptr, 10);
double h= IN_RANGE(hi,0,360)/360.0;
double w= IN_RANGE(hw,0,100)/100.0;
double b= IN_RANGE(hb,0,100)/100.0;
yylval->colorval = hsl_to_rgb ( h, 1.0, 0.5);
yylval->colorval.red *= ( 1. - w - b );
yylval->colorval.red += w;
yylval->colorval.green *= ( 1. - w - b );
yylval->colorval.green += w;
yylval->colorval.blue *= ( 1. - w - b );
yylval->colorval.blue += w;
yylval->colorval.alpha = 1.0;
return T_COLOR;
}
<PROPERTIES>argb:{HEX}{1,8} {
union { unsigned int val; struct { unsigned char b,g,r,a;};} val;
val.val = (unsigned int)strtoull ( &yytext[5], NULL, 16);
@ -538,16 +413,30 @@ if ( queue == NULL ){
yylval->colorval.blue = val.b/255.0;
return T_COLOR;
}
/* Color schemes */
<PROPERTIES>{ARGB} { return T_COL_ARGB; }
<PROPERTIES>{RGBA} { return T_COL_RGBA; }
<PROPERTIES>{RGB} { return T_COL_RGB; }
<PROPERTIES>{HSL} { return T_COL_HSL; }
<PROPERTIES>{HWB} { return T_COL_HWB; }
<PROPERTIES>{CMYK} { return T_COL_CMYK; }
/* Fluff */
<PROPERTIES>{PARENT_LEFT} { return PARENT_LEFT; }
<PROPERTIES>{PARENT_RIGHT} { return PARENT_RIGHT;}
<PROPERTIES>{COMMA} { return COMMA; }
/* Position */
<PROPERTIES>{CENTER} { return T_POS_CENTER; }
<PROPERTIES>{EAST} { return T_POS_EAST; }
<PROPERTIES>{WEST} { return T_POS_WEST; }
<PROPERTIES>{SOUTH} { return T_POS_SOUTH; }
<PROPERTIES>{NORTH} { return T_POS_NORTH; }
/* Highlight style */
<PROPERTIES>{NONE} { return T_NONE; }
<PROPERTIES>{BOLD} { return T_BOLD; }
<PROPERTIES>{ITALIC} { return T_ITALIC; }
<PROPERTIES>{UNDERLINE} { return T_UNDERLINE; }
<PROPERTIES>{CENTER} { return T_POS_CENTER; }
<PROPERTIES>{EAST} { return T_POS_EAST; }
<PROPERTIES>{WEST} { return T_POS_WEST; }
<PROPERTIES>{SOUTH} { return T_POS_SOUTH; }
<PROPERTIES>{NORTH} { return T_POS_NORTH; }
<PROPERTIES>{NONE} { return T_NONE; }
<PROPERTIES>{BOLD} { return T_BOLD; }
<PROPERTIES>{ITALIC} { return T_ITALIC; }
<PROPERTIES>{UNDERLINE} { return T_UNDERLINE; }
<INITIAL><<EOF>> {
ParseObject *po = g_queue_pop_head ( file_queue );
if ( po ) {

View File

@ -74,6 +74,40 @@ typedef struct YYLTYPE {
ThemeWidget *rofi_theme = NULL;
void yyerror(YYLTYPE *yylloc, const char *what, const char* s);
int yylex (YYSTYPE *, YYLTYPE *);
#define IN_RANGE(index,low,high) ( ( (index) > (low) )? ( ( (index) < (high) )? (index):(high) ) : ( low ) )
static double hue2rgb(double p, double q, double t){
t += (t<0)?1:0;
t -= (t>1)?1:0;
if( t < (1/6.0) ) {
return p + (q - p) * 6 * t;
}
if( t < (1/2.0) ) {
return q;
}
if( t < (2/3.0) ) {
return p + (q - p) * (2/3.0 - t) * 6;
}
return p;
}
static ThemeColor hsl_to_rgb ( double h, double s, double l )
{
ThemeColor colour;
if(s < 0.001 && s > -0.001){
colour.red = colour.green = colour.blue = l; // achromatic
}else{
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
colour.red = hue2rgb(p, q, h + 1/3.0);
colour.green = hue2rgb(p, q, h);
colour.blue = hue2rgb(p, q, h - 1/3.0);
}
return colour;
}
%}
%union {
@ -104,7 +138,6 @@ int yylex (YYSTYPE *, YYLTYPE *);
%token <sval> NAME_ELEMENT "Element name"
%token <bval> T_BOOLEAN
%token <colorval> T_COLOR
%token <distance> T_PIXEL
%token <sval> T_LINK
%token <sval> FIRST_NAME
%token T_POS_CENTER "Center"
@ -117,7 +150,24 @@ int yylex (YYSTYPE *, YYLTYPE *);
%token T_BOLD "Bold"
%token T_ITALIC "Italic"
%token T_UNDERLINE "Underline"
%token T_DASH "Dash"
%token T_SOLID "Solid"
%token T_UNIT_PX "pixels"
%token T_UNIT_EM "em"
%token T_UNIT_PERCENT "%"
%token T_COL_ARGB
%token T_COL_RGBA
%token T_COL_RGB
%token T_COL_HSL
%token T_COL_HWB
%token T_COL_CMYK
%token PARENT_LEFT "Parent left '('"
%token PARENT_RIGHT "Parent right ')'"
%token COMMA "comma separator"
%token PERCENT "Percent sign"
%token BOPEN "bracket open ('{')"
%token BCLOSE "bracket close ('}')"
@ -131,6 +181,8 @@ int yylex (YYSTYPE *, YYLTYPE *);
%type <ival> highlight_styles
%type <ival> highlight_style
%type <ival> t_line_style
%type <ival> t_unit
%type <wloc> t_position
%type <wloc> t_position_ew
%type <wloc> t_position_sn
@ -141,6 +193,8 @@ int yylex (YYSTYPE *, YYLTYPE *);
%type <property> property
%type <property_list> property_list
%type <property_list> optional_properties
%type <distance> t_distance
%type <colorval> t_color
%start entries
%%
@ -216,11 +270,6 @@ property
$$->name = $1;
$$->value.f = $3;
}
| pvalue PSEP T_COLOR PCLOSE {
$$ = rofi_theme_property_create ( P_COLOR );
$$->name = $1;
$$->value.color = $3;
}
| pvalue PSEP T_STRING PCLOSE {
$$ = rofi_theme_property_create ( P_STRING );
$$->name = $1;
@ -236,22 +285,22 @@ property
$$->name = $1;
$$->value.b = $3;
}
| pvalue PSEP T_PIXEL PCLOSE {
| pvalue PSEP t_distance PCLOSE {
$$ = rofi_theme_property_create ( P_PADDING );
$$->name = $1;
$$->value.padding = (Padding){ $3, $3, $3, $3 };
}
| pvalue PSEP T_PIXEL T_PIXEL PCLOSE {
| pvalue PSEP t_distance t_distance PCLOSE {
$$ = rofi_theme_property_create ( P_PADDING );
$$->name = $1;
$$->value.padding = (Padding){ $3, $4, $3, $4 };
}
| pvalue PSEP T_PIXEL T_PIXEL T_PIXEL PCLOSE {
| pvalue PSEP t_distance t_distance t_distance PCLOSE {
$$ = rofi_theme_property_create ( P_PADDING );
$$->name = $1;
$$->value.padding = (Padding){ $3, $4, $5, $4 };
}
| pvalue PSEP T_PIXEL T_PIXEL T_PIXEL T_PIXEL PCLOSE {
| pvalue PSEP t_distance t_distance t_distance t_distance PCLOSE {
$$ = rofi_theme_property_create ( P_PADDING );
$$->name = $1;
$$->value.padding = (Padding){ $3, $4, $5, $6 };
@ -261,7 +310,7 @@ property
$$->name = $1;
$$->value.i = $3;
}
| pvalue PSEP highlight_styles T_COLOR PCLOSE {
| pvalue PSEP highlight_styles t_color PCLOSE {
$$ = rofi_theme_property_create ( P_HIGHLIGHT );
$$->name = $1;
$$->value.highlight.style = $3|HL_COLOR;
@ -272,6 +321,11 @@ property
$$->name = $1;
$$->value.highlight.style = $3;
}
| pvalue PSEP t_color PCLOSE {
$$ = rofi_theme_property_create ( P_COLOR );
$$->name = $1;
$$->value.color = $3;
}
;
/**
@ -301,7 +355,7 @@ t_position_sn
*/
highlight_styles
: highlight_style { $$ = $1;}
| highlight_styles highlight_style { $$ = $1|$2;}
| highlight_styles highlight_style { $$ = $1|$2;}
;
/** Single style. */
highlight_style
@ -310,6 +364,87 @@ highlight_style
| T_UNDERLINE { $$ = HL_UNDERLINE; }
| T_ITALIC { $$ = HL_ITALIC; }
;
t_distance
: T_INT t_unit t_line_style {
$$.distance = (double)$1;
$$.type = $2;
$$.style = $3;
}
| T_DOUBLE t_unit t_line_style {
$$.distance = (double)$1;
$$.type = $2;
$$.style = $3;
};
t_unit
: T_UNIT_PX { $$ = PW_PX; }
| T_UNIT_EM { $$ = PW_EM; }
| PERCENT { $$ = PW_PERCENT; }
;
/******
* Line style
* If not set, solid.
*/
t_line_style
: %empty { $$ = SOLID; }
| T_SOLID { $$ = SOLID; }
| T_DASH { $$ = DASH; }
;
/**
* Color formats
*/
t_color
: T_COL_RGBA PARENT_LEFT T_INT COMMA T_INT COMMA T_INT COMMA T_DOUBLE PARENT_RIGHT {
$$.alpha = $9;
$$.red = $3/255.0;
$$.green = $5/255.0;
$$.blue = $7/255.0;
}
| T_COL_RGB PARENT_LEFT T_INT COMMA T_INT COMMA T_INT PARENT_RIGHT {
$$.alpha = 1.0;
$$.red = $3/255.0;
$$.green = $5/255.0;
$$.blue = $7/255.0;
}
| T_COL_HWB PARENT_LEFT T_INT COMMA T_DOUBLE PERCENT COMMA T_DOUBLE PERCENT PARENT_RIGHT {
$$.alpha = 1.0;
double h = IN_RANGE($3,0,360)/360.0;
double w = IN_RANGE($5,0,100)/100.0;
double b = IN_RANGE($8,0,100)/100.0;
$$ = hsl_to_rgb ( h, 1.0, 0.5);
$$.red *= ( 1. - w - b );
$$.red += w;
$$.green *= ( 1. - w - b );
$$.green += w;
$$.blue *= ( 1. - w - b );
$$.blue += w;
}
| T_COL_CMYK PARENT_LEFT T_DOUBLE PERCENT COMMA T_DOUBLE PERCENT COMMA T_DOUBLE PERCENT COMMA T_DOUBLE PERCENT PARENT_RIGHT {
$$.alpha = 1.0;
double c= IN_RANGE($3, 0, 100)/100.0;
double m= IN_RANGE($6, 0, 100)/100.0;
double y= IN_RANGE($9, 0, 100)/100.0;
double k= IN_RANGE($12, 0, 100)/100.0;
$$.red = (1.0-c)*(1.0-k);
$$.green = (1.0-m)*(1.0-k);
$$.blue = (1.0-y)*(1.0-k);
}
| T_COL_HSL PARENT_LEFT T_INT COMMA T_DOUBLE PERCENT COMMA T_DOUBLE PERCENT PARENT_RIGHT {
gdouble h = IN_RANGE($3, 0, 359);
gdouble s = IN_RANGE($5, 0, 100);
gdouble l = IN_RANGE($8, 0, 100);
$$ = hsl_to_rgb ( h/360.0, s/100.0, l/100.0 );
$$.alpha = 1.0;
}
| T_COLOR {
$$ = $1;
}
;
pvalue: N_STRING { $$ = $1; }
name_path: