Repository: fortran-lang/fortls (language: python)

Issue:
bug: CRITICAL statement in IF statement triggers "Unexpected end of scope at line"
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Description

As described in the title, when `CRITICAL` statement appears in `IF` statement, an error "Unexpected end of scope at line" is triggered. 

### Screenshots

![Screenshot 2023-01-11 193437](https://user-images.githubusercontent.com/13799118/211948421-fabbbf8f-8a6d-488b-ab93-7b0e1d68beee.png)


### Expected Behaviour

I believe the test code should be standard conforming.

### Version of Modern Fortran

v3.4.2023011101

### Version of Visual Studio Code

v1.74.3

### Platform and Architecture

WSL

### Additional Information

_No response_


Discussion / hints:
Thanks @han190, this appears to be a bug in fortls, I will transfer the issue there and issue a fix ASAP. Since you are working with coarrays, if you notice anything else that needs fixing do let me know. I have done very little work with coarrays in fortls so I would expect there would be plenty of issues.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 357b4683..27b5bb28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,8 @@
 
 ### Fixed
 
+- Fixed end of scope for `CRITICAL` keyword blocks
+  ([#255](https://github.com/fortran-lang/fortls/issues/255))
 - Fixed bug where completion of interfaces in USE ONLY would produce the snippet
   ([#150](https://github.com/fortran-lang/fortls/issues/150))
 - Fixed bug where diagnostic messages were raised for non-existent variables
diff --git a/fortls/regex_patterns.py b/fortls/regex_patterns.py
index 2a3bd6c4..d6611f30 100644
--- a/fortls/regex_patterns.py
+++ b/fortls/regex_patterns.py
@@ -40,8 +40,8 @@ class FortranRegularExpressions:
     SUBMOD: Pattern = compile(r"[ ]*SUBMODULE[ ]*\(", I)
     END_SMOD: Pattern = compile(r"SUBMODULE", I)
     END_PRO: Pattern = compile(r"(MODULE)?[ ]*PROCEDURE", I)
-    BLOCK: Pattern = compile(r"[ ]*([a-z_]\w*[ ]*:[ ]*)?BLOCK(?!\w)", I)
-    END_BLOCK: Pattern = compile(r"BLOCK", I)
+    BLOCK: Pattern = compile(r"[ ]*([a-z_]\w*[ ]*:[ ]*)?BLOCK|CRITICAL(?!\w)", I)
+    END_BLOCK: Pattern = compile(r"BLOCK|CRITICAL", I)
     DO: Pattern = compile(r"[ ]*(?:[a-z_]\w*[ ]*:[ ]*)?DO([ ]+[0-9]*|$)", I)
     END_DO: Pattern = compile(r"DO", I)
     WHERE: Pattern = compile(r"[ ]*WHERE[ ]*\(", I)
@@ -64,7 +64,7 @@ class FortranRegularExpressions:
     INT: Pattern = compile(r"[ ]*(ABSTRACT)?[ ]*INTERFACE[ ]*(\w*)", I)
     END_INT: Pattern = compile(r"INTERFACE", I)
     END_WORD: Pattern = compile(
-        r"[ ]*END[ ]*(DO|WHERE|IF|BLOCK|ASSOCIATE|SELECT"
+        r"[ ]*END[ ]*(DO|WHERE|IF|BLOCK|CRITICAL|ASSOCIATE|SELECT"
         r"|TYPE|ENUM|MODULE|SUBMODULE|PROGRAM|INTERFACE"
         r"|SUBROUTINE|FUNCTION|PROCEDURE|FORALL)?([ ]+(?!\W)|$)",
         I,


Test patch:
diff --git a/test/test_server_diagnostics.py b/test/test_server_diagnostics.py
index bd4b4631..44c254d3 100644
--- a/test/test_server_diagnostics.py
+++ b/test/test_server_diagnostics.py
@@ -428,3 +428,15 @@ def test_attribute_and_variable_name_collision():
     errcode, results = run_request(string, ["-n", "1"])
     assert errcode == 0
     assert results[1]["diagnostics"] == []
+
+
+def test_critical_scope():
+    """Test that critical scopes are correctly parsed."""
+    string = write_rpc_request(1, "initialize", {"rootPath": str(test_dir / "diag")})
+    file_path = str(test_dir / "diag" / "tst_critical.f90")
+    string += write_rpc_notification(
+        "textDocument/didOpen", {"textDocument": {"uri": file_path}}
+    )
+    errcode, results = run_request(string, ["-n", "1"])
+    assert errcode == 0
+    assert results[1]["diagnostics"] == []
diff --git a/test/test_source/diag/test_critical.f90 b/test/test_source/diag/test_critical.f90
new file mode 100644
index 00000000..819dbbf5
--- /dev/null
+++ b/test/test_source/diag/test_critical.f90
@@ -0,0 +1,7 @@
+program test_critical
+    implicit none
+    if (.true.) then
+        critical
+        end critical
+    end if
+end program test_critical