Sign in Join
Wiki copytemporary

How To Use TFPExpressionParser/fi: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: How To Use TFPExpressionParser/fi

OldNewLine
1+TFPExpressionParser sallii analysoida ja laskea [[expression/fi|laskuja]] kuten `sin(x)*cos(2*x)` [[Variable/fi|muuttujan]] `x` millä tahansa arvolla. Matemaattisten lausekkeiden lisäksi se voi käsitellä myös [[Boolean/fi|boolean]] arvoja, merkkijonoja, [[TDateTime/fi|päivämäärän/ajan]] arvoja jne. Jopa käyttäjän antamat toiminnot voidaan yhdistää.
2+
3+Se kuuluu [[FPC/fi|FPC]]:n [[FCL/fi|Free Component Library (FCL)]]-kirjastoon ja se on toteutettu [[Unit/fi|käännösyksikössä (unit)]] `fpexprpars.pp`, kansio `(fpc_source_dir)/packages/fcl-base/src`. Lisätään vain `fpexprpars` [[Uses/fi|uses]]-lauseseen jotta saadaan pääsy sen toiminnallisuuteen. ´ Katsomalla tiedostoa "fpexprpars.txt" (kohdassa `(fpc_source_dir)/packages/fcl-base/examples`) nähdään lyhyt dokumentaatio siitä.
4+
5+## Parserin luominen
6+
7+Parserin/Jäsentimen voi luoda tällaisella instanssilla:
8+
9+``` pascal
10+uses
11+ fpexprpars;
12+
13+var
14+ FParser: TFPExpressionParser;
15+begin
16+ FParser := TFpExpressionParser.Create(self);
17+ // ... do something (see below)
18+```
19+
20+Jos tätä kutsutaan [[TForm/fi|lomakkeen]] [[Method/fi|metodista]], "[[Self/fi|self]]" viittaa lomakkeeseen. Koska jäsennin periytyy `TComponent`-luokasta, sitä ei tarvitse tuhota nimenomaisesti, koska sen omistaja, lomake, tekee sen. Toisaalta on myös mahdollista luoda jäsennin missä tahansa [[Program/fi|ohjelmassa]] ilman lomaketta tai edes [[Class/fi|luokkaa]]; käytä tässä tapauksessa [[Nil/fi|nil]] jäsentimen omistajana, mutta älä unohda `.Free` kutsua tällöin käytön jälkeen:
21+
22+``` pascal
23+uses
24+ fpexprpars;
25+
26+var
27+ FParser: TFPExpressionParser;
28+begin
29+ FParser := TFPExpressionParser.Create(nil);
30+ try
31+ // ... do something (see below)
32+ finally
33+ FParser.Free;
34+ end;
35+end;
36+```
37+
38+## Sisäänrakennetut luokat
39+
40+Parseri on suunniteltu hyvin joustavasti, mutta oletusparseri on melko tyhmä. Siihen on määritettävä, mitä lausekkeita se hyväksyy. Tämä tehdään lisäämällä vastaava [[Identifier/fi|tunniste]] sisäänrakennettujen luokkien joukkoon. Niihin pääsee parserin [[Property/fi|ominaisuudella]] `BuiltIns`:
41+
42+``` pascal
43+type
44+ TBuiltInCategory = (bcStrings, bcDateTime, bcMath, bcBoolean, bcConversion, bcData, bcVaria, bcUser);
45+ TBuiltInCategories = set of TBuiltInCategory;
46+```
47+
48+Tässä on kokoelma sisäänrakennettuja symboleja, joita voidaan käyttää lisäämällä luokkia parserin `BuiltIns` - jokainen, joka "ymmärtää" [[Pascal/fi|Pascalia]], pitäisi olla selvää, mitä nämä symbolit tarkoittavat ...
49+
50+- **bcStrings**: `Length`, `Copy`, `Delete`, `Pos`, `Lowercase`, `Uppercase`, `StringReplace`, `CompareText`
51+- **bcDateTime**: `Date`, `Time`, `Now`, `DayOfWeek`, `ExtractYear`, `ExtractMonth`, `ExtractDay`, `ExtractHour`, `ExtractMin`, `ExtractSec`, `Extractmsec`, `EncodeDate`, `EncodeTime`, `ShortDayName`, `ShortMonthName`, `LongDayName`, `LongMonthName`
52+- **bcMath**: `cos`, `sin`, `arctan`, `abs`, `sqr`, `sqrt`, `exp`, `ln`, `log`, `frac`, `int`, `round`, `trunc`,
53+- **bcBoolean**: `shl`, `shr`, `IFS`, `IFF`, `IFD`, `IFI` (The `IFxxx` symbols have the same effect as fpc's `IfThen` for string (`IFS`), floating point (`IFF`), date/time (`IFD`), or integer (`IFI`) variables)
54+- **bcConversion**: `IntToStr`, `StrToInt`, `StrToIntDef`, `FloatToStr`, `StrToFloat`, `StrToFloatDef`, `BoolToStr`, `StrToBool`, `StrToBoolDef`, `DateToStr`, `TimeToStr`, `StrToDate`, `StrToDateDef`, `StrToTime`, `StrToTimeDef`, `StrToDateTime`, `StrToDateTimeDef`
55+
56+`bcData`, `bcVaria` ja `bcUser` ei käytetää missään fpexprpars:ssa. Lopussa on ohjeet miten lisätään käyttäjän määrittämiä funktioiia.
57+
58+> **Note:** Nämä symbolit eivät ole [[case-sensitive/fi|iso/pieni kirjain kohtaisia]].
59+
60+Jotta matemaattista lauseketta voidaan käyttää niin valinta `bcMath` on lisättävä parserin `Builtins`:
61+
62+``` pascal
63+ FParser.Builtins := [bcMath]; // or FParser.Builtins := FParser.Builtins + [bcMath];
64+```
65+
66+## Lausekkeet
67+
68+### Lausekkeet vakioilla
69+
70+Ensimmäisenä esimerkkinä on, että jäsennin laskee hyvin yksinkertaisen lausekkeen `1+1`. Ensimmäinen vaihe on kertoa jäsentimelle, mitä lauseketta lasketaan. Tätä tarkoitusta varten on ominaisuus `Expression`:
71+
72+``` pascal
73+ FParser.Expression := '1+1';
74+```
75+
76+Seuraava vaihe on laskea lauseke: vain kutsu `Evaluate` tai `EvaluateExpression` -
77+
78+ensimmäinen on [[Function/fi|funktio]], kun taas jälkimmäinen on [[Procedure/fi|aliohjelma]], joka antaa tuloksen parametrina.
79+
80+``` pascal
81+var
82+ parserResult: TFPExpressionResult;
83+begin
84+ ....
85+ parserResult := FParser.Evaluate; // or: FParser.EvaluateExpression(parserResult);
86+```
87+
88+Mikä on se salaperäinen `TFPExpressionResult`? Koska parseri on hyvin joustava ja voi käsitellä numeroita, merkkijonoja, päivämääriä / aikoja tai boolean arvoja, on oltava monimutkaisempi tietotyyppi, joka palauttaa laskentatuloksen:
89+
90+``` pascal
91+type
92+ TResultType = (rtBoolean, rtInteger, rtFloat, tDateTime, rtString);
93+
94+ TFPExpressionResult = record
95+ ResString : String;
96+ Case ResultType : TResultType of
97+ rtBoolean : (ResBoolean : Boolean);
98+ rtInteger : (ResInteger : Int64);
99+ rtFloat : (ResFloat : TExprFloat);
100+ rtDateTime : (ResDateTime : TDatetime);
101+ rtString : ();
102+ end;
103+```
104+
105+Jäsen `ResultType` -signaalit, jonka vain yksi tietokentistä on voimassa. On tärkeää ymmärtää tämä, koska parseri on hyvin tiukka [[Data type|tietotyyppien]] suhteen.
106+
107+Esimerkissä lisätään kaksi [[Integer/fi|kokonaislukua]], joten tulos on myös kokonaisluku. Jos toisaalta olisimme käyttäneet lauseketta `"1.0 + 1"` niin ensimmäinen numero olisi ollut reaaliluku ja tulos olisi ollut reaaliluku! Siksi on aina tarkasteltava `TFPExpressionResult`-jäsenen `ResultType`-tyyppiä ennen tuloksen valintaa. Lausekkeen tulosdatatyypin käytön yksinkertaistamiseksi `fpexprpars` paljastaa funktion `ArgToFloat`, joka saa koko lausekkeen tulos [[Record/fi|tietueen]] parametriksi ja valitsee oikean komponentin, jos reaaliluku tulosta odotetaan:
108+
109+``` pascal
110+var
111+ parserResult: TFPExpressionResult;
112+ resultValue: Double;
113+...
114+ parserResult := FParser.Evaluate; // or: FParser.EvaluateExpression(parserResult);
115+ resultValue := ArgToFloat(parserResult);
116+```
117+
118+> **Note:** Reaaliluvuilla on oltava [[period/fi|piste]] desimaalierottimena, ei [[Comma/fi|pilkku]], jota käytetään joissakin Euroopan maissa. Jos lausekkeen merkkijono tulee käyttäjän syöttämästä lausekkeesta ja sisältää desimaalilukuja, niin on korvattava pilkku pisteillä ensin ennen sen määrittämistä parserin `Expression`-lausekkeelle.
119+
120+### Lauseke muuttujalla
121+
122+Tässä esimerkissä lasketaan `sin(x)*cos(2*x)` jossa `x = 0.5` (0,5).
123+
124+#### Muuttujien määrittäminen
125+
126+Aluksi on määriteltävä muuttujat. On vain yksi `x`. Parserilla on [[Method|metodi]] `AddFloatVariable`, joka ilmoittaa reaaliluvun; on myös menetelmiä:
127+
128+- `AddBooleanVariable`
129+- `AddStringVariable`
130+- `AddDateTimeVariable`
131+
132+boolean-, merkkijono- ja päivämäärä/aika-muuttujille, vastaavasti.
133+
134+Jokainen näistä aliohjelmista odottaa muuttujan nimeä sekä sen oletusarvoa. Näyte funktiolle `sin(x)*cos(2*x)` kutsutaan vain:
135+
136+``` pascal
137+ FParser.Identifiers.AddFloatVariable('x', 0.5);
138+```
139+
140+`0.5` (0,5) syötetään tähän oletusarvoksi, koska se on argumentti, jolla halutaan laskea lauseke (alla näytetään, miten muuttujaa muutetaan). Tästä lähtien jäsennin käyttää tätä numeroa aina, kun se löytää lausekkeessa olevan muuttujan `x`.
141+
142+Voit tietysti lisätä muita nimiä, esim. [[Constant/fi|vakiota]], kuten `e` jne. ([[Pi/fi|Pii (pi)]] on jo sisäänrakennettu).
143+
144+#### Lausekkeen määrittäminen
145+
146+Seuraavassa vaiheessa lausekkeen merkkijono lähetetään parserille:
147+
148+``` pascal
149+ FParser.Expression := 'sin(x)*cos(2*x)';
150+```
151+
152+On välttämätöntä kutsua tätä muuttujien asettamisen jälkeen, koska jäsentimen on tiedettävä muuttuja lausekkeen analysoimiseksi.
153+
154+#### Lausekkeen laskeminen
155+
156+Tämä tehdään kuten aikaisemmin vakio lausekkeella - tässä on täydellinen aliohjelma, joka näyttää yhtälön ja sen tuloksen [[Dialog Examples|viestiruudussa (ShowMessage)]]:
157+
158+``` pascal
159+var
160+ FParser: TFPExpressionParser;
161+ resultValue: Double;
162+begin
163+ FParser := TFPExpressionParser.Create(nil);
164+ try
165+ FParser.BuiltIns := [bcMath];
166+ FParser.Identifiers.AddFloatVariable('x', 0.5);
167+ FParser.Expression := 'sin(x)*cos(2*x)';
168+ resultValue := FParser.Evaluate.ResFloat; // or: resultValue := ArgToFloat(FParser.Evaluate);
169+ ShowMessage(FParser.Expression + ' = ' + FloatToStr(resultValue));
170+ finally
171+ FParser.Free;
172+ end;
173+end;
174+```
175+
176+#### Muuttujien muuttaminen
177+
178+Toistaiseksi `x`:llä on aina arvo 0,5 - se käyttäytyy kuin vakio, oltaisiin voitu käyttää myös lauseketta `"sin(0.5)*cos(2*0.5)"`.
179+
180+Jotta tämä käyttäytyisi enemmän kuin "muuttuja", lasketaan nyt testi funktion `x`-arvoja välillä -10 ja 10.
181+
182+Tärkein kysymys on: Miten määrätty arvo korvataan muuttujalla? On useita mahdollisuuksia - kaikki ne edellyttävät sisäistä muuttujaa `Identifier` (tyyppi `TFPExprIdentifierDef`), joka paljastaa erilaisia ​​tapoja käyttää muuttujia ja niiden ominaisuuksia:
183+
184+- Käytetään `AddFloatVariable` funktion palautusarvoa.
185+- Haetaan tunniste kutsumalla `FindIdentifierByName`-tunnus muuttujan nimellä parametrina.
186+- Haetaan tunnisteesta`Identifiers` jäsentimen tunnisteiden kokoelmasta käyttämällä muuttujan tunnettua indeksiä: On lisätty `x` ainoana muuttujana, joten sen on oltava indeksissä 0.
187+
188+Kun `Identifier` on tunnettu, muuttujan arvoa voidaan muuttaa avaamalla ominaisuus `AsFloat` (tai `AsDateTime` jne. Vastaavasti):
189+
190+``` pascal
191+var
192+ FParser: TFPExpressionParser;
193+ argument: TFPExprIdentifierDef;
194+ s: string;
195+ x: integer;
196+ f: double;
197+begin
198+ s:='';
199+ FParser := TFPExpressionParser.Create(nil);
200+ try
201+ // Enable the use of mathematical expressions
202+ FParser.BuiltIns := [bcMath];
203+
204+ // Add the function argument
205+ argument := FParser.Identifiers.AddFloatVariable('x', 0.0);
206+
207+ // Define the function, using the argument name x as defined above
208+ FParser.Expression := 'sin(x)*cos(2*x)';
209+
210+ // Calculate some function values
211+ for x := -10 to 10 do
212+ begin
213+ argument.AsFloat := x; // Set the function argument value
214+ f := FParser.Evaluate.ResFloat; // Calculate the function value
215+ s := s + format('x[%d]:[%g]' + LineEnding, [x,f]); // Demo output to display the result
216+ end;
217+
218+ // Show the result
219+ ShowMessage(s);
220+
221+ finally
222+ FParser.Free;
223+ end;
224+end;
225+```
226+
227+## Käyttäjän määrittämien funktioiden lisääminen
228+
229+Oletusparseri tietää vain edellä mainitut sisäänrakennetut funktiot. Yksi parserin vahvuuksista on se, että on hyvin helppo ulottaa muita funktioita. Tämä voidaan tehdä kutsumalla metodia `Identifiers.AddFunction`, esim.
230+
231+``` pascal
232+ FParser.Identifiers.AddFunction('tan', 'F', 'F', @ExprTan);
233+```
234+
235+Tässä esimerkissä lisätään funktio tan(x) määrittelemällä sen nimi, koska se kutsutaan funktion lausekkeissa (ensimmäinen parametri), tulosarvojen tyyppi (toinen parametri, "F" = reaaliluku, "I" = kokonaisluku, "D" = päiväys/aika, "S" = merkkijono tai "B" = boolean) ja syöttöarvojen tyyppi (kolmas parametri, sama logiikka). Jos funktio hyväksyy useita syöttöparametreja, on määritettävä kunkin tyyppi, esim. "FF" kahdella reaaliluvun arvolla tai "FI" ensimmäinen reaaliluku ja toinen on kokonaisluku parametri. Viimeinen parametri osoittaa funktion, jota kutsutaan aina, kun lausekkeen merkkijonossa on "tan". Koska tällä toiminnolla on tietty syntaksi, on se tehtävä omassa lähdekoodissa:
236+
237+``` pascal
238+procedure ExprTan(var Result: TFPExpressionResult; Const Args: TExprParameterArray);
239+var
240+ x: Double;
241+begin
242+ x := ArgToFloat(Args[0]);
243+ Result.resFloat := tan(x);
244+end;
245+```
246+
247+Laskennan tulos palautetaan parametrina `"Result"`, joka on edellä kuvattu `TFPExpressionResult`. Laskennan argumentit siirtyvät `Args`ille, joka on vain joukko TFPExpressionResult-arvoja - koska parametreilla voi olla useita tietotyyppejä. Termi TFPExpression*Results* on ehkä hieman harhaanjohtava, koska tämä taulukko sisältää kaikki * tulo * -parametrit, jotka on määritelty AddFunction-metodin tulotyypeillä.
248+
249+---
250+*From the Free Pascal wiki, page "How To Use TFPExpressionParser/fi", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history