[java] expressie evalueren

Pagina: 1
Acties:
  • 108 views sinds 30-01-2008
  • Reageer

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Hoe kan ik in java een expressie zoals

String test = "t";
"String test_string_"+test+" = \"test\""

evalueren ?

Ik heb nl. een aantal expressies in een database staan, die ik wil evalueren na substitutie van een een aantal woorden(namen van variabelen) door de waarden verkregen via gebruikersinput.

  • tomato
  • Registratie: November 1999
  • Niet online
Ik dacht niet dat Java een eval() functie oid had (uit m'n hoofd), dus dan zou je het zelf even moeten parsen.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Is er niet per ongeluk een 'eval' functie?

Of je zou het in een methode van een class-object kunnen laden?

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Op woensdag 10 oktober 2001 00:17 schreef tomato het volgende:
Ik dacht niet dat Java een eval() functie oid had (uit m'n hoofd), dus dan zou je het zelf even moeten parsen.
"Zelf even parsen" > waar doel je op ? als ik geen eval functie tot mijn beschikking heb, hoe kan ik dan een variabele creeeren met een naam aangepast aan een ander variabele?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

laten we het vanuit een ander oogpunt bekijken: waarom wil je dat?

Waarschijnlijk is er een andere (betere) oplossing voor wat je wilt bereiken

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
dat zul je waarschijnlijk met een switch-statement moeten doen, zoiets:
code:
1
2
3
4
5
6
7
8
9
switch (varname)
{
  case "text_string_blaat":
    ...
    break;
  case "text_string_blieb":
    ...
    break;
}

[edit]
Op woensdag 10 oktober 2001 00:54 schreef OiSyN het volgende:
waarom wil je dat?
dat is een erg goede vraag :)

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Nou, om de volgende reden: ik wil grote hoeveelheden tekst samenstellen op basis van opgeslagen gegevens van gebruikers. Aangezien er nieuwe gebruikers bijkomen, en de te gebruiken en te genereren teksten veranderen, lijkt dit me simpelweg de beste oplossing.

Bij een stuk tekst sla ik een conditie/expressie op. Per gebruiker worden vervolgens alle condities afgelopen en de teksten met condities waaraan wordt voldaan worden samengevoegd en aan de gebruiker toegezonden.

Voor iedere gebruiker sla ik dezelfde gegevens op, bijvoorbeeld:

gebruiker A B C
"test" 3 2 1

vervolgense staan er teksten als volgt:

conditie tekst
A==3&&B==2 bladiebla
A==2&&C==1 andere tekst

Nu wil ik dus dat er voor de gebruiker "test" een String wordt gegenereert die "bladiebla" bevat.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
als de conditie altijd iets is als "a == b && c == d" kun je het beter anders oplossen:
code:
1
2
3
4
cond1var cond1val cond2var cond2val tekst
=============================================
A     3   B   2   bladiebla
A     2   C   1   andere tekst

op die manier hoef je de expressie niet helemaal te evalueren en kun je zoiets doen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// kijk of aan conditie1 voldaan is:
switch (cond1var)
{
  case "A":
    cond1 = (A == cond1var);
    break;
  case "B"
    cond1 = (B == cond1var);
    break;
  case "C":
    cond1 = (C == cond1var);
    break;
}

// zelfde met conditie 2
...

// als aan beide condities voldaan is moet tekst gebruikt worden
if (cond1 == true && con2 == true) return tekst;

je zou ook een array kunnen maken voor de variabelen, en dan de indexen ervan in de tabel opslaan ipv de namen zodat je geen switch statement hoeft te gebruiken.
edit:
(of een hashtable gebruiken idd :))


maar dit werkt dus alleen als de expressies altijd dezelfde vorm hebben, en niet bijvoorbeeld '(A == 3 || B == 2) && C = 5)' kunnen zijn.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

handige 'dingen' voor het koppelen van informatie aan een sleutel (in dit geval de gebruiker) zijn hash tables

Java heeft er ook een, genaamd Hashtable, in java.util

je kunt daarin een waarde aan een sleutel koppelen, en dan met behulp van die sleutel later de waarde weer opvragen
Bijvoorbeeld:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Hashtable;

class Test
{
    public static void main (String args[])
    {
      Hashtable table = new Hashtable ();

      // stop de sleutels met waarde in de hashtable
      // "aap" is de sleutel, "noot" is de waarde
      table.put ("aap", "noot");
      table.put ("piet", "bladiebla");

      // en vraag ze later weer op
      String waarde = (String)table.get ("piet");

      // output de waarde naar het scherm
      System.out.println (waarde);
    }
}

dit kleine proggie output dus "bladiebla", dat is de waarde die verbonden is aan de sleutel "piet"

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:34

.oisyn

Moderator Devschuur®

Demotivational Speaker

marcusk: De switch werkt alleen met primitieven, niet met Strings, je zult dat dan op moeten lossen met if blokken

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op woensdag 10 oktober 2001 01:14 schreef OiSyN het volgende:
marcusk: De switch werkt alleen met primitieven, niet met Strings, je zult dat dan op moeten lossen met if blokken
oh, dat is dus ook zo met Java? Maargoed, hashtable is toch beter :)

  • reinouts
  • Registratie: Januari 2000
  • Laatst online: 17-09 20:09
dit lijkt me niet zo moeilijk, tenzij ik je bedoeling niet helemaal goed begrijp.

Je maakt een paar static final Strings aan, met daarin de tekst die je evt. wil appenden. Daar maak je gebruik van in je blokje if-statements, waar je die Strings steeds toevoegt aan een StringBuffer totdat je alle conditities langsgelopen bent.

Dus:

static final String TEKST = "bladiebla";

.
.
.

public String maakTekst(int a, int b, int c) {
StringBuffer tempTekst = new StringBuffer();

if (a == 2 && b == 3) tempTekst.append(TEKST);
if ...
.
.

return tempTekst.toString();
}
edit:
multiline textfields zouden tabs moeten accepteren... ;(

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op woensdag 10 oktober 2001 01:18 schreef reinouts het volgende:
dit lijkt me niet zo moeilijk, tenzij ik je bedoeling niet helemaal goed begrijp.
als ik het goed begrijp zijn de condities als tekst opgeslagen in een tabel, dan werkt dit dus niet.

  • reinouts
  • Registratie: Januari 2000
  • Laatst online: 17-09 20:09
Op woensdag 10 oktober 2001 01:22 schreef marcusk het volgende:

[..]

als ik het goed begrijp zijn de condities als tekst opgeslagen in een tabel, dan werkt dit dus niet.
het aardige van een tabel is dat je er ook gegevens uit kunt halen. Dus stel je hebt een Tabel class, met daarin Conditie objecten met hun eigen evaluatiemethode, en Strings als key, zou je zoiets kunnen maken als:

Tabel t = new Tabel();
.
.
.
if (t.getConditie("A").evaluate(2)) tempTekst.append(TEKST);
.
.

of snap ik het nog steeds niet :?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het leuke van Java is, dat er helemaal geen eval nodig hebt.

Deze oplossing is echter alleen echt goed te gebruiken als je echt een complexe dynamische oplossing nodig hebt zoals reguliere expressies of XSL transformaties (in dit geval kan je het veel makkelijker oplossen dus volgens mij)

Maar goed, als je dit dus wel nodig hebt kan je dynamisch code genereren, compileren en via dynamic class loading laden :) .

In dit geval doe je er beter aan om in een design op te lossen. In iets complexere gevallen kan je een klein taaltje ontwerpen, dit parsen en daarna evalueren.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Voor de duidelijkheid: dit is het huidige ontwerp, de realisatie ervan begint pas later.

Er zijn aardig wat mogelijkheden, namelijk:

A t/m O
antwoorden/gegevens: 1 t/m 15

15 x 15 dus.

Daarnaast wil ik een gebruiker veel vrijheid geven (enige beperking is het tekstveld in mijn database) inhet opgeven van een expressie.

Dus "A==2 && ( B>=1 || B<5 )" moet ook mogelijk zijn.

Aangezien dit voor iedere gebruiker in het systeem verwerkt moet gaan worden (real-time), en het systeem aardig wat gebruikers voor zijn kiezen krijgt (>25.000), lijkt het me niet verstandig om hier een dynamisch code te gaan genereren en vervolgens compileren vanuit een oogpunt van resources.

Ik wil simpelweg de waarden in de expressie vervangen door de huidige waarden, en vervolgens de expressie evalueren zodat deze true danwel false oplevert. Als het teveel resources kost om dit in java op te lossen, kan het op een andere manier (php front-end, dit is een java server), door bij invoer van een nieuwe gebruiker te registreren welke teksten gekozen moeten worden, ook wel, maar dan moet ik bij het aanpassen van de condities voor alle gebruikers de nieuwe condities opnieuw evalueren.

  • B-Man
  • Registratie: Februari 2000
  • Niet online
mbravenboer: wat raad jij me (als zijnde java-expert) aan ?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Tja, als je dit goed op wilt lossen met veel operatoren, prioriteiten en haakjes, kom je toch echt op een parser uit... Je moet een grammatica ontwerpen voor je taaltje en dit parsen naar een boom. Deze kan je daarna evalueren. Als ik het goed begrijp heb je daar niet zo erg veel ervaring mee?

Ik geloof dat ik nog wel een voorbeeld heb liggen met logische formule's.

Je kan ook kiezen voor een ranzige oplossing met XML en dus een XML parser te gebruiken voor het vervelende werk.

Je krijgt dan dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"A==2 && ( B>=1 || B<5 )"

<and>
   <equal>
     <var name="A"/>
     <int value="2"/>
   </equal>

   <or>
      <larger-or-equal>
         <var name="B"/>
         <int value="2"/>
      </larger-or-equal>
      <smaller>
         <var name="B"/>
         <int value="5"/>
      </smaller>
   </or>
</and>

Uiteraard is dit uitermate ranzig, maar je hoeft geen grammatica file te ontwerpen en een parser te genereren. Maar dit is wel erg leuk werk, dus als je het geen probleem vindt zou ik dat toch maar doen :) .
Je krijgt dan uiteindelijk een abstract-syntax-tree die veel lijkt op de XML file hierboven. Daarna moet je deze nog gaan evalueren.

Was er maar een makkelijke en goede manier om Haskell te gebruiken in de JVM. In een functionele taal is dit echt supermakkelijk te doen.... zucht.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Mijn andere optie om Java code te generen is trouwens ook nog wel een goede optie.

Een andere optie is het gebruiken van een scripting omgeving. Er zijn een aantal hele goede engines waarin je gewoon scripts kunt uitvoeren en variabelen aan mee kunt geven. Werk perfect.

Schatting:
- Java code generen: minder werk dan XML file
- XML file: beetje werk
- Scripting: vergelijkbaar met hoeveelheid werk voor XML omdat je de scripting omgeving moet leren kennen.
- Parser + evalueren: meer werk

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik heb even gezocht naar java scripting omgevingen, en liep tegen BeanShell aan, en deze doet precies wat ik zoek. Ik kan een Interpreter starten, vervolgens mijn variabelen definieren, en daarna een expressie op basis van deze variabelen evalueren.

Bijvoorbeeld:
code:
1
2
3
4
5
6
7
import bsh.Interpreter;
...

Interpreter i = new Interpreter();
i.set("foo", 5);
i.eval("bar = foo*10");
System.out.println("bar = "+i.get("bar") );

-[edit]-
Mbravenboer: bedankt voor je tip omtrent java scripting engines... die zoekterm had ik nog niet gebruikt.
XML, zelf een parser schrijven, enz. is niet aan de orde binnen dit project, aangezien de ontwikkeltijd dat voornamelijk in de parser zou zitten ;) (en dat is niet de bedoeling).
Overigens vind ik het wel interessante materie, binnenkort maar eens wat proberen...

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
B-Man: Ik heb even gezocht naar java scripting omgevingen, en liep tegen BeanShell aan, en deze doet precies wat ik zoek.
Mooi :) . Leuk om te zien dat het zo makkelijk aan de praat te krijgen is...
bedankt voor je tip omtrent java scripting engines... die zoekterm had ik nog niet gebruikt.
Graag gedaan :) . Die scripting engines zijn wel aardig populair geloof ik. Ze worden ook wel vaak gebruikt om een en ander te kunnen configureren.
Overigens vind ik het wel interessante materie, binnenkort maar eens wat proberen...
Ok, parsers zijn wel leuk, maar als je nog nooit grammatica's en ASTs hebt gehad is het inderdaad wat veel gevraagd in 1 keer :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Description
JEP is a Java package for parsing and evaluating mathematical expressions. It currently supports user defined variables, constants, and functions. A number of common mathematical functions and constants are included.

Features
Easy-to-use package for parsing mathematical expressions
Supports boolean expressions (with !, &&, ||, <, >, !=, ==, >=, and <=)
Variables can be part of the expression
The values of the variables can be set externally
The expression does not to be parsed again for each time the variables change
All common functions (sin(), cos(), tan()...) included
Extendable through user defined functions
Predefined constants such as 'pi' and 'e'
Support for complex numbers and strings
Package is delivered with JavaCC grammar from which the main classes are generated
Goals
Create an open-source package that can be used for educational purposes in the fields of Engineering, Mathematics and Computer Science
Easy integration in programs that need expression evaluation
Stable, comprehensive source code for people wanting to learn more about parsing
Extendibility through good class structure
License
This package is licensed under the GNU General Public License (GPL). The terms in this license apply to everyone, except for use in the game "Martello Tower" written exclusively for "The Matthew Holland School, Nottinghamshire".


http://jep.sourceforge.net/

  • B-Man
  • Registratie: Februari 2000
  • Niet online
JEP had ik al bekeken, maar alle wiskundige functionaliteit heb ik niet nodig. Ik draai nu alleen de BeanShell core, en die doet precies wat ik wil (en een aantal toekomstige mogelijkheden die in de planning zitten, ook).

--edit

En natuurlijk (belangrijk!): JEP is GPL, en BeanShell is LGPL, en aangezien hetgeen ik aan het ontwikkelen ben voor commerciele doeleinden is, past LGPL daarin.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op donderdag 11 oktober 2001 18:19 schreef B-Man het volgende:
JEP had ik al bekeken, maar alle wiskundige functionaliteit heb ik niet nodig. Ik draai nu alleen de BeanShell core, en die doet precies wat ik wil (en een aantal toekomstige mogelijkheden die in de planning zitten, ook).

--edit

En natuurlijk (belangrijk!): JEP is GPL, en BeanShell is LGPL, en aangezien hetgeen ik aan het ontwikkelen ben voor commerciele doeleinden is, past LGPL daarin.
En anders moet je mij maar ff inhuren :)

  • reinouts
  • Registratie: Januari 2000
  • Laatst online: 17-09 20:09
FYI: BeanShell is ook de geintegreerde macro taal in jEdit (www.jedit.org). Mijn favo editor! O+
Pagina: 1