Language: C++

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <cctype>
using namespace std;

#define DEBUG(x) cerr << #x << " = " << x << endl

typedef string::const_iterator Iter;

struct Result {
  map<string, int> m;
  void add(const string& s, const int value) {
    m[s] += value;
  }
  void add(const Result &r) {
    for(const auto &keyvalue : r.m) {
      m[keyvalue.first] += keyvalue.second;
    }
  }

  void mul(const int mul) {
    for(auto &keyvalue : m) {
      keyvalue.second *= mul;
    }
  }
};

Result expr(Iter &p);
Result term(Iter &p);
int number(Iter &p);

Result expr(Iter &p) {
  Result r = term(p);
  while(*p != '.' && *p != ')') {
    if(*p == '+') ++p;
    r.add(term(p));
  }
  return r;
}

Result term(Iter &p) {
  Result r;
  if(*p == '(') {
    ++p; // skip '('
    r = expr(p);
    ++p; // skip ')'
  }
  else {
    string name;
    name.push_back(*p);
    ++p;
    if(islower(*p)) {
      name.push_back(*p);
      ++p;
    }
    r.add(name, 1);
  }
  int mul = number(p);
  r.mul(mul);
  return r;
}

int number(Iter &p) {
  int res = 0;
  while(isdigit(*p)) {
    res *= 10;
    res += *p - '0';
    ++p;
  }
  if(res == 0) return 1;
  return res;
}

void repr(const Result &r) {
  for(const auto &kv : r.m) {
    cerr << kv.first << ":" << kv.second << ", ";
  }
  cerr << endl;
}

int lcm(int a, int b) {
  return a / __gcd(a,b) * b;
}

struct Rational {
  int numer, denom;
  Rational(int number) : numer(number), denom(1) { }
  Rational(int numer_, int denom_) : numer(numer_), denom(denom_) { }
  void apply() {
    int div = __gcd(numer, denom);
    numer /= div;
    denom /= div;
  }
};

int main() {
  while(true) {
    string line; cin >> line;
    if(line == ".") break;
    string lhs = line.substr(0, line.find("->"));
    string rhs = line.substr(line.find("->") + 2);
    lhs.push_back('.');

    Iter it;
    it = lhs.begin();
    Result left = expr(it);
    it = rhs.begin();
    Result right = expr(it);

    vector<Rational> b;
    int base = right.m.begin()->second;
    for(auto kv : right.m) {
      b.push_back(kv.second, base);
    }
    for(int i = 0; i < (int)b.size(); ++i) {
      b[i].apply();
    }
  }
}

Compiler output:
a.cc: In function 'int main()':
a.cc:116:18: error: no matching function for call to 'std::vector<Rational>::push_back(int&, int&)'
  116 |       b.push_back(kv.second, base);
      |       ~~~~~~~~~~~^~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/14/vector:66,
                 from a.cc:3:
/usr/include/c++/14/bits/stl_vector.h:1283:7: note: candidate: 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Rational; _Alloc = std::allocator<Rational>; value_type = Rational]'
 1283 |       push_back(const value_type& __x)
      |       ^~~~~~~~~
/usr/include/c++/14/bits/stl_vector.h:1283:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/14/bits/stl_vector.h:1300:7: note: candidate: 'void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = Rational; _Alloc = std::allocator<Rational>; value_type = Rational]'
 1300 |       push_back(value_type&& __x)
      |       ^~~~~~~~~
/usr/include/c++/14/bits/stl_vector.h:1300:7: note:   candidate expects 1 argument, 2 provided