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
woelen
IJzer
Posts: 1298
Joined: 13 Jan 2009, 20:05
Chemistry interests: --------------
Location: Groningen
Contact:

Re: bbCode

Post by woelen » 31 Mar 2010, 19:57

Bij deze de C-code voor de formule parser (iets uitgebreider, want ik laat ook pseudo elementen zoals groepen toe).

formula.c

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "config.h"
#include "formula.h"
#include "elements.h"

/* A formula parser.
 * Chemical formulae can be described as follows:
 * Something between [] can occur zero or more times.
 * Something between {} can occur zero or one time.
 *
 * formula        ::= <topformula> | "e"
 * topformula     ::= <simple_formula> ["." <simple_formula>]
 * simple_formula ::= [<digit>] <factor> [<factor>]
 * factor         ::= <element_count>
 * factor         ::= "(" <topformula> ")" [<digit>]
 * factor         ::= "[" <topformula> "]" [<digit>]
 * element_count  ::= <element> [<digit>]
 * digit          ::= "0" | "1"  ... "9"
 * element        ::= "+" | "-" | "H" | "He" | "Li" ...
 * element        ::= <pseudoelement>
 * pseudoelement  ::= <uppercase> {<lowercase>} {<lowercase>}
 * uppercase      ::= "A" | "B" | ... "Z"
 * lowercase      ::= "'" | "*" | "a" | "b" | .... "z"
 *
 */


static char *get_symbol(char *s, char *sym);
static char *topformula_parse(char *formula, int *total_element_count);
static char *simple_formula_parse(char *s, int *total_element_count);
static char *factor_parse(char *s, int *total_element_count);
static char *element_count_parse(char *s, int *total_element_count);
static void init_count(int *count);
static void incr_count(int *count, int *incr);
static void multiply_count(int *count, int m);


char *formula_parse(char *formula, int *total_element_count)
{
  char symbol[32];
  char *s;

  /* We allow a single 'e' as formula. */
  s = get_symbol(formula, symbol);
  if (symbol[0] == 'e')
   {
    total_element_count[0]--;
    get_symbol(s, symbol);
    return (symbol[0] == 0x00) ? s : NULL;
   }
 
  /* We do not allow a single '-' or '+'. These symbols */
  /* are allowed only as part of a complete formula.    */
  if (symbol[0] == '+' || symbol[0] == '-')
    return NULL;

  s = topformula_parse(formula, total_element_count);
  if (s)
      get_symbol(s, symbol);
  return (s && (symbol[0] == 0x00)) ? s : NULL;
}

static char *topformula_parse(char *formula, int *total_element_count)
{
  char *s, *s1;
  char symbol[32];   /* More than large enough. */

  s = simple_formula_parse(formula, total_element_count);
  if (!s)
    return NULL;

  while (s1 = get_symbol(s, symbol), symbol[0] == '.')
   {
    /* We have a dot, another simple_formula is parsed. */
    s = simple_formula_parse(s1, total_element_count);
    if (!s)
      return NULL;
   }

  return s;
}



static char *simple_formula_parse(char *s, int *total_element_count)
{
  char *s1;
  int *local_element_count = ALLOCA(sizeof(int) * (1+NR_OF_ELEMENTS));
  char symbol[32];
  int multiplier;

  init_count(local_element_count);
  s1 = get_symbol(s, symbol);
  if (isdigit(symbol[0]))
   {
    /* We have a number (set of digits) in front of */
    /* a molecule (e.g. 5H20 in CuSO4.5H20). The    */
    /* complete molecule is multiplied with this    */
    /* number.                                      */
    multiplier = atoi(symbol);
    s = s1;
   }
  else
   {
    /* No number before the molecule, implicit 1. */
    multiplier = 1;
   }

  /* At this place, s points to a non-digit character. */
  /* The optional multiplier is processed. At this     */
  /* place we only can have factors. A factor is an    */
  /* expression in () or [], an element, or a charge.  */
  s1 = s;
  while (s)
   {
    get_symbol(s, symbol);
    if (symbol[0] == '[' || symbol[0] == '(' ||   /* () or []   */
        isupper(symbol[0]) ||                     /* an element */
        symbol[0] == '+' || symbol[0] == '-')     /* a charge   */
      s = factor_parse(s, local_element_count);
    else
      break;
   }
  if (s && s1 != s)
   {
    if (multiplier != 1)
      multiply_count(local_element_count, multiplier);
    incr_count(total_element_count, local_element_count);
   }
  else
   {
   	/* We did not scan anything at all. This is an error. */
   	s = NULL;
   }
  return s;
}





static char *factor_parse(char *s, int *total_element_count)
{
  char *s1;
  int *local_element_count = ALLOCA(sizeof(int) * (1+NR_OF_ELEMENTS));
  char symbol[32];

  s1 = get_symbol(s, symbol);
  if (symbol[0] == '[' || symbol[0] == '(')
   {
    char closing_bracket = (symbol[0] == '[') ? ']' : ')';

    /* We have a compound with [...] or (...) in its formula. */
    init_count(local_element_count);
    s1 = topformula_parse(s1, local_element_count);
    if (!s1)
      return NULL;
    s = get_symbol(s1, symbol);
    if (symbol[0] != closing_bracket)
      return NULL;    /* We expect closing bracket. */
    s1 = get_symbol(s, symbol);
    if (isdigit(symbol[0]))
     {
      /* The complete formula must be multiplied with a number. */
      multiply_count(local_element_count, atoi(symbol));
      s = s1;
     }
    /* The complete formula must be added to the original formula. */
    incr_count(total_element_count, local_element_count);
   }
  else if (isupper(symbol[0]) || symbol[0] == '+' || symbol[0] == '-')
   {
    /* We found an element symbol or a charge unit. */
    s = element_count_parse(s, total_element_count);
   }
  else
   {
    /* We have an improper formula. */
    return NULL;
   }
  return s;
}




static char *element_count_parse(char *s, int *total_element_count)
{
  char *s1;
  int element_number;
  int status;
  char symbol[32];
  int sign;

  s = get_symbol(s, symbol);
  status = elem_by_symbol(symbol, &element_number, NULL);
  if (status != 0)
    return NULL;   /* Unknown element */
  sign = (symbol[0]=='-') ? -1 : 1;  /* Negative charge is counted as -1. */
  s1 = get_symbol(s, symbol);
  if (isdigit(symbol[0]))
   {
    /* We have a multiplier. */
    total_element_count[element_number] += sign * atoi(symbol);
    s = s1;
   }
  else
   {
    total_element_count[element_number] += sign;
   }
  return s;
}



static void init_count(int *count)
{
  int i;
  for (i=0; i<=NR_OF_ELEMENTS; i++)
    count[i] = 0;
}




static void incr_count(int *count, int *incr)
{
  int i;
  for (i=0; i<=NR_OF_ELEMENTS; i++)
    count[i] += incr[i];
}




static void multiply_count(int *count, int m)
{
  int i;
  for (i=0; i<=NR_OF_ELEMENTS; i++)
    count[i] *= m;
}





/* The following helper function gets characters. It skips spaces */
/* and other space-like characters, it checks for end of string.  */

static char *find_next_char(char *s)
{
  while (*s <= ' ' && *s != 0x00)
    s++;
  return s;
}

static char *get_symbol(char *s, char *sym)
{
  s = find_next_char(s);

  if (isupper(*s))
   {
    int nchars;
    *(sym++) = *(s++);
    nchars = 1;
    while ((islower(*s) || *s == '*' || *s == '\'') && nchars<3)
     {
      *(sym++) = *(s++);
      nchars++;
     }
    *sym = 0x00;
    return s;
   }
   
  if (isdigit(*s))
   {
    int nchars;
    *(sym++) = *(s++);
    nchars = 1;
    while (isdigit(*s) && nchars<9)
     {
      *(sym++) = *(s++);
      nchars++;
     }
    *sym = 0x00;
    return s;
   }
  
  if (*s != 0x00) 
    *(sym++) = *(s++);
  *sym = 0x00;
  return s;
}

elements.c

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "elements.h"

int NR_OF_ELEMENTS = NR_OF_REAL_ELEMENTS;


typedef struct chem_elem
{
  char symbol[4];
  double weight;
} chem_elem;


static chem_elem elements[MAX_NR_OF_ELEMENTS+1] =
{
  {"",     -0.00054},
  {"H",     1.00794},     /* period 1 */
  {"He",    4.0026 },
  {"Li",    6.941  },     /* period 2 */
  {"Be",    9.0122 },
  {"B",    10.811  },
  {"C",    12.011  },
  {"N",    14.007  },
  {"O",    15.999  },
  {"F",    18.998  },
  {"Ne",   20.180  },
  {"Na",   22.990  },     /* period 3 */
  {"Mg",   24.305  },
  {"Al",   26.982  },
  {"Si",   28.086  },
  {"P",    30.974  },
  {"S",    32.066  },
  {"Cl",   35.453  },
  {"Ar",   39.948  },
  {"K",    39.098  },     /* period 4 */
  {"Ca",   40.078  },
  {"Sc",   44.956  },
  {"Ti",   47.88   },
  {"V",    50.942  },
  {"Cr",   51.996  },
  {"Mn",   54.938  },
  {"Fe",   55.845 },
  {"Co",   58.933  },
  {"Ni",   58.693  },
  {"Cu",   63.546  },
  {"Zn",   65.409   },
  {"Ga",   69.723  },
  {"Ge",   72.64   },
  {"As",   74.922  },
  {"Se",   78.96   },
  {"Br",   79.904  },
  {"Kr",   83.80   },
  {"Rb",   85.468  },     /* period 5 */
  {"Sr",   87.62   },
  {"Y",    88.906  },
  {"Zr",   91.224  },
  {"Nb",   92.906  },
  {"Mo",   95.94   },
  {"Tc",   97.907  },
  {"Ru",  101.07   },
  {"Rh",  102.906  },
  {"Pd",  106.42   },
  {"Ag",  107.868  },
  {"Cd",  112.411  },
  {"In",  114.818  },
  {"Sn",  118.71   },
  {"Sb",  121.760  },
  {"Te",  127.6    },
  {"I",   126.904  },
  {"Xe",  131.29   },
  {"Cs",  132.905  },     /* period 6 */
  {"Ba",  137.327  },
  {"La",  138.906  },     /* Lanthanides */
  {"Ce",  140.116  },
  {"Pr",  140.908  },
  {"Nd",  144.24   },
  {"Pm",  146.913  },
  {"Sm",  150.36   },
  {"Eu",  151.965  },
  {"Gd",  157.25   },
  {"Tb",  158.925  },
  {"Dy",  162.50   },
  {"Ho",  164.930  },
  {"Er",  167.26   },
  {"Tm",  168.934  },
  {"Yb",  173.04   },
  {"Lu",  174.967  },     /* end of Lanthanides */
  {"Hf",  178.49   },
  {"Ta",  180.948  },
  {"W",   183.84   },
  {"Re",  186.207  },
  {"Os",  190.23   },
  {"Ir",  192.22   },
  {"Pt",  195.08   },
  {"Au",  196.967  },
  {"Hg",  200.59   },
  {"Tl",  204.383  },
  {"Pb",  207.2    },
  {"Bi",  208.980  },
  {"Po",  208.982  },
  {"At",  209.987  },
  {"Rn",  222.018  },
  {"Fr",  223.020  },     /* period 7 */
  {"Ra",  226.025  },
  {"Ac",  227.028  },     /* Actinides */
  {"Th",  232.038  },
  {"Pa",  231.036  },
  {"U",   238.029  },
  {"Np",  237.048  },
  {"Pu",  244.064  },
  {"Am",  243.061  },
  {"Cm",  247.070  },
  {"Bk",  247.070  },
  {"Cf",  251.080  },
  {"Es",  252.083  },
  {"Fm",  257.095  },
  {"Md",  258.1    },
  {"No",  259.101  },
  {"Lr",  262.11   }     /* end of Actinides */
                         /* 104 and beyond --> not registered here */
};


int elem_by_number(int num, char *sym, double *weight)
{
  if (num <= 0 || num > NR_OF_ELEMENTS)
   {
    /* Element with this number does not exist */
    /* or is not registered by this software.  */
    if (sym)
      sym[0] = 0x00;
    if (weight)
      *weight = 0.0;
    return -1;
   }

  if (sym)
    strcpy(sym, elements[num].symbol);
  if (weight)
    *weight = elements[num].weight;
  return 0;
}




/* Returns the atom number, based on the symbol for the element. */
/* A + and a - also are accepted, these return element number 0. */

int elem_by_symbol(char *sym, int *num, double *weight)
{
  int i;

  if ((sym[0] == '+' || sym[0] == '-') && sym[1] == 0x00)
   {
    /* We have a charge unit, either + or -. */
    if (num)
      *num = 0;
    if (weight)
      *weight = 0.0;
    return 0;
   }

  for (i = NR_OF_ELEMENTS; i > 0; i--)
   {
    if (!strcmp(elements[i].symbol, sym))
      break;
   }

  if (i == 0)
   {
    if (num)
      *num = 0;
    if (weight)
      *weight = 0.0;
    return -1;
   }

  if (num)
    *num = i;
  if (weight)
    *weight = elements[i].weight;
  return 0;
}




/* Computes the total weight of all atoms, specified by   */
/* the vector of element occurrences. The argument        */
/* element_count is a vector, containing integer numbers, */
/* specifying how many atoms of each element there are in */
/* a certain compound. For instance H2SO4 (sulfuric acid) */
/* can be specified by putting all zero's in the vector,  */
/* except at index positions 1, 8 and 16. At index 1 the  */
/* value 2 is given, specifiying two hydrogen atoms, at   */
/* index 8 the value 4 is given, specifying four oxygen   */
/* atoms and at index 16 the value 1 is given, specifying */
/* one sulphur atom.                                      */

double elem_total_weight(int *element_count)
{
  double w;
  int i;

  w = 0;
  for (i=0; i<=NR_OF_ELEMENTS; i++)
    w += element_count[i] * elements[i].weight;

  return w;
}




/* Add a pseudo element to the array of elements. */
/* Such pseudo elements can only be added, not    */
/* removed. The only way of removing them is by   */
/* resetting to default.                          */
int elem_add_pseudo(char *sym, double weight)
{
  int len;
  if (NR_OF_ELEMENTS >= MAX_NR_OF_ELEMENTS)
    return -1;

  len = strlen(sym);
  switch (len)
  {
  	case 3:
  	  if (!(islower(sym[2]) || sym[2] == '*' || sym[2] == '\''))
  	    return -1;
      /* Fall through intentionally. */
  	case 2:
  	  if (!(islower(sym[1]) || sym[1] == '*' || sym[1] == '\''))
  	    return -1;
      /* Fall through intentionally. */
  	case 1:
  	  if (!isupper(sym[0]))
  	    return -1;
  	  break;
  	default:
  	  return -1;
  }
  
  NR_OF_ELEMENTS++;
  strcpy(elements[NR_OF_ELEMENTS].symbol, sym);
  elements[NR_OF_ELEMENTS].weight = weight;
  return NR_OF_ELEMENTS;
}


void elem_clear_pseudo(void)
{
  NR_OF_ELEMENTS = NR_OF_REAL_ELEMENTS;
}


formula.h

Code: Select all

#ifndef _CHEM_FORMULA_H
#define _CHEM_FORMULA_H

char *formula_parse(char *formula, int *total_element_count);

#endif


elements.h

Code: Select all

#ifndef _CHEM_ELEMENTS_H
#define _CHEM_ELEMENTS_H

#define NR_OF_REAL_ELEMENTS 103
#define MAX_NR_OF_ELEMENTS  200

extern int NR_OF_ELEMENTS;

int elem_by_number(int number, char *symbol, double *weight);
int elem_by_symbol(char *symbol, int *number, double *weight);
double elem_total_weight(int *element_count);
int elem_add_pseudo(char *sym, double weight);
void elem_clear_pseudo(void);

#endif


config.h

Code: Select all

#ifndef _CONFIG_H
#define _CONFIG_H

typedef unsigned char                         uint8;
typedef unsigned short int                    uint16;
typedef unsigned long int                     uint32;
typedef struct { uint32 high; uint32 low; }   uint64;

typedef char       int8;
typedef short int  int16;
typedef long int   int32;

#define MAX_NIBBLES 256
#define MAX_DIGITS  (MAX_NIBBLES/4)

/* The following constant is used for reading and writing */
/* longnums in decimal format. It is used in the files    */
/* read.c and write.c.                                    */
#define DIGITS_IN_DECIMAL_UNIT 9

#define ALLOCA(n) _alloca(n)

#endif
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

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

Re: bbCode

Post by Wouter » 31 Mar 2010, 20:01

CnC100H202{n+} CnC100H202n+
Cn is tegenwoordig wel een officiëel element. :P

Pas op met deze "herkenning", als ik Cp zeg, dan bedoel ik niet Cp maar het cyclopentadienylmolecuul. In je test krijg ik overigens "FS", wat denk ik duidt op een foute input. :P De chemie zit barstensvol met deze afkortingen, dus ik denk niet dat je ervanuit kan gaan dat als "iets" achter een letter (element) komt, dat een subscript moet zijn.

OFFTOPIC:
Waarom probeer je geen SMILESdecryptor? :P

C[C@@](C)(O1)C[C@@H](O)[C@@]1(O2)[C@@H](C)[C@@H]3CC=C4[C@]3(C2)C(=O)C[C@H]5[C@H]4CC[C@@H](C6)[C@]5(C)Cc(n7)c6nc(C[C@@]89(C))c7C[C@@H]8CC[C@@H]%10[C@@H]9C[C@@H](O)[C@@]%11(C)C%10=C[C@H](O%12)[C@]%11(O)[C@H](C)[C@]%12(O%13)[C@H](O)C[C@@]%13(C)CO
[/offtopic]
Organisch chemicus

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

Re: bbCode

Post by woelen » 31 Mar 2010, 20:01

Bovenstaande code voert niet iets uit, maar verzamelt informatie over alle atomen en ladingen, welke wordt opgeslagen in een array (voor ieder element wordt bijgehouden hoeveel er van voor komen in de formule).

I.p.v. de code die de array bijwerkt kun jij emitter code plaatsen die tags genereert voor weergave van de formule.

Ik kan er mee leven als er voor het script een heel simpel iets wordt gebruikt, voor zo'n script met preview zijn de eisen niet zo strict. Je kan dan echter geen berekeningen van molmassa's e.d. doen, want je bouwt geen echte informatie over de formule op. In mijn toepassing was het absoluut een must om een goede parser te maken.


EDIT: Wouter, je was me net voor terwijl ik dit bericht opmaakte. Bovenstaande post slaat dus op mijn C-code, 2 posts hiervoor.

Z4x, het gebruik van {} voor ladingen is voor mij niet echt een optie, want de haken voor een lading zijn niet wezenlijk anders dan de haken rondom een formule. Je ziet ze ook niet terug in mijn BNF als een apart iets. Ik behandel + en - nl. als elementen en dat moet ik ook, want ik reken met deze dingen. Voor het oplossen van vergelijkingen moet ik nl. zowel behoud van elementen als behoud van lading hebben en om lading niet speciaal af te moeten handelen heb ik hier voor het gemak ook maar een element van gemaakt met atoomnummer 0. In mijn wiskundige algoritme behandel ik lading op de zelfde manier als echte elementen.
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

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

Re: bbCode

Post by Z4x » 31 Mar 2010, 20:34

Wouter wrote:Cn is tegenwoordig wel een officiëel element. :P

Pas op met deze "herkenning", als ik Cp zeg, dan bedoel ik niet Cp maar het cyclopentadienylmolecuul. In je test krijg ik overigens "FS", wat denk ik duidt op een foute input. :P De chemie zit barstensvol met deze afkortingen, dus ik denk niet dat je ervanuit kan gaan dat als "iets" achter een letter (element) komt, dat een subscript moet zijn.

OFFTOPIC:
Waarom probeer je geen SMILESdecryptor? :P

De 'n' kan je zien als een getal. Hij wordt ook zo behandeld. Als Cn een echt element is dan voeg ik die toe als Cn en als je dan Cnn typt krijg je Cnn. Ik kan de 'n' ook weghalen, maar de 'n' lijkt me handig in sommige gevallen als de lading of aantal elementen van de formule niet duidelijk is. :) Cp is geen element en laat ie dus niet toe.


Woelen, wow, bedankt voor de code. :) Ik zal er een keer goed voor moeten gaan zitten en doornemen.

Vind je het trouwens erg als het forum een formule tag (bijvoorbeeld [f] of [formule]) zou hebben waar je voor ladingen deze { } moet gebruiken? Misschien dat het de formule ook wel wat duidelijker maakt.

[f]CH4(O3){2+} [/f]

of

[f]CH4(O3)(2+)[/f]

Programmeer technisch (is dat een woord?) zou je '(' en ')' gelijk kunnen stellen aan '{' en '}', toch?
De kunst is om te blijven oefenen, oefenen en oefenen...

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

Re: bbCode

Post by Wouter » 31 Mar 2010, 20:45

Cp, Ac, Et, Me, iPr, Bu, Ph etc zijn allemaal veelgebruikte afkortingen in de chemie. FeCp2, bijvoorbeeld. Dan kunnen ze misschien geen element zijn, maar NaOEt wordt meer gebruikt dan Na(C2H5O), je ziet zelf ook wel waarom. :P
Organisch chemicus

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

Re: bbCode

Post by Z4x » 31 Mar 2010, 21:03

Wouter wrote:Cp, Ac, Et, Me, iPr, Bu, Ph etc zijn allemaal veelgebruikte afkortingen in de chemie. FeCp2, bijvoorbeeld. Dan kunnen ze misschien geen element zijn, maar NaOEt wordt meer gebruikt dan Na(C2H5O), je ziet zelf ook wel waarom. :P
Ik heb die even snel toegevoegd ( http://lars.stonerocket.co.uk/chemie.html. ), ik vraag me af hoe woelen dat dan doet in zijn BNF/programma, want die staan niet allemaal in de elements.c

//edit: Ipr is weer geval apart. werkt met drie letters. is klein beetje meer werk om die er in te doen.

//edit: als jullie willen weten hoe de simpel parser werkt. Hier is de code:

Code: Select all

Array.prototype.exists = function(o) {
for(var i = 0; i < this.length; i++){
   if(this[i] == o) return true;
   }
   return false;
}

function tokenize(o) {
	check = 1;

		for(x = 0; x < o.length; x++){

			if(tokens.exists(o[x]) == false){check = 0;
				if(tokens.exists(o[x-1]+o[x]) == true)check = 1; 
				if(tokens.exists(o[x]+o[x+1]) == true)check = 1; 
			}
		}
	return check;
}

var data;
var tokens = [
'g','s','aq','n',
'Cp', 'Ac', 'Et', 'Me', 'iPr', 'Bu', 'Ph', <!-- afkortingen-->
'↔','←','→','[',']','=',':','<','>','e','.','·','(',')','+','-','{','}',
'0','1','2','3','4','5','6','7','8','9', 
'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr'];
var element = [
'Cp', 'Ac', 'Et', 'Me', 'iPr', 'Bu', 'Ph',
')','H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm', 'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr'];
var digit = ['0','1','2','3','4','5','6','7','8','9','n'];
var plusmin = ['+','-'];

function process (form) {
	data = form.inputbox.value;
	data = data.split(" ");

	for (i=0; i < data.length ; i++){
	if (tokenize(data[i]) == false)data[i] = 'FS';
	}
	
	data = data.join(" ")
	var output = data;
	
	for (x=0; x < data.length ; x++){
		if(digit.exists(data[x])){
		
		if( digit.exists(data[x+1]) && digit.exists(data[x+2]) ){
				if( element.exists(data[x-1]) ){
					output = output.replace(data[x-1] + data[x] +data[x+1]+data[x+2]  , data[x-1]+'<sub>'+data[x]+data[x+1]+data[x+2]+'</sub>');
				}
				if( element.exists(data[x-2]+data[x-1]) ){
					output = output.replace(data[x-2]+data[x-1]+data[x]+data[x+1]+data[x+2]  , data[x-2]+data[x-1]+'<sub>'+data[x]+data[x+1]+data[x+2]+'</sub>');
				}
			}
		
			if( digit.exists(data[x+1]) ){
				if( element.exists(data[x-1]) ){
					output = output.replace(data[x-1] + data[x] +data[x+1]  , data[x-1]+'<sub>'+data[x]+data[x+1]+'</sub>');
				}
				if( element.exists(data[x-2]+data[x-1]) ){
					output = output.replace(data[x-2]+data[x-1]+data[x]+data[x+1]  , data[x-2]+data[x-1]+'<sub>'+data[x]+data[x+1]+'</sub>');
				}
			}
			
			if( element.exists(data[x-1])){
				output = output.replace(data[x-1]+data[x]  ,  data[x-1]+'<sub>'+ data[x]+'</sub>');
			}			
			if( element.exists(data[x-2]+data[x-1])){
				output = output.replace(data[x-2]+data[x-1]+data[x]  ,  data[x-2]+data[x-1]+'<sub>'+data[x]+'</sub>');
			}
		}

		if(data[x] == '{'){
		
		if( data[x+4] == '}'){
			output = output.replace(data[x]+data[x+1]+data[x+2]+data[x+3]+data[x+4],  '<sup>'+data[x+1]+data[x+2]+data[x+3]+'</sup>');
		}
		
		if( data[x+3] == '}'){
			output = output.replace(data[x]+data[x+1]+data[x+2]+data[x+3] ,  '<sup>'+data[x+1]+data[x+2]+'</sup>');
		}		
		
		if( data[x+2] == '}'){
			output = output.replace(data[x]+data[x+1]+data[x+2] ,  '<sup>'+data[x+1]+'</sup>');
		}
		
		}
}


	document.getElementById('example').innerHTML = output;
	document.forms['output_html'].elements['outputbox'].value = output;
			while (output.indexOf('<sub>') != -1)output = output.replace('<sub>', '[sub]');
			while (output.indexOf('</sub>') != -1)output = output.replace('</sub>', '[/sub]');
			while (output.indexOf('<sup>') != -1)output = output.replace('<sup>', '[sup]');
			while (output.indexOf('</sup>') != -1)output = output.replace('</sup>', '[/sup]');
	document.forms['output_bb'].elements['outputbox'].value = output; //bbcode of formula
	

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

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

Re: bbCode

Post by woelen » 31 Mar 2010, 21:45

Mijn programma laat het toe groepen te definieren. Ik heb een webapplicatie gemaakt met vergelijkbare achterliggende code, speel daar maar eens mee en je kunt zelf dit soort "elementen" definieren.

Hier is de online calculator: http://woelen.homescience.net:18080/chemeq/.

Hier is de tutorial waarin beschreven staat hoe je groepen kunt maken: http://woelen.homescience.net:18080/che ... tutor.html.

Ik hoef dit soort elementen dus niet in een tabel op te nemen, als je ze nodig hebt, dan maak je ze zelf aan.
The art of wondering makes life worth living...
Want to wonder? http://www.oelen.net/science

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

Re: bbCode

Post by Z4x » 31 Mar 2010, 22:43

Oja, dat is wel erg handig dat je dat zelf kan aanmaken en kan zeggen dat Et bijvoorbeeld CH3CH2 is. Op een forum met formule tags (bbcode) werkt dat niet zo handig, maar we zouden van te voren de meest gebruikte afkortingen al kunnen aanmaken.
De kunst is om te blijven oefenen, oefenen en oefenen...

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

Re: bbCode

Post by Z4x » 31 Mar 2010, 23:46

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 Uh, ik moet hier toch ff op terug komen. Het klopt niet helemaal wat ik zeg. Normaal werkt een bbcode zo:

Je voert dit in [ssub]Hoi[/sub] (expres stuk gemaakt) en forum zet met php om in <sub>Hoi</sub> als ie de pagina laat zien. Dus in de database staat ook [ssub]etc.

Nou heb ik een custom bbcode gemaakt die bij een formule tag dit doet:

Code: Select all

<script language="JavaScript" src="formula.js"></script>

<script language="JavaScript">process('{TEXT}');< /scrip>
waar {TEXT} je formule is. dus als je invoert tijdens posten dit: [formule]H2O[/formule] dan staat dat in de database en als je de pagina ziet staat er dit in de HTML/code (gemaakt door php van forum):

<script language="JavaScript" src="formula.js"></script>

<script language="JavaScript">process('H2O');</script>

Dit is op zich beter voor indexatie,want mensen typen tijdens googlen eerder H2O dan H<sub>2</sub>O zou ik zeggen.

vervolgens verwerkt de javascript de H2O en maakt er H2O van maar als de javascript niet werkt (of uit staat) dan komt er niks te staan, want er wordt niks verwerkt.
deze methode heeft als voordeel dat je server ontlast, al vraag ik me af hoeveel dat is.
edit: de lijn: <script language="JavaScript">process('H2O');</script>, blijft trouwens gewoon staan en daar naast komt dan H2O te staan ( in html)

op zich zou je de javascript methode wel kunnen gebruiken als tijdelijk oplossing, want als er wel een keer php versie komt (en phpbb makkelijker custom bbcode met php functie kan maken) dan staat er in de database gewoon goed [formule]H2O[/formule].

zo is het trouwens ook dat als je de simpele parser op het forum invoert met {} voor ladingen/ionen en later bedenkt dat je liever BNF parser wil met () voor ladingen/ionen dan kan je of gewoon de BNF parser aanpaseen ook {} te kunnen lezen of simpel een search/replace in de database doen voor {} die gebruikt worden in formule tags.

ik denk dat [f]H2O[/f] mooier is als [formule]H2O[/formule]
De kunst is om te blijven oefenen, oefenen en oefenen...

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

Re: bbCode

Post by Wouter » 02 Apr 2010, 13:30

Google trekt zich niets aan van opmaak (dwz. H2O is gelijk aan H2O). Maar javascript wordt compleet overgeslagen. Tekst tussen javascript wordt waarschijnlijk niet gevonden, de context is immers verdwenen.
Organisch chemicus

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

Re: bbCode

Post by Z4x » 02 Apr 2010, 14:12

Wouter wrote:Google trekt zich niets aan van opmaak (dwz. H2O is gelijk aan H2O). Maar javascript wordt compleet overgeslagen. Tekst tussen javascript wordt waarschijnlijk niet gevonden, de context is immers verdwenen.
Ik weet het niet zeker, maar ik dacht dat google wel wat simpele javascript leest (en dan vooral zoekt of er links in zitten). Maar volgens mij is dat niet zo belangrijk, want op de html pagina staat gewoon (als voorbeeld):
<script language="JavaScript">process('H2O');</script>
En dan leest/indexeert de searchbot/google gewoon de H2O. (echt 100% zeker ben ik het helaas niet). De H2O die het script maakt komt namelijk achter die lijn te staan, het verplaatst het niet.

Via PHP de formule tag laten laten lopen is beter, maar dat is gewoon heel erg moeilijk omdat phpbb (bbCode) zo raar werkt.
De kunst is om te blijven oefenen, oefenen en oefenen...

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

Re: bbCode

Post by Wouter » 02 Apr 2010, 15:04

Ik weet 100% zeker dat google dit overslaat, omdat de crawler geen javascript begrijpt. De crawler begrijpt zelfs de gehele zin niet meer, op dat moment en de kans bestaat dat de zin dan niet wordt opgenomen. De crawler leest alleen HTML en bekende opmaak. Javascript is een eigen taaltje, waarbij de functies gebruikergedefiniëerd zijn, dat kan een crawler niet begrijpen.
Organisch chemicus

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

Re: bbCode

Post by Z4x » 02 Apr 2010, 19:48

Ik merk wel dat je indexeren belangrijk vindt (en op zich is dat het ook).

Is het misschien anders een idee om naast de tabbladen 'opties' en 'bijlage toevoegen' een tab te maken met formula en dat je daar de formule kan intypen (met voorbeeld) en op invoegen klikt en dat het met sub/sup wordt ingevoegd in de textbox.

Zo gebruik je dus geen [formule] of [f] tag maar de normale [sub.] en [sup.] (geen punt dan natuurlijk, maar anders pakt het forum em nu).

Ik weet niet hoe makkelijk het is om daar eigenlijk een tabblad bij te doen
De kunst is om te blijven oefenen, oefenen en oefenen...

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

Re: bbCode

Post by Wouter » 02 Apr 2010, 23:17

Ik ga dit weekend weer uitgebreid aan het forum werken, misschien kan ik wel wat bedenken of proberen. Maar ik geef geen garanties. :P
Organisch chemicus

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

Re: bbCode

Post by Z4x » 05 May 2010, 10:38

Op het wetenschapsforum ben ik mijn script ook aan het "verkopen" en daar geeft Jan van den Velde de suggestie om voor alles wat 'omhoog' moet een dakje te zetten. Dus NH4^+ geeft NH4+.

Zijn originele berichten:
Als het daarover gaat lijkt SO4^2- zo zot nog niet

Ja. Alle getallen direct ná een letter subscript, alle getallen direct na een spatie en voor een letter gewoon, alle karakters tussen ^ en plus of min in superscript. Dat dekt het dacht ik toch?
Is dit misschien iets? In plaats van de curly brackets (zoals nu: http://lars.stonerocket.co.uk/chemie.html.)?
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