Parseur en python

Bonjour à tous,

Grace aux conseils avisés que des zoniens m’ont donné dans ce topic, je sais maintenant que pour faire ce que je voudrais faire, je dois passer par de la programmation. J’ai déjà commencé à me renseigner sur python qui a l’air d’être nioub-friendly mais j’avoue que mon expérience de la programmation date de la tortue sur C64 :stuck_out_tongue:

Bref, je m’en sortirai pas sans aide et ce même si j’essaierai de faire un maximum par moi-même. Tout commentaire constructif sera donc le très bienvenu. Dans un premier temps j’ai essayé de mettre en français les règles de mon parseur :

Variables : T, G, X, Y, Z
Valeurs possibles : 	T =(1 à 44)+ valeurs spéciales (4,5,6,7,8) et (42/8)
			G =(100 à 185)+ valeur spéciale (172)
			X, Y et Z =(0 à 600)

-Ouvrir le fichier "input" et créer un fichier "output".
-Lire chaque ligne du fichier input.
-A chaque G rencontré, création d'une ligne dans le fichier output avec la valeur de G.
-Dans cette ligne du fichier output, écrire la première valeur de X, Y, Z qui suivent le G et la valeur de T qui précède le G dans le fichier input.
-Si dans la suite il y a un nouveau Y ou un nouveau X sans nouveau G, reproduire la ligne précédente en changeant la valeur de X ou de Y.
-Si G=172 suivi de G=186,création d'une double ligne avec G=172 et les premières valeurs de X,Y et Z rencontrées pour la première ligne. Pour la seconde ligne G=186 avec le même Y mais le plus grand X rencontré dans la suite avant un nouveau Y. Au nouveau Y, reproduire la double ligne précédente avec le nouveau Y.

Est-ce que ça vous semble un bon début ou bien je commence pas du tout comme il faut ? 

Merci d’avance,

inb4 bubu.
Sinon, essaie quand même de faire des boucles dans ton pseudo code , exemple :
Pour chaque ligne de input faire
         Si blabla
                  faitqq
         Sinon
                  faireautrechose
        
Ah et met une commande par ligne, ça rend le pseudo code plus clair.

[quote=“Miaouss, post:1, topic: 55095”][/quote]

Alors perso :

Je trouve casse gueule de faire une variable globale contenant des speciales.

Soit tu fais des tableaux soit tu fais un dict :

T = { “normal” : [1,…,44], “special”:[4,5…,42/8]}

Chiant que je n’ai pas le temps sinon je te l’aurais fait -_- il te faut ca pour quand ? (je risque d’avoir du temps pendant la nuit du hack ce wkend).

te faut un regex, c’est le plus simple pour ce que tu veux faire, tu peux quasiement tout faire en 1 ligne avec un joli regex. Par contre c’est une science, demande à Ivru, il est bon en regex :wink:

en php tu ferais un truc du genre
if preg_math($pattern, $ligne_input, $match) fwrite($output, explode($match,’,’));

le truc c’est d’ecrire la pattern et de recuperer dans match les bons indexs trouvés

Tu peux nous donner un exemple de fichier d’entrée à traiter ? Ca serait pas mal pour t’aider.

Oui nomme tes variables et regarde du côté des expressions régulières, c’est hyper pratique pourun parseur.

Cool, plein de monde !

Oui effectivement j’aurais du penser à réfléchir un peu avec des boucles, c’est un des premiers trucs que les vidéo sur python m’ont montré :cassetete: Je vais aussi voir pour mettre un fichier de départ et d’arrivée

Merci tout plein, j’avais peur que ça n’intéresse personne (ce qui aurait été compréhensible). Je reviens dès que possible pour répondre et amener d’autre infos.

Serieux, t’es toujours sur ce probleme la ? Et on te poses toujours les memes questions pour t’aider…

@miaouss:
On a du mal à comprendre ce que tu souhaites, tu devrais plus découper ton pseudo-code. Aussi avec des boucles comme le dit kaneloon.

En tout cas pour la partie technique si tu le fais en python sers toi de la fonction split() et/ou list() en fonction de ce que tu veux faire.

import string
str_source="le chat est là "
str_cible1=list(str_source)
print str_cible1
[‘l’, ‘e’, ’ ', ‘c’, ‘h’, ‘a’, ‘t’, ’ ', ‘e’, ‘s’, ‘t’, ’ ', ‘l’, ‘\xc3’, ‘\xa0’, ’ ']
str_cible2=str_source.split()
print str_cible2
[‘le’, ‘chat’, ‘est’, ‘l\xc3\xa0’]
Tu boucles sur l'un ou l'autre de ces tableaux, pour faire tes traitements en te servant des fonctions de liste : http://docs.python.org/2/tutorial/datastructures.html


et à la fin tu recomposes ton texte. Là comme je n'ai rien fait il est identique au départ
print string.join(str_cible1,'')
le chat est là
print string.join(str_cible2,'')
le chat est là
Sinon il y a la library re : http://docs.python.org/2/howto/regex.html

(edit: petite correction nom de variable)

[quote=“AnA-l, post:8, topic: 55095”][/quote]
Oui j’y suis encore ou plutôt j’y reviens. Lors du dernier topic je me suis rendu compte que ce serait plus compliqué que je ne le pensais et j’ai donc attendu d’avoir le temps de m’y consacrer. Là par exemple, quand je reçois un morceau de code comme celui de phili_b ou le tien dans le dernier topic, ça me prend plein de temps d’essayer de comprendre comment ça marche et à quoi ça sert…

Sinon pendant que je réécris mon pseudo-code, voici les fichiers de départ et d’arrivée demandés : [attachment=1967:De atdedit.txt] Ca c’est le fichier de départ.
[attachment=1968:Info CNC.txt] Ca c’est ce à quoi je dois arriver.

[quote=“Miaouss, post:10, topic: 55095”][/quote]

:wassat: :blink: En tout cas moi je ne comprends pas  quelle logique il y a entre ces 2 fichiers.

Si je puis me permettre, essaie de faire la formation http://www.codecademy.com/tracks/python
Comme tu dis être noob, ca peut être un bon départ pour se mettre à niveau…

http://inforef.be/swi/python.htm

juste le meilleur bouquin de programmation de python et si ce n’est un des meilleurs bouquins qui soit.

Tu sens que le type est prof et excellent pedagogue.

[quote=« phili_b, post:11, topic: 55095 »][/quote]

Pareil.

Du coup, si tu veux aboutir, parce que ca a l’air compliqué, il faut que tu fasses les choses dans l’ordre :

1/ tu ecris des spec clair et en francais. Pas besoin de pseudo code ici, il faut juste que tu exprimes clairement ce que ce doit faire. Il faut que tu sois exaustif sur les traitements. Ca va te forcer a reflechir à ce que ce doit faire precisement

2/ tu commences les premiers algo de traitement en pseudo code. Te limite pas au comment des methodes. Juste la structure.

3/ tu codes le 2.

Pour le 1, on peut pas t’aider : j’ai absolement pas compris la logique qui te permet de passer du fichier 1 au fichier 2. C’est une logique metier, tu la connais, il faut que tu l’ecrives.

Pour le 2 et le 3, on pourra t’aider, une fois que tu nous auras donner le 1 :slight_smile:

OK je commence un peu à comprendre. Sauf erreur le fichier d’input (ancien format) est un peu comme un fichier d’impression : ce sont des commandes unitaires qui positionnenent un état d’une des variables. Tandis que le nouveau format est une liste d’états globaux. Je veux bien que quelqu’un me dise si j’ai tort, mais si j’ai raison je pense qu’on peut commencer à t’aider :wink:
 
Edit : Bon la logique métier a l’air un peu plus compliquée que ce que je pensais, mais voilà un squelette sur lequel tu peux te baser.

# -*- coding:Latin-1 -*-
import sys

stackG = []
stackT = []
stackX = []
stackY = []
stackZ = []

# On ouvre le fichier à lire
f = open("De atdedit.txt", 'r') 
# Tant qu'il y a une ligne à lire :
for line in f: 
# 	Découper la ligne en une liste de champs
	fields = line.split('\t')
# 	Tant qu'il y a un champ à traiter dans la liste :
	for field in fields:
# 		Si le champ est un G :
		if field.startswith('G', 0, 1):
# 			Ajouter la valeur de G à la liste de valeurs de G
			stackG.append(field)
# 		Fin (si)
# 		Si le champ est un T :
		if field.startswith('T', 0, 1):
# 			Ajouter la valeur de T à la liste de valeurs de T
			stackT.append(field)
# 		Fin (si)
# 		Si le champ est un X :
		if field.startswith('X', 0, 1):
# 			Ajouter la valeur de X à la liste de valeurs de X
			stackX.append(field)
# 		Fin (si)
# 		Si le champ est un Y :
		if field.startswith('Y', 0, 1):
# 			Ajouter la valeur de Y à la liste de valeurs de Y
			stackY.append(field)
# 		Fin (si)
# 		Si le champ est un Z :
		if field.startswith('Z', 0, 1):
# 			Ajouter la valeur de Z à la liste de valeurs de Z
			stackZ.append(field)
# 		Fin (si)

############ LOGIQUE METIER


# 		Si les listes de T, X, Y et Z ont au moins un élement :
		if len(stackT) > 0 and len(stackX) > 0 and len(stackY) > 0 and len(stackZ) > 0:
#			Ecrire dans le fichier de sortie une ligne avec toutes les valeurs de fin de listes
			print("{0}\t{1}\t{2}\t{3}\t{4}".format(stackG[-1], stackX[-1], stackY[-1], stackZ[-1], stackT[-1]))
# 			Tant que la liste de valeurs de G a plus d'un élement :
			while len(stackG) > 1:
# 				Ecrire dans le fichier de sortie une ligne avec toutes les valeurs de fin de listes
				print("{0}\t{1}\t{2}\t{3}\t{4}".format(stackG[-1], stackX[-1], stackY[-1], stackZ[-1], stackT[-1]))
# 				Si la liste de valeurs de G a deux élements ou plus :
				if len(stackG) > 1:
# 					Supprimer le dernier élement
					stackG.pop()
# 				Fin (si)
# 			Fin (tant que)
# 		Fin (si)


############ FIN LOGIQUE METIER

# 	Fin (tant que)
# Fin (tant que)
# On ferme le fichier qu'on lit
f.close() 

Pour lancer ça et rediriger la sortie vers un fichier :
 

python script.py > fichier_sortie.txt

Edit 2:

Plusieurs petites choses :

  • ici j'ai traité tous les types de champ (G, T, X, Y, Z) avec des stacks, parce que je n'ai pas 100% compris la logique métier, en pratique peut-être que pour X, Y, Z (et peut-être même T) une seule valeur suffit ;
  • si par rapport à ce que tu veux ce script sort trop de lignes, mais que dans le tas il y a bien toutes celles dont tu as besoin (avec juste des lignes qui polluent autour) alors il faut rajouter des règles "métier" pour filtrer les lignes en trop ;
  • n'hésite pas à tester au fur et à mesure, si ça se trouve avec des lignes en trop ça marche quand même dans le logiciel (ce qui serait déjà une première étape assez sympa).
Bon courage ! :)

[quote=« Bussiere, post:13, topic: 55095 »][/quote]

Il y a aussi « Dive into Python » de Mark Pilgrim (traduit en français) qui est excellent et pédagogue. :slight_smile:

[quote=“phili_b, post:16, topic: 55095”][/quote]
Non mais il a pas un problème de langage de prog hein, mais d’algo. (ou de description du problème)

Mon principal problème c’est que les infos utiles sont noyées dans des infos inutiles. Mon deuxième problème et que les infos sont présentées dans un certain ordre dans le fichier de départ et que c’est ordre doit être modifié.

Exemple : la ligne 1 du fichier d’arrivée est composée d’infos se trouvant sur la ligne 4, 6 et 10 du fichier de départ

EDIT : sorry Histrion, j’avais même pas vu que t’avais rajouté du code ! Merci beaucoup. Là je suis en train de faire les exercices de Codacademy mais ça me servira surement d’avoir une structure de base pour la suite :wink:

EDIT2 : pour ceux qui se posent la question, la logique métier n’est vraiment pas compliquée. La machine a besoin de savoir quel genre d’action elle va entreprendre (le code G), quel outil utiliser (le code T) et où effectuer l’action (coordonnées X, Y et Z)

[quote=“Miaouss, post:18, topic: 55095”][/quote]

non, la logique metier, c’est le traitement que tu fais quand tu te tape le fichier à la main.
La tu dis que les données ne sont pas dans l’ordre, et qu’il faut les remettre dans l’ordre. C’est ca qu’il faut que tu decrives d’abord dans des specs.
Par exemple “si T est defini sur une ligne, chercher la 4eme occurence de X et l’affecter à Z, puis afficher T:X->Z”.

J’ecris n’importe quoi, mais tant que tu auras pas fait ca, tu vas te perdre dans du pseudo code et des problèmatiques purement technique de codage.

Fait d’abord ce que je t’ai dis, ensuite le pseudo code, et tu verras que le codage sera beaucoup plus facile.

[quote=“Miaouss, post:18, topic: 55095”][/quote]

En fait le fichier d’origine je pense que ce sont des commandes (genre "mettre G à la valeur "). Alors que le fichier déstination ce sont des états (chacune des lignes est un état du système). Du coup dans le fichier d’origine il y a probablement pas mal de commande redondantes (par exemple : G0 puis G20 puis G60 = G60 directement sans avoir à passer par les états intermédiaires).

Je spécule hein… Mais encore une fois pour avoir bossé sur des formats liés aux imprimantes ça m’y fait beaucoup penser (et de manière générale ça fait penser à un format de commande d’un outil “robotique”). 

Edit : 

Si j’ai raison, en prenant mon script normalement la sortie devrait produire le même comportement de la machine que le fichier initial. A ceci près qu’il y aura peut-être plein de mouvement intermédiaires inutiles.