0% found this document useful (0 votes)
3 views

CSC305 Lecture Note 2

The document provides an overview of programming languages, defining them as formal sets of instructions for computers, and detailing their syntax, semantics, and pragmatics. It categorizes programming languages into generations, from low-level machine code to high-level languages, and discusses key features, attributes of good programs, and the trade-offs between compiled and interpreted languages. Additionally, it highlights the characteristics and capabilities of each generation of computers, emphasizing the evolution of programming languages alongside technological advancements.

Uploaded by

Gerald Egwudo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

CSC305 Lecture Note 2

The document provides an overview of programming languages, defining them as formal sets of instructions for computers, and detailing their syntax, semantics, and pragmatics. It categorizes programming languages into generations, from low-level machine code to high-level languages, and discusses key features, attributes of good programs, and the trade-offs between compiled and interpreted languages. Additionally, it highlights the characteristics and capabilities of each generation of computers, emphasizing the evolution of programming languages alongside technological advancements.

Uploaded by

Gerald Egwudo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

SURVEY OF PROGRAMMING LANGUAGES

CSC305

A computer program is a sequence of instructions written using a Computer Programming


Language to perform a specified task by the computer. The two important terms used in
the above definition are:
• Sequence of instruction
• Computer Programming Language

A programming language is a formal set of instructions that enables humans to


communicate with computers to perform specific tasks. Programming languages consist
of syntax (rules for structuring statements) and semantics (meaning of each statement),
which together allow programmers to write code that computers can interpret and
execute.
Programming languages range from low-level languages like assembly, which are closer to
machine code, to high-level languages like Python, Java, and C++, which are more
abstracted and user-friendly.

Purpose of Programming Languages


Programming languages enable humans to write instructions that a computer can
understand and execute. They abstract the complexity of machine code (binary) into a
more human-readable form, making it easier to develop, debug, and maintain complex
programs.

A programming language can be described by the combination of its semantics, syntax and
pragmatic.

Key Features of Programming Languages:


1. Syntax: This defines the structure and rules for combining symbols in the language.
Just as grammar dictates how sentences are structured in English, syntax dictates
how code is written.
2. Semantics: This refers to the meaning behind the syntax. For instance, different
programming commands or statements have specific meanings that define what
they will make the computer do.
3. Primitives: These are the most basic elements or building blocks of the language,
like numbers, letters, and other symbols. Every programming language has its own
set of primitives.
4. Control Structures: These are commands like loops (for, while) and conditionals
(if, else) that determine the flow of a program, allowing the computer to make
decisions or repeat actions.
5. Data Types and Structures: Programming languages allow you to define and use
various types of data (like numbers, text, or more complex data structures like lists
or objects) which help in managing and organizing information.
1. Syntax
Syntax refers to the structure or rules that govern how a program is written. It dictates the
correct arrangement of symbols, keywords, and punctuation to form a valid program.
Syntax errors occur when the program doesn’t follow the rules of the language.
Example:
In Python, an if statement must be followed by a colon :.

In the incorrect syntax, the missing colon will result in a syntax error because the language
expects a specific structure.
2. Semantics
Semantics refers to the meaning of a program or what the instructions do. A program with
correct syntax might still not make sense in terms of what it is trying to achieve, leading to
semantic errors or unintended behavior.
Example:

In the above example, the syntax is correct, but there is a semantic issue because dividing
by zero is mathematically undefined, leading to a runtime error. The meaning of dividing by
zero doesn't make sense, even though the program is syntactically correct.
3. Pragmatics
Pragmatics concerns how the language is intended to be used in practice, focusing on
efficiency, readability, and maintainability. Even if the code is syntactically and
semantically correct, it might not follow best practices or might be inefficient.
Example:
Both examples calculate the sum of numbers from 1 to 100. The first version is syntactically and
semantically correct, but the second version is more pragmatic because it’s shorter, easier to
read, and more efficient by using built-in functions.

Summary:

• Syntax: The rules for writing valid code (e.g., colons, indentation, parentheses).
• Semantics: The meaning of the code and what it does (e.g., logical errors like dividing by
zero).
• Pragmatics: Best practices and practical usage (e.g., efficient, readable code).

