StringParseResult ParseStringExpression(const char *expr, int start, int end) { StringParseResult lhs = ParseTerm(expr, start, end); if (lhs.result) { StringParseResult rhs = ParseStringExpression(expr, lhs.position, end); if (rhs.result) { StringExpression *ret = xcalloc(1, sizeof(StringExpression)); ret->op = CONCAT; ret->val.concat.lhs = lhs.result; ret->val.concat.rhs = rhs.result; return (StringParseResult) {ret, rhs.position}; } else { return lhs; } } else { return lhs; } }
static ParseResult ParsePrimary(const char *expr, int start, int end) { if (start < end && expr[start] == '(') { ParseResult res = ParseExpression(expr, start + 1, end); if (res.result) { /* Check there is a matching ')' at the end */ if (res.position < end && expr[res.position] == ')') { return (ParseResult) { res.result, res.position + 1 }; } else { /* Didn't find a matching bracket. Give up */ FreeExpression(res.result); return (ParseResult) { NULL, res.position }; } } else { return res; } } else { StringParseResult strres = ParseStringExpression(expr, start, end); if (strres.result) { Expression *res = xcalloc(1, sizeof(Expression)); res->op = EVAL; res->val.eval.name = strres.result; return (ParseResult) { res, strres.position }; } else { return (ParseResult) { NULL, strres.position }; } } }
static StringParseResult ParseQname(const char *expr, int start, int end) { StringParseResult lhs, rhs; StringExpression *ret, *subret, *dot; lhs = ParseStringExpression(expr, start, end); if (!lhs.result) { return lhs; } if (lhs.position == end || expr[lhs.position] != '.') { return lhs; } rhs = ParseStringExpression(expr, lhs.position + 1, end); if (!rhs.result) { FreeStringExpression(lhs.result); return rhs; } dot = xcalloc(1, sizeof(StringExpression)); dot->op = LITERAL; dot->val.literal.literal = xstrdup("."); subret = xcalloc(1, sizeof(StringExpression)); subret->op = CONCAT; subret->val.concat.lhs = dot; subret->val.concat.rhs = rhs.result; ret = xcalloc(1, sizeof(StringExpression)); ret->op = CONCAT; ret->val.concat.lhs = lhs.result; ret->val.concat.rhs = subret; return (StringParseResult) {ret, rhs.position}; }