[flang] Fix parsing ambiguity: MODULESUBROUTINEFOO at top level
authorpeter klausler <pklausler@nvidia.com>
Tue, 4 Sep 2018 16:28:02 +0000 (09:28 -0700)
committerpeter klausler <pklausler@nvidia.com>
Tue, 4 Sep 2018 18:55:27 +0000 (11:55 -0700)
Original-commit: flang-compiler/f18@cfda0945ea03245fd169d04b3b13ee3a4cbc3bc8
Reviewed-on: https://github.com/flang-compiler/f18/pull/172
Tree-same-pre-rewrite: false

flang/lib/parser/grammar.h

index ae7b01c..4a2220d 100644 (file)
@@ -277,9 +277,21 @@ TYPE_PARSER(construct<Program>(some(StartNewSubprogram{} >>
 // R502 program-unit ->
 //        main-program | external-subprogram | module | submodule | block-data
 // R503 external-subprogram -> function-subprogram | subroutine-subprogram
-TYPE_PARSER(construct<ProgramUnit>(indirect(functionSubprogram)) ||
+// N.B. "module" must precede "external-subprogram" in this sequence of
+// alternatives to avoid ambiguity with the MODULE keyword prefix that
+// they recognize.  I.e., "modulesubroutinefoo" should start a module
+// "subroutinefoo", not a subroutine "foo" with the MODULE prefix.  The
+// ambiguity is exacerbated by the extension that accepts a function
+// statement without an otherwise empty list of dummy arguments.  That
+// MODULE prefix is disallowed by a constraint (C1547) in this context,
+// so the standard language is not ambiguous, but disabling its misrecognition
+// here would require context-sensitive keyword recognition or (or via)
+// variant parsers for several productions; giving the "module" production
+// priority here is a cleaner solution, though regrettably subtle.  Enforcing
+// C1547 is done in semantics.
+TYPE_PARSER(construct<ProgramUnit>(indirect(Parser<Module>{})) ||
+            construct<ProgramUnit>(indirect(functionSubprogram)) ||
     construct<ProgramUnit>(indirect(subroutineSubprogram)) ||
-    construct<ProgramUnit>(indirect(Parser<Module>{})) ||
     construct<ProgramUnit>(indirect(Parser<Submodule>{})) ||
     construct<ProgramUnit>(indirect(Parser<BlockData>{})) ||
     construct<ProgramUnit>(indirect(Parser<MainProgram>{})))