The syntax, i.e. grammar, of a programing language is classically given since Algol 1960, by Backus-Naur Form, also known as context free grammars. A context-free grammar provides a simple and precise mechanism for describing the methods by which phrases in some natural language are built from smaller blocks, capturing the "block structure" of sentences in a natural way. This is of help to compiler writers who use automated tools to produce a syntax tree from the code's text, while verifying the correctness of the code. The meaning of the code, i.e. semantics, can also profit from formal specification. This avoids ambiguity, and can aid users in understanding, while benefiting compiler writers in generating low-level code from the syntax trees. No single formalism has become dominant, for various reasons, so this thesis undertakes a survey of the most significant approaches. English is the common means of specifying meaning, but is fraught with ambiguity, as all natural languages are. Operational semantics, e.g. by abstract machines, work by viewing code as modifying a "state" of an abstract machine. Denotational semantics views the program, and parts thereof, as defining functions, for which rigorous definitions can be sought. The latter emphasis leads naturally to abstract parts of logic and the thesis looks closely at the lambda calculus for denotational semantics.