Created
July 27, 2021 07:05
-
-
Save mutoo/73c82de9dee89bf527856670038f3623 to your computer and use it in GitHub Desktop.
a nearley grammar of BNF for svg path data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The grammar for path data | |
# it's implementing the svg 1.1 spec | |
# https://www.w3.org/TR/SVG11/paths.html#PathDataBNF | |
# | |
# N.B. This Implementation Is Ambiguous! | |
# e.g. M0.6.5 -> M 0 6.5 | M 0.6 0.5 | |
# | |
@{% | |
const it = (it) => it; | |
const nullish = () => null; | |
const arr2str = (arr) => arr.join(''); | |
const sign2coef = (sign) => sign === '-'? -1: 1; | |
const inArr = ([id]) => [id]; | |
const joinArr = ([head, _, rest]) => [head, ...(rest||[])]; | |
const cmdWithParams = ([cmd, _, params]) => [cmd, params]; | |
%} | |
#test -> digit:+ {% ([digits]) => arr2str(digits) %} | |
#test -> digit_sequence {% id %} | |
#test -> exponent {% id %} | |
#test -> fractional_constant {% id %} | |
#test -> floating_point_constant {% id %} | |
#test -> integer_constant {% id %} | |
#test -> flag {% id %} | |
#test -> number {% id %} | |
#test -> nonnegative_number {% id %} | |
#test -> coordinate_pair {% id %} | |
#test -> moveto_argument_sequence {% id %} | |
#test -> moveto {% id %} | |
#test -> closepath {% id %} | |
#test -> drawto_commands {% id %} | |
#test -> moveto_drawto_command_group {% id %} | |
#test -> moveto_drawto_command_groups {% id %} | |
svg_path -> | |
wsp:* moveto_drawto_command_groups:? wsp:* {% ([_, cgs, __]) => (cgs || []).flatMap(it) %} | |
moveto_drawto_command_groups -> | |
moveto_drawto_command_group {% inArr %} | |
| moveto_drawto_command_group wsp:* moveto_drawto_command_groups {% joinArr %} | |
moveto_drawto_command_group -> | |
moveto wsp:* drawto_commands:? {% ([head, _, rest]) => [head, ...(rest||[]).flatMap(it)] %} | |
drawto_commands -> | |
drawto_command {% inArr %} | |
| drawto_command wsp:* drawto_commands {% joinArr %} | |
drawto_command -> | |
closepath | |
| lineto | |
| horizontal_lineto | |
| vertical_lineto | |
| curveto | |
| smooth_curveto | |
| quadratic_bezier_curveto | |
| smooth_quadratic_bezier_curveto | |
| elliptical_arc | |
moveto -> | |
[Mm] wsp:* moveto_argument_sequence {% cmdWithParams %} | |
moveto_argument_sequence -> | |
coordinate_pair {% inArr %} | |
| coordinate_pair comma_wsp:? lineto_argument_sequence {% joinArr %} | |
closepath -> | |
[Zz] {% it %} | |
lineto -> | |
[Ll] wsp:* lineto_argument_sequence {% cmdWithParams %} | |
lineto_argument_sequence -> | |
coordinate_pair {% inArr %} | |
| coordinate_pair comma_wsp:? lineto_argument_sequence {% joinArr %} | |
horizontal_lineto -> | |
[Hh] wsp:* horizontal_lineto_argument_sequence {% cmdWithParams %} | |
horizontal_lineto_argument_sequence -> | |
coordinate {% inArr %} | |
| coordinate comma_wsp:? horizontal_lineto_argument_sequence {% joinArr %} | |
vertical_lineto -> | |
[Vv] wsp:* vertical_lineto_argument_sequence {% cmdWithParams %} | |
vertical_lineto_argument_sequence -> | |
coordinate {% inArr %} | |
| coordinate comma_wsp:? vertical_lineto_argument_sequence {% joinArr %} | |
curveto -> | |
[Cc] wsp:* curveto_argument_sequence {% cmdWithParams %} | |
curveto_argument_sequence -> | |
curveto_argument {% inArr %} | |
| curveto_argument comma_wsp:? curveto_argument_sequence {% joinArr %} | |
curveto_argument -> | |
coordinate_pair comma_wsp:? coordinate_pair comma_wsp:? coordinate_pair {% ([cp0, _, cp1, __, cp2]) => [cp0, cp1, cp2] %} | |
smooth_curveto -> | |
[Ss] wsp:* smooth_curveto_argument_sequence {% cmdWithParams %} | |
smooth_curveto_argument_sequence -> | |
smooth_curveto_argument {% inArr %} | |
| smooth_curveto_argument comma_wsp:? smooth_curveto_argument_sequence {% joinArr %} | |
smooth_curveto_argument -> | |
coordinate_pair comma_wsp:? coordinate_pair {% ([cp0, _, cp1]) => [cp0, cp1] %} | |
quadratic_bezier_curveto -> | |
[Qq] wsp:* quadratic_bezier_curveto_argument_sequence {% cmdWithParams %} | |
quadratic_bezier_curveto_argument_sequence -> | |
quadratic_bezier_curveto_argument {% inArr %} | |
| quadratic_bezier_curveto_argument comma_wsp:? quadratic_bezier_curveto_argument_sequence {% joinArr %} | |
quadratic_bezier_curveto_argument -> | |
coordinate_pair comma_wsp:? coordinate_pair {% ([cp0, _, cp1]) => [cp0, cp1] %} | |
smooth_quadratic_bezier_curveto -> | |
[Tt] wsp:* smooth_quadratic_bezier_curveto_argument_sequence | |
smooth_quadratic_bezier_curveto_argument_sequence -> | |
coordinate_pair {% inArr %} | |
| coordinate_pair comma_wsp:? smooth_quadratic_bezier_curveto_argument_sequence {% joinArr %} | |
elliptical_arc -> | |
[Aa] wsp:* elliptical_arc_argument_sequence {% cmdWithParams %} | |
elliptical_arc_argument_sequence -> | |
elliptical_arc_argument {% inArr %} | |
| elliptical_arc_argument comma_wsp:? elliptical_arc_argument_sequence {% joinArr %} | |
elliptical_arc_argument -> | |
nonnegative_number comma_wsp:? nonnegative_number comma_wsp:? number comma_wsp flag comma_wsp:? flag comma_wsp:? coordinate_pair | |
{% ([rx, _, ry, __, rotate, ___, largeArc, ____, sweep, _____, [x, y]]) => [rx, ry, rotate, sweep, largeArc, x, y] %} | |
coordinate_pair -> | |
coordinate comma_wsp:? coordinate {% ([x, _, y]) => [x, y] %} | |
coordinate -> | |
number {% id %} | |
nonnegative_number -> | |
integer_constant {% ([int]) => parseInt(int) %} | |
| floating_point_constant {% ([float]) => parseFloat(float) %} | |
number -> | |
sign:? integer_constant {% ([sign, int]) => sign2coef(sign) * parseInt(int) %} | |
| sign:? floating_point_constant {% ([sign, float]) => sign2coef(sign) * parseFloat(float) %} | |
flag -> | |
[01] {% ([f]) => parseInt(f) %} | |
comma_wsp -> | |
(wsp:+ comma:? wsp:*) {% nullish %} | |
| (comma wsp:*) {% nullish %} | |
comma -> | |
"," {% nullish %} | |
integer_constant -> | |
digit_sequence {% ([ds]) => arr2str(ds) %} | |
floating_point_constant -> | |
fractional_constant exponent:? {% ([frac, exp]) => `${frac}${exp||''}` %} | |
| digit_sequence exponent {% ([ds, exp]) => `${arr2str(ds)}${exp}` %} | |
fractional_constant -> | |
digit_sequence:? "." digit_sequence {% ([ds0, _, ds1]) => `${ds0?arr2str(ds0):''}.${arr2str(ds1)}` %} | |
| digit_sequence "." {% ([ds, _]) => arr2str(ds) %} | |
exponent -> | |
( "e" | "E" ) sign:? digit_sequence {% ([e, sign, ds]) => `e${sign||''}${arr2str(ds)}` %} | |
sign -> | |
[+-] {% id %} | |
digit_sequence -> | |
digit {% ([digit]) => [digit] %} | |
| digit digit_sequence {% ([d, ds]) => [d, ...ds] %} | |
digit -> | |
[0-9] {% id %} | |
wsp -> [ \t\n\v\f] {% nullish %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://www.w3.org/TR/SVG/paths.html#PathDataBNF