Skip to content

Commit

Permalink
redeployed
Browse files Browse the repository at this point in the history
  • Loading branch information
Alhern committed Apr 26, 2022
1 parent 833216e commit b083a4b
Show file tree
Hide file tree
Showing 12 changed files with 1,380 additions and 1 deletion.
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include README.md LICENSE requirements.txt setup.py
recursive-include programs *
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,40 @@
# alda
# alda
A French programming language created with the SLY library. :croissant:

## Requirements
:warning: alda requires the SLY library (sly~=0.4) and therefore the use of Python 3.6 or greater :

pip3 install -r requirements.txt

## Installation

If you want to generate your own source and binary packages, make sure you have the following packages installed:

sudo apt-get install python3-stdeb python-all dh-python fakeroot

You can then run the following commands to generate the source and binary packages:

python3 setup.py --command-packages=stdeb.command bdist_deb

Or if you want to generate the source package only:

python3 setup.py --command-packages=stdeb.command sdist_dsc

If you used the `bdist_deb` command, you will find the source and binary packages in the `deb_dist` directory:

cd deb_dist

You can now install the deb package with the following command:

sudo dpkg -i python3-alda_1.0.0-1_all.deb

:warning: If you use Python 3.9 and you encounter any error during the installation, I suggest trying to install it with an older version of Python such as Python 3.7.

## Usage

alda [-h] [-f FILE] [-s]

optional arguments:
-h, --help show this help message and exit
-f FILE, --file FILE Execute program from .alda file
-s, --shell Start ALDA shell
Empty file added alda/__init__.py
Empty file.
152 changes: 152 additions & 0 deletions alda/alda_interpreter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

class AldaExecute:

def __init__(self, tree, env):
self.env = env
result = self.eval_node(tree)

if result is not None and isinstance(result, int):
print(result)
if isinstance(result, str):
print(result)
if isinstance(result, float):
print(result)

def eval_node(self, node):

if isinstance(node, float):
return node
if isinstance(node, int):
return node
if isinstance(node, str):
return node

if node is None:
return None

if node[0] == 'nombre_flottant':
return node[1]

if node[0] == 'nombre':
return node[1]

if node[0] == 'chaine':
return node[1]

if node[0] == 'liste_stat':
res = []
for i in range(1, len(node)):
res.append(self.eval_node(node[i]))
return res

# ARITHMETIQUE

if node[0] == 'plus':
return self.eval_node(node[1]) + self.eval_node(node[2])
elif node[0] == 'moins':
return self.eval_node(node[1]) - self.eval_node(node[2])
elif node[0] == 'fois':
return self.eval_node(node[1]) * self.eval_node(node[2])
elif node[0] == 'divise':
return self.eval_node(node[1]) // self.eval_node(node[2])
elif node[0] == 'mod':
return self.eval_node(node[1]) % self.eval_node(node[2])

# OPERATEURS DE COMPARAISON

if node[0] == 'egal':
return self.eval_node(node[1]) == self.eval_node(node[2])
if node[0] == 'negal':
return self.eval_node(node[1]) != self.eval_node(node[2])
if node[0] == 'pgr':
return self.eval_node(node[1]) > self.eval_node(node[2])
if node[0] == 'mgr':
return self.eval_node(node[1]) < self.eval_node(node[2])
if node[0] == 'pegr':
return self.eval_node(node[1]) >= self.eval_node(node[2])
if node[0] == 'megr':
return self.eval_node(node[1]) <= self.eval_node(node[2])

# CONDITIONS

if node[0] == 'si':
if (
len(node) == 3): # si on a un seul ordre dans la commande (càd pas de SINON), on évalue la
# condition et on ne retourne rien si elle est fausse :
if self.eval_node(node[1]):
return self.eval_node(node[2])
else:
return
else: # si on a un SINON dans la commande, on l'évalue :
if self.eval_node(node[1]):
return self.eval_node(node[2])
if node[3]:
return self.eval_node(node[3])
else:
return

# OPERATEURS LOGIQUES

if node[0] == 'et':
return self.eval_node(node[1]) and self.eval_node(node[2])

if node[0] == 'ou':
return self.eval_node(node[1]) or self.eval_node(node[2])

# FONCTION

if node[0] == 'fo_def':
self.env[node[1]] = node[2]

if node[0] == 'fo_appel':
try:
return self.eval_node(self.env[node[1]])
except LookupError:
print(f"Fonction indéfinie : {node[1]}")
return

# BOUCLES

if node[0] == 'tantque':
condition = self.eval_node(node[1])
while condition:
self.eval_node(node[2])
condition = self.eval_node(node[1])

if node[0] == 'de':
for i in range(self.eval_node(node[1]), self.eval_node(node[2])):
self.eval_node(node[3])

# VARIABLES

if node[0] == 'var_assigne':
self.env[node[1]] = self.eval_node(node[2])
return node[1]

if node[0] == 'nom':
try:
return self.env[node[1]]
except LookupError:
print(f"Nom indéfini : '{node[1]}'")
return 0

if node[0] == 'ecris':
print(self.eval_node(node[1]))
return node[1]

# LISTE

if node[0] == 'liste_elem':
if node[1][0] == 'nom' and node[2][0] == 'nom':
return '%s, %s' % (node[1][1], node[2][1])
if node[1][0] == 'nom': # en faisant ça on évite d'afficher la valeur
return '%s, %s' % (node[1][1], self.eval_node(node[2]))
if node[2][0] == 'nom':
return '%s, %s' % (self.eval_node(node[1]), node[2][1])
else:
return '%s, %s' % (self.eval_node(node[1]), self.eval_node(node[2]))

if node[0] == 'liste':
return '[%s]' % (self.eval_node(node[1]))
106 changes: 106 additions & 0 deletions alda/alda_lexer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from sly import Lexer


class AldaLexer(Lexer):
tokens = {NOM, NOMBRE, NOMBRE_FLOTTANT, ECRIS,
CHAINE, PLUS, MOINS, FOIS,
DIVISE, MOD, EGAL, NEGAL, PGR,
MGR, PEGR, MEGR, EST,
SI, ALORS, SINON, TANTQUE,
FAIS, DE, JUSQUA, ET,
OU, CGAU, CDRO, PGAU,
PDRO, VIRGULE, VRAI, FAUX,
INCR, DECR, PVIRG, FO,
DPTS}

ignore = ' \t'

literals = {'+', '-', '*', '/', '==', '!=', '>', '<', '>=', '<=', '=', '[', ']', '(', ')', '{', '}', ';'}

ECRIS = r'ECRIS'
PLUS = r'\+'
MOINS = r'-'
FOIS = r'\*'
DIVISE = r'/'
MOD = r'%'
PEGR = r'>=(?!=)'
MEGR = r'<=(?!=)'
EGAL = r'(?<!=)={2}(?!=)'
NEGAL = r'!=(?!=)'
PGR = r'>'
MGR = r'<'
EST = r'(?<!=)=(?!=)'
CGAU = r'\['
CDRO = r'\]'
PGAU = r'\('
PDRO = r'\)'
VIRGULE = r','
PVIRG = r';'
DPTS = r':'

SINON = r'SINON'
SI = r'SI'
ALORS = r'ALORS'
TANTQUE = r'TANTQUE'
FO = r'FO'
FAIS = r'FAIS'
DE = r'DE'
JUSQUA = r'JUSQUA'
ET = r'ET'
OU = r'OU'
VRAI = r'VRAI'
FAUX = r'FAUX'
INCR = r'INCR'
DECR = r'DECR'

NOM = r'[a-zA-Z_][a-zA-Z0-9_]*'

CHAINE = r"(\"[^\"]*\")|('[^']*')"

NOM['sinon'] = SINON
NOM['si'] = SI
NOM['alors'] = ALORS
NOM['tantque'] = TANTQUE
NOM['fo'] = FO
NOM['fais'] = FAIS
NOM['de'] = DE
NOM['jusqua'] = JUSQUA
NOM['incr'] = INCR
NOM['decr'] = DECR
NOM['et'] = ET
NOM['ou'] = OU

@_(r'\d+\.\d+')
def NOMBRE_FLOTTANT(self, t):
t.value = float(t.value)
return t

@_(r'\d+')
def NOMBRE(self, t):
t.value = int(t.value)
return t

@_(r"\".*?\"")
def CHAINE(self, t):
t.value = self.remove_quotes(str(t.value))
return t

@_(r'\#.*')
def COMMENTAIRE(self, t):
pass

@_(r'\n+')
def ignore_newline(self, t):
self.lineno += t.value.count('\n')

def remove_quotes(self, string):
if string[0] == '\"' or string[0] == '\'':
return string[1:-1]
return string

def error(self, t):
print("Caractère non autorisé : '%s'" % t.value[0])
self.index += 1
Loading

0 comments on commit b083a4b

Please sign in to comment.