Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Compylateur
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Compylateur

Posté le 08/05/2020 14:00

Bonjour à tous !

Il y a quelques temps j'ai fait un 'compilateur' qui permet d'exécuter un algorithme en langage naturel en le 'traduisant' en Python. Le code est atroce et repose sur un remplacement entre les commandes en langage naturel et les commandes en Python (à coup de dictionnaires et de tests conditionnels )… J'aimerais faire de ce projet un 'vrai' compilateur (on reste sur du Python ). Et j'ai quelques questions :

- La phase d'analyse lexicale repose pour l'instant sur une recherche et un replacement, avec un dictionnaire qui contient en clés les commandes en langage naturel, et en items, les commandes correspondantes en Python… Je me doute que ce n'est pas pertinent… En fait l'analyse lexicale est mélangée à la phase d'analyse syntaxique.

- Comment faire pour basculer du langage naturel au Python ? Faut-il forcément passer par un hard code, ou est-ce que d'autre technique plus esthétiques existent ?

- L'analyse syntaxique est un bête replace basé sur un dico… Du coup ça revient à la question précédente : comment éviter le hard code ?

- La phase sémantique… Je ne suis pas sûr d'avoir bien compris toutes les subtilités… Dans mon cas, après le remplacement bête et méchant, la syntaxe Python n'est pas bonne, du coup je passe à travers différents tests conditionnels pour avoir un 'vrai' script fonctionnel… Encore une fois le hard code à coup de if me plaît moyen…

- En derniers je refait un passage sur mon code généré et j'ajoute les alinéas. Est-ce que je devrais les gérer plus tôt (je pense à la phase d'analyse syntaxique… mais le placement des alinéas dépend du contexte du code, et sur une ligne donnée je vois pas trop comment faire…

Merci d'avance !


Précédente 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ··· 18, 19, 20 Suivante
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 30/05/2020 16:12 | #


Ah je crois que je viens de comprendre… c'est produit = INT la première fois est après on prend le modèle récursif produit = INT FOIS produit ?

Du coup toute ma grammaire va être définie par : nom_pattern -> SIMPLE | RECURRENCE ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 30/05/2020 16:18 | #


C'est ça, enfin sauf que la règle produit = INT on la prend la dernière fois.

Du coup toute ma grammaire va être définie par : nom_pattern -> SIMPLE | RECURRENCE ?

Non, ça c'est que pour les cas simples (malheureusement). En fait tu vois ce que j'ai écrit c'est en gros une liste :

liste_de_truc -> truc | true liste_de_truc

Quand tu es en train de lire ta liste, soit tu es au dernier élément et tu empruntes la règle liste_de_truc -> truc, soit tu n'es pas au dernier élément et tu empruntes la règle liste_de_truc -> truc liste_de_truc. La somme et le produit ne sont que des exemples de ça avec en plus un séparateur (PLUS et FOIS).

Toi tu vas avoir des règles un peu plus élaborées, par exemple jusqu'ici je ne gérait pas les parenthèses dans mes expressions arithmétiques. Si je veux les rajouter, ça donne ça :

expr -> produit
produit -> somme | somme FOIS produit
somme -> atome | atome PLUS somme
atome -> INT | ( expr )

Et là, pouf ! T'as vu, on ne fait pas que descendre. Un atome peut contenir une expression aussi complexe qu'on veut pourvu qu'elle soit entre parenthèses. Donc la fonction atome() va appeler expr() qui appelle déjà indirectement atome(), c'est pour ça que c'est récursif !

Prends bien le temps de comprendre cette grammaire avant de continuer. Quand tu auras saisi à quoi servent et comment on utilise des grammaires, tu seras sur une bonne base pour faire un vrai bon parser
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 30/05/2020 16:48 | #


Ouaip, je crois que ça va me prendre un peu de temps rien que pour comprendre xD

Ajouté le 30/05/2020 à 20:15 :
Je fais essayer de réfléchir à des éléments simples de grammaires pour me mettre en jambe

Ajouté le 31/05/2020 à 10:10 :
C'pour voir si j'ai compris, pour une addition (un truc simple ^^') la grammaire c'est somme -> NUM | NUM (OPTR, "+") somme mais je peux aussi avoir des variables : somme -> UNDEF | UNDEF (OPTR, "+") somme… Après je vois pas trop comment tu fait, mais chez moi UNDEF, NUM, OPTR, c'est pas un 'type' c'est juste une str… x)
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 31/05/2020 10:21 | #


