---------------
r = 2.5
area = pi*r*r
---------------
2.5
19.635
---------------
program:
    end              // end oznacza koniec danych wejciowych
    expr_list end

expr_list:
    expression print // print jest znakiem nowego wiersza lub rednikiem
    expression print expr_list

expression:
    expression + term
    expression - term
    term

term:
    term / primary
    term*primary
    primary

primar y:
    number           // number jest literaem zmiennoprzecinkowym
    name             // name jest identyfikatorem
    name = expression
    - primar y
     ( expression )
---------------
enum class Kind : char {
    name, number, end,
    plus='+', minus='-', mul='*', div='/', print=';', assign='=', lp='(', rp=')'
};

struct Token {
    Kind kind;
    string string_value;
    double number_value;
};
---------------
class Token_stream {
public:
    Token get();            // wczytuje i zwraca nastpny token
    const Token& current(); // ostatnio wczytany token
    //...
};
---------------
double expr(bool get) // dodaje i odejmuje
{
    double left = term(get);

    for (;;) { // wieczno
        switch (ts.current().kind) {
        case Kind::plus:
            left += term(true);
            break;
        case Kind::minus:
            left -= term(true);
            break;
        default:
            return left;
        }
    }
}
---------------
+    -    *    /    %    &    |    ^    <<    >>
---------------
=    +=    -=    *=    /=    %=    &=    |=    ^=    <<=    >>=
---------------
double term(bool get) // mnoy i dzieli
{
    double left = prim(get);

    for (;;) {
        switch (ts.current().kind) {
        case Kind::mul:
            left*= prim(true);
            break;
        case Kind::div:
            if (auto d = prim(true)) {
                left /= d;
                break;
            }
            return error("Dzielenie przez 0");
        default:
            return left;
        }
    }
}
---------------
double prim(bool get)  // obsuguje wyraenia pierwotne
{
    if (get) ts.get(); // wczytuje nastpny token

    switch (ts.current().kind) {
    case Kind::number: // staa zmiennoprzecinkowa
    { double v = ts.current().number_value;
      ts.g et();
      return v;
    }
    case Kind::name:
    { double& v = table[ts.current().string_value];      // znajduje odpowiednik
      if (ts.get().kind == Kind::assign) v = expr(true); // znaleziono operator =: przypisanie
      return v;
    }
    case Kind::minus: // jednoargumentowy minus
        return -prim(true);
    case Kind::lp:
    { auto e = expr(true);
      if (ts.current().kind != Kind::rp) return error("Oczekiwano ')'");
      ts.get();       // zjada ')'
      return e;
    }
    default:
        return error("Oczekiwano wyraenia pierwotnego");
    }
}
---------------
map<string,double> table;
---------------
radius = 6378.388;
---------------
double& v = table["radius"];
// ... expr() oblicza warto do przypisania...
v = 6378.388;
---------------
double expr(bool);
---------------
class Token_stream {
public:
    Token_stream(istream& s) : ip{&s}, owns{false} { }
    Token_stream(istream*p) : ip{p}, owns{true} { }

    ~Token_stream() { close(); }

    Token get();      // wczytuje token i go zwraca
    Token& current(); // ostatnio wczytany token

    void set_input(istream& s) { close(); ip = &s; owns=false; }
    void set_input(istream*p) { close(); ip = p; owns = true; }

private:
    void close() { if (owns) delete ip; }

    istream*ip;            // wskanik do strumienia wejciowego
    bool owns;             // czy Token_stream jest wacicielem strumienia istream?
    Token ct {Kind::end} ; // biecy token
};
---------------
Token Token_stream::get()
{
    char ch = 0;
    *ip>>ch;

    switch (ch) {
    case 0:
        return ct={Kind::end}; // przypisanie i zwrot
---------------
ct.kind = Kind::end; // przypisanie
return ct;           // zwrot
---------------
case ';': // koniec wyraenia; drukowanie
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
    return ct={static_cast<Kind>(ch)};
---------------
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': 
(case '8': case '9': case '.':
ip->putback(ch);        // wstawia pierwsz cyfr (albo .) z powrotem do strumienia wejciowego
*ip >> ct.number_value; // wczytuje liczb do ct
ct.kind=Kind::number;
return ct;
---------------
default: // name, name = lub bd
    if (isalpha(ch)) {
        ip->putback(ch);      // umieszcza pierwszy znak z powrotem w strumieniu wejciowym
        *ip>>ct.string_value; // wczytuje acuch do ct
        ct.kind=Kind::name;
        return ct;
}
---------------
error("Niepoprawny token");
return ct={Kind::print};
---------------
Token Token_stream::g et()
{
    char ch = 0;
    *ip>>ch;

    switch (ch) {
    case 0:
        return ct={Kind::end}; // przypisanie i zwrot
    case ';': // koniec wyraenia; drukuje
    case '*':
    case '/':
    case '+':
    case '-':
    case '(':
    case ')':
    case '=':
        return ct=={static_cast<Kind>(ch)};

    case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': 
    (case '8': case '9': case '.':
        ip->putback(ch);          // wstawia pierwsz cyfr (albo .) z powrotem do strumienia wejciowego
        *ip >> ct.number_value;   // wczytuje liczb do ct
        ct.kind=Kind::number;
        return ct;
    default: // name, name = lub bd
        if (isalpha(ch)) {
            ip->putback(ch);      // umieszcza pierwszy znak z powrotem w strumieniu wejciowym
            *ip>>ct.string_value; // wczytuje acuch do ct
            ct.kind=Kind::name;
            return ct;
        }

        error("Niepoprawny token");
        return ct={Kind::print};
    }
}
---------------
Token Token_stream::get()
{
    char ch;

    do { // pomija biae znaki oprcz '\n'
        if (!ip->get(ch)) return ct={Kind::end};
    } while (ch!='\n' && isspace(ch));

    switch (ch) {
    case ';':
    case '\n':
        return ct={Kind::print};
---------------
default: // NAME, NAME= lub bd
    if (isalpha(ch)) {
        string_value = ch;
        while (ip->get(ch) && isalnum(ch))
            string_value += ch; // docza ch na kocu string_value
        ip->putback(ch);
        return ct={Kind::name};
    }
---------------
int no_of_errors;

double error(const string& s)
{
    no_of_errors++;
    cerr << "Bd: " << s << '\n';
    return 1;
}
---------------
Token_stream ts {cin}; // uycie danych z cin

void calculate()
{
    for (;;) {
        ts.g et();
        if (ts.current().kind == Kind::end) break;
        if (ts.current().kind == Kind::print) continue;
        cout << expr(false) << '\n';
    }
}

int main()
{
    table["pi"] = 3.1415926535897932385; // standardowo zdefiniowane nazwy
    table["e"] = 2.7182818284590452354;

    calculate();

    return no_of_errors;
}
---------------
cout << expr(false) << '\n';
---------------
#include<iostream> // wejcie i wyjcie
#include<string>   // acuchy
#include<map>      // mapa
#include<cctype>   // isalpha() itp.
---------------
using namespace std;
---------------
dc 150/1.1934
---------------
Token_stream ts {cin};

int main(int argc, char*argv[])
{
    switch (argc) {
    case 1: // odczyt ze standardowego strumienia wejciowego
        break;
    case 2: // odczyt z acucha argumentw
        ts.set_input(new istringstream{argv[1]});
        break;
    default:
        error("Zbyt wiele argumentw ");
        return 1;
    }

    table["pi"] = 3.1415926535897932385; // standardowe nazwy
    table["e"] = 2.7182818284590452354;

    calculate();

    return no_of_errors;
}
---------------
dc "rate=1.1934;150/rate;19.75/rate;217/rate"
---------------
vector<string> arguments(int argc, char*argv[])
{
    vector<string> res;
    for (int i = 0; i!=argc; ++i)
        res.push_back(argv[i]);
    return res;
}
---------------
bool b = not (x or y) and z;
int x4 = ~ (x1 bitor x2) bitand x3;
---------------
bool b = !(x || y) && z;
int x4 = ~(x1 | x2) & x3;
---------------
void f(int x, int y)
{
    int j = x = y;       // warto x=y jest wartoci x po przypisaniu
    int*p = &++x;        // p wskazuje x
    int*q = &(x++);      // bd: x++ nie jest wartoci lewostronn (nie jest wartoci przechowywan w x)
    int*p2 = &(x>y?x:y); // adres wikszej wartoci
    int& r = (x<y)?x:1;  // bd: 1 nie jest wartoci lewostronn
}
---------------
void f()
{
    int i = 1;
    while (0 < i) ++i;
    cout << "i ma teraz warto ujemn!" << i << '\n';
}
---------------
int x = f(2)+g(3); // nie wiadomo, czy najpierw zostanie wywoana funkcja f(), czy g()
---------------
int i = 1;
v[i] = i++; // wynik niezdefiniowany
---------------
f1(v[i],i++);   // dwa argumenty
f2((v[i],i++)); // jeden argument
---------------
if (i<=0 || max<i) //...
---------------
if ( (i<=0) || (max<i) ) //...
---------------
if (i <= (0||max) < i) //...
---------------
if (i&mask == 0) // ups! wyraenie == jako argument operatora &
---------------
if ((i&mask) == 0) //...
---------------
if (0 <= x <= 99) //...
---------------
if (0<=x && x<=99) //...
---------------
if (a = 7) // ups! przypisanie stae w warunku
---------------
if (7 == a) // prba ochrony przed niepoprawnym uyciem operatora =; niezalecane
---------------
void f(string& s1, string& s2, string& s3)
{
    const char*cs = (s1+s2).c_str();
    cout << cs;
    if (strlen(cs=(s2+s3).c_str())<8 && cs[0]=='a') {
        // uycie cs
    }
}
---------------
void f(string& s1, string& s2, string& s3)
{
    cout << s1+s2;
    string s = s2+s3;
    if (s.length()<8 && s[0]=='a') {
        // uycie s
    }
}
---------------
void g(const string&, const string&);

void h(string& s1, string& s2)
{
    const string& s = s1+s2;
    string ss = s1+s2;
    g(s,ss); // tu mona uywa s i ss
}
---------------
void f(Shape& s, int n, char ch)
{
    s.move(string{n,ch}); // utworzenie acucha z n kopii ch do przekazania do Shape::move()
    //...
}
---------------
int x1 = 7;
constexpr int x2 = 7;

constexpr int x3 = x1;     // bd: inicjator nie jest wyraeniem staym
constexpr int x4 = x2;     // OK

void f()
{
    constexpr int y3 = x1; // bd: inicjator nie jest wyraeniem staym
    constexpr int y4 = x2; // OK
    //...
}
---------------
constexpr int isqrt_helper(int sq, int d, int a)
{
    return sq <= a ? isqrt_helper(sq+d,d+2,a) : d;
}

constexpr int isqrt(int x)
{
    return isqrt_helper(1,3,x)/2 - 1;
}

constexpr int s1 = isqrt(9); // s1 ma warto 3
constexpr int s2 = isqrt(1234);
---------------
const int x = 7;
const string s = "asdf";
const int y = sqrt(x);
---------------
constexpr int xx = x;    // OK
constexpr string ss = s; // bd: s nie jest wyraeniem staym
constexpr int yy = y;    // bd: sqrt(x) nie jest wyraeniem staym
---------------
struct Point {
    int x,y,z;
    constexpr Point up(int d) { return {x,y,z+d}; }
    constexpr Point move(int dx, int dy) { return {x+dx,y+dy}; }
    // ...
};
---------------
constexpr Point origo {0,0};
constexpr int z = origo.x;

constexpr Point a[] = {
    origo, Point{1,1}, Point{2,2}, origo.move(3,3)
};
constexpr int x = a[1].x;      // x ma warto 1

constexpr Point xy{0,sqrt(2)}; // bd: sqrt(2) nie jest wyraeniem staym
---------------
constexpr int square(int x)
{
    return x*x;
}

constexpr int radial_distance(Point p)
{
    return isqrt(square(p.x)+square(p.y)+square(p.z));
}

constexpr Point p1 {10,20,30}; // domylny konstruktor jest constexpr
constexpr p2 {p1.up(20)};      // Point::up() jest constexpr
constexpr int dist = radial_distance(p2);
---------------
constexpr Point move(int dx, int dy) const { return {x+dx,y+dy}; }
---------------
template<> class complex<double> {
public:
    constexpr complex(double re = 0.0, double im = 0.0);
    constexpr complex(const complex<float>&);
    explicit constexpr complex(const complex<long double>&);

    constexpr double real(); // odczytuje cz rzeczywist
    void real(double);       // ustawia cz rzeczywist
    constexpr double imag(); // odczytuje cz urojon
    void imag(double);       // ustawia cz urojon

    complex<double>& operator= (double);
    complex<double>& operator+=(double);
    // ...
};
---------------
constexpr complex<float> z1 {1,2};    // uwaga: <float> nie <double>
constexpr double re = z1.real();
constexpr double im = z1.imag();
constexpr complex<double> z2 {re,im}; // z2 jest kopi z1
constexpr complex<double> z3 {z1};    // z3 jest kopi z1
---------------
constexpr const char*p1 = "asdf";
constexpr const char*p2 = p1;   // OK
constexpr const char*p2 = p1+2; // bd: kompilator nie zna wartoci p1
constexpr char c = p1[2];       // OK, c=='d'. Kompilator zna warto wskazywan przez p1
---------------
void f(double d)
{
    char c = d; // uwaga: konwersja double na char
}
---------------
void f(double d)
{
    char c {d}; // bd: konwersja double na char
}
---------------
unsigned char uc = 1023; // binarna liczba 1111111111: uc ma warto 11111111, czyli 255
---------------
signed char sc = 1023;   // zaley od implementacji
---------------
float f = FLT_MAX;   // najwiksza warto typu float
double d = f;        // OK: d == f

double d2 = DBL_MAX; // najwiksza warto typu double
float f2 = d2;       // niezdefiniowane, jeli FLT_MAX<DBL_MAX

long double ld = d2; // OK: ld = d3
long double ld2 = numeric_limits<long double>::max();
double d3 = ld2;     // niezdefiniowane, jeli sizeof(long double)>sizeof(double)
---------------
int*p = (1+2)*(2*(1-1)); // w porzdku, chocia dziwne
---------------
void f(int*p, int i)
{
    bool is_not_zero = p; // true, jeli p!=0
    bool b2 = i;          // true, jeli i!=0
    // ...
}
---------------
void fi(int);
void fb(bool);

void ff(int*p, int*q)
{
    if (p) do_something(*p);          // OK
    if (q!=nullptr) do_something(*q); // OK, ale rozwleke
    // ...
    fi(p);                            // bd: nie mona konwertowa wskanika na int
    fb(p);                            // OK: konwersja wskanika na bool (niespodzianka!?)
}
---------------
int i = 2.7;     // i ma warto 2
char b = 2000.7; // niezdefiniowane dla 8-bitowych znakw: 2000 nie mona reprezentowa w 8-bitowej 
                 // zmiennej typu char
---------------
int i = float(1234567890);
---------------
char checked_cast(int i)
{
    char c = i; // ostrzeenie: nieprzenone (10.5.2.1)
    if (i != c) throw std::runtime_error{"Nieudana konwersja int na char"};
    return c;
}

void my_code(int i)
{
    char c = checked_cast(i);
    // ...
}