Replace keys in values with key->values from same dictionary
Well what you want there is evaluating expressions while keeping track
of dependencies, so you should definitely not implement it via regular
expressions and hoping that running it ten times is enough.

The best way in Python would probably be using the
ast module to parse and
figure out the referenced variables, then calculate dependencies and
evaluate the parsed expressions via
compile
and eval
while passing in the referenced variables in the local parameter.

That way you make sure that the expressions are actually valid, you can
use Python expressions and you can (and should) also detect cycles in
the specification.

Below is a sketch how to do that, not saying that is the best code,
please edit or comment with improvements, I couldn't find a good example
while searching.

import ast, _ast

params = {
    'ad': '2*dmcg/factor*(xw/factor)',
    'dmcg': 2.05e-07,
    'dxwn_3vna': 10.0,
    'factor': 1,
    'xw': '0+dxwn_3vna',
    'foo': 'bar',
    'bar': 'foo'
}

parsed = {}

for key, value in params.iteritems():
    parsed[key] = value

    if type(value) in (str, unicode):
        parsed[key] = ast.parse(value, mode="eval")

evaluated = {key: value for key, value in parsed.iteritems()}


So at this point the evaluated dictionary is mostly a copy of the
params, except that expressions have been parsed.

def referenced(code):
    return [node.id for node in ast.walk(code) if "id" in node._fields]


referenced returns a list with the names of referenced variables in
the expression.

evaluating = []

def resolve(key, value):
    if key in evaluating:
        raise Exception("Loop while evaluating {}".format(key))

    if type(value) is not _ast.Expression:
        evaluated[key] = value
        return value

    evaluating.append(key)

    locals = {name: resolve(name, evaluated[name]) for name in referenced(value)}

    result = eval(compile(value, "&lt;unknown&gt;", "eval"), globals(), locals)

    evaluated[key] = result

    evaluating.pop()

    return result


resolve evaluates the expression recursively but also keeps track of
the stack (in evaluating), so it can detect cycles by looking up the
current variable.  It also assigns the results immediately, so in
further invocations it will return early (the not _ast.Expression
case).

for key, value in parsed.iteritems():
    try:
        resolve(key, value)
    except Exception as exception:
        print ("Error while evaluating {}: {}".format(key, exception))

print(evaluated)


Lastly, iterate over all entries and try to evaluate them.