bbCode

Wil je nieuwe functies op het forum? Heb je fouten gevonden die moeten worden verbeterd? Hier kan je suggesties doen om het forum te verbeteren.
User avatar
Wouter
Krypton
Posts: 1980
Joined: 02 Aug 2008, 01:47
Chemistry interests: Organic
Location: Groesbeek, Gelderland
Contact:

Re: bbCode

Post by Wouter » 28 Mar 2010, 22:16

Z4x wrote://edit: Ik weet niet of je de vorige bbcode_formula.php in je www folder hebt gezet, maar verwijder hem daar maar wel. Er zit geen controle op de invoer en ik wil niet dat je last krijgt van "code injects", dus gewoon weggooien die .php. ;)
Ik zet voorlopig nog niets op de server. Ik denk niet dat dit veilig genoeg is om op dit forum te testen. No offence natuurlijk, maar beveiliging is een belangrijk onderdeel van het forum.
Organisch chemicus

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 28 Mar 2010, 23:25

De javascript bijlage is wel veilig hoor wouter (formula.js), dat wordt client-side uitgevoerd (op de computer van diegene die de website bezoekt). Check de code maar.

Volgens mij hebben jullie ook een test forum voor de nieuwe forum style, dan zou je de javascript methode daar misschien kunnen proberen als je tijd hebt. Het is zo geïnstalleerd, drie stappen ongeveer, zie vorige post. Ik ben namelijk wel benieuwd of het werkt. :)
woelen wrote:Z4x, BNF is niet een code die je zo kunt verwerken, maar het is een beschrijving van een grammatica. Op basis van een BNF kun je echter wel gemakkelijk tot een vertaler komen, die formules kan inlezen en vertalen naar een ander formaat. Ik was helemaal vergeten dat je hier nog mee bezig was :$ .
Daar kwam ik vandaag ook achter, het zijn de "regels" ja. :)
woelen wrote: Als je wilt, dan kan ik je de parser/emitter voor mijn chemeq programma wel mailen. Ik heb een implementatie in C en eentje in Java. Uiteraard geeft de emitter in mijn geval geen BB-code, maar genereert deze vectoren voor een wiskundig algoritme om de vergelijkingen op te lossen, maar jij zou de structuur van de software wel moeten kunnen doorgronden.
Dat zou heel mooi zijn (de C versie, java heb ik nog nooit gebruikt), dan kan ik kijken hoe jij dat doet en of ik het begrijp. Heb je ook comments bij je code?

Ik dacht er trouwens aan om een chemische vergelijking tussen de formule tags eerst op te verdelen in "blokjes" door te kijken naar spaties (ruimtes) en die blokjes dan 1 voor 1 te bekijken volgens de BNF "regels".

Wat handig zou zijn, is dat ik zeker weet welke methode wouter bereid is in te voeren. De javascript methode of de php methode. Ik denk dat de javascript de beste methode is. Bij php moet je namelijk de hele phpbb bbcode openbreken (de simpele GET methode werkt niet en is onveilig). Dat javascript niet hetzelfde werkt op verschillende browsers hebben we geen last van denk ik want de gedeeltes die anders werken slaan op het bewerken van elements/div's/css enzo. Het bekijken van stringen en vergelijken werkt denk overal hetzelfde.

Ik heb het de komende periode trouwens redelijk druk, dus ik weet niet hoe vaak ik er aan kan werken, maar het heeft niet echt haast dacht ik.
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 29 Mar 2010, 10:39

woelen wrote: formula ::= <topformula> | "e"
topformula ::= <simple_formula> ["." <simple_formula>]
simple_formula ::= [<digit>] <factor> [<factor>]
factor ::= <element_count> | "(" <topformula> ")" [<digit>] | "[" <topformula> "]" [<digit>]
element_count ::= <element> [<digit>]
digit ::= "0" | "1" ... "9"
element ::= "+" | "-" | "H" | "He" | "Li" ... | "Mt" | "Uun" | "Uuu" | <pseudoelement>
pseudoelement ::= <uppercase> {<lowercase>} {<lowercase>}
uppercase ::= "A" | "B" | ... "Z"
lowercase ::= "'" | "*" | "a" | "b" | .... "z"
Valt onder de digit ook meer dan 9? Bijvoorbeeld "20".
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
woelen
Kobalt
Posts: 1300
Joined: 13 Jan 2009, 20:05
Chemistry interests: --------------
Location: Groningen
Contact:

Re: bbCode

Post by woelen » 29 Mar 2010, 12:29

