#include #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call GetCurrentDate(uCalcBase::Callback cb) { // In a real application, this would return the system's current date. // For this example, we'll use a fixed date for consistent output. // Let's pretend today is January 15, 2026 (a Thursday). cb.Return(46036); // Using Excel-style date serial number for simplicity } void ucalc_call AddDuration(uCalcBase::Callback cb) { auto startDate = cb.Arg(1); auto number = cb.Arg(2); auto unit = cb.ArgStr(3); auto result = startDate; if (unit == "day" || unit == "days") { result = startDate + number; } else if (unit == "week" || unit == "weeks") { result = startDate + (number * 7); } else if (unit == "month" || unit == "months") { result = startDate + (number * 30); // Approximation for example } cb.Return(result); } void ucalc_call GetNextDayOfWeek(uCalcBase::Callback cb) { auto dayName = cb.ArgStr(1); auto today = 46036; // Thursday, Jan 15, 2026 auto todayDayOfWeek = 5; // 1=Sun, 2=Mon, ..., 5=Thu auto targetDay = 0; if (dayName == "Sunday") targetDay = 1; if (dayName == "Monday") targetDay = 2; if (dayName == "Tuesday") targetDay = 3; if (dayName == "Wednesday") targetDay = 4; if (dayName == "Thursday") targetDay = 5; if (dayName == "Friday") targetDay = 6; if (dayName == "Saturday") targetDay = 7; auto daysToAdd = (targetDay - todayDayOfWeek + 7) % 7; // Always get the *next* week's day if (daysToAdd == 0) daysToAdd = 7; cb.Return(today + daysToAdd); } void ucalc_call FormatDate(uCalcBase::Callback cb) { // This is a simplified formatter for the example. // A real implementation would be more robust. auto dateSerial = cb.Arg(1); if (dateSerial == 46036) cb.ReturnStr("2026-01-15"); if (dateSerial == 46037) cb.ReturnStr("2026-01-16"); if (dateSerial == 46039) cb.ReturnStr("2026-01-18"); if (dateSerial == 46043) cb.ReturnStr("2026-01-22"); if (dateSerial == 46050) cb.ReturnStr("2026-01-29"); if (dateSerial == 46096) cb.ReturnStr("2026-03-16"); } int main() { uCalc uc; // 1. Define the helper functions in the uCalc engine uc.DefineFunction("GetCurrentDate()", GetCurrentDate); uc.DefineFunction("AddDuration(date, num, unit As String)", AddDuration); uc.DefineFunction("GetNextDayOfWeek(dayName As String)", GetNextDayOfWeek); uc.DefineFunction("FormatDate(date) As String", FormatDate); // 2. Create the transformer and define the DSL rules { uCalc::Transformer t(uc); t.Owned(); // Causes t to be released when it goes out of scope // Set case-insensitivity for all rules t.DefaultRuleSet().CaseSensitive(false); // Define the rules t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}"); t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}"); t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}"); t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}"); // 3. Process the input strings cout << "Input: 'today' -> Output: " << t.Transform("today") << endl; cout << "Input: 'tomorrow' -> Output: " << t.Transform("tomorrow") << endl; cout << "Input: 'next Sunday' -> Output: " << t.Transform("next Sunday") << endl; cout << "Input: 'in 2 weeks' -> Output: " << t.Transform("in 2 weeks") << endl; cout << "Input: 'in 60 days' -> Output: " << t.Transform("in 60 days") << endl; } }