151 | | In order to make the heredoc preprocessor reentrant, no global variables are used. Instead, lines [source:/trunk/compilers/pirc/src/hdocprep.l#L83 83 to 98] define a struct global_state. The comments in the code briefly describe what each field is for, but they will be discussed in more detail later if we walk through the actual processing of the heredocs. A new instance of this struct can be created by invoking [source:/trunk/compilers/pirc/src/hdocprep.l#L157 init_global_state]. For now, it is useful to know that this struct has a pointer to a Parrot interpreter object, the name of the file being processed, and a pointer to the output file. |
152 | | |
153 | | The function [source:/trunk/compilers/pirc/src/hdocprep.l#L208 process_heredocs] is the main function of the heredoc preprocessor that the main compiler program (PIRC) invokes. This function opens the file to be processed, initializes the lexer, creates a new global_state struct instance, as described above, invokes the lexer to do the processing and cleans up afterwards. |
154 | | |
| 151 | In order to make the heredoc preprocessor reentrant, no global variables are used. Instead, lines [source:/trunk/compilers/pirc/src/hdocprep.l#L83 83 to 98] define a {{{struct global_state}}}. The comments in the code briefly describe what each field is for, but they will be discussed in more detail later if we walk through the actual processing of the heredocs. A new instance of this struct can be created by invoking [source:/trunk/compilers/pirc/src/hdocprep.l#L157 init_global_state]. For now, it is useful to know that this struct has a pointer to a Parrot interpreter object, the name of the file being processed, and a pointer to the output file. |
| 152 | |
| 153 | The function [source:/trunk/compilers/pirc/src/hdocprep.l#L208 process_heredocs] is the main function of the heredoc preprocessor that the main compiler program (PIRC) invokes. This function opens the file to be processed, initializes the lexer, creates a new {{{global_state}}} struct instance, as described above, invokes the lexer to do the processing and cleans up afterwards. |
| 154 | |
| 155 | We will now walk through two different scenarios, in order to simplify the discussion. Scenario 1 discussed the case of single heredoc parsing, and Scenario 2 discusses multiple heredoc parsing. Multiple heredoc parsing starts out with Scenario 1, but is a bit more advanced. |
| 156 | |
| 157 | ==== Scenario 1: single heredoc parsing ==== |
| 158 | |
| 159 | Consider the following input: |
| 160 | |
| 161 | {{{ |
| 162 | |
| 163 | .sub main |
| 164 | $S0 = <<'EOS' |
| 165 | This |
| 166 | is |
| 167 | a |
| 168 | heredoc |
| 169 | string. |
| 170 | |
| 171 | EOS |
| 172 | .end |
| 173 | |
| 174 | }}} |
| 175 | |
| 176 | The lexer starts out in the {{{INITIAL}}} state by default (as per Flex specification). When reading input such as {{{<<'EOS'}}}, the rule on [source:/trunk/compilers/pirc/src/hdocprep.l#L306 line 306] is activated. The actual string ("EOS") is stored in the field {{{state->delimiter}}}, and an escaped {{{newline}}} character is stored in the {{{heredoc}}} buffer. |
| 177 | |
| 178 | ==== Scenario 2: multiple heredoc parsing ==== |
| 179 | |
| 180 | ==== POD parsing ==== |