Sorry, hij is inderdaad ietwat slordig geformuleerd. Ik laat meerdere cijfers toe. Als je het helemaal correct wilt beschrijven dan kun je het zo beschrijven:

formula ::= <topformula> | "e"
topformula ::= <simple_formula> {"." <simple_formula>}
simple_formula ::= {<digit>} <factor> {<factor>}
factor ::= <simple_factor> {<digit>}
simple_factor ::= <element> | "(" <topformula> ")" | "[" <topformula> "]"
digit ::= "0" | "1" ... "9"
element ::= "+" | "-" | "H" | "He" | "Li" ... | "Mt" | "Uun" | "Uuu" | <pseudoelement>
pseudoelement ::= <uppercase> [<lowercase>] [<lowercase>]
uppercase ::= "A" | "B" | ... "Z"
lowercase ::= "'" | "*" | "a" | "b" | .... "z"

Ik heb hem voor jou ook iets verder gestructureerd. Ik heb het concept van een simple_factor toegevoegd, waardoor het iets leesbaarder wordt.
Iets dat tussen {} staat kan 0 of meer keren voorkomen, iets dat tussen [] staat 0 of 1 keer.
Iets tussen "" komt letterlijk voor in de formule.

Een voorbeeld:

K4Fe(CN)6.3H2O (geel bloedloogzout)

topformula = "K4Fe(CN)6.3H2O" = "K4Fe(CN)6" "." "3H2O"
eerste simple_formula = "K4Fe(CN)6"
tweede simple_formula = "3H2O"

Nu ga ik de eerste simple_formula verder uitwerken:

simple_formula = "K4" "Fe" "(CN)6"
eerste factor = "K4", welke bestaat uit een simple factor "K" en een digit "4"
tweede factor = "Fe", welke bestaat uit een simple factor "Fe"
derde factor = "(CN)6", welke bestaat uit simple factor "(CN)" en een digit "6"

Die derde factor is op zijn beurt weer te schrijven als "(" + <topformula> + ")", waarbij de topformula "CN" is.
Die topformula breek je weer verder af.

Je ziet dus, dat je recursie hebt in de parsing van een chemische formule. Een topformula kan via onderliggende simpel_factors weer een topformula bevatten. Dit kan nog dieper worden gedaan met haken binnen haken. De BNF laat willekeurige diepte van recursie toe. Dit is iets dat ook in het echt wel eens wordt gebruikt. Zelf heb ik een keer een complex gemaakt, waarvan de formule haken bevat en dit gehele complex werd op zijn beurt weer gebruikt als een ligand in een omvattend complex (als eerste complex een tin-complex, en dit tin-complex als ligand aan een platina atoom). Exacte info zou ik weer op moeten zoeken.
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 29 Mar 2010, 12:39

Ik ben wel benieuwd hoe je die BNF in je programma hebt opgelost (en of ik de code überhaupt kan begrijpen). :)
woelen wrote:Je ziet dus, dat je recursie hebt in de parsing van een chemische formule. Een topformula kan via onderliggende simpel_factors weer een topformula bevatten. Dit kan nog dieper worden gedaan met haken binnen haken. De BNF laat willekeurige diepte van recursie toe. Dit is iets dat ook in het echt wel eens wordt gebruikt.
Hoe los je zoiets op met programmeren? Lijkt me heel moeilijk.

Heb je de post voor de vorige van mij ook gelezen? :$
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
woelen
Kobalt
Posts: 1300
Joined: 13 Jan 2009, 20:05
Chemistry interests: --------------
Location: Groningen
Contact:

Re: bbCode

Post by woelen » 29 Mar 2010, 14:41

Je maakt een tokenizer welke de verschillende typen symbolen kan extraheren. Zo'n symbool wordt een token genoemd. Uit de BNF kun je halen welke tokens allemaal mogelijk zijn, dat zijn nl. de exacte strings (de literals). In dit geval zijn dat "e", ".", "(", ")", "[", "]", "+", "-", "H", He", "Li", ..., "Mt", "Uun", "Uuu", "0", "1", ... "9". De tokenizer is heel simpel. Iedere keer als je deze aanroept, dan neemt hij het eerstvolgende token van de string en de rest laat hij staan. Deze tokenizer noem ik voor het gemaak even gettoken().

