IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Parser du Python en PHP [PHP 5.4]


Sujet :

Langage PHP

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 100
    Points : 161
    Points
    161
    Par défaut Parser du Python en PHP
    Bonjour à tous,

    Je suis en train de créer un moteur en PHP/HTML pour créer des visual novels (équivalent numériques des livres dont vous êtes le héros). Voici des exemples rapidement mis en place à partir de projet de jeu pré-existants : Sadik City, Wind Fortress, Queen At Arms.

    La plupart des visuals novels sont actuellement réalisés avec Ren'Py, un programme en Python. L'auteur crée son histoire sans utiliser de base de données, en éditant des fichiers dans un langage fortement inspiré du Python.

    J'aimerais créer un script PHP qui permet d'importer automatiquement des jeux réalisés sous Ren'Py (et vice-versa, mais c'est une autre histoire). Il faut donc que je parse des fichiers écrits en quasi-python, pour récupérer les diverses informations. Et là que ça se complique car "les fonctions Python n'ont pas de begin ou end explicites, ni d'accolades qui pourraient marquer là ou commence et ou se termine le code de la fonction. Les seuls délimiteurs sont les deux points («:») et l'indentation du code." (source ici).

    Voici un exemple de code, tiré de la document officielle de Ren'Py, auquel j'ai ajouté quelques commentaires :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #création des personnages
    define sylvie = Character('Sylvie') 
    define me = Character('Me')
     
    # début du jeu
    label start:
        me "Will you be my artist for a visual novel?"
        "Silence."
        "She is shocked, and then..."
        sylvie "Sure, but what is a \"visual novel?\""
    	# Le joueur doit choisir parmi une des deux réponses proposées
    	menu:
    		"It's a story with pictures.":
    			 jump vn
     
    		"It's a hentai game.":
    			 jump hentai
     
    # si le joueur a répondu "It's a story with pictures."
    label vn:
    	me "It's a story with pictures and music."
    	jump marry
     
    # si le joueur a répondu "It's a hentai game."
    label hentai:
    	me "it's a game with lots of sex."
    	jump marry
     
    # suite du jeu commun au deux choix
    label marry:
        "--- years later ---"

    Afin de pouvoir traiter ce code, j'aimerais convertir ce code en un tableau, sous la forme suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    $tableau = array(
    	'define sylvie = Character("Sylvie")',
    	'define me = Character("Me")',
    	'label start' => array(
    		'me "Will you be my artist for a visual novel?"',
    		'"Silence"',
    		'"She is shocked, and then..."',
    		'sylvie "Sure, but what is a \"visual novel?\""',
    		'menu' => array(
    			'"It is a story with pictures."' => array(
    				'jump vn'
    			),
    			'"It is a hentai game."' => array(
    				'jump hentai'
    			)
    		)
    	),
    	'label vn' => array(
    		'me "It is a story with pictures and music."',
    		'jump marry'
    	),
    	'label hentai' => array(
    		'me "it is a game with lots of sex."',
    		'jump marry'
    	),
    	'label marry' => array(
    		'"--- years later ---"'
    	)
    );
    Malheureusement, toutes les idées que j'ai eu sont compliquées à mettre en place et fort peu élégantes, alors que si cela se trouve, cela peut se faire en quelques lignes de code. Le principe est somme toute assez simple !

    Avez-vous des idées de fonctions PHP qui permettrait de classer les éléments selon leur indentation ?

    Merci beaucoup d'avoir pris le temps de lire ce message et peut-être d'y répondre,
    Korbn, aka Dr Schizo

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 100
    Points : 161
    Points
    161
    Par défaut
    Voilà le code que j'ai pondu. C'est un peu tordu, mais cela fonctionne parfaitement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    private $reste = array(); // le tableau source, qui contient toutes les lignes encore à traiter
    private $indent = 0; // le niveau d'indentation actuel
    public function importer() {
        $texte = readfile('script.rpy'); // on récupère le script source en Ren'Py
        $this->reste = explode(chr(13).chr(10),$texte); // une ligne du script équivaut à une ligne dans le tableau des lignes restantes
        // on supprime les lignes vides
        $this->reste = array_filter($this->reste, function($var){
            return (!(trim($var) == ''));
        });
        $resultat = $this->parse();
    }
    /* parse les lignes restantes */
    private function parse(){
        $retour = array();
        while(count($this->reste)>0){ // tant qu'il reste des lignes à analyser
            $i = $this->countIndent(current($this->reste)); // quel est le niveau d'indentation de la prochaine ligne ?
            // si on reste au même niveau d'indentation
            if($i==$this->indent){
                $ligne = trim(array_shift($this->reste)); // on supprime la première ligne du tableau des lignes restantes
                $retour[] = $ligne; // pour l'ajouter au tableau cible  
            }
            // si on passe au niveau d'indentation supérieur
            elseif($i>$this->indent){
                $this->indent = $i; // on met à jour l'indentation
                $key = array_pop($retour); // on parse le contenu de cette fonction
                $retour[$key] = $this->parse(); // on parse les ligned
            }
            // si on revient au niveau d'indentation inférieur
            else{
                $this->indent--; // on met à jour l'indentation
                break;
            }
        }
        return $retour;
    }
    /* récupère le niveau d'indentation de la ligne */
    private function countIndent($string){
        $i = 0;
        while(substr($string,$i,1)==' '){
            $i++;
        }
        return floor($i/4);
    }
    Maintenant que toutes les données sont stockées dans un tableau, je vais pouvoir commencer à travailler avec =)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. php parser en python
    Par sakura.sou dans le forum Réseau/Web
    Réponses: 4
    Dernier message: 06/09/2009, 23h27
  2. [Système] Lancer un script python en PHP
    Par gannher dans le forum Langage
    Réponses: 10
    Dernier message: 13/09/2007, 11h24
  3. [Système] Exécuter script python depuis php
    Par philpython dans le forum Langage
    Réponses: 1
    Dernier message: 22/03/2007, 13h57
  4. [PHP-JS] Parser du xml en php
    Par Christophe Charron dans le forum Langage
    Réponses: 4
    Dernier message: 29/06/2006, 23h48
  5. zope python, apache php
    Par bbmt dans le forum Zope
    Réponses: 1
    Dernier message: 24/05/2006, 18h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo