Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Python tests

on:
push:
branches: [ 'main' ]
pull_request:
branches: [ 'main' ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Test with pytest
run: |
pytest
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
*.pyc
__pycache__/
.idea/
.idea/

.pytest_cache

Projet Compilation.pdf
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A simple tool to **analyze**, **compile**, and **run** NNP programs.

[![Python tests](https://github.com/lasercata/Compilation_project/actions/workflows/python-tests.yml/badge.svg)](https://github.com/lasercata/Compilation_project/actions/workflows/python-tests.yml)

---

## 📁 Project Structure
Expand Down Expand Up @@ -29,7 +31,7 @@ A simple tool to **analyze**, **compile**, and **run** NNP programs.
│   ├── parser_ui.py
│   └── utils.py
└── tests/
└── nn_programs/
├── nna/
│   ├── correct1.nno
│   ├── ...
Expand Down Expand Up @@ -107,9 +109,22 @@ options:

```bash
./main.py c -h
./main.py c tests/nna/correct1.nno -o correct1.obj
./main.py c nn_programs/nna/correct1.nno -o correct1.obj
./main.py r correct1.obj
./main.py r tests/nna/correct1.nno -c
./main.py r nn_programs/nna/correct1.nno -c
```

---

### Run tests
To run all the tests:
```
python -m pytest
```

To have the details:
```
python -m pytest -vv
```

---
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ tra(7)
retourProc()
reserver(3)
reserverBloc()
traStat(3,0)
traStat(3, 0)
empiler(0)
get()
empiler(1)
Expand All @@ -49,4 +49,4 @@ affectation()
empiler(1)
valeurPile()
put()
finProg()
finProg()
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ reserver(3)
reserverBloc()
empiler(3)
empiler(4)
traStat(3,2)
traStat(3, 2)
empiler(0)
get()
empiler(1)
Expand All @@ -24,4 +24,4 @@ affectation()
empiler(1)
valeurPile()
put()
finProg()
finProg()
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ mult()
retourFonct()
reserverBloc()
empiler(7)
traStat(3,1)
traStat(3, 1)
put()
finProg()
finProg()
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ empilerAd(0)
valeurPile()
empiler(1)
sous()
traStat(3,1)
traStat(3, 1)
mult()
retourFonct()
reserverBloc()
empiler(3)
traStat(3,1)
traStat(3, 1)
put()
finProg()
finProg()
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ reserverBloc()
empiler(2)
empiler(0)
valeurPile()
traStat(3,2)
finProg()
traStat(3, 2)
finProg()
52 changes: 27 additions & 25 deletions src/anasyn.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,9 @@ def compile(self, show_ident_table: bool = False) -> str:

Args:
:show_ident_table: if True, prints the identifier table.

Output:
The compiled instructions
'''

try:
Expand All @@ -988,54 +991,53 @@ def compile(self, show_ident_table: bool = False) -> str:


########################################################################
def main_anasyn(file_content: str, fn_out: str, show_ident_table: bool, debug_lvl):
def main_anasyn(file_content: str, fn_out: str = '', show_ident_table: bool = False, debug_lvl=logging.INFO) -> str:
'''
TODO: Docstring for main_anasyn.
Main function for the syntax analysis, and generation of the compiled instructions.

In:
- file_content: the content of the file (the NNP program) ;
- fn_out: the name of the potential output file. If "", prints to stdout instead ;
- show_ident_table: if true, displays the ident table ;
- debug_lvl: indicates the logging level.

- file_content : the content of the file (the NNP program) ;
- fn_out : the name of the potential output file. If "", prints to stdout instead ;
- show_ident_table : if true, displays the ident table ;
- debug_lvl : indicates the logging level.
Out:
The generated compiled instructions.

Throws:
SyntaxError if there is a syntax error
FileNotFoundError if there is a problem to open the output file
RuntimeError if no instructions are generated
'''

#---Run the analysis
G = Grammar(file_content, debug_lvl)

try:
instructions_str = G.compile(show_ident_table)
instructions_str = G.compile(show_ident_table)

except SyntaxError as err:
print(f'Syntax error: {err}')
return
if instructions_str == '':
raise RuntimeError('No instruction generated!')

#---Write to file / stdout
#-Select file or stdout
if fn_out != '':
try:
output_file = open(fn_out, 'w')

except:
print("Error: can't open output file!")
return
output_file = open(fn_out, 'w')

else:
output_file = sys.stdout

#-Write
if instructions_str != '':
output_file.write(instructions_str)

if debug_lvl == logging.DEBUG:
print(f'Output to file: "{fn_out}"')
output_file.write(instructions_str)

else:
if debug_lvl == logging.DEBUG:
print('No instruction generated!')
if debug_lvl == logging.DEBUG:
print(f'Output to file: "{fn_out}"')

#-Close file
if fn_out != '':
output_file.close()

return instructions_str


########################################################################

Expand Down
17 changes: 14 additions & 3 deletions src/parser_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def __init__(self):
#---Init
examples = 'Examples :'
examples += '\n\t./main.py c -h'
examples += '\n\t./main.py c tests/nna/correct1.nno -o correct1.obj'
examples += '\n\t./main.py c nn_programs/nna/correct1.nno -o correct1.obj'
examples += '\n\t./main.py r correct1.obj'
examples += '\n\t./main.py r tests/nna/correct1.nno -c'
examples += '\n\t./main.py r nn_programs/nna/correct1.nno -c'

self.parser = argparse.ArgumentParser(
# prog='anasyn',
Expand Down Expand Up @@ -190,7 +190,17 @@ def parse_compile(self, args):

src_code = get_file_content(args.inputfile[0], self.parser_c)

main_anasyn(src_code, args.outputfile, args.show_ident_table, args.debug)
try:
main_anasyn(src_code, args.outputfile, args.show_ident_table, args.debug)

except SyntaxError as err:
print(f'Syntax error: {err}')

except FileNotFoundError:
print("Error: can't open output file!")

except RuntimeError as err:
print(f'Error: {err}')

def parse_run(self, args):
'''Parse the arguments for the `compile` mode'''
Expand All @@ -202,6 +212,7 @@ def parse_run(self, args):
try:
instructions = G.compile()
print(instructions)

except SyntaxError as err:
# self.parser_r.error('syntax error: ' + str(err))
print('Syntax error: ' + str(err))
Expand Down
Empty file added tests/__init__.py
Empty file.
47 changes: 47 additions & 0 deletions tests/test_anasyn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

##-Imports
#---General
from os import listdir

import pytest

#---Project
from src.anasyn import main_anasyn


##-Init
nna_path = 'nn_programs/nna/'
nnp_path = 'nn_programs/nnp/'

files_nna = sorted([f for f in listdir(nna_path) if 'correct' in f])
files_nnp = sorted([f for f in listdir(nnp_path) if 'correct' in f])

nna_tuples = [(nna_path + src, nna_path + 'expected/' + src + '.expected') for src in files_nna]
nnp_tuples = [(nnp_path + src, nnp_path + 'expected/' + src + '.expected') for src in files_nnp]

error_programs = sorted([nna_path + f for f in listdir(nna_path) if 'error' in f])


##-Tests
@pytest.mark.parametrize('src_fn, expected_compiled_fn', nna_tuples + nnp_tuples)
def test_correct(src_fn: str, expected_compiled_fn: str):
'''Tests to compile the correct programs'''

with open(src_fn) as src_file:
with open(expected_compiled_fn) as compiled_file:
src = src_file.read()
compiled = compiled_file.read().strip()

assert main_anasyn(src).strip() == compiled, f'Failed for file "{src_fn}"'

@pytest.mark.parametrize('src_fn', error_programs)
def test_error(src_fn: str):
'''Tests to compile the programs with errors'''

with open(src_fn) as src_file:
src = src_file.read()

with pytest.raises(SyntaxError):
main_anasyn(src).strip()
Loading
Loading