Attributes of a Good Program


1. Clarity, Simplicity, and Unity
A language should make it clear what each line of code does, using simple syntax that is
easy to understand.
Example (Python):

Explanation: This Python code is clear and simple, showing straightforward addition. The
function add_numbers has a clear purpose, and the code to call it is concise and readable.
2. Orthogonality
Orthogonality in a language means you can combine features in flexible ways without
unexpected results.
Example (Python):

Explanation: In this example, multiplication and addition work independently, so they can
be combined without any surprises. Python allows combining operators in meaningful
ways, demonstrating orthogonality.
3. Naturalness for the Application
The language should offer features that naturally align with the problem you’re solving. For
data analysis, for instance, Python’s list comprehensions are very useful.
Example (Python list comprehension for data filtering):

Explanation: Python’s list comprehensions are natural for data filtering, allowing you to
easily extract even numbers from a list. The syntax closely matches the problem, making it
a natural fit.
4. Support for Abstraction
Languages that support abstraction allow you to hide complex details behind simple
functions or classes.
Example (Python Class):
Explanation: The Rectangle class abstracts the details of area calculation. Instead of
dealing with width and height directly each time, you can just call rect.area() to get the
area.
5. Ease of Program Verification
A language with simple syntax makes it easier to check if the program does what it’s
supposed to. In Python, concise syntax helps in easily spotting errors.
Example (Simple conditional check):

Explanation: This function has a simple syntax for verifying if a number is even. The clear
logic helps easily verify its correctness, as there’s minimal complexity in the condition.
6. Programming Environment
An integrated development environment (IDE) like PyCharm or Visual Studio Code, with
features like autocompletion, debugging, and syntax highlighting, enhances productivity.
Example (Debugging in Visual Studio Code with breakpoints): In Visual Studio Code, you
can set a breakpoint in the is_even function (from the previous example) and run the
debugger to see how each line is executed, which helps in troubleshooting.
Explanation: Using a supportive IDE with debugging tools allows easy testing and
modification, especially in large projects. This makes it easier to identify and fix errors
quickly.
7. Portability of Programs
Python is cross-platform, meaning code can often run on different operating systems with
little to no modification.
Example (Simple script):

Explanation: A basic “Hello, World!” program written in Python runs on Windows, macOS,
and Linux without any changes. Python’s cross-platform compatibility makes it highly
portable.

Interpreted Language Trade-Off:


Interpreted languages, like Python or JavaScript, don’t compile all at once. Instead, each
line of code is interpreted every time it’s run, which makes them slower at execution
compared to compiled languages (like C++ or Java). The benefit here is faster development
and easier testing—making interpreted languages great for quick scripts or simple
applications where execution speed isn’t as critical.
1. Reliability: This is about ensuring the system works well and can be easily fixed if
something goes wrong. In programming languages, reliability could mean a clear structure,
strong error checking, or easy debugging, all of which help identify and resolve issues
quickly.
2. Expandability: This refers to how easy it is to upgrade the system or program if it needs
to handle more or do something new. A language or system that is modular—built in small,
interchangeable parts—allows developers to add features or improve performance more
easily without having to overhaul everything.
3. Programmability: There should be a balance between how simple it is to write code and
how complex the hardware (computers) required to run it might be. If a language is too
complex, it could be costly in terms of time and resources to program with it, even if it does
work well with advanced hardware.
4. Maintainability: This emphasizes the ease of keeping a system working well over time.
For example, if a program needs frequent updates or bug fixes, a language or design that
allows straightforward editing or maintenance is preferable.
5. Compatibility: This is about how well the language or program can work with other parts
of a system—like the computer, operating system, or other software. Compatibility
simplifies integration and reduces the complexity of getting everything to work together.
6. Adaptability: A system’s adaptability measures its flexibility to meet various needs
without requiring hardware or major code changes. An adaptable language is one that
allows you to use it in many different scenarios, often with minimal adjustments.
7. Availability: This refers to the likelihood that the system or program is functioning
correctly at any given time. High availability is related to reliability, but it’s more about how
consistently accessible the system is for use.
8. Development Status and Cost: These involve practical considerations like budget and
project timeline. Development costs can be influenced by many factors, including how
much you can use existing hardware or software, the risks of using new technologies, and
how likely it is that new tech developments will affect your project.

Summary Table:
Compiled Interpreted Hybrid (Compiled + Interpreted)

Languages Languages
C Python Java

C++ JavaScript C#

Go Ruby Python (PyPy)

Rust PHP JavaScript (modern engines)

Fortran Perl MATLAB

Swift Lua

Pascal Shell Scripting (Bash)

COBOL

Conclusion:
• Compiled languages offer high performance and are well-suited for system-level
programming but require compilation before execution.
• Interpreted languages offer flexibility and ease of use but generally have slower
execution due to line-by-line interpretation.
• Hybrid languages combine the best of both worlds, offering a balance between
flexibility and performance optimization.

Classification of Programming Language Generation


Generations of computers have seen changes based on evolving technologies. The
generations are actually based on evolving chip technology rather than any particular time
frame.
The five generations of computers are characterized by the electrical current flowing
through the processing mechanisms listed below:
• The first is within vacuum tubes
• Transistors
• Integrated circuits
• Microprocessors
• Artificial intelligence

First Generation (1GL)


Machine-level programming language used to program first-generation computers.
Originally, no translator was used to compile or assemble the first-generation language.
Computers usually operate on a binary level which are sequences of 0's and 1 'so, in the
early days of computer programming binary machine code was used to program
computers.

Second Generation Languages (2GL)


Assembly languages: the obvious drawbacks of binary programming became smaller by
the introduction of second-generation languages (2GL). These languages allowed
mnemonic abbreviations as symbolic names and the concept of commands and operands
was introduced. Compilation systems, called assemblers, were developed to translate the
assembly language/symbolic programs into machine code.

Third Generation Languages (3GL)


Third generation languages /high level languages/Problem oriented languages: these
languages allow control structures which are based on logical data objects: variables of a
specific type. They provide a level of abstraction allowing machine-independent
specification of data, functions or processes, and their control. A programmer can now
focus on the problem to be solved without being concerned with the internal hardware
structure of the target computer. When considering high level programming languages,
there are four groups of programming languages: imperative, declarative, object oriented
and functional languages.

Fourth Generation Languages (4GL)


Fourth generation languages/Non procedural languages deal with the following two fields
which become more and more important: database and query languages, and program or
application generators. The steadily increasing usage of software packages like database
systems, spread sheets, statistical packages, and other (special purpose) packages
makes it necessary to have a medium of control available which can easily be used by non-
specialists. In fourth generation languages the user describes what he wants to be solved,
instead of how he wants to solve a problem - as it is done using procedural languages. In
general, fourth generation languages are not only languages, but interactive programming
environments. E.g. SOL (Structured Query Language): a query language for relational
databases based on Codd's requirements for non- procedural query languages.

Fifth Generation Language (5GL)


5GL is a programming language based around solving problems using constraints given to
program rather using an algorithm written by a programmer. 5GL allows computers to have
their own ability to think and their own inferences can be worked out by using the
programmed information in large databases. 5GL gave birth to the dream of robot with AI
and Fuzzy Logic. The fifth-generation languages are also called 5GL. It is based on the
concept of artificial intelligence. It uses the concept that that rather than solving a problem
algorithmically, an application can be built to solve it based on some constraints, i.e., we
make computers learn to solve any problem. Parallel Processing & superconductors are
used for this type of language to make real artificial intelligence. Advantages of this
generation is that machines can make decisions, it reduces programmer effort to solve a
problem and very easier than 3GL or 4GL to learn and use. Examples are: PROLOG, LISP,
etc.

Characteristics of each generation


1A) Computer Characteristics and Capabilities for 1GL

• Size – Relatively big size. Size was equivalent to a room.


• Speed – slow speed, hundred instructions per second.
• Cost – cost was very high.
• Language– Machine and Assembly Language.
• Reliability – high failure rate, Failure of circuits per second.
• Power– high power Consumption and it generated much heat.
B) Trends and Developments in Computer Hardware

• Main Component – based on vacuum tubes


