Sign in Join
Wiki copytemporary

How To Use TFPExpressionParser/fi

English · Suomi

TFPExpressionParser sallii analysoida ja laskea laskuja kuten sin(x)*cos(2*x) muuttujan x millä tahansa arvolla. Matemaattisten lausekkeiden lisäksi se voi käsitellä myös boolean arvoja, merkkijonoja, päivämäärän/ajan arvoja jne. Jopa käyttäjän antamat toiminnot voidaan yhdistää.

Se kuuluu FPC:n Free Component Library (FCL)-kirjastoon ja se on toteutettu käännösyksikössä (unit) fpexprpars.pp, kansio (fpc_source_dir)/packages/fcl-base/src. Lisätään vain fpexprpars 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ä.

Parserin luominen

Parserin/Jäsentimen voi luoda tällaisella instanssilla:

pascal
uses
      fpexprpars;
    
    var
      FParser: TFPExpressionParser;
    begin
      FParser := TFpExpressionParser.Create(self);
      // ... do something (see below)

Jos tätä kutsutaan lomakkeen metodista, "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 ohjelmassa ilman lomaketta tai edes 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:

pascal
uses
      fpexprpars;
    
    var
      FParser: TFPExpressionParser;
    begin
      FParser := TFPExpressionParser.Create(nil);
      try
        // ... do something (see below)
      finally
        FParser.Free;
      end;
    end;

Sisäänrakennetut luokat

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 tunniste sisäänrakennettujen luokkien joukkoon. Niihin pääsee parserin ominaisuudella BuiltIns:

pascal
type
      TBuiltInCategory = (bcStrings, bcDateTime, bcMath, bcBoolean, bcConversion, bcData, bcVaria, bcUser);
      TBuiltInCategories = set of TBuiltInCategory;

Tässä on kokoelma sisäänrakennettuja symboleja, joita voidaan käyttää lisäämällä luokkia parserin BuiltIns - jokainen, joka "ymmärtää" Pascalia, pitäisi olla selvää, mitä nämä symbolit tarkoittavat ...

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.

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Huomaa: Nämä symbolit eivät ole iso/pieni kirjain kohtaisia.

Jotta matemaattista lauseketta voidaan käyttää niin valinta bcMath on lisättävä parserin Builtins:

pascal
FParser.Builtins := [bcMath];   // or FParser.Builtins := FParser.Builtins + [bcMath];

Lausekkeet

Lausekkeet vakioilla

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:

pascal
FParser.Expression := '1+1';

Seuraava vaihe on laskea lauseke: vain kutsu Evaluate tai EvaluateExpression -

ensimmäinen on funktio, kun taas jälkimmäinen on aliohjelma, joka antaa tuloksen parametrina.

pascal
var
      parserResult: TFPExpressionResult;
    begin
     ....
      parserResult := FParser.Evaluate;  // or: FParser.EvaluateExpression(parserResult);

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:

pascal
type
      TResultType = (rtBoolean, rtInteger, rtFloat, tDateTime, rtString);
    
      TFPExpressionResult = record
        ResString   : String;
        Case ResultType : TResultType of
          rtBoolean  : (ResBoolean  : Boolean);
          rtInteger  : (ResInteger  : Int64);
          rtFloat    : (ResFloat    : TExprFloat);
          rtDateTime : (ResDateTime : TDatetime);
          rtString   : ();
      end;

Jäsen ResultType -signaalit, jonka vain yksi tietokentistä on voimassa. On tärkeää ymmärtää tämä, koska parseri on hyvin tiukka tietotyyppien suhteen.

Esimerkissä lisätään kaksi 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 tietueen parametriksi ja valitsee oikean komponentin, jos reaaliluku tulosta odotetaan:

pascal
var
      parserResult: TFPExpressionResult;
      resultValue: Double;
    ...
      parserResult := FParser.Evaluate;   // or: FParser.EvaluateExpression(parserResult);
      resultValue := ArgToFloat(parserResult);

https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png Huomaa: Reaaliluvuilla on oltava piste desimaalierottimena, ei 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.

Lauseke muuttujalla

Tässä esimerkissä lasketaan sin(x)*cos(2*x) jossa x = 0.5 (0,5).

Muuttujien määrittäminen

Aluksi on määriteltävä muuttujat. On vain yksi x. Parserilla on metodi AddFloatVariable, joka ilmoittaa reaaliluvun; on myös menetelmiä:

boolean-, merkkijono- ja päivämäärä/aika-muuttujille, vastaavasti.

Jokainen näistä aliohjelmista odottaa muuttujan nimeä sekä sen oletusarvoa. Näyte funktiolle sin(x)*cos(2*x) kutsutaan vain:

pascal
FParser.Identifiers.AddFloatVariable('x', 0.5);

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.

Voit tietysti lisätä muita nimiä, esim. vakiota, kuten e jne. (Pii (pi) on jo sisäänrakennettu).

Lausekkeen määrittäminen

Seuraavassa vaiheessa lausekkeen merkkijono lähetetään parserille:

pascal
FParser.Expression := 'sin(x)*cos(2*x)';

On välttämätöntä kutsua tätä muuttujien asettamisen jälkeen, koska jäsentimen on tiedettävä muuttuja lausekkeen analysoimiseksi.

Lausekkeen laskeminen

Tämä tehdään kuten aikaisemmin vakio lausekkeella - tässä on täydellinen aliohjelma, joka näyttää yhtälön ja sen tuloksen viestiruudussa (ShowMessage):

pascal
var
      FParser: TFPExpressionParser;
      resultValue: Double;
    begin
      FParser := TFPExpressionParser.Create(nil);
      try
        FParser.BuiltIns := [bcMath];
        FParser.Identifiers.AddFloatVariable('x', 0.5);
        FParser.Expression := 'sin(x)*cos(2*x)';
        resultValue := FParser.Evaluate.ResFloat;  // or: resultValue := ArgToFloat(FParser.Evaluate);
        ShowMessage(FParser.Expression + ' = ' + FloatToStr(resultValue));
      finally
        FParser.Free;
      end;
    end;

Muuttujien muuttaminen

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)".

Jotta tämä käyttäytyisi enemmän kuin "muuttuja", lasketaan nyt testi funktion x-arvoja välillä -10 ja 10.

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:

Kun Identifier on tunnettu, muuttujan arvoa voidaan muuttaa avaamalla ominaisuus AsFloat (tai AsDateTime jne. Vastaavasti):

pascal
var
      FParser: TFPExpressionParser;
      argument: TFPExprIdentifierDef;
      s: string;
      x: integer;
      f: double;
    begin
      s:='';
      FParser := TFPExpressionParser.Create(nil);
      try
        // Enable the use of mathematical expressions
        FParser.BuiltIns := [bcMath];
    
        // Add the function argument
        argument := FParser.Identifiers.AddFloatVariable('x', 0.0);
    
        // Define the function, using the argument name x as defined above
        FParser.Expression := 'sin(x)*cos(2*x)';
    
        // Calculate some function values
        for x := -10 to 10 do
        begin
          argument.AsFloat := x;                             // Set the function argument value
          f := FParser.Evaluate.ResFloat;                    // Calculate the function value
          s := s + format('x[%d]:[%g]' + LineEnding, [x,f]); // Demo output to display the result
        end;
    
        // Show the result
        ShowMessage(s);
    
      finally
        FParser.Free;
      end;
    end;

Käyttäjän määrittämien funktioiden lisääminen

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.

pascal
FParser.Identifiers.AddFunction('tan', 'F', 'F', @ExprTan);

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:

pascal
procedure ExprTan(var Result: TFPExpressionResult; Const Args: TExprParameterArray);
    var
      x: Double;
    begin
      x := ArgToFloat(Args[0]);
      Result.resFloat := tan(x);
    end;

Laskennan tulos palautetaan parametrina "Result", joka on edellä kuvattu TFPExpressionResult. Laskennan argumentit siirtyvät Argsille, 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ä.


From the Free Pascal wiki, page "How To Use TFPExpressionParser/fi", as the Internet Archive kept it on 2025-04-19, last changed on 2025-01-01. 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.

Revision 2, last changed by WikiArchive .

Edited on wiki.freepascal.org by 2 people, 2019–2022

From the official wiki's backup of 26 May 2024: who edited this page there, and when. Edits made there after that date were not recorded, and the earlier versions are not shown here; the main page says why.

WhenWhoWhat changed
DjzepiCreated page
Djzepi
Djzepi
Kai Burghardtresolve Category: Pages using deprecated enclose attributes (minor)

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.