• [^] # Re: Salaud !

    Posté par . En réponse au journal Générateur de générateur de 'parser'.. Évalué à 1.

    Travailler moins ca veut surtout dire passer plus de temps pour que
    le chose fonctionne mieux. Passer peu de temps à developper c'est
    avoir beaucoup de temps pour faire des tests unitaires et des
    validation fonctionnelle. Et c'est fort appréciable.

    > Blague à part, ce que tu dis sur la génération d'un parser HTTP à
    > partir de l'EBNF m'interresse.

    Et moi dont, malheureusement je ne le génère pas a partir de
    l'EBNF, ce que je génère c'est un 'parser.yacc' et un 'lexer.lex'
    issus de template. Voici comment cela se passe :

    Première étape définir ce qui nous intéresse, c'est à dire mettre
    dans un fichier server_definition.txt la syntaxe suivante non
    exhaustive pour simplifier:


    GET data
    POST data
    "connection:" CONNECTION data
    "accept:" ACCEPT data
    "accept-encoding:" ACCEPTENCODING data
    "cache-control:" CACHECONTROL data
    "pragma:" PRAGMA data


    Voila c'est la liste de ce que mon parser va comprendre.

    Maintenant générons les différents fichiers:
    sh> gen_yacc
    Désormais j'ai un fichier parser.yacc qui sait que CONNECTION
    prend 1 argument

    sh> gen_lex
    Désormais je dispose d'un lexer.lex qui sait que la token
    CONNECTION c'est "connection:"

    sh> gen_files
    Désormais dans le répertoire commands/ j'ai les fonctions
    suivantes: cmd_get.c, cmd_post.c, cmd_connection.c, cmd_accept.c,
    cmd_acceptencoding.c, cmd_cachecontrol.c, cmd_pragma.c.

    Chacune ne seront appelées que si la grammaire est correcte.
    Derniere étape:
    sh> make
    Je dipose maintenant d'un binaire qui comprends
    server_definition.txt.


    Le but final est bien sur de pas partir de server_definition.txt
    mais de l'EBNF contenu dans la RFC.

    Ce n'est qu'une premier étape car vous pouvez bien imaginer que il
    reste un peu de parsing a faire dans les fonction cmd_xxx.

    L'exemple typique c'est
    GET /url HTTP/1.1.
    Car mon parseur va appeler cmd_get avec comme paramètre
    "/url/ HTTP/1.1"
    je suis donc dans l'obligation de découper, cependant et vous me
    l'accorderez facilement, ce découpage n'a rien de très compliqué.

    La difficulté du parseur HTTP c'est que les valeurs peuvent
    s'étendre sur plusieurs lignes, en effet la valeur d'un header
    n'est pas terminée tant qu'on n'as pas trouver un autre header ou
    alors la fin des headers '\r\n\r\n'.
    Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
    peut s'ecrire
    Accept-encoding: gzip;q=1.0,
    identity;q=0.5,
    *;q=0

    C'est une des raisons pour lesquelles j'utilise de ''templates''.
    Un pour le lexer et un pour le parser.