4 * Copyright (C) 2014 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
16 /* grammar for parsing delta exceptions */
19 * Edsko de Vries's article `Writing a Reentrant Parser with Flex and Bison'
20 * (http://www.phpcompiler.org/articles/reentrantparser.html)
21 * was extremely helpful in writing this code.
24 %output
"tadeltas-bison.c"
25 %defines
"tadeltas-bison.h"
31 %lex
-param
{ void* scanner
}
33 %name
-prefix
"TA_deltas_"
34 %parse
-param
{ Deltas_Context
* context
}
40 /* we don't change the name prefix of flex functions */
41 #define TA_deltas_lex yylex
53 #include "tadeltas-flex.h"
56 TA_deltas_error
(YYLTYPE *locp
,
57 Deltas_Context
* context
,
61 store_error_data
(YYLTYPE *locp
,
62 Deltas_Context
* context
,
66 /* calls to `yylex' in the generated bison code use `scanner' directly */
67 #define scanner context->scanner
70 /* BAD_XXX and INVALID_CHARACTER indicate flex errors */
71 %token INVALID_CHARACTER
73 %token
<integer
> BAD_INTEGER
74 %token
<name
> BAD_NAME
75 %token
<real
> BAD_REAL
76 %token
<integer
> INTEGER
81 %type
<integer
> font_idx
82 %type
<integer
> glyph_idx
83 %type
<name
> glyph_name
85 %type
<integer
> integer
86 %type
<range
> left_limited
87 %type
<range
> number_set
88 %type
<range
> point_set
89 %type
<range
> ppem_set
91 %type
<range
> range_elem
92 %type
<range
> range_elems
94 %type
<range
> right_limited
96 %type
<range
> unlimited
100 %destructor
{ TA_deltas_free
($$
); } <deltas
>
101 %destructor
{ number_set_free
($$
); } <range
>
107 /* `number_range' list elements are stored in reversed order; */
108 /* the call to `TA_deltas_new' fixes this */
109 /* (`Deltas' list elements are stored in reversed order, too, */
110 /* but they don't need to be sorted so we don't care */
114 { context
->result
= $input; }
121 { $result = TA_deltas_prepend
($left, $entry); }
127 | font_idx glyph_idx point_set x_shift y_shift ppem_set EOE
129 $entry = TA_deltas_new
($font_idx,
137 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
147 context
->font_idx
= $font_idx;
151 $font_idx = $integer;
152 if
($font_idx >= context
->font
->num_sfnts
)
154 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Font_Index
);
157 context
->font_idx
= $font_idx;
164 FT_Face face
= context
->font
->sfnts
[context
->font_idx
].face
;
167 $glyph_idx = $integer;
168 if
($glyph_idx >= face
->num_glyphs
)
170 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Glyph_Index
);
173 context
->glyph_idx
= $glyph_idx;
177 FT_Face face
= context
->font
->sfnts
[context
->font_idx
].face
;
180 /* explicitly compare with `.notdef' */
181 /* since `FT_Get_Name_Index' returns glyph index 0 */
182 /* for both this glyph name and invalid ones */
183 if
(!strcmp
($glyph_name, ".notdef"))
187 $glyph_idx = FT_Get_Name_Index
(face
, $glyph_name);
196 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Glyph_Name
);
199 context
->glyph_idx
= $glyph_idx;
206 $glyph_name = strdup
("p");
209 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
215 $glyph_name = strdup
("x");
218 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
224 $glyph_name = strdup
("y");
227 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
233 /* `$NAME' was allocated in the lexer */
238 $glyph_name = $BAD_NAME;
247 FT_Face face
= context
->font
->sfnts
[context
->font_idx
].face
;
251 error = FT_Load_Glyph
(face
, context
->glyph_idx
, FT_LOAD_NO_SCALE
);
254 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Glyph
);
258 num_points
= face
->glyph
->outline.n_points
;
260 context
->number_set_min
= 0;
261 context
->number_set_max
= num_points
- 1;
264 { $point_set = $number_set; }
271 { $x_shift = $shift; }
278 { $y_shift = $shift; }
284 if
($real < DELTA_SHIFT_MIN ||
$real > DELTA_SHIFT_MAX
)
286 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Shift
);
296 context
->number_set_min
= DELTA_PPEM_MIN
;
297 context
->number_set_max
= DELTA_PPEM_MAX
;
300 { $ppem_set = $number_set; }
307 { $integer = $INTEGER; }
310 $integer = $BAD_INTEGER;
317 { $real = $integer; }
319 { $real = $integer; }
321 { $real = -$integer; }
347 { $number_set = $unlimited; }
349 { $number_set = $right_limited; }
351 { $number_set = $left_limited; }
353 { $number_set = $range_elems; }
354 | right_limited
',' range_elems
356 $number_set = number_set_prepend
($right_limited, $range_elems);
357 if
($number_set == NUMBERSET_NOT_ASCENDING
)
359 number_set_free
($right_limited);
360 number_set_free
($range_elems);
361 store_error_data
(&@$
, context
, TA_Err_Deltas_Ranges_Not_Ascending
);
364 if
($number_set == NUMBERSET_OVERLAPPING_RANGES
)
366 number_set_free
($right_limited);
367 number_set_free
($range_elems);
368 store_error_data
(&@$
, context
, TA_Err_Deltas_Overlapping_Ranges
);
372 | range_elems
',' left_limited
374 $number_set = number_set_prepend
($range_elems, $left_limited);
375 if
($number_set == NUMBERSET_NOT_ASCENDING
)
377 number_set_free
($range_elems);
378 number_set_free
($left_limited);
379 store_error_data
(&@$
, context
, TA_Err_Deltas_Ranges_Not_Ascending
);
382 if
($number_set == NUMBERSET_OVERLAPPING_RANGES
)
384 number_set_free
($range_elems);
385 number_set_free
($left_limited);
386 store_error_data
(&@$
, context
, TA_Err_Deltas_Overlapping_Ranges
);
395 $unlimited = number_set_new
(context
->number_set_min
,
396 context
->number_set_max
,
397 context
->number_set_min
,
398 context
->number_set_max
);
399 /* range of `$unlimited' is always valid */
400 if
($unlimited == NUMBERSET_ALLOCATION_ERROR
)
402 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
411 $right_limited = number_set_new
(context
->number_set_min
,
413 context
->number_set_min
,
414 context
->number_set_max
);
415 if
($right_limited == NUMBERSET_INVALID_RANGE
)
417 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Range
);
420 if
($right_limited == NUMBERSET_ALLOCATION_ERROR
)
422 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
431 $left_limited = number_set_new
($integer,
432 context
->number_set_max
,
433 context
->number_set_min
,
434 context
->number_set_max
);
435 if
($left_limited == NUMBERSET_INVALID_RANGE
)
437 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Range
);
440 if
($left_limited == NUMBERSET_ALLOCATION_ERROR
)
442 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
450 { $result = $range_elem; }
451 | range_elems
[left
] ',' range_elem
453 $result = number_set_prepend
($left, $range_elem);
454 if
($result == NUMBERSET_NOT_ASCENDING
)
456 number_set_free
($left);
457 number_set_free
($range_elem);
458 store_error_data
(&@$
, context
, TA_Err_Deltas_Ranges_Not_Ascending
);
461 if
($result == NUMBERSET_OVERLAPPING_RANGES
)
463 number_set_free
($left);
464 number_set_free
($range_elem);
465 store_error_data
(&@$
, context
, TA_Err_Deltas_Overlapping_Ranges
);
474 $range_elem = number_set_new
($integer,
476 context
->number_set_min
,
477 context
->number_set_max
);
478 if
($range_elem == NUMBERSET_INVALID_RANGE
)
480 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Range
);
483 if
($range_elem == NUMBERSET_ALLOCATION_ERROR
)
485 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
490 { $range_elem = $range; }
494 integer
[left
] '-' integer
[right
]
496 $range = number_set_new
($left,
498 context
->number_set_min
,
499 context
->number_set_max
);
500 if
($range == NUMBERSET_INVALID_RANGE
)
502 store_error_data
(&@$
, context
, TA_Err_Deltas_Invalid_Range
);
505 if
($range == NUMBERSET_ALLOCATION_ERROR
)
507 store_error_data
(&@$
, context
, TA_Err_Deltas_Allocation_Error
);
518 TA_deltas_error
(YYLTYPE *locp
,
519 Deltas_Context
* context
,
522 context
->error = TA_Err_Deltas_Syntax_Error
;
524 context
->errline_num
= locp
->first_line
;
525 context
->errline_pos_left
= locp
->first_column
;
526 context
->errline_pos_right
= locp
->last_column
;
528 strncpy
(context
->errmsg
, msg
, sizeof
(context
->errmsg
));
533 store_error_data
(YYLTYPE *locp
,
534 Deltas_Context
* context
,
537 context
->error = error;
539 context
->errline_num
= locp
->first_line
;
540 context
->errline_pos_left
= locp
->first_column
;
541 context
->errline_pos_right
= locp
->last_column
;
543 context
->errmsg
[0] = '\0';
552 "# 0 a p 1-3 x 0.3 y -0.2 @ 20-30; \\\n"
553 "0 exclam p 2-4 x 0.7 y -0.4 @ 6,7,9,10,11; \\\n"
554 "a p 12345678901234567890 x 0.5 @ 23-25";
564 Deltas_Context context
;
569 const char* filename
;
574 fprintf
(stderr
, "need an outline font as an argument\n");
580 error = FT_Init_FreeType
(&library
);
583 fprintf
(stderr
, "error while initializing FreeType library (0x%X)\n",
588 error = FT_New_Face
(library
, filename
, 0, &face
);
591 fprintf
(stderr
, "error while loading font `%s' (0x%X)\n",
597 /* we construct a minumum Deltas_Context */
598 sfnts
[0].face
= face
;
603 context.font
= &font
;
606 error = TA_deltas_scanner_init
(&context
, input
);
609 TA_deltas_parse
(&context
);
610 TA_deltas_scanner_done
(&context
);
612 TA_deltas_free
(context.result
);
615 FT_Done_FreeType
(library
);
622 /* end of tadeltas.y */