SNUOOPSLA Lab.
Chap6. Expressions and statements
© copyright 2001 SNU OOPSLA Lab.
SNUOOPSLA Lab.C++
Contents A Desk Calculator Operator Summary Statement Summary Comments and Indentation
SNUOOPSLA Lab.C++
1.Desk Calculator Main part of desk calculator
Parser : syntactic analysis Input function : input and lexical analysis Symbol table : permanent information Driver : initialization, output,errors
SNUOOPSLA Lab.C++
Grammarprogram :
ENDexpr_list
ENDexpr_list :
expression PRINT
expression PRINT expr_listexpression:
term+expression
term-expression
termc
1.1 The Parser
term :
primary/term
primary*termprimary
primary:
NUMBERNAME
NAME=expression
-primary
(expression)
Expr()
Term()
Prim()
Call hierarchy
//handle primariesdouble prim(bool get){ switch(curr_tok) {
case NUMBER: ...case NAME: …case MINUS: …case LP: …default:…}
}
Call hierarchy//add and subtractdouble expr(bool get){ … for ( ; ; )
switch(curr_tok) {case PLUS: left+=term(true);...case MINUS : left-=term(true);
…default : return left;}
}// multiply and dividedouble term(bool get){ ... for ( ; ; )
switch(curr_tok) {case MUL: left*=prim(true); ...case DIV : if(double d=prim(true)) {
left/=d;…} ...default : return left;}
}
Whether the function needs to call get_token() to get the next token
SNUOOPSLA Lab.C++
1.1 The Parser The symbol table is a map
map<string, double> table;
Table is indexed by a string Resulting value
Example>>
User input : radius = 6378.388
Calculator : double& v = table[“radius”];
v=6378.388
1.2 The Input Function Read characters and compose higher-level tokens from them
Token_value get_token(){ char ch=0;
cin>>ch;
switch(ch){case 0; return curr_tok=END;
//assign and returncase ‘;’: case ‘*’: case ‘/’: case ‘+’: …
return curr_tok=Token_value(ch);
case ‘0’:case ‘1’: case ‘2’: case ‘3’: …cin.putback(ch);cin>>number_value;return curr_tok=NUMBER;
default : if (isalpha(ch)){ cin.putback(ch); cin>>string_value;
return curr_tok=NAME; }...}
‘;’,parentheses and the operators handling
Number handling
Name handlingProblem:must terminate a name by a space
Problem: expression terminator ‘;’ needed
version1 of get_token()
SNUOOPSLA Lab.C++
1.3 Low-level Input
Token_value get_token(){ char ch;
do { //skip whitespace except ‘\n’if (!cin.get(ch)) return curr_tok=END;
} while (ch!=‘\n’&&isspace(ch));switch(ch) {case ‘;’:case ‘\n’: return curr_tok=PRINT;
Default: if(isalpha(ch)){ string_value=ch; while(cin.get(ch)&&isalnum(ch))
string_value.push_back(ch);cin.putback(ch);return curr_tok=NAME;
} error(“bad token”); return curr_tok=PRINT;Make a newline equivalent
to the semicolon
version2 of get_token()
SNUOOPSLA Lab.C++
1.5 The Driver A driver is required to start things
int main(){...
While(cin) {
//…if (curr_tok!= PRINT)
cout<< expr() << ‘\n’ ;}...
}
SNUOOPSLA Lab.C++
1.7 Command-Line Arguments The expression presented as a command-line
argument could avoid a few keystrokesex>> dc 150/1.1934
2
0
“dc” “150/1.1934”
Argc:
Argv:
SNUOOPSLA Lab.C++
1.7 Command-Line Arguments How to use a command-line argument with
minimal reprogramming=>Solution : use a global pointer input to point
to the input stream
SNUOOPSLA Lab.C++
1.7 Command-Line Arguments
Istream* input; //pointer to input streamint main(int argc, char* argv[]){ switch(argc) {
case 1: input= &cin; break;
case 2: input =new istringstream(argv[1]); break;
default:error(“too many arguments”); return 1;
}…}
new version of main()
Read from standard input
Read argument string
SNUOOPSLA Lab.C++
2.1 Results The result types of arithmetic operators are determine
d by a set of rules known as “ the usual arithmetic conversions”
The result of an operator with lvalue operand =>lvalue
void f(int x, int y){ int j=x=y;// the value of x=y is the value of x after the assignment
int* p =&++x; //p points to xint* q=&(x++); //error: x++ is not an lvalueint *pp=&(x>y;x,y); //address of the int with the larger value
}
SNUOOPSLA Lab.C++
2.2 Evaluation Order The order of evaluation of subexpressions within a ex
pression is undefined ,(comma),&&(logical and),||(logical or) guarantee that t
heir left-hand operand is evaluated before their right-hand operand
Parentheses can be used to force grouping
SNUOOPSLA Lab.C++
2.3 Operator Precedence Precedence levels and associativity rules are chosen t
o reflect the most common usage If you start feeling the need for parentheses, you mig
ht consider breaking up the expression by using an extra variable
SNUOOPSLA Lab.C++
2.3 Operator Precedence Examples>>
if (I<=0||max<I) = if ((I<=0)||(max<I)) if (I&mask==0) = if(I&(mask==0)) if(0<=x<=99) = if ((0<=x)<=99) if (a = 7)
SNUOOPSLA Lab.C++
2.4 Bitwise Logical Operators &,|,^,~,>>,<< A typical use of these is to implement the notion of a
small set(a bit vector) Example
enum ios_base::iostate{ goodbit=0,eofbit=01,failbit=010,badbit=0100
};state=goodbit;if (state&(badbit|failbit)) //stream no goodstate|= eofbit;int diff= cin.rdstate()^cout.rdstate();
SNUOOPSLA Lab.C++
2.5 Increment and Decrement ++,-- as both prefix and postfix operators Example >> copy a zero-terminated string
int length!=strlen(1);for (int I=0;I<=length;I++) p[I]=q[I];
while (*q!=0) {*p=*q;p++; q++;
}*p=0;
while(*q!=0) {*p++=*q++;
}*p=0;
while((*p++=*q++)!=0) { }
while (*p++=*q++);
version1
version2
version3
version4
version5
Wasteful :read the string twice
*p++=*q++equal *q
needn’t the empty block and “!=0” is redundant
SNUOOPSLA Lab.C++
2.6 Free Store New operator : creating an object on the free
store independent of the scope Delete operator : destroy the object
SNUOOPSLA Lab.C++
2.6 Free Store How we might write a compiler in the style used for the de
sk calculatorstruct Enode{
Token_value oper;Enode* left;Enode* right; …
};
Enode* expr(bool get){ Enode*left=term(get);
for( ; ; )switch(curr_tok){case PLUS:case MINUS:{Enode* n= new Enode;…}
default: return left;}
void generate(Enode* n){ switch(n->oper){
case PLUS:…delete n;
//delete an Enode// from the free store}
}
SNUOOPSLA Lab.C++
2.6.1 Arrays Arrays of objects can also be created using new
char* s = new char[strlen(p)+1];delete[] p;
A vector is a proper object and can be allocated and deallocated using plain new and delete
vector<int>* p= new vector<int>(n);delete p;
SNUOOPSLA Lab.C++
2.6.2 Memory Exhaustion new,delete,new[],delete[]
void* operator new(size_t);void operator delete(void*)void* operator new[](size_t);void operator delete[](void*);
What happens when new can find no store to allocate=> By default, the allocator throws a bad_alloc exception
try { for( ; ; ) new char[10000];}catch(bad_alloc) { cerr<<“Memory exhausted!\n”;}
We can specify what new should do upon memory exhaustion
void out_of_store(){ cerr<<…}int main() { set_new_handler(out_of_store); …}
//make out_of_store the new_handler
SNUOOPSLA Lab.C++
2.7 Explicit Type Conversion “raw memory” holds or will hold objects of a type not k
nown to the compiler
int* p= static_cast<int*>(malloc((100));//new allocation used as intIO_device* dl= reinterpret_cast<IO_device*>(0Xff00);//device at 0Xff00
The correctness of the conversions are completely in the hands of the programmer
SNUOOPSLA Lab.C++
2.7 Explicit Type Conversion static_cast
convert between related types reinterpret_cast
convert between unrelated types dynamic_cast
a form of run-time checked conversion const_cast
a cast for removing const qualifiers
SNUOOPSLA Lab.C++
2.8 Constructors The construction of a value of type T from a value e => T
(e) : function-style cast
complex z= complex (d); //make a complex from d
The constructor notation t() is used to express the default value of type T
int j=int (); //default int value The value of an explicit use of the constructor for a built-
in type is 0 converted to that type
SNUOOPSLA Lab.C++
3. Statement SummaryStatement:declaration {statement-list }try {statement-list } handler-listexpression ;
if (condition) statementif (condition) statement else statementswitch (condition) statement
while (condition) statementdo statement while(expression);for( for-init-statement condition ; expression) statement
case constant-expression : statementdefault : statementbreak;continue;
return expression ;
goto identifier;identifier : statement
statement-list: statement statement-listcondition: expression
type-specifier declaration=expressionhandler-list:catch(exception-declaration) {
statement-list} handler-list handler-list
SNUOOPSLA Lab.C++
3.1 Declarations as Statements
The reason for allowing declarations wherever a statement can be used
=> to enable the programmer to minimize uninitialized variables and to allow better locality in code
Postponing the definition of a variable until a suitable initializer is available
=> better performance
String s; /*…*/ s=“The best is the enemy of the good.”;
can easily be much slower thanString s=“Voltaire”;
SNUOOPSLA Lab.C++
3.2 Selection Statements If statement switch-statement
Switch(val) {case 1:
f();break;
case 2:g();break;
default:h();break;
}
if (val==1) f();
else if(val==2)g();
elseh();
SNUOOPSLA Lab.C++
3.2.1 Declarations in Conditions Introduce the variable into the smallest scope Delay the definition of a local variable until
one can give it an initial value
If (double d= prim(true)) {
left/=d;
break;
}
Double d;d2=d;if(d=prim(true)){
left/=d;break;
}d=2.0; //two unrelated uses of d
SNUOOPSLA Lab.C++
3.3 Iteration Statement For-statement While-statement Do-statement
The initializer part of a for-statement is in scope until the end of the for-statement
for( int I=0; I<max;I++) v[I]=I*I;
SNUOOPSLA Lab.C++
3.4 Goto When it is useful
C++ code is generated by a program in the rare cases in which optimal efficiency is essential
For (i=0; i<n; i++)
for(j=0; j<m; m++) if (nm[i][j]==a) goto found;
/*...*/
found://...
SNUOOPSLA Lab.C++
4. Comments and Indentation Make the task of reading and understanding a
program much more pleasant
Top Related