Stel je hebt als input de string "K4Fe(CN)6.3H2O", dan zal de eerste aanroep van gettoken() de string "K" opleveren, de volgende aanroep van gettoken() levert "4" op, volgende aanroepen leveren op "Fe", "(", "C", "N", ")", "6", ".", "3", "H", "2", "O". Als je iets tegenkomt dat je niet in je set van toegestande tokens hebt, dan heb je een tokenize-error en is de formule niet OK. Stel je hebt een formule met bijv. "Ot", dan zal de tokenizer "O" lezen (voor het element zuurstof) en de volgende aanroep zal dan een kleine "t" tegenkomen en dat komt in geen enkel token voor. De tokenizer moet je zodanig schrijven dat deze altijd het langst mogelijke token extraheert, dus "OsCl4" zou "O" kunnen leveren, maar ook "Os", het laatste is het element osmium. Je moet dus het laatste nemen, want anders krijg je een tokenize-error bij de volgende aanroep. Jouw programma moet dus een tabel bevatten van alle mogelijke tokens die je kunt tegenkomen.

De tokenizer kun je schrijven zonder dat je nog iets van parsing afweet. Ik ga er in de rest van deze post vanuit dat je een werkende tokenizer hebt.

Programmeren doe je letterlijk conform de BNF beschrijving. Dus je maakt een functie of method met de naam "parse_formula". Hierin roep je gettoken() aan. Is het token een "e", dan is je formule een "e" en ben je klaar. Je moet nog wel checken of er niks achter de "e" staat. Is het geen "e", dan is het een topformula en je roept de functie parse_topformula() aan. Aan deze functie geef je het uitgelezen token mee als argument.

In parse_topformula() roep je parse_simple_formula() aan. Als deze goed is geschreven, dan leest deze alle tussenliggende tokens weg tot aan de punt of tot het einde van de string of hij geeft aan dat de rest van de formule geen geldige simple_formula is. Vervolgens zit je in een while-lus en zolang je een punt leest als volgend token, roep je weer parse_simple_formula aan. Dit is nodig om ook formules als UO3.H2O2.H2O aan te kunnen.

Vervolgens schrijf je parse_simple_formula(). Hierin lees je tokens in een while lus zolang het digits zijn. Zodra geen digit meer hebt ga je een andere while lus in die niets anders doet dan parse_factor() aanroepen, totdat je geen token meer in kunt lezen.

Zie je? Zo kun je vanuit de BNF de hele parser uitschrijven. Het wordt een echt programma, van een scriptje kun je niet meer spreken, maar dat kun je ook niet verwachten voor een toch vrij complex gebeuren als dit. Je kunt zo heel formeel en volgens een strakke procedure de hele formule-parser uitwerken. Zelf heb ik een opleiding in de informatica (en electrotechniek) achter de rug en dan krijg je dit op de universiteit, ik kan me voorstellen dat voor jou dit best wel lastig is.

Ook recursie is geen probleem met deze manier van werken. Vanuit de parse_simple_factor() functie roep je gewoon weer parse_topformula() aan en je doet alsof je neus bloedt. Dus, als het programma draait dan kun je best hebben dat parse_topformula() meerdere malen wordt aangeroepen en dat je stack frame er als volgt uit ziet:

parse_formula
parse_topformula
parse_simple_formula
parse_factor
parse_simple_factor
parse_topformula ---> recursie, treedt op bij de "(CN)" van K4Fe(CN)6
parse_simple_formula --> recursie, parsing van de "CN"
parse_factor


Als jij jezelf niet comfortabel voelt met recursie, schrijf dan eens een simpel programmaatje dat de waarde van de fibonacci reeks uitrekent voor een gegeven waarde. Zoek maar eens op "fibonacci" en "recursion" op Internet, dan krijg je wel voorbeelden.
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

User avatar
Wouter
Krypton
Posts: 1980
Joined: 02 Aug 2008, 01:47
Chemistry interests: Organic
Location: Groesbeek, Gelderland
Contact:

Re: bbCode

Post by Wouter » 29 Mar 2010, 14:52

OFFTOPIC:
Testforum heb ik twee weken terug afgemaakt, in de negatieve zin. :P

Ik zal zien wat ik komende week kan doen. Het nadeel van tekst formatteren aan de hand van javascript is dat de gebruiker juist afhankelijk is van de browser die ze gebruiken. Google of Bing begrijpen ook geen javascript, dus het is ook slecht voor de indexatie van de pagina. Bij voorkeur is zo'n toepassing dus via PHP actief.
Organisch chemicus

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 29 Mar 2010, 15:11

Wouter wrote:

OFFTOPIC:
Testforum heb ik twee weken terug afgemaakt, in de negatieve zin. :P

