CSCE 121: Introduction to Program Design and Concepts Dr. J

Slides:



Advertisements
Similar presentations
Chapter 6 Writing a Program
Advertisements

CSCE 121: Introduction to Program Design and Concepts Dr. J. Michael Moore Spring 2015 Set 7: Errors 1 Based on slides created by Bjarne Stroustrup.
CSCE 121: Introduction to Program Design and Concepts Dr. J. Michael Moore Spring 2015 Set 5: Functions 1 Based on slides created by Bjarne Stroustrup.
Chapter 7 Completing a Program John Keyser’s Modification of Slides by Bjarne Stroustrup
CS 106 Introduction to Computer Science I 11 / 09 / 2007 Instructor: Michael Eckmann.
True or false A variable of type char can hold the value 301. ( F )
Computer Science 1620 Loops.
Computer Science 1620 Variables and Memory. Review Examples: write a program that calculates and displays the average of the numbers 45, 69, and 106.
Unit 181 Recursion Definition Recursive Methods Example 1 How does Recursion work? Example 2 Problems with Recursion Infinite Recursion Exercises.
 Monday, 9/30/02, Slide #1 CS106 Introduction to CS1 Monday, 9/30/02  QUESTIONS (on HW02, etc.)??  Today: Libraries, program design  More on Functions!
Chapter 5: Loops and Files.
CS 106 Introduction to Computer Science I 03 / 28 / 2008 Instructor: Michael Eckmann.
CS 106 Introduction to Computer Science I 03 / 30 / 2007 Instructor: Michael Eckmann.
CHAPTER 10 Recursion. 2 Recursive Thinking Recursion is a programming technique in which a method can call itself to solve a problem A recursive definition.
Grammars and Parsing. Sentence  Noun Verb Noun Noun  boys Noun  girls Noun  dogs Verb  like Verb  see Grammars Grammar: set of rules for generating.
Introduction to Python
Outlines Chapter 3 –Chapter 3 – Loops & Revision –Loops while do … while – revision 1.
A Computer Science Tapestry 1 Recursion (Tapestry 10.1, 10.3) l Recursion is an indispensable technique in a programming language ä Allows many complex.
CHAPTER 02 Recursion Compiled by: Dr. Mohammad Omar Alhawarat.
Functions and an Introduction to Recursion.  Recursive function ◦ A function that calls itself, either directly, or indirectly (through another function)
CSCE 121: Introduction to Program Design and Concepts, Honors Dr. J. Michael Moore Spring 2015 Set 3: Objects, Types, and Values 1 Based on slides.
COIT29222 Structured Programming Slide 1 COIT29222-Structured Programming Lecture Week 06  Reading: Study Guide Book 2, Modules 9 & 10 Textbook (4 th.
Program A computer program (also software, or just a program) is a sequence of instructions written in a sequence to perform a specified task with a computer.
1 Chapter 13 Recursion. 2 Chapter 13 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing Recursive.
Recursion Textbook chapter Recursive Function Call a recursive call is a function call in which the called function is the same as the one making.
Chapter 6 Writing a Program John Keyser’s Modification of Slides by Bjarne Stroustrup
224 3/30/98 CSE 143 Recursion [Sections 6.1, ]
Lesson 3 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
File Input and Output in C++. Keyboard and Screen I/O #include cin (of type istream) cout (of type ostream) Keyboard Screen executing program input data.
Java Programming: From Problem Analysis to Program Design, 4e Chapter 2 Basic Elements of Java.
Fundamental Programming: Fundamental Programming Introduction to C++
CPS120: Introduction to Computer Science Decision Making in Programs.
CPS120: Introduction to Computer Science Functions.
Lecture 4 Looping. Building on the foundation Now that we know a little about  cout  cin  math operators  boolean operators  making decisions using.
CPS120: Introduction to Computer Science Lecture 14 Functions.
Data Structures R e c u r s i o n. Recursive Thinking Recursion is a problem-solving approach that can be used to generate simple solutions to certain.
Looping and Counting Lecture 3 Hartmut Kaiser
Slides adapted from: Bjarne Stroustrup, Programming – Principles and Practice using C++ Chapter 6 Writing a Program Hartmut Kaiser
CSCE 121: Introduction to Program Design and Concepts Dr. J. Michael Moore Spring 2015 Set 4: Computation 1 Based on slides created by Bjarne Stroustrup.
1 Using Yacc. 2 Introduction Grammar –CFG –Recursive Rules Shift/Reduce Parsing –See Figure 3-2. –LALR(1) –What Yacc Cannot Parse It cannot deal with.
© 2011 Pearson Education, publishing as Addison-Wesley Chapter 8: Recursion Presentation slides for Java Software Solutions for AP* Computer Science 3rd.
1 Recursion Recursion is a powerful programming technique that provides elegant solutions to certain problems. Chapter 11 focuses on explaining the underlying.
GE 211 Dr. Ahmed Telba. // compound assignment operators #include using namespace std; int main () { a =5 int a, b=3; a = b; a+=2; // equivalent to a=a+2.
Slides adapted from: Bjarne Stroustrup, Programming – Principles and Practice using C++ Chapter 7 Completing a Program Hartmut Kaiser
Introduction to Python Dr. José M. Reyes Álamo. 2 Three Rules of Programming Rule 1: Think before you program Rule 2: A program is a human-readable set.
COIT29222 Structured Programming 1 COIT29222-Structured Programming Lecture Week 02  Reading: Textbook(4 th Ed.), Chapter 2 Textbook (6 th Ed.), Chapters.
Loops and Files. 5.1 The Increment and Decrement Operators.
CSC 143A 1 CSC 143 Introduction to C++ [Appendix A]
Fundamental Programming Fundamental Programming More on Repetition.
C++ Programming Lecture 14 Arrays – Part I The Hashemite University Computer Engineering Department (Adapted from the textbook slides)
Sudeshna Sarkar, IIT Kharagpur 1 Programming and Data Structure Sudeshna Sarkar Lecture 3.
Chapter 7 Continued Arrays & Strings. Arrays of Structures Arrays can contain structures as well as simple data types. Let’s look at an example of this,
1 Recursion Recursive function: a function that calls itself (directly or indirectly). Recursion is often a good alternative to iteration (loops). Its.
CMSC 104, Section 301, Fall Lecture 18, 11/11/02 Functions, Part 1 of 3 Topics Using Predefined Functions Programmer-Defined Functions Using Input.
Chapter 6 Writing a Program Bjarne Stroustrup
Fundamental Programming Fundamental Programming Data Processing and Expressions.
Functions and Libraries. The idea of a function Functions in programming A function is a block of code that has been given a name. To invoke that code.
REPETITION CONTROL STRUCTURE
Chapter 1.2 Introduction to C++ Programming
The Selection Structure
Recursive Thinking Chapter 9 introduces the technique of recursive programming. As you have seen, recursive programming involves spotting smaller occurrences.
Recursive Thinking Chapter 9 introduces the technique of recursive programming. As you have seen, recursive programming involves spotting smaller occurrences.
Introduction to C++ Programming
Chapter 7 Completing a Program
Chapter 7 Completing a Program
Chapter 7 Completing a Program
Presentation transcript:

CSCE 121:509-512 Introduction to Program Design and Concepts Dr. J CSCE 121:509-512 Introduction to Program Design and Concepts Dr. J. Michael Moore Spring 2015 Set 9: Calculator Program Based on slides created by Bjarne Stroustrup and Jennifer Welch

Purpose of Chapters 6 and 7 Give an example of how to write a program to solve a non-trivial problem Analysis: refine understanding of the problem Design: create overall structure of program Implementation: write code, debug, test Repeat!

General Strategy What is the problem to be solved? Is the statement clear? Is it doable? Break the problem into manageable parts Consider tools, libraries that can help Build a small, limited version solving a key part of the problem May have to try multiple times Build full-scale solution Ideally rely on prototype

Problem: A Simple Calculator User enters an arithmetic expression at the keyboard Program evaluates the expression and prints result to the screen Repeat until user wants to quit

Give it a Try ?

Don’t Reinvent the Wheel! Computers have been evaluating expressions for over 50 years There has to be a solution already Do some background research to figure out how to approach this problem Describe the problem with a grammar Write a parser

Grammar Calculator program needs to know if the input string of characters is a properly formatted arithmetic expression (3+4)/7 is good 3+4)/7 is bad A grammar is a collection of “rules” that specify a set of strings that are properly formatted (according to the rules)

Rules of a Grammar Each rule has the form (LHS)  (RHS) To apply the rules: Start with a special LHS (the “start symbol”) Continually do replacements according to the rules until you can’t do any more End result is a properly formatted string (according to the given rules) RHS is a mix of “terminals” and “non-terminals” Terminals are characters that appear in the final result Nonterminals can be replaced; they appear in LHS

An Example Grammar Design a grammar that will generate all (and only) strings of parentheses that are “balanced” S  ( S ) // S is start symbol, ( and ) are terminals S  S S S  empty string // this is how to stop

Another Example Grammar Small Java-like fragment (| means or) Block  { StmtList } | { } // { and } are terminals StmtList  Stmt | StmtList Stmt Stmt  Block | while (Cond) Stmt | // while, (, ) are terminals AssmtStmt | return | // return is a terminal Cond  x == y // x, ==, and y are terminals AssmtStmt  z := a + b // z, :=, a, + and b are terminals

Parse Tree Use grammar on previous slide to draw a parse tree for { while (x == y) z := a + b return }

Applications of Grammars Describe programming language Crucial part of compiler Describe natural languages Diagramming sentences Expert systems: programs that perform tasks with a lot of domain knowledge (e.g., medicine) Domain knowledge can be modeled as a set of rules Logic programming: special kind of programming language (e.g., Prolog) supports this way of writing programs. Program reasons backwards from a goal by chaining rules together until getting to the initial assumptions Even describe music, dance, structure of RNA, 2-D graphics!

A Grammar for Arithmetic Expressions Expression  Term | Expression + Term | Expression – Term Term  Primary | Term * Primary Term / Primary Primary  Number | ( Expression ) Number  floating-point literal (rely on C++ for this) Terminals are +, 1, *, /, (, ), and the characters that make up floating-point literals (we’re not going into details of the grammar for them; instead, we’ll rely on the built-in capabilities of C++)

Parse Tree Examples Draw parse trees for the following expressions using the grammar on previous slide: 2 2+3 2+3*7 (2+3)*7

How Does Having a Grammar Help? We will write a “recursive descent parser”, based on this grammar to Identify if input is properly formatted and If so, evaluate the expression Take a short detour about recursion…

Recursion Grammars are recursive structures Definition in terms of itself To avoid never terminating, must have stopping cases A natural way to compute recursive structures is to use recursion Function that calls itself either directly or indirectly

Recursion in Programming Advantage: can simplify thinking about a problem and help develop an elegant solution Especially if the problem is already framed in a recursive style Disadvantage: straightforward implementations can be inefficient Closely related to the notion of proof by induction in mathematics

Recursive Definition of Factorial Compute factorial of positive integer n, denoted n! Mathematical definition #1 (nonrecursive): n! = 1*2*3*…*(n-1)*n Mathematical definition #2 (recursive): if n = 1, then n! = 1 if n > 1, then n! = n*(n-1)! Rule 1 is the stopping case Rule 2 defines factorial in terms of factorial, but OK because we are getting closer to stopping case