• Main memory –Magnetic drum
• secondary Memory – Magnetic drum & magnetic tape.
• Input Media – Punched cards & paper tape
• Output Media – Punched card & printed reports.
Example – ENIAC, UNIVAC, Mark –I, mark-III, IBM 700 series, IBM 700 series, IBM 701
series IBM 709 series etc.
2A) Computer Characteristics and Capabilities 2GL

• Size – Smaller than first generation Computers.


• Speed – Relatively fast as compared to first generation, thousand instructions per
second.
• Cost – cost Slightly lower than first generation.
• Language – Assembly Language and High-level languages like FORTRAN, COBOL,
BASIC.
• Reliability – Failure of circuits per days.
• Power– Low power Consumption.
B) Trends and Developments in Computer Hardware

• Main Component – Based on Transistor.


• Main Memory – Magnetic core.
• Secondary Memory – Magnetic tape & magnetic Disk.
• Input Media – Punched cards
• Output Media – Punched card & printed reports.
Example – IBM-7000, CDC 3000 series, PDP, PDP3, PDP 5, PDP8, ATLAS, IBM- 7094 etc.
3A) Computer Characteristics and Capabilities for 3GL

• Size – Smaller than Second Generation Computers. Disk size mini computers.
• Speed – Relatively fast as compared to second generation, Million instructions per
second (MIPS).
• Cost – cost lower than Second generation.
• Language– High level languages like PASCAL, COBOL, BASIC, C etc.
• Reliability – Failure of circuits in Weeks.
• Power– Low power Consumption.
B) Trends and Developments in Computer Hardware

• Main Component – Based on Integrated Circuits (IC)


• Primary Memory – Magnetic core.
• Secondary Memory– Magnetic Tape & magnetic disk.
• Input Media – Key to tape & key to disk
• Output Media – Printed reports & Video displays.
Example – IBM-307 Series, CDC 7600 series, PDP (Personal Data processer) II etc.
4A) Computer Characteristics and Capabilities 4GL
• Size – Typewriter size micro-Computer.
• Speed – Relatively fast as compared to Third generation, Tens of Millions
instructions per second.
• Cost – Cost lower than third generation.
• Language– High level languages like C++, KL1, RPG, SQL.
• Reliability – Failure of circuits in months.
• Power– Low power Consumption.
B) Trends and Developments in Computer Hardware

• Main Component – Large scale integrated (LSI) Semiconductor circuits called


MICRO PROCESSOR or chip and VLSI (Very Large scale integrated).
• Main Memory – Semiconductor memory like RAM, ROM and cache memory is used
as a primary memory.
• Secondary Memory – Magnetic disk, Floppy disk, and Optical disk (CD, DVD).
• Input Media – keyboard.
• Output Media – Video displays, Audio responses and printed reports.
Example – CRAY 2, IBM 3090/600 Series, IBM AS/400/B60 etc.
5A) Computer Characteristics and Capabilities 5GL

• Size –Credit card size microcomputers.


• Speed – Billions of instructions per second.
• Cost – Cost Slightly lower than first generation.
• Language– Artificial Intelligence (AI) Languages like LISP, PROLOG etc
• Reliability – Failure of circuits in year.
• Power– Low power Consumption.
B) Trends and Developments in Computer Hardware

• Main Component – based on ULSI (Ultra Large scale integrated) Circuit. That is also
called Parallel Processing method.
• Memory – Optical disk and magnetic disk.
• Input Media – Speech input, Tactile input.
• Output Media – Graphics displays, Voice responses.
• Example – Lap-Tops, palm –Tops, Note books, PDA (personal Digital Assistant) etc.

Levels of Abstraction in Programming Languages


Programming languages are classified from low-level to high-level based on how close they
are to machine code (binary) or human-readable code. There are five generations (1GL to
5GL):
1. Low-Level Languages (1st & 2nd Generations)
o Machine Language (1GL): Direct binary code (0s and 1s) understandable by
computers. It runs very fast since no translation is needed, but it’s difficult to
write, understand, and debug.
o Assembly Language (2GL): Uses mnemonics instead of binary, which is
easier for humans. It still requires knowledge of computer architecture, and
uses an assembler to convert to machine code.
o Features: Fast, error-prone, hard to debug, non-portable (specific to
hardware).
2. Middle-Level Languages
o These languages are close to both low- and high-level languages, such as C,
C++, and Java. They allow direct memory access through pointers (like low-
level languages) while also supporting features of high-level languages.
o Features: Support memory access, system-level operations, and user-
friendly syntax.
3. High-Level Languages (3rd Generation Languages)
o Languages like Python, JavaScript, and FORTRAN. They are closer to human
language and allow complex instructions to be written in a simple,
understandable syntax.
o Features: Easier to read and write, portable across systems, error-handling
features, problem-oriented, requires translators (compilers or interpreters).
4. Higher-Level Languages (5th Generation Languages)
o Also called 5GL languages, these are designed for advanced tasks like
symbolic reasoning and natural language processing. Examples include
Prolog, which is used for tasks involving AI and logic-based tasks.
o Features: Focus on parallel processing, interaction with symbols, and
natural language. Often used in AI.

A. Translators for Programming Languages


Different translators are used to convert programming languages into machine-readable
code:
• Assembler: Used for low-level assembly languages to convert code into machine
language.
• Compiler: Translates high-level code into machine language at once, making it
faster for languages like C.
• Interpreter: Translates and executes line-by-line, making it slower but suitable for
languages like Python.

B. Overview of Some High-Level Languages


1. C: Popular for system programming, especially Unix, known for its efficiency.
2. C++: Built on C, adds object-oriented features, widely used in gaming and software
applications.
3. Java: An object-oriented language popular for web and cross-platform applications.
4. FORTRAN: Focused on numerical and scientific computing.
5. VBScript: Developed by Microsoft, used for making dynamic web pages.
6. Pascal and BASIC: Common in early computer science education.
7. PHP: Commonly used in web development.
These classifications help in choosing the right language for a task by understanding each
one’s advantages and limitations.

Language Paradigm
Paradigm is a model or world view. Paradigms are important because they define a
programming language and how it works. A great way to think about a paradigm is as a set
of ideas that a programming language can use to perform tasks in terms of machine-code
at a much higher level. These different approaches can be better in some cases, and worse
in others.

• Imperative/Procedural programming languages


• Functional/applicative programming languages
• Logic/declarative/ruled based programming languages
• Object-oriented programming languages
• Scripting Language

Paradigm-Based Classification
1. Imperative Programming (Python)
Imperative programming involves giving step-by-step commands to solve a problem.
Explanation: In imperative programming, we explicitly tell the computer how to perform a
task, step-by-step. Here, we initialize total to zero and use a for loop to iterate over the
numbers 1 to 5, adding each number to total. The result is printed at the end.
• Key Paradigm Concept: We are directly manipulating total (a variable) and using
commands in a specific order to achieve the desired outcome.
• Output: Sum: 15
2. Functional Programming (Python)
• Functional programming focuses on using functions and avoids changing states.
Python supports this style with functions like map, filter, and lambda.

Explanation: Functional programming emphasizes the use of functions and avoids


changing states. Here, we use two functions:
• filter: Selects even numbers from the list numbers (lambda x: x % 2 == 0 checks if x
is even).
• map: Squares each even number selected by filter.
This code produces a new list even_squares without modifying numbers.
• Key Paradigm Concept: Functions (like map and filter) create new values without
changing existing ones.
• Output: Even squares: [4, 16]
3. Object-Oriented Programming (OOP) (Python)
• In OOP, code is organized around objects that represent real-world entities.
The key concepts of OOP are
i. Objects
ii. Classes
iii. Subclasses
iv. Inheritance
v. Inclusion polymorphism.

Explanation: Object-oriented programming organizes code into objects that contain both
data and behavior. Here:
• We define a Car class with attributes make and model.
• __init__ is the constructor method that initializes a new Car instance with specified
make and model.
• The display method prints out the car's make and model.
car1 = Car("Toyota", "Camry") creates an instance of Car, and car1.display() calls the
display method for this instance.
• Key Paradigm Concept: An object (car1) combines both state (make, model) and
behavior (display() method).
• Output: Car: Toyota Camry
4. Concurrent Programming (Python with threading)
• Concurrent programming allows multiple tasks to run at the same time. Here’s a
simple example using Python's threading library.
Explanation: Concurrent programming allows tasks to run in parallel. In this code:
• print_numbers prints numbers from 1 to 5.
• print_letters prints letters A to E.
By using threading. Thread, we create two threads (thread1 and thread2). start() begins
each thread, and join() waits for both threads to finish.
• Key Paradigm Concept: Threads allow tasks to overlap, demonstrating parallel
execution.
• Output: Interleaved numbers and letters, e.g., Number: 1, Letter: A, Number: 2,
etc., though the exact sequence can vary.
5. Logic Programming (Prolog-style Logic in Python)
• Python doesn’t natively support logic programming, but simple rule-based logic can
be emulated.
Explanation: In logic programming, the focus is on defining relationships. Here:
• We create a family dictionary to define parent-child relationships.
• The function is_parent (child, parent) checks if parent is the parent of child by
looking it up in the dictionary.
Key Paradigm Concept: Relationships are defined, and the code “asks” if a specific
relationship exists (i.e., is_parent ("john", "mary")).
• Output:
o True (John is Mary’s parent),
o True (Mary is Anna’s parent),
o False (Anna is not John’s parent).
6. Scripting Programming (Bash example shown in Python)
• Scripting languages are often used for automating tasks and manipulating text.

Explanation: Scripting is often used to automate tasks. Here, we:


• Create a new folder called "NewFolder" with os.mkdir.
• Open a file called greeting.txt in this folder, write "Hello, world!" to it, and close the
file automatically with with open.
Key Paradigm Concept: This example demonstrates a script’s ability to interact with the
file system to perform common tasks like folder and file creation.
• Output: Confirmation that the folder and file are created. You’d see Folder and file
created! in the output.

Grammar
Grammar in programming, is a set of rules that defines the structure of valid programs.
1. Purpose of Grammar in Programming
• Grammar is used to describe the structure of programming languages, which
allows the compiler (or interpreter) to transform code (a sequence of characters)
into a syntax tree.
• This syntax tree represents the logical structure of the code, showing the
relationships between elements, which is crucial for the compiler to translate the
code into machine code (for execution) or to type check (ensuring data types are
used correctly).
2. Backus-Naur Form (BNF)
• BNF is a notation system invented by John Backus and improved by Peter Naur for
describing programming language grammar.
• In BNF, a grammar is defined by four main components represented as (T, N, P, S):
o T (Tokens): The basic symbols or “vocabulary” of the language, like
keywords (e.g., while, for) and symbols (+, ().
o N (Nonterminals): These aren’t actual language elements but help define
the structure of the syntax tree. They are often enclosed in < >, like
<expression>.
o P (Production Rules): Rules that define how nonterminals and tokens
combine. These rules follow a format like <non-terminal> ::= <expression>,
where ::= is a separator, and | is used for multiple options.
o S (Start Symbol): A special non-terminal from which all grammatically valid
programs begin their structure.
3. Example Grammar for Arithmetic Expressions
The provided example grammar recognizes simple arithmetic expressions involving
addition and multiplication, as well as parentheses and variables (a, b, c):

This can also be expressed compactly:

In this example:
• <exp> represents an expression.
• It shows that an expression could be:
o Another expression added to an expression (<exp> + <exp>)
o An expression multiplied by another (<exp> * <exp>)
o An expression in parentheses
o Or a single value like "a", "b", or "c".
Example Expressions Valid in This Grammar
• a+b
• a*b+c
• (a + b) * (c + a)
• ((a * b) + c)
4. Types of Grammars and Chomsky’s Hierarchy
• Context-free grammars are the primary type used in programming languages since
they handle nested structures (like expressions within parentheses).
• Other grammar types in Chomsky’s hierarchy (developed by Noam Chomsky)
include:
o Regular grammars: Recognize simpler patterns, often used in lexical
analysis (the process of breaking down code into tokens).
o Unrestricted grammars: Very powerful and as flexible as Turing machines
(which can theoretically solve any problem given enough time).
In summary, grammars are the foundation of how compilers understand and process
programming languages, and they use context-free grammars to build syntax trees for
code interpretation.

Leftmost Derivation and Rightmost Derivation refer to two different approaches to


expanding a parse tree for a given string based on the grammar rules.
Example Grammar:
Consider the following grammar for arithmetic expressions:
Deriving the Expression: a + b * c

Leftmost Derivation Sequence:


Rightmost Derivation Sequence:

Different types of operators in C, C++, and Java programming languages


Operators are symbols that perform actions on variables or values, called operands.
Here’s an overview of the main types of operators and how they work:
1. Arithmetic Operators
• Purpose: Perform basic math operations like addition, subtraction, multiplication,
division, and modulus (remainder).
• Examples: +, -, *, /, %, ++, and --.
• Types:
o Unary Operators: Act on a single operand. Examples are ++ (increment) and
-- (decrement).
o Binary Operators: Require two operands, like + (add) and * (multiply).
2. Relational Operators
• Purpose: Compare two values. The result is either true or false.
• Examples: == (equal to), != (not equal to), >, <, >=, and <=.
• Usage: Used in conditions, such as if statements, to check whether one value is
larger, smaller, or equal to another.
3. Logical Operators
• Purpose: Combine multiple conditions, or reverse the result of a condition.
• Examples: && (logical AND), || (logical OR), and ! (logical NOT).
• Result: Returns a boolean value (true or false), useful for decision-making in
conditions.
4. Bitwise Operators
• Purpose: Perform operations on binary digits (bits) of the values.
• Examples: & (bitwise AND), | (bitwise OR), ^ (bitwise XOR), and ~ (bitwise NOT).
• Usage: Often used in low-level programming for faster processing, as it works
directly with bits rather than whole numbers.
5. Assignment Operators
• Purpose: Assign a value to a variable.
• Basic Assignment: =, where the value on the right is assigned to the variable on the
left.
• Combined Assignment Operators: Combine an arithmetic operation with
assignment.
o Examples:
▪ += Adds a value to a variable, then assigns the result to the variable
(e.g., a += 5 is the same as a = a + 5).
▪ -=: Subtracts a value from a variable, then assigns the result (e.g., a -=
2 is a = a - 2).
▪ *=: Multiplies a value by a variable, then assigns the result (e.g., a *= 3
is a = a * 3).
▪ /=: Divides a variable by a value, then assigns the result (e.g., a /= 2 is
a = a / 2).

Division and modulus are two arithmetic operations commonly used in


programming:
1. Division (/)
The division operator / divides one number (the dividend) by another (the divisor) and gives
the result as a quotient.
• Example:
In integer division (common in languages like C/C++ when both numbers are integers), it
returns only the whole number part of the result, discarding any remainder. So 10 / 3 gives
3 in integer division, as it rounds down.
• Floating-point Division: When at least one of the numbers is a floating-point
number (like 10.0 / 3), it gives a precise answer:

2. Modulus (%)
The modulus operator % returns the remainder when one number is divided by another.
• Example:

Here, 10 % 3 equals 1 because when 10 is divided by 3, the quotient is 3 with a remainder


of 1.
The modulus operator is often used when we need to check if a number is even or odd:
• An even number gives 0 when modulus 2 is applied (e.g., 8 % 2 == 0).
• An odd number gives 1 (e.g., 9 % 2 == 1).
Summary
• Division (/): Gives the quotient of a division.
• Modulus (%): Gives the remainder of a division.

A simple C++ program demonstrating different types of operators:


REVISION QUESTIONS

• Define grammar in the context of programming languages.


In programming languages, grammar is a set of rules that defines the correct syntax for
constructing valid statements or expressions. These rules specify how different language
components (like keywords, operators, and variables) should be arranged to form valid
code. Grammar ensures consistency and structure, allowing compilers and interpreters to
understand and process code correctly.

• What are terminals and nonterminals in a grammar?


Terminals are the actual symbols or tokens in the language, like keywords (if, while),
operators (+, *), and literals (5, "hello"). These appear directly in the code.
Nonterminals represent abstract language constructs, like <expression> or <statement>,
and are placeholders that can be expanded into sequences of terminals or other
nonterminals according to production rules. Nonterminals help define the structure of the
language.

• What is a production rule?


A production rule defines how a nonterminal can be expanded into other nonterminals or
terminals. It consists of a left-hand side (LHS) nonterminal, a separator (::=), and a right-
hand side (RHS) expression of terminals and nonterminals. For example, <expression> ::=
<term> | <expression> + <term> means that an <expression> can either be a <term> or the
sum of an <expression> and a <term>.

• Explain Backus-Naur Form (BNF) and its importance in defining programming


languages.
BNF (Backus-Naur Form) is a formal notation used to define the syntax of programming
languages. It consists of production rules with nonterminals and terminals to specify
grammar precisely and unambiguously. BNF is essential in compiler construction because
it provides a clear and structured way to define and parse the syntax of programming
languages.

• What is the purpose of the separator (::=) in production rules?


The separator ::= (meaning “is defined as”) divides the left-hand side (LHS) nonterminal
from the right-hand side (RHS) expression in production rules. This separation helps
clarify that the LHS nonterminal can be expanded into the structure defined on the RHS,
which is essential for accurately parsing and understanding the language syntax.

• How does the pipe symbol (|) function in grammar definitions?


The pipe symbol (|) in grammar definitions represents alternative options within a
production rule. For example, <statement> ::= <if-statement> | <loop-statement> means a
<statement> can be either an <if-statement> or a <loop-statement>. It simplifies grammar
definitions by listing multiple options for expanding a nonterminal in a single rule.

• What is a derivation tree (or parse tree), and how is it constructed?


A derivation tree, or parse tree, visually represents the structure of an expression based on
grammar rules. It is constructed by starting with the initial nonterminal and expanding it
according to production rules until all branches consist of terminals. The tree's structure
shows the hierarchical organization of language components, helping compilers verify
syntax and interpret code.
• Describe the concept of recursion in grammar rules with an example.
Recursion in grammar occurs when a production rule references itself, allowing it to define
repeating or nested structures. For instance, <expression> ::= <expression> + <term> |
<term> is recursive because <expression> is defined in terms of itself. Recursion is useful
for defining complex structures like arithmetic expressions or nested statements.

• Explain the difference between syntax and semantics in the context of


programming languages.
Syntax refers to the formal structure and rules that define how code should be written,
which is determined by grammar. Semantics refers to the meaning or behavior of the code
when executed. Syntax errors occur when code doesn’t follow grammar rules, while
semantic errors happen when code doesn’t perform as intended, even if syntactically
correct.

• What are context-free grammars, and why are they commonly used in
programming language design?
Context-free grammars (CFGs) are grammars where production rules have a single
nonterminal on the LHS, allowing rules to be applied independently of context. CFGs are
widely used in programming languages because they can describe many structures (like
nested loops and conditionals) effectively, making them suitable for parsing languages. An
example is <expression> ::= <expression> + <term> | <term>.

• What is a parse tree, and how does it represent the structure of a program?
A parse tree, also known as a derivation tree, is a tree structure that represents the
syntactic structure of a string according to a given grammar. In a parse tree, each internal
node corresponds to a nonterminal symbol, and each leaf node corresponds to a terminal
symbol from the grammar. The tree illustrates how a start symbol of a grammar can be
expanded into the terminals by applying production rules, representing how the program or
expression is structured syntactically.

• Given the grammar below, draw a parse tree for the expression a + b * c.
• Explain why parse trees are useful in compilers and interpreters.
Parse trees are essential in compilers and interpreters because they provide a hierarchical
structure that represents the order in which operations and constructs should be
evaluated. They help compilers understand how each part of the code relates to the overall
syntax of the language. This structure enables error checking, optimization, and code
generation, as it clearly shows the relationships between expressions, operations, and
statements.

• In the context of parse trees, what is the difference between a leaf node and an
internal node?
In a parse tree, a leaf node represents a terminal symbol, which is an actual character or
token in the language (such as a number, operator, or keyword). A nonterminal is typically
represented by an internal node, which is expanded into other nodes (either terminals or
nonterminals) according to the production rules. Internal nodes define the structure of the
language, while leaf nodes represent the smallest units of syntax.

You might also like