Ik zal zien wat ik komende week kan doen. Het nadeel van tekst formatteren aan de hand van javascript is dat de gebruiker juist afhankelijk is van de browser die ze gebruiken. Google of Bing begrijpen ook geen javascript, dus het is ook slecht voor de indexatie van de pagina. Bij voorkeur is zo'n toepassing dus via PHP actief.
Indexatie heeft er niks mee te maken. De javascript werkt alleen tijdens het posten van een bericht, na het posten staat ie als html op internet. Dus als bijvoorbeeld H<sub>2</sub>O. Op internet staat toch ook niet
Hallo
? Daar staat een <div> met special achtergrond kleur en andere html omheen, alleen als je een bericht maakt heb je te maken met tags (om gebruikers makkelijk te maken).

Dit zeg ik er over op chemieforum:
Ander puntje is het gebruik van Javascript wat betekend dat het client-side (op de bezoekers PC) wordt uitgevoerd. Dit heeft als voordeel dat je niet last hebt van een beveiligingslek ('injectie' kan niet), maar mensen die javascript hebben uitgeschakeld kunnen de [formule] tag niet gebruiken. Nou ja, wel gebruiken, maar alles tussen de tags wordt gewoon niet omgezet. (ik vraag me af wie vandaag de dag geen javascript gebruikt, maar toch dat je het weet).

edit: met dat laatste bedoel ik alleen tijdens het maken van een post. als iemand dus de formule tag gebruikt en javascript aan heeft en het bericht heeft gepost dan staat de molecuulformule gewoon goed in de database met html. dat werkt dus altijd en overal, maar tijdens het maken van een post (preview) wordt het als je geen javascript hebt niet omgezet. ik hoop dat ik duidelijk ben. smile.gif
topic: http://www.chemieforum.nl/forum/index.p ... opic=18355.
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 29 Mar 2010, 15:19

Bedankt woelen voor de uitgebreide post. Ik snap het wel redelijk denk ik, maar het omzetten naar code is de moeilijke stap. :)
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
Wouter
Krypton
Posts: 1980
Joined: 02 Aug 2008, 01:47
Chemistry interests: Organic
Location: Groesbeek, Gelderland
Contact:

Re: bbCode

Post by Wouter » 29 Mar 2010, 19:28

Z4x wrote:Indexatie heeft er niks mee te maken. De javascript werkt alleen tijdens het posten van een bericht, na het posten staat ie als html op internet. Dus als bijvoorbeeld H<sub>2</sub>O. Op internet staat toch ook niet Ja, je hebt inderdaad gelijk. Ik zat met mijn hoofd bij het idee dat het pas in de viewtopic.php wordt verwerkt, maar dat heeft geen logica.
Organisch chemicus

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 30 Mar 2010, 19:27

Ik heb een stukje script dat checkt dat alle tekens in de formule 'mogen'. Dus een '>' of een 'é' mogen niet en worden gewoon vervangen met niks.

Probleempje is nu, hoe pas ik nou de uiteindelijk formule aan? Ik bedoel, ik kan wel met een functie steeds verder en verder verdelen, maar wanneer kan ik dan de 3 met <sub>3</sub> vervangen? Of de (9+) met <sup>9+</sup>? Een simpele replace() werkt trouwens niet want dan pakt ie iedere keer dezelfde. Stel je doet replace() en zet om alle dingen sterretjes. Dan krijg je voor "FeCl KO2" dit "*FeCl* *KO2*", maar voor "H2O2 H2O" dit "**H2O*2* H2O". Dat werkt dus niet.

Ik bedenk me nu ook dat als je voor ladingen haakjes gebruikt, je niet een ingewikkelde BNF test hoeft te doen. Een simpele parser zou dan ook kunnen. Je hebt alleen deze situaties/checks nodig:

Bij een los cijfer voor een legaal token -> niks doen (bijv. 2CO)
Bij een los cijfer na een legaal token of haakje sluiten -> verlagen (bijv. H2 of (CH)2 )
Bij een haakje openen en de volgende tokens een cijfer en eindigen met + of - en haakje sluiten -> haakjes weg en verhogen (bijv. Na(2+) )

That's it. Of vergeet ik iets? :$
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
woelen
Kobalt
Posts: 1300
Joined: 13 Jan 2009, 20:05
Chemistry interests: --------------
Location: Groningen
Contact:

Re: bbCode

Post by woelen » 30 Mar 2010, 22:15

En wat gebeurt er als ik intik K4Fe)CN)6 ?? Jouw simpele regels laten dit toe, want er zijn geen ongeldige tokens en je kunt je vertaalregels toepassen en toch komt er nonsens uit. Op zo'n formule wil je gewoon een foutmelding en anders niets. Dat is waar een op BNF gebaseerde parser voor nodig is.

Het vertalen van cijfers door sequenties met lower script en upper script doe je op het moment dat je in de parser een simple_factor hebt gehad en het volgende is een set van digits. In de parse_factor() functie weet je dat je een simple_factor hebt gehad, dus de {<digit>} zet je tussen <sub > en < /sub >.

Dus, je totale programma bestaat uit
1) een scanner/tokenizer
2) een parser
3) een emitter
Alle drie kun je onafhankelijk van elkaar ontwerpen.
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 30 Mar 2010, 22:42

woelen wrote:En wat gebeurt er als ik intik K4Fe)CN)6 ?? Jouw simpele regels laten dit toe, want er zijn geen ongeldige tokens en je kunt je vertaalregels toepassen en toch komt er nonsens uit. Op zo'n formule wil je gewoon een foutmelding en anders niets. Dat is waar een op BNF gebaseerde parser voor nodig is.

Het vertalen van cijfers door sequenties met lower script en upper script doe je op het moment dat je in de parser een simple_factor hebt gehad en het volgende is een set van digits. In de parse_factor() functie weet je dat je een simple_factor hebt gehad, dus de {<digit>} zet je tussen <sub > en < /sub >.

Dus, je totale programma bestaat uit
1) een scanner/tokenizer
2) een parser
3) een emitter
Alle drie kun je onafhankelijk van elkaar ontwerpen.
Ja, tja... nou zit ik met een dilemma. Ik ben het met je eens dat BNF beter is en een foutmelding goed is, maar of dat al die extra moeite waard is? Ik bedoel, stel dat iemand inderdaad K4Fe)CN)6 intikt (en K4Fe(CN)6 bedoelde), dan klikt ie na typen van bericht op preview, ziet dat het fout is en past het aan. Als ie met BNF een fout melding krijgt en ziet dat het fout is, dan moet ie het ook aanpassen... dus die foutmelding is eerder een soort van 'luxe'. Daarnaast zit ik er mee dat het voor mij best moeilijk is zo'n BNF gebaseerde parser te schrijven.

Als die simpele regels van mij altijd consistent werken (en dan gaan we er van uit dat iemand de formule goed intikt en anders na preview corrigeert) en voeg mijn "tokenizer()" erin die niet bestaande elementen en rotzooi uit de formule haalt, dan is dit wel de kortste klap. Ik neig er nu na om zo'n simpel scriptje op te zetten en te proberen.

Jullie gaan het script gebruiken en wouter moet em invoeren, zeggen jullie maar wat jullie liever hebben! Voor de duidelijkheid de punten nog op een rij:

Gebruik simpele parser:

Pro's
- makkelijk te schrijven
- werkt snel en simpel
- grote kans dat ie volledig (binnenkort) afgemaakt wordt
Con's
- geen fout melding
- consistentie? (ik denk dat ie altijd wel goed werkt, maar niet zeker)

Gebruik BNF parser:

Pro's
- volgens BNF regels, altijd correcte formule verwerking
- fout melding
Con's
- moeilijkere code (geen scriptje maar echt programma), meer werk om te maken
- kans dat ik em niet af kan maken of dat het lang duurt voordat ie af is
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 31 Mar 2010, 16:04

Ik heb toch de simpele gemaakt, was best makkelijk. De code is iets anders dan ik had gezegd in bovenstaande post. Volgens mij werkt ie altijd goed.

Ik zit er wel aan te denken om alsnog een BNF parser te schrijven, want dan kan ik misschien ook (als woelen die code wil delen) de ionen laten uitrekenen en gewicht, toch? Is wel veel werk, maar die mogelijkheid is er.

Zouden jullie de bijlage willen uitproberen? (bij IE moet je op de gele balk klikken en 'Geblokeerde inhoud toestaan...' klikken).

//edit: ik vond ook dit: http://www.webqc.org/balance.php. en daar werken ze bij ladingen/ionen met { } in plaats van (), misschien wel beter, dan is wat alles tussen { } zit altijd een lading.
//versie 3.1 heeft {} ondersteuning, werkt beter vind ik.
De kunst is om te blijven oefenen, oefenen en oefenen...

User avatar
Z4x
Gallium
Posts: 1599
Joined: 03 Aug 2009, 15:29
Chemistry interests: Overall
Location: Grunn

Re: bbCode

Post by Z4x » 31 Mar 2010, 19:31

De kunst is om te blijven oefenen, oefenen en oefenen...

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest