> ...I got stuck in implementing statements, code block, if and while statements.

As already pointed out, it easier to use parser generating tools like
Flex and Bison <https://gnu.org/software/bison/>. The latter has a
complete calculator example in for example C++ - easy to start with, and
then modify.

There is no clear distinction between a compiler or an interpreter, as
one can choose the point of execution; an interpreter might decide to
generate compiler code, and then execute it. This is possible with LLVM
<http://clang.llvm.org>, which has examples on how to get started.

As for code blocks and assignments/definitions, one needs a stacked name
look-up table: the lexer checks the name if it is defined on the table,
and if so, returns its correct grammatical type. If there is an inner
block (environment), one pushes a new level on the name table stack,
which is popped when the environment ends. Definitions always creates
names in the current level, whereas assignments write into existing
variables.