Recursive Factorial Program Follow the recursive definition int fact(int n) { if (n==1) return 1; int rest = fact(n-1); // calling self int result = n*rest; return result; } Each call to fact does a little bit of work itself (checking for stopping case and one multiplication) and passes on the bulk of the work to the next recursive call

Memory Management with Recursive Programs During execution, each call to fact gets a separate stack frame, with separate copies of the formal parameter n and local variables rest and result Overhead of recursion: Space: extra copies of variables in stack frames Time: for function calls

Recursion and Iteration Both involve repetition: Iteration has explicit repetition, in the loop Recursive has implicit repetition, in the sequence of function calls Iteration has less overhead Can convert recursive solution (which may be easier to find in some cases) to iterative solution

Rules for Recursive Functions Always have at least one stopping case (also called base case) Each recursive call must get you closer to a stopping case

Direct vs. Indirect Recursion Direct recursion is when a function calls itself As in factorial example Indirect recursion (or mutual recursion) is when function f1 calls function f2, …, which calls function f1 Path can be of any length We’ll see an example of this in the upcoming calculator program

Back to Calculator Problem: Grammar Rules Use the grammar as a guide in developing a set of mutually recursive functions Expression  Term | Expression + Term | Expression – Term Term  Primary | Term * Primary Term / Primary Primary  Number | ( Expression ) Number  floating-point literal (rely on C++ for this) expression(): deals with + and -, calls term term(): deals with * and /, calls primary primary(): deals with ( and ), calls expression All three return value All three call something to get terminals… Have a function for each nonterminal

Tokens Need some code to provide the terminals of the grammar from the user’s input Call each terminal a Token: +,-,*,/, (, ), floating-point literal For now, assume we have a class Token and each Token object t has t.kind and t.value (numeric value for floating-point literal) For now, assume we have a function get() that reads characters from cin and composes Tokens

Token struct struct Token { char kind; double value; Token(char ch) : kind(ch), value(0) {} Token(char ch, double val) : kind(ch), value(val) {} }; Token get_token() { /* collect characters from cin and turn into a Token */ }

Expression: First Attempt Expression  Term | Expression + Term | Expression – Term Expression: First Attempt double expression() { /* try to get a Term, if that doesn’t work (?) try to get an Expression by recursively calling expression, then try to get + or -, then try to get a Term */ } How can we tell if getting a Term failed? Even worse, we are setting ourselves up for an infinite loop: recursive call that does not get us any closer to the stopping case (end of input string)

Expression: Second Attempt Expression  Term | Expression + Term | Expression – Term Expression: Second Attempt Problem with this grammar is that it has “left recursion”: Calls itself without having consumed any of the input string Get around the problem by converting from recursion to iteration “Unrolling” the recursion shows that we can rephrase the rule as Expression  Term +|- Term +|- Term +|- … Term Swapping the order of Term and Expression (i.e., Expression  Term + Expression) causes a different problem: order of operations will no longer be left to right, but right to left.

Expression Function Expression  Term +|- Term +|- … Term double expression() { double val = term(); // get first term while (true) { Token t = get_token(); // get next token switch (t.kind) { case ‘+’: val += term(); break; // add case ‘-’: val -= term(); break; // subtract default: return val; } // pattern changes }

Term Same problem with left recursion here. Unroll to get Term  Primary | Term * Primary | Term / Primary Term Same problem with left recursion here. Unroll to get Term  Primary *|/ Primary *|/ … Primary

Divide by 0? Term Function Term  Primary *|/ Primary *|/ … Primary double term() { double val = primary(); while (true) { Token t = get_token(); switch (t.kind) { case ‘*’: val *= primary(); break; case ‘/’: val /= primary(); break; default: return val; } } Divide by 0?

Term Function Version 2 double term() { double val = primary(); while (true) { Token t = get_token(); switch (t.kind) { case ‘*’: val *= primary(); break; case ‘/’: { // scope for variable d double d = primary(); if (d==0) error(“divide by zero”); val /= d; break;} default: return val; } }

Primary Function Primary  Number | ( Expression ) double primary() { Token t = get_token(); switch (t.kind) { case ‘(‘: { // scope for d and t double d = expression(); t = get_token(); if (t.kind != ‘)’ error(“’)’ expected”); return d; } case ‘8’: return t.value; // ’8’ means number default: error(“primary expected”); }

How to Start? main calls expression, since Expression is the start symbol of the grammar. int main() try { cout << expression() << endl; } catch(runtime_error& e) { cerr << e.what() << endl; return 1; catch(...) { cerr << “exception\n”; return 2;

Program Organization main() expression() term() primary() get_token()

Try it Out See calc1.cpp Doesn’t work Let’s look more carefully at expression()

Expression Function Revisited Expression  Term +|- Term +|- … Term double expression() { double val = term(); // get first term while (true) { Token t = get_token(); // get next token switch (t.kind) { case ‘+’: val += term(); break; // add case ‘-’: val -= term(); break; // subtract default: return val; } // pattern changes } If token t is not + or – , we just throw it away. This can’t be a good idea.

Putting Back a Token We need a way to “put back” a token that we are not yet ready to deal with Issue arises in expression() term() We need a concept of a “token stream” Higher-level abstraction of the input stream, where characters are grouped into tokens Ability to put back a token (analogous to cin)

Token_stream class Token_stream { bool full; // is there a Token in the buffer? Token buffer; // keep put-back Token here public: Token_stream() : full(false), buffer(0) {} Token get(); // next slide void putback(Token t) { if (full) error(“putback into full buffer”); buffer = t; full = true; } };

Getting a Token Token Token_stream::get() { if (full) { full = false; return buffer;} char ch; cin >> ch; switch(ch) { case '(': case ')': case '+': case '-': case '*': case '/': return Token(ch); case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); // put digit back into the input stream double val; cin >> val; // let C++ do work to get floating pt num return Token('8',val); } default: error("Bad token");

Try it Out See calc2.cpp Notices bad syntax Doesn’t print out answer unless extra character is typed (in certain cases)

Fixes and Additions Let user repeatedly enter expressions Have user enter special character ‘;’ to make program print out value See calc3.cpp int main() try { double val = 0; while (true) { Token t = ts.get(); if (t.kind == ';') // modify Token::get() also cout << val << endl; else ts.putback(t); val = expression(); } ...

Acknowledgments Photo on slide 1: by John Koetsier, licensed under CC BY-NC-ND 2.0 Material on grammars from Automata, Computability, and Complexity: Theory and Applications, by Elaine Rich Slides are based on those for the textbook: http://www.stroustrup.com/Programming/6_writing.ppt http://www.stroustrup.com/Programming/7_completing.ppt