File: parse-automatic.rst

package info (click to toggle)
cmake-format 0.6.13-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,436 kB
  • sloc: python: 16,990; makefile: 14
file content (217 lines) | stat: -rw-r--r-- 6,183 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
=================
Automatic Parsers
=================

cmake provides help commands which can print out the usage information for all
of the builtin statements that it supports. You can get a list of commands
with

.. code::

   cmake --help-command-list

And you can get the help text for a command with (for example):

.. code::

   cmake --help-command add_custom_command

In general (but not always) the usage string is given an a restructured-text
block that looks like this:

.. code::

    ::

     add_custom_command(TARGET <target>
                        PRE_BUILD | PRE_LINK | POST_BUILD
                        COMMAND command1 [ARGS] [args1...]
                        [COMMAND command2 [ARGS] [args2...] ...]
                        [BYPRODUCTS [files...]]
                        [WORKING_DIRECTORY dir]
                        [COMMENT comment]
                        [VERBATIM] [USES_TERMINAL])

The syntax of these usage strings isn't 100% consistent but if we could
generate a parser that even understands *most* of these strings then that
would greatly reduce the maintenance load.


--------------
Expect Objects
--------------

The output of the specification parser is an "Expect Tree". A tree of
objects representing what is expected from a statement. If a sequence
of tokens satisfies an expected subtree then the a corresponding parse
tree is generated. If a mandatory expected subtree is not satisfied
then an error is generated. If an optional expected subtree is not
satisfied then the next sibling is tried.


------------
Case studies
------------


Inconsistent usage of angle brackets
====================================

Sometimes mandatory arguments are shown in angle brackets, sometimes not. I
can't really figure a pattern for when they are used and when  they are not.


Ellipses
========

Whether or not there is a space between an elipsis and the preceding token
seems to imply something about what is repeated.

::

 add_custom_command(TARGET <target>
                    PRE_BUILD | PRE_LINK | POST_BUILD
                    COMMAND command1 [ARGS] [args1...]
                    [COMMAND command2 [ARGS] [args2...] ...]
                    [BYPRODUCTS [files...]]
                    [WORKING_DIRECTORY dir]
                    [COMMENT comment]
                    [VERBATIM] [USES_TERMINAL])


Note that the elipsis for "COMMAND" is inside the bracket above, but is
outside the bracket here:

::

 add_dependencies(<target> [<target-dependency>]...)


Choices
=======

Pipe character is used to separate choices.

::

 configure_file(<input> <output>
                [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
                [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

Sometimes it's a mandatory choice

::

 ctest_test([BUILD <build-dir>] [APPEND]
            [START <start-number>]
            [END <end-number>]
            [STRIDE <stride-number>]
            [EXCLUDE <exclude-regex>]
            [INCLUDE <include-regex>]
            [EXCLUDE_LABEL <label-exclude-regex>]
            [INCLUDE_LABEL <label-include-regex>]
            [EXCLUDE_FIXTURE <regex>]
            [EXCLUDE_FIXTURE_SETUP <regex>]
            [EXCLUDE_FIXTURE_CLEANUP <regex>]
            [PARALLEL_LEVEL <level>]
            [TEST_LOAD <threshold>]
            [SCHEDULE_RANDOM <ON|OFF>]
            [STOP_TIME <time-of-day>]
            [RETURN_VALUE <result-var>]
            [CAPTURE_CMAKE_ERROR <result-var>]
            [QUIET]
            )

Sometimes the choice is among literals, in which case there are no surrounding
brackets.

::

 file(GLOB <variable>
      [LIST_DIRECTORIES true|false] [RELATIVE <path>]
      [<globbing-expressions>...])


Manditory Sequence
==================

In this case the literal pattern is listed inside the mandatory group pattern
(angle brackets).

::

 file(GENERATE OUTPUT output-file
      <INPUT input-file|CONTENT content>
      [CONDITION expression])

This one is pretty complex, and also demonstrates the nested bracket usage.
I think the indication here is that "you must have one of these choices.

::

 get_property(<variable>
              <GLOBAL             |
               DIRECTORY [dir]    |
               TARGET    <target> |
               SOURCE    <source> |
               INSTALL   <file>   |
               TEST      <test>   |
               CACHE     <entry>  |
               VARIABLE>
              PROPERTY <name>
              [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])

Nested Optionals
================

::

 install(TARGETS targets... [EXPORT <export-name>]
         [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
           PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
          [DESTINATION <dir>]
          [PERMISSIONS permissions...]
          [CONFIGURATIONS [Debug|Release|...]]
          [COMPONENT <component>]
          [OPTIONAL] [EXCLUDE_FROM_ALL]
          [NAMELINK_ONLY|NAMELINK_SKIP]
         ] [...]
         [INCLUDES DESTINATION [<dir> ...]]
         )


Multiple Forms
==============

::

 string(SUBSTRING <string> <begin> <length> <output variable>)
 string(STRIP <string> <output variable>)
 string(GENEX_STRIP <input string> <output variable>)
 string(COMPARE LESS <string1> <string2> <output variable>)


----------
Conclusion
----------

After implementing a prototype parser and testing it on some of the above cases
it is clear that the help text is not very consistent and is likely to be very
challenging to get an implementation that works reliabily and knows when it
fails. For example:

::

 add_custom_command(TARGET <target>
                    PRE_BUILD | PRE_LINK | POST_BUILD
                    COMMAND command1 [ARGS] [args1...]
                    [COMMAND command2 [ARGS] [args2...] ...]
                    [BYPRODUCTS [files...]]
                    [WORKING_DIRECTORY dir]
                    [COMMENT comment]
                    [VERBATIM] [USES_TERMINAL])

In this form of the command, the `PRE_BUILD` `PRE_LINK` or `POST_BUILD`
argument is required. Normally it seems like they would put this in angle
brackets as `<PRE_BUILD|PRE_LINK|POST_BUILD>` but they do not. So it's
ambiguous where the pipes are splitting and what the groups are.