Hi Ihor,
   Chiming in here with a slight variant on what
others have said. Best!
Tom

I don't think this should be handled at the syntactic
layer at all. The empty string block language should
be syntactically valid with any special behavior
needed being handled later.

Linters could treat it as a warning/error though,
but the parsing is made significantly easier if
the empty string is present allowing the grammar
to be fully closed and regular.

Thus, I don't think we need to make this a syntactic
error or pun a src block without a lang to another type.

I think we can add an implementation for when the
block language is the empty string. This keeps
the grammar regular by removing a special case.

I assume that internally the empty string block lang
would mostly call the example block codepaths,
except that it should probably issue a warning or fail
if someone tries to org-src-edit the block so that we
can alert them that they are missing the lang.

Treating src blocks missing a lang as paragraphs is
incorrect because according to the syntax spec they
are syntactically still blocks (greater or lesser depending
on your inclinations).

I think the general principle we want to follow here is
that a block (or any entity in general) should not lose
its type because some part of its syntax is malformed
(I have made similar arguments about property drawers).

That is, if something starts with #+begin_NAME stuff
and there is a corresponding #+end_NAME, then it
is a block.

The choice of how a src block without a lang should
behave is a bit more complex as there are multiple
consumers of src blocks that make different assumptions.

As mentioned above. I think that if a block is missing the lang
we could think of it instead as the null language. If we have the
:var language because someone has other contents on the line
they have a well formed src block, but will get a different error
because there is currently no known language ":var".