Dans un langage de programmation traditionnel, supporter les variables ce serait comme ça :

somme -> atome | atome + somme
atome -> NUM | VAR

Maintenant je sais que toi tu as des tokens UNDEF... attention à ne pas tomber dans l'erreur de mettre des UNDEF partout parce que tu vas te retrouver avec des constructions bizarres à des endroits où tu ne t'y attends pas (ça risque d'accepter trop de choses).

Après je vois pas trop comment tu fait, mais chez moi UNDEF, NUM, OPTR, c'est pas un 'type' c'est juste une str… x)

À la limite on s'en fout tant que tu arrives à coder expect() correctement. J'ai supposé que tes tokens c'était des objets avec un attribut .type et qui est à valeur dans une sorte d'énumération. Si tes tokens c'est juste des paires genre ("OPTR", "+") tu peux faire ça :

def expect(valid_tokens = []):
    t = lookahead
    lookahead = get_next_token()
    if valid_tokens != [] && t[0] not in valid_tokens:
       raise SyntaxError("expected one of " + ", ".join(valid_tokens))
    return t

def somme():
    i1 = expect(["INT"])
    # etc

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 31/05/2020 11:18 | #


Les UNDEF c'est tout ce qui est… indéfini… donc ça comprend les variables, mais aussi d'autres choses comme le texte…

Pour la fonction expect, je suis en train de regarder comment faire… je pense la mettre dans la fonction parser pour éviter les variables globales… ? Pour les tokens, je vais faire un objet, ce sera plus simple
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 31/05/2020 11:28 | #


Il devrait y avoir un minimum de trucs indéfinis dans ton langage. Honnêtement, je vois pas trop ce que ça représente. Le pseudo-code c'est quand même assez précis.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 31/05/2020 11:28 | #


J'ai remanié mon code

J'ai ça pour le parser :

# ==================================================
# Parser
# ==================================================

# --- Main function --- #

def parser(l_token):
    token_see = l_token.get()

# --- Secondary functions --- #

def expect(target = [], l_token):
    last = token_see
    token_see = l_token.get()
    if target != [] and last.type() not in target:
        raise SyntaxError("unknown operand, one of these is expected : " + ", ".join(target))
    return last


Avec expect appelé par parser

Ajouté le 31/05/2020 à 11:31 :
Au niveau des trucs indéfinis, j'ai que le texte, par exemple dans Afficher "ABC est un texte" j'ai les tokens :
(UNDEF, "ABC")
(ASSI, "est")
(UNDEF, "un")
(UNDEF, "texte")


Mais avec les guillemets le doute peut-être facilement levé… À part le texte, je n'ai que les variables sur UNDEF et bien sûr tous les mots qui ne veulent rien dire… ou faute de frappe… x)

Ajouté le 31/05/2020 à 11:57 :
Le lien du code : https://gitea.planet-casio.com/Shadow/Compylateur/src/branch/master/compylateur.py

Pour l'instant expect me renvoie un objet Token

Est-ce qu'il y aurait un moyen de faire un truc plus propre au niveau de l'erreur ? Parce que là j'ai toute une foule de détail sur la position du raise (dont on se moque… vu que l'erreur n'est pas là… x) )
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 31/05/2020 12:40 | #


Au niveau des trucs indéfinis, j'ai que le texte, par exemple dans Afficher "ABC est un texte" j'ai les tokens :

Ah ben non, tu devrais avoir deux tokens : le mot-clé Afficher suivi de la chaîne de caractères "ABC est un texte" !

Une foule de détails, tu parles du Traceback? On ne s'en fout pas du tout, au contraire.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 31/05/2020 13:48 | #


Ah, ok, pour le texte je change ça le mot-clé Afficher est déjà géré

Oui je parle du Traceback, et il n'y a pas d'intérêt à savoir que le raise est placé ligne 58 dans la fonction expect appelée par parser… l'erreur est dans le code en cours de compilation, pas dans le compilateur… ?

Ajouté le 31/05/2020 à 14:32 :
J'ai terminé la gestion du texte. Du coup le token UNDEF n'existe plus ce qui est du texte est géré comme du texte avec un token TEXT et les autres mots sont considérés comme de variables : token VAR. Si une variable ne colle pas niveau syntaxe, l'analyse syntaxique mettra en évidence l'erreur, donc je ne pense pas avoir besoin de faire un truc plus poussé au niveau du lexer… ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 31/05/2020 22:35 | #


Nope, c'est bon en effet, ton lexer n'a pas besoin d'en dire plus. La grammaire maintenant o/
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 10:37 | #


La grammaire… J'ai deux-trois questions…

- Dans quel ordre sont appelé les fonctions, j'ai parser qui fera tourner le schmilblick mais je ne sais pas dans quel ordre expect et les autres fonctions grammaticales sont appelées… ?

- Chaque fonctions grammaticale détecte un pattern et si la grammaire testée ne correspond pas ça renvoie une erreur… C'est pas bon comme raisonnement, si je teste un produit alors que j'ai une somme ça ne va pas coller… et pourtant je n'ai pas d'erreur… Comment savoir quelle fonction grammaticale je dois lancer ? Est-ce que je dois faire une fonction qui mâchouille le taf et qui fait une première détection avant d'appeler la fonction qui va analyser ça dans le détail ?

- Dans ma tête je suis resté : une fonction par pattern est-ce que c'est bon ?

- J'ai encore du mal avec le côté récursif et la manière dont je dois coder les fonctions grammaticales… ^^'

Merci d'avance !
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 01/06/2020 10:44 | #


- Dans quel ordre sont appelé les fonctions, j'ai parser qui fera tourner le schmilblick mais je ne sais pas dans quel ordre expect et les autres fonctions grammaticales sont appelées… ?

Il n'y a pas d'ordre précis, en fait tu vas appeler dans parser() la fonction correspondant au symbole de grammaire qui représente un programme complet, et cette fonction va appeler récursivement les fonctions correspondants à d'autres symboles de grammaire selon les règles de grammaire qui sont appliquées. En fait les appels et leur ordre vont dépendre de la tête du programme. expect() sera appelé tout en bout de chaîne, chaque fois qu'une fonction correspondant à un symbole de grammaire voudra lire directement un token.

Chaque fonctions grammaticale détecte un pattern et si la grammaire testée ne correspond pas ça renvoie une erreur

C'est pas tout à fait ça, tu es dans un parser dit "prédictif", autrement dit au moment où tu appelle une fonction grammaticale, tu *sais* que le pattern qu'elle reconnaît est exactement ce qui doit suivre dans le programme et rien d'autre. Si la fonction grammaticale échoue c'est que le programme contient une erreur de syntaxe.

Comment savoir quelle fonction grammaticale je dois lancer ?

Au tout début tu lances la fonctions grammaticale correspondant au programme complet. Et ensuite ça se débrouille tout seul. Regarde la fonction somme() de tout à l'heure (putain j'ai inversé somme et produit pendant hyper longtemps sans m'en rendre compte xD) :

def somme():
    p1 = produit()
    if lookahead.type != PLUS:
        return Somme(p1)
    expect([PLUS])
    s = somme()
    return Somme(p1, s)

somme() appelle produit() toute seule. Si ton programme c'est 3×4+1+5×7 et que tu appelles somme() tu vas tout récupérer d'un coup.

La seule décision qui est prise c'est s'il faut appliquer la règle "somme → produit" ou "somme → produit PLUS somme" et ça c'est selon la tête du lookahead.

- Dans ma tête je suis resté : une fonction par pattern est-ce que c'est bon ?

Une fonction par symbole de grammaire, si un symbole contient plusieurs règles de production (symbole → règle1 | règle2 | etc), il faut tester le lookahead pour savoir laquelle appliquer.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 10:53 | #


Au tout début tu lances la fonctions grammaticale correspondant au programme complet

Hu… ? J'ai pas compris… x) C'est la fonction parser ?

Je pense que je vais commencer par essayer de détecter les additions A + B ensuite j'essaye A + B + C + … Et ainsi de suite ^^' J'ai encore du mal à voir comment ça va se goupiller, mais en commençant, ça va peut-être aller mieux ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 01/06/2020 11:00 | #


Non, dans ta grammaire il y a plein de symboles et il y en a un qui représente le programme complet (on appelle ça le symbole d'entrée). Un peu comme il a y a une fonction principale dans ton programme (le main() en C par exemple), il y a un symbole d'entrée dans la grammaire. Par exemple, le symbole programme dans la grammaire suivante qui reconnaît des affectations avec des expressions arithmétiques :

programme -> (vide) | affectation programme
affectation -> VAR EGAL expr
expr -> somme
somme -> produit | produit PLUS somme | produit MOINS somme
produit -> atome | atome FOIS produit | atome DIVISION produit
atome -> ENTIER | VARIABLE | ( expr )

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 11:03 | #


Oula… x)

