Design and Implementation of a Calculation DSL and Engine

The article presents a domain‑specific language that mimics Excel formulas, a stack‑based parser and recursive engine for evaluating calculations, and a multi‑layer architecture—including a dynamic priority scheduler—to efficiently resolve field dependencies, improve maintainability, and enable monitoring across large data systems.

Tencent Cloud Developer
Tencent Cloud Developer
Tencent Cloud Developer
Design and Implementation of a Calculation DSL and Engine

In large data systems, massive calculation requirements often lead developers to embed complex logic directly in code, resulting in bloated and hard‑to‑maintain implementations. To address this, a domain‑specific language (DSL) is proposed to define calculation rules as an independent, reusable service.

What is a DSL? A domain‑specific language focuses on a particular application domain, unlike general‑purpose languages. It abstracts common patterns (e.g., SQL) to improve development efficiency.

Designing a Calculation DSL The DSL mirrors Excel’s calculation capabilities. For example, to compute the amount by which actual expenses exceed a budget:

IF(C2 > B2, IMSUB(C2, B2), 0)  // C2: actual expense, B2: budget, IMSUB: subtraction

Corresponding DSL syntax uses placeholders for fields:

IF({budget} > {actual_expenses}, IMSUB({budget}, {actual_expenses}), 0)

Advantages of the DSL

Similar to Excel, reducing learning cost.

Formal definition makes the DSL more standardized.

Well‑designed DSL facilitates future extensions.

Calculation Engine Implementation

DSL Parsing A stack‑based parser handles nested DSL expressions. Example parsing code:

$dsl = 'IF({budget}>={actual_expenses},IMSUB({budget},{actual_expenses}),0,1)';
$stack = [];
$result = [];
$comparisonOperators = ['<', '>', '&', '|', '='];
$placeholders = [',', '(', ')'];
for ($index = 0; $index < strlen($dsl); $index++) {
    $key = $dsl[$index];
    switch ($key) {
        case '}':
            $variable = '';
            while (true) {
                $item = array_pop($stack);
                if ($item === '{') break;
                $variable = $item . $variable;
            }
            $result[] = $this->getVariable($variable);
            break;
        case '(':
            $method = '';
            while (true) {
                $item = array_pop($stack);
                if (is_null($item)) break;
                $method = $item . $method;
            }
            $result[] = $method;
            $result[] = $key;
            break;
        case in_array($key, $placeholders):
            $variable = '';
            while (true) {
                $item = array_pop($stack);
                if (is_null($item)) break;
                $variable = $item . $variable;
            }
            if ($variable != '') $result[] = $variable;
            $result[] = $key;
            break;
        case in_array($key, $comparisonOperators):
            if ($dsl[$index + 1] == '=') {
                $result[] = $key . '=';
                $index++;
            } else {
                $result[] = $key;
            }
            break;
        default:
            $stack[] = $key;
            break;
    }
}

Data Structuring After parsing, the DSL yields a tree‑like structure that can be populated with actual values from a predefined data model.

Data structure diagram
Data structure diagram

Recursive Calculation Each node may represent a function, a placeholder, or a constant. Recursion evaluates nested functions:

/**
 * IF function core logic
 */
public function calculate() {
    // Evaluate comparison result
    if ($this->getComparativeResult()) {
        return $this->getResult($this->params[1]); // true branch
    } else {
        return $this->getResult($this->params[2]); // false branch
    }
}
/**
 * Get calculation result
 */
public function getResult($params) {
    // If the parameter is a function, recurse
    if (is_array($params)) {
        return (new Calculate($params))->calculate(); // recursive call
    }
    // Otherwise return the literal value
    return $params;
}

Architecture Overview

The system consists of five layers: Application, Communication, DSL Parsing, Core Calculation, and Persistence/Messaging. The DSL parsing layer and core calculation layer together form the calculation engine.

Architecture diagram
Architecture diagram

Project Integration

The architecture is divided into five tiers, with the upper application layer exposing APIs, the communication layer handling data exchange, the DSL parsing layer performing validation and structuring, the core calculation layer executing the logic, and the final layer persisting results and publishing messages.

Integration diagram
Integration diagram

Problems and Reflections

Efficiency Gains Are Slow Parallel execution does not linearly improve performance; beyond a certain concurrency level, gains diminish due to hidden dependencies.

Performance chart
Performance chart

Computation Dependencies Some fields depend on the results of others (e.g., B depends on A, C depends on A and B), creating bottlenecks.

Dependency diagram
Dependency diagram

Solution: Optimal Scheduling

The proposed strategy assigns priority levels based on dependency depth (e.g., A and D have priority 0, B and E priority 1, C priority 2). Fields with the same priority are computed in parallel, minimizing resource usage.

Priority algorithm diagram
Priority algorithm diagram

Dynamic Priority Algorithm When a field finishes, dependent fields are re‑evaluated and may be promoted to a higher priority for immediate execution.

Dynamic scheduling diagram
Dynamic scheduling diagram

Summary

The architecture now includes a strategy allocation layer between DSL parsing and core calculation. This layer schedules tasks based on dynamic priorities, handles events, and ensures efficient resource utilization. Monitoring is added at each stage (parsing, strategy allocation, calculation, persistence) to detect and log errors promptly.

Monitoring diagram
Monitoring diagram
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MonitoringDSLParsingBackend DevelopmentParallel ComputingCalculation Engine
Tencent Cloud Developer
Written by

Tencent Cloud Developer

Official Tencent Cloud community account that brings together developers, shares practical tech insights, and fosters an influential tech exchange community.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.