Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«QT 4: ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ GUI Π½Π° Π‘++Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 26

Автор Жасмин Π‘Π»Π°Π½ΡˆΠ΅Ρ‚

Ѐункция value() объявлСна с ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ const. ΠŸΡ€ΠΈ объявлСнии ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… cachedValue ΠΈ cacheIsValid ΠΌΡ‹ использовали ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово mutable, Ρ‡Ρ‚ΠΎΠ±Ρ‹ компилятор позволял Π½Π°ΠΌ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ эти ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ Π² функциях Ρ‚ΠΈΠΏΠ° const. ΠœΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Π·Π°ΠΌΠ°Π½Ρ‡ΠΈΠ²ΠΎΠΉ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ value() Π½Π΅ Ρ‚ΠΈΠΏΠ° const ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ слова mutable, Π½ΠΎ это Π½Π΅ пропустит компилятор, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ value() ΠΈΠ· data() β€” Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ const.


Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΈ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ЭлСктронная Ρ‚Π°Π±Π»ΠΈΡ†Π°, Ссли Π½Π΅ Π±Ρ€Π°Ρ‚ΡŒ Π² расчСт синтаксичСский Π°Π½Π°Π»ΠΈΠ· Ρ„ΠΎΡ€ΠΌΡƒΠ». Π’ ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠΉ части Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ€Π°Π·Π΄Π΅Π»Π° Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°ΡŽΡ‚ΡΡ функция evalExpression() ΠΈ Π΄Π²Π΅ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ evalTerm() ΠΈ evalFactor(). Π˜Ρ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ слоТСн, Π½ΠΎ ΠΎΠ½ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ сюда, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠΌΠ΅Π»ΠΎ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Π½Ρ‹ΠΉ Π²ΠΈΠ΄. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ этот ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ Π½Π΅ относится ΠΊ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ графичСского интСрфСйса, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ спокойно Π΅Π³ΠΎ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΈ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ с Π³Π»Π°Π²Ρ‹ 5.

Ѐункция evalExpression() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ выраТСния ΠΈΠ· ячСйки элСктронной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Π’Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ состоит ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ‚Π΅Ρ€ΠΌΠΎΠ², Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… Π·Π½Π°ΠΊΠ°ΠΌΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Β«+Β» ΠΈΠ»ΠΈ Β«β€”Β». Π’Π΅Ρ€ΠΌΡ‹ состоят ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΎΠ² (factors), Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… Π·Π½Π°ΠΊΠ°ΠΌΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Β«*Β» ΠΈΠ»ΠΈ Β«/Β». Разбивая выраТСния Π½Π° Ρ‚Π΅Ρ€ΠΌΡ‹, Π° Ρ‚Π΅Ρ€ΠΌΡ‹ Π½Π° Ρ„Π°ΠΊΡ‚ΠΎΡ€Ρ‹, ΠΌΡ‹ обСспСчиваСм ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΡƒΡŽ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.

НапримСр, Β«2*C5+D6Β» являСтся Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ‚Π΅Ρ€ΠΌ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Β«2*C5Β», Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ‚Π΅Ρ€ΠΌ β€” Β«D6Β». Β«2*C5Β» являСтся Ρ‚Π΅Ρ€ΠΌΠΎΠΌ, ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ„Π°ΠΊΡ‚ΠΎΡ€ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Β«2Β», Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ„Π°ΠΊΡ‚ΠΎΡ€ β€” Β«C5Β»; Β«D6Β» состоит ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΊΡ‚ΠΎΡ€Π° β€” Β«D6Β». Π€Π°ΠΊΡ‚ΠΎΡ€ΠΎΠΌ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ число (Β«2Β»), ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ячСйки (Β«C5Β») ΠΈΠ»ΠΈ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² скобках, ΠΏΠ΅Ρ€Π΅Π΄ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π·Π½Π°ΠΊ минуса.

Рис. 4.10. Блок—схСма синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ элСктронной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹.

Блок—схСма синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ элСктронной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ прСдставлСна Π½Π° рис. 4.10. Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ грамматичСского символа (Expression, Term ΠΈ Factor β€” Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Ρ‚Π΅Ρ€ΠΌ ΠΈ Ρ„Π°ΠΊΡ‚ΠΎΡ€) имССтся ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ функция—члСн, которая выполняСт Π΅Π³ΠΎ синтаксичСский Π°Π½Π°Π»ΠΈΠ· ΠΈ структура ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠΎ ΠΎΡ‚Ρ€Π°ΠΆΠ°Π΅Ρ‚ Π΅Π³ΠΎ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΡƒ. ΠŸΠΎΡΡ‚Ρ€ΠΎΠ΅Π½Π½Ρ‹Π΅ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ синтаксичСскиС Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρ‹ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ парсСрами с рСкурсивным спуском (recursiveβ€”descent parsers).

Π”Π°Π²Π°ΠΉΡ‚Π΅ Π½Π°Ρ‡Π½Π΅ΠΌ с evalExpression(), Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая выполняСт синтаксичСский Ρ€Π°Π·Π±ΠΎΡ€ выраТСния:

01 QVariant Cell::evalExpression(const QString &str, int &pos) const

02 {

03 QVariant result = evalTerm(str, pos);

04 while (str[pos] != QChar::Null) {

05 QChar op = str[pos];

06 if (op != '+' && op != '-') return result;

07 ++pos;


08 QVariant term = evalTerm(str, pos);

09 if (result.type() == QVariant::Double

10 && term.type() == QVariant::Double) {

11 if (op == '+') {

12 result = result.toDouble() + term.toDouble();

13 } else {

14 result= result.toDouble() - term.toDouble();

15 }

16 } else {

17 result = Invalid;

18 }

19 }

20 return result;

21 }

Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ evalTerm() для получСния значСния ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Ρ‚Π΅Ρ€ΠΌΠ°. Если Π·Π° Π½ΠΈΠΌ ΠΈΠ΄Π΅Ρ‚ символ Β«+Β» ΠΈΠ»ΠΈ Β«β€”Β», ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π· evalTerm(); Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ состоит ΠΈΠ· СдинствСнного Ρ‚Π΅Ρ€ΠΌΠ°, ΠΈ ΠΌΡ‹ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС значСния всСго выраТСния. ПослС получСния Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ΅Ρ€Π²Ρ‹Ρ… Π΄Π²ΡƒΡ… Ρ‚Π΅Ρ€ΠΌΠΎΠ² ΠΌΡ‹ вычисляСм Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π² зависимости ΠΎΡ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π°. Если ΠΏΡ€ΠΈ ΠΎΡ†Π΅Π½ΠΊΠ΅ ΠΎΠ±ΠΎΠΈΡ… Ρ‚Π΅Ρ€ΠΌΠΎΠ² ΠΈΡ… значСния Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ‚ΠΈΠΏ double, ΠΌΡ‹ рассчитываСм Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π² Π²ΠΈΠ΄Π΅ числа Ρ‚ΠΈΠΏΠ° double; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΌΡ‹ устанавливаСм Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Invalid.

ΠœΡ‹ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ эту ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ, ΠΏΠΎΠΊΠ° Π½Π΅ закончатся Ρ‚Π΅Ρ€ΠΌΡ‹. Π­Ρ‚ΠΎ даст ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ слоТСния ΠΈ вычитания ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‚ свойством «ассоциативности слСва» (leftβ€”associative), Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Β«1β€”2β€”3Β» ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Β«(1β€”2)β€”3Β», Π° Π½Π΅ Β«1β€”(2β€”3)Β».

01 QVariant Cell::evalTerm(const QString &str, int &pos) const

02 {

03 QVariant result = evalFactor(str, pos);

04 while (str[pos] != QChar::Null) {

05 QChar op = str[pos];

06 if (op != '*' && op != '/')

07 return result;

08 ++pos;


09 QVariant factor = evalFactor(str, pos);

10 if (result.type() == QVariant::Double &&

11 factor.type() == QVariant::Double) {

12 if (op == '*') {

13 result = result.toDouble() * factor.toDouble();

14 } else {

15 if (factor.toDouble() == 0.0) {

16 result = Invalid;

17 } else {

18 result = result.toDouble() / factor.toDouble();

19 }

20 }

21 } else {

22 result = Invalid;

23 }

24 }

25 return result;

26 }

Ѐункция evalTerm() ΠΎΡ‡Π΅Π½ΡŒ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ evalExpression(), Π½ΠΎ, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ послСднСй, ΠΎΠ½Π° ΠΈΠΌΠ΅Π΅Ρ‚ Π΄Π΅Π»ΠΎ с опСрациями умноТСния ΠΈ дСлСния. Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ evalTerm() Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΠ΄Π½Ρƒ Ρ‚ΠΎΠ½ΠΊΠΎΡΡ‚ΡŒ, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ: нСльзя Π΄ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ дСлСния Π½Π° Π½ΡƒΠ»ΡŒ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ошибкС Π½Π° Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… процСссорах. Π₯отя Π½Π΅ рСкомСндуСтся ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ равСнство чисСл с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ ΠΈΠ·-Π·Π° ошибки округлСния, ΠΌΠΎΠΆΠ½ΠΎ спокойно Π΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Π½Π° равСнство Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ 0.0 для прСдотвращСния дСлСния Π½Π° Π½ΡƒΠ»ΡŒ.

01 QVariant Cell::evalFactor(const QString &str, int &pos) const

02 {

03 QVariant result;

04 bool negative = false;

05 if (str[pos] == '-') {

06 negative = true;

07 ++pos;

08 }

09 if (str[pos] == '(') {

10 ++pos;

11 result = evalExpression(str, pos);

12 if (str[pos] != ')')

13 result = Invalid;

14 ++pos;

15 } else {

16 QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");

17 QString token;

18 while (str[pos].isLetterOrNumber() || str[pos] == '.') {

19 token += str[pos];

20 ++pos;

21 }


22 if (regExp.exactMatch(token)) {

23 int column = token[0].toUpper().unicode() - 'A';

24 int row = token.mid(1).toInt() - 1;

25 Cell *c = static_cast<Cell *>(tableWidget()->item(row, column));

26 if (c) {

27 result = c->value();

28 } else {

29 result = 0.0;

30 }

31 } else {

32 bool ok;

33 result = token.toDouble(&ok);

34 if (!ok)

35 result = Invalid;

36 }

37 }


38 if (negative) {

39 if (result.type() == QVariant::Double) {

40 result = -result.toDouble();

41 } else {

42 result = Invalid;

43 }

44 }

45 return result;

46 }

Ѐункция evalFactor() Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ слоТнСС, Ρ‡Π΅ΠΌ evalExpression() ΠΈ evalTerm(). ΠœΡ‹ Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌ с ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ, Π½Π΅ являСтся Π»ΠΈ Ρ„Π°ΠΊΡ‚ΠΎΡ€ ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ провСряСм Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠΉ скобки. Если ΠΎΠ½Π° имССтся, ΠΌΡ‹ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π²Π½ΡƒΡ‚Ρ€ΠΈ скобок ΠΊΠ°ΠΊ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, вызывая evalExpression(). ΠŸΡ€ΠΈ Π°Π½Π°Π»ΠΈΠ·Π΅ выраТСния Π² скобках evalExpression() Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ evalTerm(), которая Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ evalFactor(), которая вновь Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ evalExpression(). ИмСнно Π² этом мСстС осущСствляСтся рСкурсия ΠΏΡ€ΠΈ синтаксичСском Π°Π½Π°Π»ΠΈΠ·Π΅.

Если Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΎΠΌ Π½Π΅ являСтся Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΌΡ‹ выдСляСм ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ лСксСму (token), ΠΈ ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ячСйки ΠΈΠ»ΠΈ Π±Ρ‹Ρ‚ΡŒ числом. Если эта лСксСма удовлСтворяСт рСгулярному Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ QRegExp, ΠΌΡ‹ считаСм, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° являСтся ссылкой Π½Π° ячСйку, ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ value() для этой ячСйки. Π―Ρ‡Π΅ΠΉΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°ΡΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Π² любом мСстС Π² элСктронной Ρ‚Π°Π±Π»ΠΈΡ†Π΅, ΠΈ ΠΎΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ячСйки. Вакая Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ‚ΡŒ Π½Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΈ просто ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ value() ΠΈ ΠΊ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌΡƒ синтаксичСскому Π°Π½Π°Π»ΠΈΠ·Ρƒ ячССк с ΠΏΡ€ΠΈΠ·Π½Π°ΠΊΠΎΠΌ Β«dirtyΒ» («грязный») для пСрСрасчСта Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ всСх зависимых ячССк. Если лСксСма Π½Π΅ являСтся ссылкой Π½Π° ячСйку, ΠΌΡ‹ рассматриваСм Π΅Π΅ ΠΊΠ°ΠΊ число.

Π§Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚, Ссли ячСйка A1 содСрТит Ρ„ΠΎΡ€ΠΌΡƒΠ»Ρƒ Β«=A1Β»? Или Ссли ячСйка A1 содСрТит Β«=A2Β», Π° ячСйка A2 содСрТит Β«=A1Β»? Π₯отя Π½Π°ΠΌΠΈ Π½Π΅ написан ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ для обнаруТСния бСсконСчных Ρ†ΠΈΠΊΠ»ΠΎΠ² Π² рСкурсивных зависимостях, парсСр прСкрасно справится с этой ситуациСй ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΈΡ‚ нСдопустимоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Ρ‚ΠΈΠΏΠ° QVariant. Π­Ρ‚ΠΎ даст Π½ΡƒΠΆΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ устанавливаСм Ρ„Π»Π°ΠΆΠΎΠΊ cacheIsDirty Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ false ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ cachedValue Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Invalid Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ value() ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ evalExpression(). Если evalExpression() рСкурсивно Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ value() для Ρ‚ΠΎΠΉ ΠΆΠ΅ ячСйки, ΠΎΠ½Π° Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Invalid, ΠΈ Ρ‚ΠΎΠ³Π΄Π° всС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Invalid.