J'ai du mal à comprendre comment il faut que je pense pour établir la grammaire… et après pour faire comprendre la grammaire au parser…

Je vais essayer de détecter les additions simples xD sans avoir d'erreur…

Ajouté le 01/06/2020 à 11:34 :
J'ai bricolé un truc… :
def somme(l_token, token_ahead):
    token_ahead = expect(l_token, token_ahead, ["VAR", "NUM"])
    token_ahead = expect(l_token, token_ahead, ["OPTR"])
    if token_ahead.value == "+":
        token_ahead = expect(l_token, token_ahead, ["VAR", "NUM"])
        return True


Ça ne gère que les trucs comme A + B, A peut être un chiffre ou une variable. Si la syntaxe n'est pas respectée ça renvoie une erreur…

J'ai pas de variables globales, du coup ça charge un peu x)
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 01/06/2020 11:42 | #


Euh ton affaire avec token_ahead va pas marcher à moins que tu le renvoies. Je te conseille d'utiliser une variable globale pour l'instant, et ensuite de mettre tout ça dans une classe, ce sera isolé et t'auras pas à charger/casser les prototypes comme ça.

Ensuite tu devrais pas renvoyer True mais renvoyer un arbre de syntaxe. Même si ça ça peut attendre.

Sinon ça a l'air pas mal mais tu devrait soit appeler somme() dans le if, ou remplacer le if par un while, pour avoir un vraie grammaire utile. Ici tu as codé la grammaire

somme -> (VAR|NUM) | (VAR|NUM) PLUS (VAR|NUM)

ce qui est un peu limitant.

Enfin, tu devrais factoriser (VAR|NUM) qui va revenir souvent. Dans la grammaire ça donnerait ça :

somme -> atome | atome PLUS atome
atome -> VAR | NUM

Et dans le code ça donnerait ça (le lexer est aussi en variable globale, t'emmerde pas avec ça maintenant) :

def somme():
    atome_1 = atome()
    if token_ahead.type == "OPTR" and token_ahead.value == "+" :
        expect(["OPTR"])
        atome_2 = atome()
        return Plus(atome_1, atome_2) # tu verras après
    else:
        return atome_1 # tu verras après

def atome():
    return expect(["VAR", "NUM"])

Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 11:45 | #


Oui, c'est juste… j'ai oublié de le renvoyer

Donc factoriser VAR | NUM ça c'est pas trop dur et ensuite la récursivité. J'essaye et je reviens o/

Ajouté le 01/06/2020 à 12:23 :
Le coup des variables globales ça me met des bug bizarres x) Et après pour les remettre en local ça va être chiant… ? Je vois pas trop l'intérêt d'avoir des globales…

Pour atome j'ai fait ça : atome = lambda: except(["VAR", "NUM"])

Du coup j'ai pas fait la récursivité x) je vais essayer de tout remettre en local avant
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 01/06/2020 13:01 | #


Le coup des variables globales ça me met des bug bizarres x) Et après pour les remettre en local ça va être chiant… ? Je vois pas trop l'intérêt d'avoir des globales…

Les bugs sont certainement ailleurs. Tu pourras utiliser une classe ce qui t'éviteras d'avoir des paramètres bourrins partout. Actuellement ton truc est buggé parce que tu renvoies pas le nouveau lookahead à chaque étape. L'intérêt d'avoir des "globales" ici c'est que le code est simple et tu peux te concentrer sur ton parser, parce que s'il faut debugger ton programme en plus de la logique du parser on n'est pas rendus. x)
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 13:28 | #


Ma liste de token n'est pas reset, à chaque nouvelle compilation les listes de tokens se concatènent et je fini avec des trucs aussi énorme que faux…

J'ai un doute, les classes c'est class Nom_de_ma_classe(): ? Mais du coup c'est objets ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir En ligne Administrateur Points: 24582 Défis: 170 Message

Citer : Posté le 01/06/2020 13:28 | #


Une classe c'est le "modèle" d'un objet. Donc oui globalement c'est pareil.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5504 Défis: 18 Message

Citer : Posté le 01/06/2020 13:30 | #


Du coup je peux faire un truc comme :

class GlobalVar():
    def __init__(self):
        self.l_token = TokenList()
        self.token_ahead = Token()


et je déclare en global : gl_var = GlobalVar() ?
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Précédente 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ··· 18, 19, 20 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 71 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd