ftd::p1
grammar
ftd
is based on a low-level grammar called ftd::p1
grammar.
section
A ftd::p1
file is composed of “sections”. A section looks like this:
an ftd::p1
file with two sections
-- section-kind section: the caption of the section header-kind header-1: some header value hello: world the body of the first section -- something: yo: 42
Each section starts with --
.
The section has these properties:
section kind
The section kind can be define after --
and before the section name. This is optional parameter.
In our case the section-kind
is the section kind.
Since section kind is optional, so a section can be defined with or without section kind.
section with section kind
-- string name: Some caption -- string list name:
section without section kind
-- my-section:
section name
The section name is the only mandatory parameter for a section. Name starts after --
or section kind if present, and ends with the first :
. Trailing :
is mandatory.
In our example, the name of the first section is some section
, and the second section’s name is something
.
Section name contains alphanumeric characters, underscores, space, dots(.
), hash(#
), and hyphens(-
). Colon terminates the section name.
Leading and trailing whitespaces are not considered part of the section name.
section caption
What comes after :
in the section line, till the end of the first line is called the caption
of the section.
The caption
is optional.
In our example, the first section’s caption is “the caption of the section”, and the second section does not have a caption.
Leading and trailing whitespaces are not considered part of the caption.
section headers
After the “section line” (the first line that starts with --
), zero or more section headers can be passed. Header can be passed in two ways: inline
and block
A section header consists of name (mandantory), kind (optional) and value (optional).
inline header
In our example, the section has two headers, having names header-1
and hello
, with values some header value
and world
respectively. Also the first header header-1
has kind header-kind
An empty newline or the start of a new section marks the end of the headers.
Leading and trailing whitespaces of both header name and header value are ignored.
inline
header
-- section-kind section: the caption of the section header-kind header-1: some header value hello: world
block header
We can also pass headers in block. This is commonly used when the value of header is long and passing it in inline
creates readability issue.
block
header
-- section-kind section-name: -- section-name.block-header: Lorem ipsum dolor sit amet. Vel magni dolorum et doloremque nostrum aut dicta unde 33 quod quisquam sed ducimus placeat et placeat reiciendis ad nostrum rerum. Qui quasi eserunt ut aliquid galisum et harum porro et libero facilis cum corporis voluptatem est beatae minima non voluptatem maxime. Est quod ipsum sed neque labore ut tempora porro ut quae distinctio ad enim voluptatem ex praesentium molestiae. Ea iusto consectetur ab sequi voluptatem et inventore iste.
The block header can be declared after inline
header. It starts with --
, follow by header kind, if present, then section name with .
and after this header name. Now, header value can be passed in caption or body area.
In above example, the header name is block-header
and has long value as Lorem ipsum dolor...
which is passed as body
Header value can also take list of sections as value. And in that case, it needs end
statement to show the closing of header.
block
header
-- section-kind section-name: -- section-name.block-header: -- some section: -- another section: -- end: section-name.block-header
section body
Like header, body can be passed in two ways: inline
and block
The body is optional.
Leading and trailing newlines are not considered part of the body.
inline
body
After the first empty line that comes after the section header, till the start of next section is considered the body of the section.
Section with inline body
-- some section: This is body -- another section: header: header value This is body
block
body
A section body can be passed as a block
. This is particularly helpful in case if the block
headers are defined. In that case, the body
can’t be passed in inline
.
Section with block body
-- some my-section: .... some block headers -- my-section.my-body: This is body
In above example, my-body
is the body of section.
Unlike header
, body
doesn’t accept list of sections as value.
sub-section
A section can contain zero or more sub-sections
:
-- some-section: -- subsection1: yo yo -- subsection2: subsection2 body -- end: some-section
subsections
are nothing but list of sections itself. If subsections are defined, the section need to mark it’s end using end
keyword.
In above example, subsection1
and subsection2
are two subsections for some-section
section. Also, the section is marked as end using -- end: some-section
statement.
In above example, some-section
section has two sub-section
s, with names subsection1
and subsection2
respectively. The first one has a caption, yo yo
, and the second one has a body, subsection2 body
.
Programmatic Access
ftd::p11
module in ftd
crate can be used to read ftd.p1
files. Wrappers of this crate in Python and other programming languages would hopefully come soon.