17 recursion 2
play

17. Recursion 2 Input: 3 + 5 * 20 Output: 103 Input: (3 + 5) * 20 - PowerPoint PPT Presentation

Motivation: Calculator Goal: we build a command line calculator Example Input: 3 + 5 Output: 8 Input: 3 / 5 Output: 0.6 17. Recursion 2 Input: 3 + 5 * 20 Output: 103 Input: (3 + 5) * 20 Output: 160 Input: -(3 + 5) + 20 Building a Calculator,


  1. Motivation: Calculator Goal: we build a command line calculator Example Input: 3 + 5 Output: 8 Input: 3 / 5 Output: 0.6 17. Recursion 2 Input: 3 + 5 * 20 Output: 103 Input: (3 + 5) * 20 Output: 160 Input: -(3 + 5) + 20 Building a Calculator, Formal Grammars, Extended Backus Naur Output: 12 Form (EBNF), Parsing Expressions binary Operators + , - , * , / and numbers floating point arithmetic precedences and associativities like in C++ parentheses unary operator - 492 493 Naive Attempt (without Parentheses) Analyzing the Problem double lval; Example std::cin >> lval; Input: char op; while (std::cin >> op && op != ’=’) { 13 + 4 ∗ (15 − 7 ∗ 3) = double rval; std::cin >> rval; Needs to be stored such that evaluation can be performed if (op == ’+’) lval += rval; Input 2 + 3 * 3 = else if (op == ’ ∗ ’) Result 15 lval ∗ = rval; else ... } std::cout << "Ergebnis " << lval << "\n"; 494 495

  2. Analyzing the Problem Formal Grammars Alphabet: finite set of symbols Strings: finite sequences of symbols 13 + 4 ∗ (15 − 7 ∗ 3) A formal grammar defines which strings are valid. “Understanding an expression requires lookahead to upcoming symbols! We will store symbols elegantly using recursion. To describe the formal grammar, we use: We need a new formal tool (that is independent of C++ ). Extended Backus Naur Form (EBNF) 496 497 Expressions -(3-(4-5))*(3+4*5)/6 What do we need in a grammar? Number , ( Expression ) Factor - Number, -( Expression ) Factor * Factor, Factor Term Factor / Factor , ... Term + Term, Term Expression Term - Term, ... 499

  3. The EBNF for Expressions The EBNF for Expressions A factor is A term is a number, factor, an expression in parentheses or factor * factor, factor / factor, non-terminal symbol a negated factor. factor * factor * factor, factor / factor * factor, ... ... factor = unsigned_number | "(" expression ")" term = factor { " ∗ " factor | "/" factor }. | " − " factor . terminal symbol optional repetition alternative 500 501 The EBNF for Expressions Parsing factor = unsigned_number Parsing: Check if a string is valid according to the EBNF . | "(" expression ")" Parser: A program for parsing. Useful: From the EBNF we can (nearly) automatically generate a | " − " factor . parser: Rules become functions term = factor { " ∗ " factor | "/" factor }. Alternatives and options become if –statements. Nonterminial symbols on the right hand side become function calls Optional repetitions become while –statements expression = term { "+" term |" − " term }. 502 503

  4. Rules Functions (Parser) Expression is read from an input stream. factor = unsigned_number | "(" expression ")" // POST: returns true if and only if in_stream = factor ... | " − " factor . // and in this case extracts factor from in_stream bool factor (std::istream& in_stream); term = factor { " ∗ " factor | "/" factor }. // POST: returns true if and only if in_stream = term ..., // and in this case extracts all factors from in_stream bool term (std::istream& in_stream); expression = term { "+" term |" − " term }. // POST: returns true if and only if in_stream = expression ..., // and in this case extracts all terms from in_stream bool expression (std::istream& in_stream); 504 505 Functions (Parser with Evaluation) One Character Lookahead... Expression is read from an input stream. . . . to find the right alternative. // POST: leading whitespace characters are extracted from in_stream, and the first non − whitespace character // // POST: extracts a factor from in_stream // is returned (0 if there is no such character) // and returns its value char lookahead (std::istream& in_stream) double factor (std::istream& in_stream); { if (in_stream.eof()) // eof: end of file (checks if stream is finished ) // POST: extracts a term from in_stream return 0; // and returns its value in_stream >> std::ws; // skip all whitespaces double term (std::istream& in_stream); if (in_stream.eof()) return 0; // end of stream // POST: extracts an expression from in_stream return in_stream.peek(); // next character in in_stream // and returns its value } double expression (std::istream& in_stream); 506 507

  5. Cherry-Picking Evaluating Factors double factor (std :: istream& in_stream) { . . . to extract the desired character. double value; // POST: if expected matches the next lookahead then consume it if (consume(in_stream, ’(’)) { // and return true; return false otherwise value = expression (in_stream); bool consume (std::istream& in_stream, char expected) consume(in_stream, ’)’); { } else if (consume(in_stream, ’ − ’)) { if (lookahead(in_stream) == expected){ value = − factor (in_stream); in_stream >> expected; // consume one character } else { return true; in_stream >> value; } } factor = "(" expression ")" return false ; return value; } | " − " factor } | unsigned_number . 508 509 Evaluating Terms Evaluating Expressions double term (std::istream& in_stream) double expression (std :: istream& in_stream) { { double value = factor (in_stream); double value = term(in_stream); while(true){ while(true){ if (consume(in_stream, ’ ∗ ’)) if (consume(in_stream, ’+’)) value ∗ = factor(in_stream); value += term (in_stream); else if (consume(in_stream, ’ − ’)) else if (consume(in_stream, ’/’)) value /= factor(in_stream) value − = term(in_stream) else else return value; return value; } } } } term = factor { " ∗ " factor | "/" factor }. expression = term { "+" term |" − " term }. 510 511

  6. Recursion! EBNF — and it works! EBNF ( calculator.cpp , Evaluation from left to right): Factor factor = unsigned_number | "(" expression ")" | " − " factor . Term term = factor { " ∗ " factor | "/" factor }. expression = term { "+" term |" − " term }. Expression std::stringstream input ("1 − 2 − 3"); std::cout << expression (input) << "\n"; // − 4 512 513 Calculating with Rational Numbers Rational numbers ( ◗ ) are of the form n d with n and d in ❩ C++ does not provide a built-in type for rational numbers 18. Structs Goal Rational Numbers, Struct Definition We build a C++ -type for rational numbers ourselves! 514 515

  7. Vision A First Struct Invariant: specifies valid How it could (will) look like value combinations (infor- // input struct rational { mal). std::cout << "Rational number r =? "; int n; member variable ( n umerator) rational r; int d; // INV: d != 0 std::cin >> r; }; std::cout << "Rational number s =? "; rational s; member variable ( d enominator) std::cin >> s; struct defines a new type // computation and output formal range of values: cartesian product of the value ranges of std::cout << "Sum is " << r + s << ".\n"; existing types real range of values: rational � int × int . 516 517 Accessing Member Variables A First Struct: Functionality A struct defines a new type , not a variable ! struct rational { int n; // new type rational int d; // INV: d != 0 struct rational { Meaning: every object of the new type is rep- }; int n; resented by two objects of type int the ob- int d; // INV: d != 0 jects are called n and d . rational add (rational a, rational b){ }; rational result; result.n = a.n ∗ b.d + a.d ∗ b.n; // POST: return value is the sum of a and b result.d = a.d ∗ b.d; rational add (const rational a, const rational b) return result; { } rational result; result.n = a.n * b.d + a.d * b.n; = a n · b d + a d · b n r n := a n + b n result.d = a.d * b.d; r d a d b d a d · b d member access to the int objects of a . return result; } 518 519

  8. Input Vision comes within Reach ... // Input r rational r; std::cout << "Rational number r:\n"; std::cout << " numerator =? "; // computation std::cin >> r.n; const rational t = add (r, s); std::cout << " denominator =? "; std::cin >> r.d; // output std::cout << "Sum is " << t.n << "/" << t.d << ".\n"; // Input s the same way rational s; ... 520 521 Struct Definitions Struct Defintions: Examples name of the new type (identifier) struct T { struct rational_vector_3 { T 1 name 1 ; names of the underlying names of the member rational x; T 2 name 2 ; types variables . . rational y; . . . . rational z; T n name n ; }; } ; underlying types can be fundamental or user defined Range of Values of T : T 1 × T 2 × ... × T n 522 523

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend