fortrangoingonforty/armfortas / 7dd03cc

Browse files

Skip comment lines between preprocessor continuations

The preprocessor's line-joining loop appended comment-only
lines (starting with !) to the logical line instead of skipping
them. This produced tokens like `character(*), parameter :: !>`
that the lexer then split into a truncated declaration plus a
stray comment, causing parse failures on valid Fortran like
stdlib_io_aux.f90's documented parameter lists.

Per F2018 6.3.2.4, comment lines and blank lines between
continuation lines must be ignored.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
7dd03cc3c8ca5986853dd7b2a5a2d0df3b578fcc
Parents
817221c
Tree
5443ee8

1 changed file

StatusFile+-
M src/preprocess/mod.rs 8 5
src/preprocess/mod.rsmodified
@@ -259,16 +259,19 @@ impl Preprocessor {
259
                 while has_trailing_continuation(&logical_line) {
259
                 while has_trailing_continuation(&logical_line) {
260
                     if i < raw_lines.len() {
260
                     if i < raw_lines.len() {
261
                         let next = raw_lines[i].trim_start();
261
                         let next = raw_lines[i].trim_start();
262
-                        // A directive between free-form continued lines must
263
-                        // remain its own logical line so conditional blocks
264
-                        // can be evaluated before later Fortran continuation.
265
                         if next.starts_with('#') {
262
                         if next.starts_with('#') {
266
                             break;
263
                             break;
267
                         }
264
                         }
268
-                        // Remove the trailing & from the code portion.
265
+                        // F2018 6.3.2.4: comment lines and blank lines
266
+                        // may appear between a continuation line and
267
+                        // its successor. Skip them without breaking
268
+                        // the continuation.
269
+                        if next.starts_with('!') || next.is_empty() {
270
+                            i += 1;
271
+                            continue;
272
+                        }
269
                         let amp_pos = find_code_trailing_ampersand(&logical_line).unwrap();
273
                         let amp_pos = find_code_trailing_ampersand(&logical_line).unwrap();
270
                         logical_line.truncate(amp_pos);
274
                         logical_line.truncate(amp_pos);
271
-                        // Consume the next line, skipping leading & if present.
272
                         let next = next.strip_prefix('&').unwrap_or(next);
275
                         let next = next.strip_prefix('&').unwrap_or(next);
273
                         logical_line.push_str(next);
276
                         logical_line.push_str(next);
274
                         i += 1;
277
                         i += 1;