├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── BLOGS.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── images ├── components.png ├── issues-1.PNG ├── issues-2.PNG ├── logo.png └── simc-pipeline.png ├── ins.sh ├── readme-lang ├── README-French.md ├── README-GER.md ├── README-ITA.md ├── README-RU.md ├── README-eng.md └── README-pt.md ├── setup.py ├── simc-codes ├── .gitkeep ├── array-declaration.simc ├── char-input-test.simc ├── q1.simc ├── q10.simc ├── q100.simc ├── q102.simc ├── q103.simc ├── q104.simc ├── q105.simc ├── q106.simc ├── q107.simc ├── q108.simc ├── q109.simc ├── q110.simc ├── q112.simc ├── q113.simc ├── q114.simc ├── q12.simc ├── q13.simc ├── q14.simc ├── q15.simc ├── q17.simc ├── q18.simc ├── q19.simc ├── q2.simc ├── q20.simc ├── q201.simc ├── q22.simc ├── q23.simc ├── q24.simc ├── q25.simc ├── q26.simc ├── q27.simc ├── q28.simc ├── q29.simc ├── q3.simc ├── q30.simc ├── q31.simc ├── q32.simc ├── q33.simc ├── q34.simc ├── q35.simc ├── q36.simc ├── q37.simc ├── q38.simc ├── q39.simc ├── q4.simc ├── q40.simc ├── q41.simc ├── q42.simc ├── q43.simc ├── q44.simc ├── q45.simc ├── q46.simc ├── q47.simc ├── q48.simc ├── q49.simc ├── q5.simc ├── q51.simc ├── q52.simc ├── q53.simc ├── q54.simc ├── q55.simc ├── q56.simc ├── q57.simc ├── q58.simc ├── q59.simc ├── q6.simc ├── q60.simc ├── q61.simc ├── q64.simc ├── q65.simc ├── q66.simc ├── q67.simc ├── q68.simc ├── q69.simc ├── q7.simc ├── q70.simc ├── q71.simc ├── q72.simc ├── q73.simc ├── q74.simc ├── q75.simc ├── q76.simc ├── q77.simc ├── q78.simc ├── q79.simc ├── q80.simc ├── q81.simc ├── q82.simc ├── q83.simc ├── q84.simc ├── q85.simc ├── q86.simc ├── q87.simc ├── q88.simc ├── q9.simc ├── q90.simc ├── q92.simc ├── q93.simc ├── q94.simc ├── q95.simc ├── q96.simc ├── q97.simc ├── q98.simc └── q99.simc └── simc ├── __init__.py ├── compiler.py ├── global_helpers.py ├── lexical_analyzer.py ├── op_code.py ├── package-index ├── parser ├── __init__.py ├── array_parser.py ├── conditional_parser.py ├── function_parser.py ├── loop_parser.py ├── parser_constants.py ├── simc_parser.py ├── struct_parser.py └── variable_parser.py ├── scope_resolve.py ├── simc.py ├── simpack.py ├── symbol_table.py └── token_class.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: sim-c 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | **Steps to Reproduce** 13 | 14 | **Expected behavior** 15 | 16 | **Screenshots (if any)** 17 | 18 | **Additional context (if any)** 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the feature and the solution** 11 | 12 | **Example code (if any** 13 | 14 | **Screenshots (if any)** 15 | 16 | 17 | **Note**: You can only start working on this issue if a maintainer approves of the feature. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Closes #{Issue Number} 2 | 3 | **Implementation details** 4 | 5 | **Test Case 1** 6 | 7 | **simC Code** 8 | 9 | **C Code (If generated)** 10 | 11 | **Error message (If any)** 12 | 13 | 14 | NOTE:- You can add more test cases if you want 15 | 16 | Number of unit tests passing: [{Passing Unit Tests} / {Total Unit Tests}] 17 | Number of code tests passing: [{Passing Code Tests} / {Total Code Tests}] 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .DS_Store 3 | *.pyc 4 | a.out 5 | a.exe 6 | build/* 7 | dist/* 8 | simc.spec 9 | .vscode 10 | simc.egg-info/* 11 | simc/modules/ -------------------------------------------------------------------------------- /BLOGS.md: -------------------------------------------------------------------------------- 1 | # KWoC 2020 2 | 3 | - Aryaman Kolhe - KWoC Project Report 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at cimplec.simc@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to simC 2 | 3 | ### Please star (⭐) the repository to show your support to the project. 4 | 5 | ## Pull Requests (PRs) 6 | 7 | - PR will be reviewed within a maximum of 72 hours of submitting the request. 8 | - The following rules are to be followed while submitting a PR:- 9 | - Branch Name: The name of the branch should start with 'in' followed by hyphen (-) and the issue number. Eg:- If you are working on issue number 57 then your branch name should be in-57. You need to make sure that in your fork you create a branch following this pattern. 10 | - Commit Message: Commit message should make sense, anyone should be able to get an idea of what changes were made in that particular commit. Irrelevant or inapporpriate commit messages are highly discouraged. 11 | - Docstrings: Docstrings are special comments in python which helps one to understand what a function or class does, the parameters passed, and the data returned from that function. We expect everyone to adhere to the format in your code. To get a better idea of the format of docstrings, please refer to the codebase. 12 | - Comments: The comments should be meaningful and one should be able to understand what the line(s) of code mean from the comments. Do not add unecessary comments in each line, leave out comments from code which is self-explanatory. 13 | - Variables: Variable names used in your code should explain what the variable is. Some unacceptable variable names are:- a, b, hello, world, etc. While creating variable name with multiple words in it, the words should be separated by underscore (_) e.g:- player_initial_energy and should not be written in camel case e.g- playerInitialEnergy. 14 | - Run tests: Run the tests using simC's test-suite and report the number of tests passing, if this is missing then the PR will be closed immediately. 15 | - Follow PR template: Fill all the details in PR template as it helps us understand the PR better, the PR will be closed if any mandatory field is found empty. 16 | - After successful submission of PR, it will be subjected to testing and if the code fails any of the tests you will be given a time period of 3 days to fix the issue, else your PR will be closed. 17 | 18 | ## New Issue (New feature or bug) 19 | 20 | - The time period for reviewing of a new issue is a maximum of 36 hours, you can expect to hear from a maintainer within this time frame. 21 | - The implementation of the new feature or fixing of the bug should only be started after a maintainer approves the feature or bug report in the discussion. 22 | - Once approved start implementing the feature or fix the bug and submit a pull request. 23 | 24 | Note:- The bug and feature issue rules mentioned above are for issues opened by an outside collaborator and not a core dev. 25 | 26 | ## Start Contributing 27 | 28 |

Go through simC's Wiki to get an in-depth understanding of simC.

29 | 30 |

Three files are important for you when you start contributing to this project, you should have a rough idea of these files, the order is:-

31 | 32 | - [lexical_analyzer.py](https://github.com/cimplec/sim-c/blob/master/simc/lexical_analyzer.py) 33 | - [simc_parser.py](https://github.com/cimplec/sim-c/blob/master/simc/parser/simc_parser.py) 34 | - [compiler.py](https://github.com/cimplec/sim-c/blob/master/simc/compiler.py) 35 | 36 | 37 | ## Contributing 38 | 39 | To get started with simC follow the official documentation:- https://cimplec.github.io/docs/ 40 | 41 | The following resources are a good place to get to know more about simC:- 42 | 43 | 1) Writing code in C? Simplify your life with sim-C Dev.to, Medium. 44 | 2) Getting Started with sim-C Dev.to, Medium. 45 | 46 | ## Unit Testing 47 | 48 | - Make sure you test your code using the test suite before you make a PR. 49 | - To test your code, the steps are as follows:- 50 | 1) Install sim-C test suite:- 51 | ```bash 52 | user@programmer~:$ pip install git+https://github.com/cimplec/test-suite 53 | ``` 54 | 2) Run the tests 55 | ```bash 56 | user@programmer~:$ simc-test 57 | ``` 58 | - If any test fails make sure to fix your code so that the error goes away. 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sim-C 2 | 3 |

4 | 5 |

6 | 7 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) ![GitHub issues](https://img.shields.io/github/issues/cimplec/sim-c?color=darkgreen) ![GitHub closed issues](https://img.shields.io/github/issues-closed/cimplec/sim-c?color=red) ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/cimplec/sim-c?color=darkred) 8 | 9 | ## What is sim-C? 10 | 11 |

Often people have trouble programming in C (especially beginners) due to its low level syntax and unavailability of stable third party libraries. We present sim-C a high-level front end for C which creates a dynamically typed syntax for C. Users can write code in this high level syntax and then compile it to optimized C code. sim-C does not process the code and simply translates it to C thus, there is no possibility of the code running slowly. So, with sim-C users can write code faster using the high level syntax and at the same time be able to harness the power and speed of a C program.

12 | 13 | ## Pipeline 14 | 15 |

16 | 17 |

18 | 19 | ## Important links 20 | 21 | 1. Official documentation 22 | 2. simC Wiki 23 | 24 | ## New Developers 25 | 26 |

New developers can join simC New Devs slack channel where they can get help from core developers on their issues, link to the slack channel - simC New Devs Slack

27 | 28 | ## OSS Programs 29 | 30 | 1) Hacktoberfest 2020 31 | 2) KWoC (Kharagpur Winter of Code) 2020 32 | 3) SWoC (Script Winter of Code) 2021 33 | 34 | ## Contributor blogs 35 | 36 | Follow this [link](https://github.com/cimplec/sim-c/blob/master/BLOGS.md) to read blogs written by contributors after completing various OSS programs. 37 | 38 | ## License 39 | 40 | sim-C is licensed under GNU General Public License (GPL) v3.0. [LICENSE](https://github.com/cimplec/sim-c/blob/master/LICENSE) 41 | -------------------------------------------------------------------------------- /images/components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/images/components.png -------------------------------------------------------------------------------- /images/issues-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/images/issues-1.PNG -------------------------------------------------------------------------------- /images/issues-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/images/issues-2.PNG -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/images/logo.png -------------------------------------------------------------------------------- /images/simc-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/images/simc-pipeline.png -------------------------------------------------------------------------------- /ins.sh: -------------------------------------------------------------------------------- 1 | pip uninstall simc -y 2 | python setup.py install 3 | -------------------------------------------------------------------------------- /readme-lang/README-French.md: -------------------------------------------------------------------------------- 1 | 2 | # sim-C 3 | 4 |

5 | 6 |

7 | 8 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) 9 | 10 | ## Qu'est-ce que sim-C? 11 | 12 |

Souvent, les gens ont du mal à programmer en C (en particulier les débutants) en raison de sa syntaxe de bas niveau et de l'indisponibilité de bibliothèques tierces stables. Nous présentons sim-C un frontal de haut niveau pour C qui crée une syntaxe typée dynamiquement pour C. L'utilisateur peut écrire du code dans cette syntaxe de haut niveau, puis le compiler en code C optimisé. sim-C ne traite pas le code et le traduit simplement en C, il n'y a donc aucune possibilité que le code s'exécute lentement. Ainsi, avec sim-C, les utilisateurs peuvent écrire du code plus rapidement en utilisant la syntaxe de haut niveau et en même temps être en mesure d'exploiter la puissance et la vitesse d'un programme C. Faisons à nouveau C cool.

13 | 14 | ## Pipeline 15 | 16 |

17 | 18 |

19 | 20 | ## Commencer à contribuer 21 | 22 |

sim-C qui a une base de code très intuitive, vous serez prêt à contribuer en un rien de temps! Lors de l'ajout de fonctionnalités à sim-C, vous devez uniquement apporter des modifications aux fichiers suivants:

23 | 24 |

1. lexical_analyzer.py 25 | L'analyse lexicale est la première phase d'un compilateur. Il prend le code source modifié des préprocesseurs de langage qui sont écrits sous forme de phrases. L'analyseur lexical décompose ces syntaxes en une série de jetons, en supprimant tout espace ou commentaire dans le code source. Selon le type de fonctionnalité, ajoutez-le à la fonction respective: is_keyword, numeric_val, string_val, keyword_identifier et / ou lexical_analyze.

26 | 27 |

2. op_code.py 28 | Il est responsable de la création des opcodes. Si besoin est, vous devez modifier uniquement la fonction opcode2dig qui renvoie la représentation entière du type opcode.

29 | 30 |

3. simc_parser.py 31 | Parser est un composant interpréteur utilisé pour diviser les données en éléments plus petits provenant de la phase d'analyse lexicale. Un analyseur prend l'entrée sous la forme d'une séquence de jetons et produit une sortie. Ici, vous devrez peut-être créer une fonction distincte qui définit la grammaire et vérifie la syntaxe. La fonction doit renvoyer l'OpCode. De plus, si nécessaire, vous devez ajouter la fonctionnalité à la fonction d'analyse qui analyse les jetons, appelle la fonction particulière et renvoie les opcodes.

32 | 33 |

4. compiler.py 34 | Enfin, vous devez définir le type d'opcode dans le compilateur et écrire la syntaxe C attendue pour la fonctionnalité.

35 | 36 |

Vous pouvez écrire un test dans test.simc et vérifier s'il produit des résultats dans le fichier test.c.

37 | 38 | 39 | ## Commencer 40 | 41 | Pour démarrer avec simC suivez la documentation officielle: - https://cimplec.github.io/docs/ 42 | 43 | Les ressources suivantes sont un bon endroit pour en savoir plus sur simC: - 44 | 45 | 1) Écrire du code en C? Simplifiez-vous la vie avec sim-C Dev.to, Medium. 46 | 2) Premiers pas avec sim-C Dev.to, Medium. 47 | 48 | En dehors de ces articles de blog, vous pouvez également consulter le documents officiels. 49 | 50 | Avant d'aller plus loin, veuillez parcourir les règles dans [CONTRIBUTING.md](../CONTRIBUTING.md) 51 | 52 | ## Licence 53 | 54 | sim-C est sous licence GNU General Public License (GPL) v3.0. [LICENCE](../LICENSE) 55 | 56 | ## L'équipe 57 | 58 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 59 | - [Dhairya Jain](https://github.com/dhairyaj) 60 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 61 | -------------------------------------------------------------------------------- /readme-lang/README-GER.md: -------------------------------------------------------------------------------- 1 | # sim-C 2 | 3 |

4 | 5 |

6 | 7 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) 8 | 9 | ## Was ist sim-C? 10 | 11 |

Häufig haben Menschen (insbesondere Anfänger) Probleme beim Programmieren in C aufgrund der Syntax auf niedriger Ebene und der Nichtverfügbarkeit von stabilen Bibliotheken von Drittanbietern. Wir stellen sim-C ein High-Level-Frontend für C vor, das eine dynamisch typisierte Syntax für C erzeugt. Der Benutzer kann Code in dieser High-Level-Syntax schreiben und ihn dann zu optimiertem C-Code kompilieren. sim-C verarbeitet den Code nicht und übersetzt ihn einfach in C, so dass es keine Möglichkeit gibt, dass der Code langsam läuft. Mit sim-C können Benutzer also unter Verwendung der High-Level-Syntax schneller Code schreiben und gleichzeitig die Leistung und Geschwindigkeit eines C-Programms nutzen. Lassen Sie uns C wieder kühl machen.

12 | 13 | ## Die Pipeline 14 | 15 |

16 | 17 |

18 | 19 | ## Mit dem Beitragen beginnen 20 | 21 |

sim-C, das über eine sehr intuitive Codebasis verfügt, werden Sie im Handumdrehen bereit sein, einen Beitrag zu leisten! 22 | Beim Hinzufügen jeglicher Funktionalität zu sim-C müssen Sie nur in den folgenden Dateien Änderungen vornehmen:

23 | 24 |

1. lexical_analyzer.py 25 | Die lexikalische Analyse ist die erste Phase eines Compilers. Sie übernimmt den modifizierten Quellcode von Sprachpräprozessoren, die in Form von Sätzen geschrieben werden. Der lexikalische Analysator zerlegt diese Syntaxen in eine Reihe von Token, indem er alle Leerzeichen oder Kommentare im Quellcode entfernt. Je nach Art der Funktionalität fügen Sie diese der jeweiligen Funktion hinzu: is_Schlüsselwort, numeric_val, string_val, keyword_identifier und/oder lexical_analyze.

26 | 27 |

2. op_code.py 28 | Sie ist für die Erstellung von Opcodes zuständig. Gegebenenfalls müssen Sie nur die Funktion opcode2dig ändern, die die ganzzahlige Darstellung des Opcode-Typs zurückgibt.

29 | 30 |

3. simc_parser.py 31 | Der Parser ist eine Interpreterkomponente, die verwendet wird, um die Daten in kleinere Elemente zu zerlegen, die aus der lexikalischen Analysephase stammen. Ein Parser nimmt Eingaben in Form einer Folge von Token entgegen und erzeugt Ausgaben. Hier kann es erforderlich sein, eine separate Funktion zu erstellen, die die Grammatik definiert und auf die Syntax prüft. Die Funktion sollte den OpCode zurückgeben. Gegebenenfalls müssen Sie auch die Funktionalität an die Parser-Funktion anhängen, die die Token parst, die jeweilige Funktion aufruft und den OpCode zurückgibt.

32 | 33 |

4. compiler.py 34 | Schließlich müssen Sie den Opcode-Typ im Compiler definieren und die erwartete C-Syntax für die Funktionalität schreiben.

35 | 36 |

Sie können einen Test in test.simc schreiben und in der Datei test.c überprüfen, ob er Ergebnisse liefert.

37 | 38 | 39 | ## Beginnen Sie 40 | 41 | Um mit simC zu beginnen, folgen Sie der offiziellen Dokumentation:- https://cimplec.github.io/docs/ 42 | 43 | Die folgenden Ressourcen sind ein guter Ort, um mehr über simC zu erfahren:- 44 | 45 | 1) Schreiben von Code in C? Vereinfachen Sie Ihr Leben mit sim-C Dev.to, Medium. 46 | 2) Erste Schritte mit sim-C Dev.to, Medium. 47 | 48 | Abgesehen von diesen Blog-Einträgen können Sie auch die offizielle Dokumente. 49 | 50 | Bevor Sie weitergehen, gehen Sie bitte die Regeln in [CONTRIBUTING.md](../CONTRIBUTING.md) 51 | 52 | ## Lizenz 53 | 54 | sim-C ist unter der GNU General Public License (GPL) v3.0 lizenziert. [LIZENZ](../LICENSE) 55 | 56 | ## Das Team 57 | 58 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 59 | - [Dhairya Jain](https://github.com/dhairyaj) 60 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 61 | -------------------------------------------------------------------------------- /readme-lang/README-ITA.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # sim-C 4 | 5 |

6 | 7 |

8 | 9 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) 10 | 11 | ## Cos'è simC? 12 | 13 |

Spesso le persone hanno problemi a programmare in C (specialmente i principianti) a causa della sua sintassi di basso livello e dell'indisponibilità di librerie di terze parti stabili. Presentiamo sim-C un front-end di alto livello per C che crea una sintassi tipizzata dinamicamente per C. L'utente può scrivere codice in questa sintassi di alto livello e quindi compilarlo in codice C ottimizzato. sim-C non elabora il codice e lo traduce semplicemente in C, quindi non c'è possibilità che il codice funzioni lentamente. Quindi, con sim-C gli utenti possono scrivere codice più velocemente utilizzando la sintassi di alto livello e allo stesso tempo essere in grado di sfruttare la potenza e la velocità di un programma C. Facciamo raffreddare di nuovo C.

14 | 15 | ## Tubatura 16 | 17 |

18 | 19 |

20 | 21 | ## Inizia a contribuire 22 |

sim-C che ha una base di codice molto intuitiva, sarai pronto a contribuire in pochissimo tempo! 23 | Durante l'aggiunta di qualsiasi funzionalità a sim-C è necessario apportare modifiche solo ai seguenti file:

24 | 25 |

1. lexical_analyzer.py 26 | L'analisi lessicale è la prima fase di un compilatore. Prende il codice sorgente modificato dai preprocessori del linguaggio scritti sotto forma di frasi. L'analizzatore lessicale suddivide queste sintassi in una serie di token, rimuovendo eventuali spazi o commenti nel codice sorgente. A seconda del tipo di funzionalità aggiungilo alla rispettiva funzione: is_keyword, numeric_val, string_val, keyword_identifier e / o lexical_analyze.

27 | 28 |

2. op_code.py 29 | È responsabile della creazione di codici operativi. Se necessario, è necessario modificare solo la funzione opcode2dig che restituisce la rappresentazione intera del tipo di codice operativo.

30 | 31 |

3. simc_parser.py 32 | Parser è un componente interprete che viene utilizzato per suddividere i dati in elementi più piccoli provenienti dalla fase di analisi lessicale.Un parser prende l'input sotto forma di sequenza di token e produce output. Qui potrebbe essere necessario creare una funzione separata che definisce la grammatica e controlla la sintassi. La funzione dovrebbe restituire l'OpCode. Inoltre, se necessario, devi aggiungere la funzionalità alla funzione di analisi che analizza i token, chiama la particolare funzione e restituisce gli opcode.

33 | 34 |

4. compiler.py 35 | Infine è necessario definire il tipo di codice operativo nel compilatore e scrivere la sintassi C prevista per la funzionalità.

36 | 37 |

Puoi scrivere un test in test.simc e verificare se sta producendo risultati nel file test.c.

38 | 39 | 40 | ## Iniziare 41 | 42 | Per iniziare con simC segui la documentazione ufficiale:- 43 | https://cimplec.github.io/docs/ 44 | 45 | Le seguenti risorse sono un buon posto per conoscere meglio simC: - 46 | 47 | 1) Scrivi codice in C? Semplifica la tua vita con sim-C Dev.to, Medium. 48 | 2) Iniziare con sim-C Dev.to, Medium. 49 | 50 | Oltre a questi post del blog, puoi anche consultare i documenti ufficiali . 51 | 52 | Prima di procedere oltre, leggi le regole in [CONTRIBUTING.md](../CONTRIBUTING.md) 53 | 54 | ## Licenza 55 | 56 | sim-C è concesso in licenza con GNU General Public License (GPL) v3.0. [LICENSE](../LICENSE) 57 | 58 | ## Il gruppo 59 | 60 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 61 | - [Dhairya Jain](https://github.com/dhairyaj) 62 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 63 | -------------------------------------------------------------------------------- /readme-lang/README-RU.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # sim-C 4 | 5 |

6 | 7 |

8 | 9 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![Звезды GitHub](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![Участники GitHub](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs приветствуются](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![последняя фиксация GitHub](https://img.shields.io/github/last-commit/cimplec/sim-c) 10 | 11 | ## Что такое sim-C? 12 | 13 |

Часто люди (особенно новички) испытывают проблемы с программированием на C из-за его синтаксиса низкого уровня и недоступности стабильных сторонних библиотек. Мы представляем sim-C как высокоуровневый интерфейс для C, который создает динамически типизированный синтаксис для C. Пользователь может писать код в этом синтаксисе высокого уровня, а затем компилировать его в оптимизированный код C. sim-C не обрабатывает код, а просто переводит его на C, поэтому нет возможности, что код будет работать медленно. Таким образом, с помощью sim-C пользователи могут писать код быстрее, используя синтаксис высокого уровня, и в то же время иметь возможность использовать мощность и скорость программы C. Давайте снова заставим C остыть.

14 | 15 | ## Трубопровод 16 | 17 |

18 | 19 |

20 | 21 | ## Начать участие 22 | 23 |

sim-C с интуитивно понятной кодовой базой, вы будете готовы внести свой вклад в кратчайшие сроки! 24 | При добавлении каких-либо функций в sim-C вам необходимо внести изменения только в следующие файлы:

25 | 26 |

1. lexical_analyzer.py 27 | Лексический анализ - это первая фаза компилятора. Он берет модифицированный исходный код из языковых препроцессоров, которые записываются в форме предложений. Лексический анализатор разбивает эти синтаксисы на серию токенов, удаляя любые пробелы или комментарии в исходном коде. В зависимости от типа функциональности добавьте его к соответствующей функции: is_keyword, numeric_val, string_val, keyword_identifier и / или lexical_analyze.

28 | 29 |

2. op_code.py 30 | Он отвечает за создание кодов операций. При необходимости вам нужно изменить только функцию opcode2dig, которая возвращает целочисленное представление типа кода операции.

31 | 32 |

3. simc_parser.py 33 | Синтаксический анализатор - это компонент интерпретатора, который используется для разбиения данных на более мелкие элементы, поступающие на этапе лексического анализа. Парсер принимает входные данные в виде последовательности токенов и производит выходные данные. Здесь вам может потребоваться создать отдельную функцию, которая определяет грамматику и проверяет синтаксис. Функция должна вернуть OpCode. Кроме того, при необходимости вы должны добавить функциональность к функции синтаксического анализа, которая анализирует токены, вызывает конкретную функцию и возвращает коды операций.

34 | 35 |

4. compiler.py 36 | Наконец, вам нужно определить тип кода операции в компиляторе и написать ожидаемый синтаксис C для функциональности.

37 | 38 |

Вы можете написать тест в test.simc и проверить, дает ли он результаты в файле test.c.

39 | 40 | 41 | ## Начать 42 | 43 | Чтобы начать работу с simC, следуйте официальной документации: - https://cimplec.github.io/docs/ 44 | 45 | Следующие ресурсы - хорошее место, чтобы узнать больше о simC: - 46 | 47 | 1) Написание кода на C? Упростите свою жизнь с помощью sim-C Dev.to , Средний . 48 | 2) Начало работы с sim-C Dev.to , Средний. 49 | 50 | Помимо этих сообщений в блоге, вы также можете ознакомиться с официальными документами . 51 | 52 | Прежде чем двигаться дальше, ознакомьтесь с правилами на [CONTRIBUTING.md](../CONTRIBUTING.md) 53 | 54 | ## Лицензия 55 | 56 | sim-C находится под лицензией GNU General Public License (GPL) v3.0. [ЛИЦЕНЗИЯ](../LICENSE) 57 | 58 | ## Команда 59 | 60 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 61 | - [Dhairya Jain](https://github.com/dhairyaj) 62 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 63 | -------------------------------------------------------------------------------- /readme-lang/README-eng.md: -------------------------------------------------------------------------------- 1 | 2 | # sim-C 3 | 4 |

5 | 6 |

7 | 8 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) 9 | 10 | ## What is sim-C? 11 | 12 |

Often people have trouble programming in C (especially beginners) due to its low level syntax and unavailability of stable third party libraries. We present sim-C a high-level front end for C which creates a dynamically typed syntax for C. User can write code in this high level syntax and then compile it to optimized C code. sim-C does not process the code and simply translates it to C thus, there is no possibility of the code running slowly. So, with sim-C users can write code faster using the high level syntax and at the same time be able to harness the power and speed of a C program. Let us make C cool again.

13 | 14 | ## Pipeline 15 | 16 |

17 | 18 |

19 | 20 | ## Start Contributing 21 | 22 |

sim-C which has a highly intuitive codebase, you'll be ready to contribute in no time! 23 | While adding any functionality to sim-C you need to make changes in the following files only:

24 | 25 |

1. lexical_analyzer.py 26 | Lexical analysis is the first phase of a compiler. It takes the modified source code from language preprocessors that are written in the form of sentences. The lexical analyzer breaks these syntaxes into a series of tokens, by removing any whitespace or comments in the source code. Depending on the type of functionality add it to the respective function: is_keyword, numeric_val, string_val, keyword_identifier and/or lexical_analyze.

27 | 28 |

2. op_code.py 29 | It is responsible for creating opcodes. If need be you need to change the opcode2dig function only which returns the integer representation of opcode type.

30 | 31 |

3. simc_parser.py 32 | Parser is an interpreter component that is used to break the data into smaller elements coming from lexical analysis phase. A parser takes input in the form of sequence of tokens and produces output. Here you may need to create a separate function which defines the grammar and checks for the syntax. The function should return the OpCode. Also, if need be you have to append the functionality to the parse function which parses the tokens, calls the particular function and returns opcodes.

33 | 34 |

4. compiler.py 35 | Finally you need to define the opcode type in the compiler and write the expected C syntax for the functonality.

36 | 37 |

You can write a test in test.simc and verify whether it's producing results in the test.c file.

38 | 39 | 40 | ## Get started 41 | 42 | To get started with simC follow the official documentation:- https://cimplec.github.io/docs/ 43 | 44 | The following resources are a good place to get to know more about simC:- 45 | 46 | 1) Writing code in C? Simplify your life with sim-C Dev.to, Medium. 47 | 2) Getting Started with sim-C Dev.to, Medium. 48 | 49 | Apart from these blog posts, you can also checkout the official docs. 50 | 51 | Before moving further please go through the rules in [CONTRIBUTING.md](../CONTRIBUTING.md) 52 | 53 | ## License 54 | 55 | sim-C is licensed under GNU General Public License (GPL) v3.0. [LICENSE](../LICENSE) 56 | 57 | ## The Team 58 | 59 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 60 | - [Dhairya Jain](https://github.com/dhairyaj) 61 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 62 | -------------------------------------------------------------------------------- /readme-lang/README-pt.md: -------------------------------------------------------------------------------- 1 | 2 | # sim-C 3 | 4 |

5 | 6 |

7 | 8 | [![GitHub](https://img.shields.io/github/license/cimplec/sim-c)](https://github.com/cimplec/sim-c/blob/master/LICENSE) ![GitHub stars](https://img.shields.io/github/stars/cimplec/sim-c?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/cimplec/sim-c) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg) ![GitHub last commit](https://img.shields.io/github/last-commit/cimplec/sim-c) 9 | 10 | ## O que é sim-C? 11 | 12 |

Muitas vezes as pessoas têm problemas para programar em C (especialmente iniciantes) devido à sua sintaxe de baixo nível e indisponibilidade de bibliotecas externas. Nós apresentamos sim-C, um *front end* de alto nível para C que cria uma sintaxe *dynamically typed* para C. O utlizador pode escrever código nesta sintaxe de alto nível e depois compliar para código C otimizado. sim-C não processa o código e o simplesmente traduz para C portanto, não é possível que o código seja lento. Por isso, com sim-C os utilizadores podem escrever código rapidamente usando a sintaxe de alto nível e ao mesmo tempo ser capazes de aproveitar a potência e velocidade de um programa de C. Deixa-nos fazer C fixe outra vez.

13 | 14 | ## Pipeline 15 | 16 |

17 | 18 |

19 | 20 | ## Começa a Contribuir 21 | 22 |

sim-C tem uma base de código muito intuitiva, estarás pronto a contribuir num instante! 23 | Enquanto adicionas funcionalidades ao sim-C precisas de fazer alterações apenas nos seguintes ficheiros:

24 | 25 |

1. lexical_analyzer.py 26 | Análise lexical é a primeira fase do compilador. Pega no código fonte modificado dos processadores de linguagem que estão escritos na forma de frases. O analisador lexical separa estas sintaxes em séries de *tokens*, removendo espaços ou comentários no código fonte. Dependendo do tipo de funcionalidade adiciona-a à respetiva função: is_keyword, numeric_val, string_val, keyword_identifier e/ou lexical_analyze.

27 | 28 |

2. op_code.py 29 | É responsável por criar *opcodes*. Se necessário, precisas de alterar apenas a função opcode2dig, que retorna a representação inteira do topo de *opcode*

30 | 31 |

3. simc_parser.py 32 | O analisador é uma componente do interpretador que é usado para separar informação em elementos mais pequenos vindos da fase da análise lexical. Um analisador recebe *input* na forma de uma sequência de *tokens* e produz um resultado. Aqui pode ser preciso criar uma função separada que defina a gramática e que verifique a sintaxe. A função deve retornar o *opcode*. Além disto, se necessário, deves anexar a funcionalidade à função parse que analisa os *tokens*, chama a função pretendida e returna os *opcodes*.

33 | 34 |

4. compiler.py 35 | Finalmente, tens de definir o tipo de *opcode* no compilador e escrever a sintaxe experada em C para a funcionalidade.

36 | 37 |

Você pode escrever testes em test.simc e verificar se está a produzir resultados no ficheiro test.c

38 | 39 | 40 | ## Começar 41 | 42 | Para começar com simC segue a documentação oficial:- https://cimplec.github.io/docs/ 43 | 44 | Os seguintes recursos são um bom sítio para conhecer melhor simC:- 45 | 46 | 1) Escreves código em C? Simplifica a tua vida com sim-C Dev.to, Medium. 47 | 2) Começar com sim-C Dev.to, Medium. 48 | 49 | Além destas publicações em blogs, podes verificar os documentos oficiais. 50 | 51 | Antes de continuares, por favor lê as regras em [CONTRIBUTING.md](../CONTRIBUTING.md) 52 | 53 | ## Licença 54 | 55 | sim-C tem uma lincença GNU General Public License (GPL) v3.0. [LICENSE](../LICENSE) 56 | 57 | ## A Equipa 58 | 59 | - [Siddhartha Dhar Choudhury](https://github.com/frankhart2018) 60 | - [Dhairya Jain](https://github.com/dhairyaj) 61 | - [Mathias Fernandes Duarte Coelho](https://github.com/Math-O5) 62 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import codecs 3 | import pathlib 4 | from setuptools import setup, find_packages 5 | 6 | # The directory containing this file 7 | HERE = pathlib.Path(__file__).parent 8 | 9 | # The text of the README file 10 | README = (HERE / "README.md").read_text() 11 | 12 | 13 | def read(rel_path): 14 | here = os.path.abspath(os.path.dirname(__file__)) 15 | with codecs.open(os.path.join(here, rel_path), "r") as fp: 16 | return fp.read() 17 | 18 | 19 | def get_version(rel_path): 20 | for line in read(rel_path).splitlines(): 21 | if line.startswith("__version__"): 22 | delim = '"' if '"' in line else "'" 23 | return line.split(delim)[1] 24 | else: 25 | raise RuntimeError("Unable to find version string.") 26 | 27 | 28 | # This call to setup() does all the work 29 | setup( 30 | name="simc", 31 | version=get_version("simc/__init__.py"), 32 | description="A dynamically typed high-level front end for C", 33 | long_description=README, 34 | long_description_content_type="text/markdown", 35 | url="https://github.com/cimplec/simc", 36 | author="Siddhartha Dhar Choudhury", 37 | author_email="sdharchou@gmail.com", 38 | license="GNU General Public License v3", 39 | packages=find_packages(), 40 | entry_points={ 41 | "console_scripts": [ 42 | "simc = simc.simc:run", 43 | "simpack = simc.simpack:get_package", 44 | ] 45 | }, 46 | package_data={"simc": ["package-index"]}, 47 | install_requires=["requests"], 48 | classifiers=[ 49 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 50 | "Programming Language :: Python :: 3", 51 | "Programming Language :: Python :: 3.9", 52 | "Programming Language :: Python :: 3.8", 53 | "Programming Language :: Python :: 3.7", 54 | "Programming Language :: Python :: 3.6", 55 | ], 56 | ) 57 | -------------------------------------------------------------------------------- /simc-codes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/simc-codes/.gitkeep -------------------------------------------------------------------------------- /simc-codes/array-declaration.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var name[3] = {1,2,3} 3 | END_MAIN 4 | -------------------------------------------------------------------------------- /simc-codes/char-input-test.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var c = input("Enter a character: ","c") 3 | print(c) 4 | END_MAIN 5 | -------------------------------------------------------------------------------- /simc-codes/q1.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var my_string = "Hello SimC!" 3 | print("My cool string is : {my_string}") 4 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q10.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | //right upper triangle pattern 3 | 4 | var rows = 5 5 | var i = 0 6 | var j = 0 7 | while(i<=rows) 8 | { 9 | j = 0 10 | 11 | //printing empty space 12 | while(j=ctr) 10 | { 11 | x = ctr*ctr 12 | sum = sum + x 13 | print (x) 14 | print (" ") 15 | ctr = ctr + 1 16 | } 17 | print("The sum is : {sum}") 18 | 19 | END_MAIN 20 | -------------------------------------------------------------------------------- /simc-codes/q110.simc: -------------------------------------------------------------------------------- 1 | // Print sum of numbers divisible by 9 from 100 to 200 2 | 3 | MAIN 4 | 5 | var sum=0 6 | var num=0 7 | var x=100 8 | 9 | while(x<=200) 10 | { 11 | if(x%9==0) 12 | { 13 | sum = sum + x 14 | num = num + 1 15 | } 16 | x = x + 1 17 | } 18 | print("The sum is : {sum} \n") 19 | print("The number of such numbers is : {num}") 20 | 21 | END_MAIN 22 | -------------------------------------------------------------------------------- /simc-codes/q112.simc: -------------------------------------------------------------------------------- 1 | fun area_circumcircle_square( side ) { 2 | return 3.14159 * side * side / 2 3 | } 4 | MAIN 5 | var sideLength = input( "Enter side length: ", "f" ) 6 | var answer = area_circumcircle_square( sideLength ) 7 | print( "Area of the given Square's Circumcircle: {answer}" ) 8 | 9 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q113.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var rad = 0.06 3 | var h = 0.21 4 | var vol = PI*rad*rad*h 5 | print("The volume of the cylinder with radius 6cm and height 21cm is : {vol} cubic metres") 6 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q114.simc: -------------------------------------------------------------------------------- 1 | //If a metal cube of side 3m is melted to make small balls, find the number of balls formed if each ball has a radius of 1.5cm 2 | MAIN 3 | var vol1 = 3*3*3 4 | var vol2 = 4/3 * PI * ((1.5/100)*(1.5/100)*(1.5/100)) 5 | var number_of_balls = vol1/vol2 6 | print("The number of balls formed are: {number_of_balls}") 7 | END_MAIN 8 | -------------------------------------------------------------------------------- /simc-codes/q12.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n = 3 3 | var i = 0 4 | var j = 0 5 | while(i0){ 5 | sum = sum + n % 10 6 | n= n/10 7 | } 8 | print("{sum} is the Sum of the digits.") 9 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q14.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var side = 4 3 | var perimeter = 4 * side 4 | print("The perimeter of square of length {side} = {perimeter}") 5 | END_MAIN 6 | -------------------------------------------------------------------------------- /simc-codes/q15.simc: -------------------------------------------------------------------------------- 1 | //Compute perimeter of a rectangle 2 | MAIN 3 | var width = 5 4 | var length = 7 5 | var perimeter = 2*(length + width) 6 | print("Perimeter = {perimeter}") 7 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q17.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Multiply the digits of a number together 3 | var num = input("Enter a number: ", "i") 4 | var result = 1 5 | var temp = num 6 | if (num == 0) { // Manage the special case if the user enters 0 7 | result = 0 8 | } 9 | while (temp > 0) { 10 | result = result * (temp % 10) 11 | temp = temp / 10 12 | } 13 | print("If you multiply all of the digits in ") 14 | print(num) 15 | print(", you get ") 16 | print(result) 17 | print("\n") 18 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q18.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Check if the number is a palindrome 3 | var num = input("Enter a number: ", "i") 4 | var temp1 = num 5 | var temp2 = 0 6 | while (num > 0) { 7 | temp2 = temp2 * 10 + (num % 10) 8 | num = num / 10 9 | } 10 | 11 | if(temp1 == temp2) { 12 | print("Number is palindrome ") 13 | } 14 | else { 15 | print("Number is not a palindrome") 16 | } 17 | END_MAIN 18 | -------------------------------------------------------------------------------- /simc-codes/q19.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Convert a binary number to a decimal number 3 | 4 | // Read in the binary number and count its digits 5 | var num = input("Enter a binary number: ", "i") 6 | var digs = 0 7 | var tmp = num 8 | while (tmp > 0) { 9 | digs = digs+1 10 | tmp = tmp/10 11 | } 12 | 13 | // Generate the binary result 14 | var val = 1 15 | var result = 0 16 | tmp = num 17 | while (tmp > 0) { 18 | if (tmp % 10 > 0) { 19 | result = result + val 20 | } 21 | val = val * 2 22 | tmp = tmp / 10 23 | } 24 | 25 | // Print the result 26 | print(num) 27 | print(" in binary is ") 28 | print(result) 29 | print(" in decimal\n") 30 | 31 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q2.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // taking input from the user 3 | var number1 = input("Enter first number : ", "f") 4 | var number2 = input("Enter second number : ", "f") 5 | var sum=0 6 | 7 | 8 | // A logic to print sum of two numbers 9 | sum=number1+number2 10 | print("The value of Sum is = {sum}") 11 | END_MAIN 12 | -------------------------------------------------------------------------------- /simc-codes/q20.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // User input takes a binary number as input 3 | var dec_num = input("Enter a Number: ", "i") 4 | var bin_num = 0 5 | var lsb = 0 6 | var counter = 0 7 | var temp_dec = dec_num // for presentation purpose in print statement 8 | 9 | 10 | // working 11 | // the decimal number is converted in a single single bit and is then worked upon (starting from lsb [Least significant bit (rightmost)]) 12 | // the bit is first isolated, converted into decimal by multiplying 8 ^ position of the bit and added to the decimal number 13 | // the binary number is then divided so that the lsb is shifted to right by one position 14 | 15 | while(dec_num > 0) { 16 | lsb = dec_num % 2 17 | bin_num = bin_num + lsb * 10 ^ counter 18 | dec_num = dec_num / 2 19 | counter = counter + 1 20 | } 21 | print("{temp_dec} in Binary format is {bin_num}") 22 | 23 | END_MAIN 24 | -------------------------------------------------------------------------------- /simc-codes/q201.simc: -------------------------------------------------------------------------------- 1 | // Calculate modulo of two numbers without using the inbuilt modulo operator (%), second method. 2 | // A == (A/B)*B + (A%B) 3 | MAIN 4 | var numerator = input("Numerator: ", "i") 5 | var divisor = input("Divisor: ", "i") 6 | var rest = numerator 7 | var abs_divisor = divisor 8 | 9 | // Load the abs value for divisor 10 | if(divisor < 0) { 11 | abs_divisor = -divisor 12 | } 13 | 14 | // The zero is not defined for division 15 | if(divisor == 0) { 16 | print("Divisor is not defined in zero.\n") 17 | return 0 18 | } 19 | 20 | // Calculate the division A/B 21 | var divided = rest/divisor 22 | 23 | // The division of A/B is equivalent to subtract B from A until A is greater or equal to B. 24 | rest = rest - (divided*divisor) 25 | 26 | // 27 | if(rest < 0) { 28 | rest = rest + abs_divisor 29 | } 30 | 31 | print("The remain of {numerator} MOD({divisor}) = {rest}\n") 32 | END_MAIN 33 | -------------------------------------------------------------------------------- /simc-codes/q22.simc: -------------------------------------------------------------------------------- 1 | // to find maximum and minimum digit of a number. 2 | MAIN 3 | var n = input("Input number : ", "i") 4 | var small = 9 5 | var large = 0 6 | var digit 7 | if(n==0){ 8 | small = 0 9 | large = 0 10 | } 11 | else if(n>0){ 12 | while(n>0) 13 | { 14 | digit=n%10 15 | 16 | if(digit>large){ 17 | large=digit; 18 | } 19 | if(digit<=small){ 20 | small=digit; 21 | } 22 | n=n/10 23 | } 24 | } 25 | else{ 26 | print("Enter a non-negative integer") 27 | exit(0) 28 | } 29 | print("Maximum digit of the number is : {large}\n") 30 | print("Minimum digit of the number is : {small}") 31 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q23.simc: -------------------------------------------------------------------------------- 1 | // to find greatest of three numbers 2 | 3 | MAIN 4 | 5 | //Take input of the three numbers 6 | var n1 = input("Input first number : ", "i") 7 | var n2 = input("Input second number : ", "i") 8 | var n3 = input("Input third number : ", "i") 9 | 10 | //Compare the three numbers pairwise and print the maximum among them 11 | if(n1>=n2 && n1>=n3){ 12 | print("Maximum of the three numbers is: {n1}") 13 | } 14 | else if(n2>=n1 && n2>=n3){ 15 | print("Maximum of the three numbers is: {n2}") 16 | } 17 | else{ 18 | print("Maximum of the three numbers is: {n3}") 19 | } 20 | 21 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q24.simc: -------------------------------------------------------------------------------- 1 | //To find least of three numbers 2 | 3 | MAIN 4 | 5 | //Take input of the three numbers 6 | var n1 = input("Input the first number : ", "i") 7 | var n2 = input("Input the second number : ", "i") 8 | var n3 = input("Input the third number : ", "i") 9 | 10 | //Compare the three numbers pairwise and print the least among them 11 | if(n1<=n2 && n1<=n3){ 12 | print("Least of the three numbers is: {n1}") 13 | } 14 | else if(n2<=n1 && n2<=n3){ 15 | print("Least of the three numbers is: {n2}") 16 | } 17 | else{ 18 | print("Least of the three numbers is: {n3}") 19 | } 20 | 21 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q25.simc: -------------------------------------------------------------------------------- 1 | // Print reverse of a number. 2 | MAIN 3 | var n = input("Input number : ", "i") 4 | var reverse = 0 5 | var digit 6 | if(n<0){ 7 | print("Enter non-negative integer") 8 | } 9 | else{ 10 | while(n>0) 11 | { 12 | digit=n%10 13 | reverse = reverse*10 + digit 14 | n=n/10 15 | } 16 | print("Reverse of the number is : {reverse}") 17 | } 18 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q26.simc: -------------------------------------------------------------------------------- 1 | // to find factorial of a number without recursion 2 | 3 | MAIN 4 | 5 | //Take input of the number whose factorial is to be calculated 6 | var n = input("Input number : ", "i") 7 | var i = 1 8 | var factorialofn = 1 9 | while(i<=n){ 10 | factorialofn = factorialofn*i; 11 | i++ 12 | } 13 | print("Factorial of n is: {factorialofn}") 14 | 15 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q27.simc: -------------------------------------------------------------------------------- 1 | // Sum of factorial of digits of a number. 2 | MAIN 3 | var n = input("Input number : ", "i") 4 | var digit 5 | var sum = 0 6 | if(n==0){ 7 | sum = 1 8 | } 9 | else{ 10 | while(n>0) 11 | { 12 | digit=n%10 13 | var f = 1 14 | var k = digit+1 15 | var i = 1 16 | while(i < k) { 17 | f = f*i 18 | i=i+1 19 | } 20 | sum = sum + f 21 | n=n/10 22 | } 23 | 24 | } 25 | print("Sum of factorial of digits of the number is : {sum}") 26 | END_MAIN 27 | 28 | -------------------------------------------------------------------------------- /simc-codes/q28.simc: -------------------------------------------------------------------------------- 1 | //Calculate value of nPx 2 | 3 | MAIN 4 | 5 | //Take input of the n and x to calculate nPx 6 | var n = input("Input value of n in nPx : ", "i") 7 | var x = input("Input value of x in nPx : ", "i") 8 | 9 | var i = 1 10 | var nfact = 1 11 | while(i<=n){ 12 | nfact = nfact*i 13 | i++ 14 | } 15 | 16 | var nminusx = n-x 17 | var nminusxfact = 1 18 | var j = 1 19 | while(j<=nminusx){ 20 | nminusxfact = nminusxfact*j 21 | j++ 22 | } 23 | 24 | var npx = nfact/nminusxfact 25 | 26 | print("Value of nPx is: {npx}") 27 | 28 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q29.simc: -------------------------------------------------------------------------------- 1 | //Calculate value of nCx 2 | 3 | MAIN 4 | 5 | //Take input of the n and x to calculate nCx 6 | var n = input("Input value of n in nCx : ", "i") 7 | var x = input("Input value of x in nCx : ", "i") 8 | 9 | var i = 1 10 | var nfact = 1 11 | while(i<=n){ 12 | nfact = nfact*i 13 | i++ 14 | } 15 | 16 | var nminusx = n-x 17 | var nminusxfact = 1 18 | var j = 1 19 | while(j<=nminusx){ 20 | nminusxfact = nminusxfact*j 21 | j++ 22 | } 23 | 24 | var k = 1 25 | var xfact = 1 26 | while(k<=x){ 27 | xfact = xfact*k 28 | k++ 29 | } 30 | 31 | var ncx = nfact/(nminusxfact*xfact) 32 | 33 | print("Value of nCx is: {ncx}") 34 | 35 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q3.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n = input("Enter a num: ","i") 3 | 4 | var a = 1 5 | if(n==1){ 6 | a = 0 7 | } 8 | else{ 9 | var root = n^0.5 10 | var i = 2 11 | while(i <= root) { 12 | if(n%i == 0){ 13 | a = 0 14 | break 15 | } 16 | i = i+1 17 | } 18 | } 19 | 20 | if(a == 0){ 21 | print("{n} is not prime") 22 | } 23 | else{ 24 | print("{n} is prime") 25 | } 26 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q30.simc: -------------------------------------------------------------------------------- 1 | 2 | MAIN 3 | // Calculate the sum of series: x^1/1 - x^2/2 + x^3/3 .. 4 | var x = input("Enter the variable x : ", "i") 5 | var num = input("Enter the limit of the series: ", "i") 6 | var sum = 0 7 | var calc = 1 8 | for i in 0 to num by +1 { 9 | calc = calc*x 10 | if(i%2==0) { 11 | sum = sum + calc/(i+1) 12 | } 13 | else{ 14 | sum = sum - calc/(i+1) 15 | } 16 | } 17 | print("Sum of the series is : ") 18 | print(sum) 19 | END_MAIN 20 | -------------------------------------------------------------------------------- /simc-codes/q31.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var year = input("Input the year : " , "i") 3 | 4 | if(year%4==0 && year%100 !=0){ 5 | print("Yes , It is a leap year!") 6 | } 7 | else if(year%400 ==0){ 8 | print("Yes , It is a leap year!") 9 | } 10 | else{ 11 | print("No , It is not a leap year!") 12 | } 13 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q32.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | 3 | var x = input("Enter value of the base : ", "f" ) 4 | var n = input("Enter value of the range : ", "f" ) 5 | 6 | var i=1 7 | var total= x 8 | var multi = x 9 | n= n+1 10 | var multi_temp=1.0 11 | 12 | for i in 1 to n by +1{ 13 | multi_temp=multi/i 14 | total = total + multi_temp 15 | multi = multi* x; 16 | } 17 | 18 | print("The final value is {total}") 19 | 20 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q33.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n 3 | var i=1 4 | var s = 0.0 5 | n=input("Enter Range of Number: ","i") 6 | while(i<=n){ 7 | s = s + 1/i 8 | i++ 9 | } 10 | print("Sum is %f") 11 | print(s) 12 | END_MAIN 13 | -------------------------------------------------------------------------------- /simc-codes/q34.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var string1 = input() 3 | var string2 = input() 4 | print("First String is : {string1}") 5 | print("Second String is : {string2}") 6 | BEGIN_C 7 | int len1 = 0; 8 | int len2 = 0; 9 | while(string1[len1]!='\0') len1++; 10 | while(string2[len2]!='\0') len2++; 11 | char result[len1+len2]; 12 | for(int i=0;i 9 | END_C 10 | 11 | // sqrt wrapper function 12 | fun square_root(value) { 13 | var result = 0.0 14 | 15 | BEGIN_C 16 | result = sqrt(value); 17 | END_C 18 | 19 | return result 20 | } 21 | 22 | MAIN 23 | // User input 24 | print("Enter sides of the ABC triangle") 25 | var side_a = input("Enter side A : ", "d") 26 | var side_b = input("Enter side B : ", "d") 27 | var side_c = input("Enter side C : ", "d") 28 | 29 | // Heron's formula 30 | // area = sqrt(s * (s - a) * (s - b) * (s - c)) 31 | var semi_perimeter = side_a + side_b + side_c 32 | semi_perimeter /= 2 33 | 34 | var squared_area = semi_perimeter 35 | squared_area *= semi_perimeter - side_a 36 | squared_area *= semi_perimeter - side_b 37 | squared_area *= semi_perimeter - side_c 38 | 39 | var tri_area = square_root(squared_area) 40 | 41 | print("The area is {tri_area}") 42 | END_MAIN 43 | -------------------------------------------------------------------------------- /simc-codes/q37.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | 3 | var num1 = input("Enter the first number : ", "i") 4 | var num2 = input("Enter the second number : ", "i") 5 | 6 | var count1 = 0 7 | var count2 = 0 8 | 9 | var i =1 10 | 11 | while(i<=num1) { 12 | if(num1 % i == 0){ 13 | count1++; 14 | } 15 | i++ 16 | } 17 | i=1 18 | while(i<=num2){ 19 | if(num2 % i == 0){ 20 | count2++; 21 | } 22 | i++ 23 | } 24 | 25 | var d 26 | 27 | if(num1 > num2){ 28 | d=num1 - num2 29 | } 30 | else{ 31 | d= num2-num1 32 | } 33 | 34 | if(d == 2 && count1 == 2 && count2 == 2){ 35 | print("The Two Numbers are Twin Prime"); 36 | } 37 | else{ 38 | print("The two Numbers are Not Twin Prime"); 39 | } 40 | END_MAIN 41 | 42 | -------------------------------------------------------------------------------- /simc-codes/q38.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Finding hypotenuse of a triangle using Pythagoras Theorem 3 | var perp = input("Enter the length of the perpendicular of the triangle:\t","f") 4 | var base = input("Enter the length of the base of the triangle:\t","f") 5 | var num1=perp^2 6 | var num2=base^2 7 | var num3=num1+num2 8 | // Finding the square root of the sum of squares of the perpendicular and base 9 | var sqrt=num3/2 10 | var temp=0 11 | var v1 12 | 13 | while(sqrt!=temp ) { 14 | temp=sqrt 15 | 16 | v1=(num3/temp + temp) 17 | sqrt=v1/2 18 | } 19 | print("The length of the hypotenuse of the triangle is = {sqrt}") 20 | END_MAIN 21 | 22 | -------------------------------------------------------------------------------- /simc-codes/q39.simc: -------------------------------------------------------------------------------- 1 | 2 | MAIN 3 | var p = input("Input principle : ", "i") 4 | var r = input("Input Rate of interest : ", "i") 5 | var t = input("Input Time : ", "i") 6 | var amount= p*r*t/100 7 | print("Simple interest =") 8 | print(amount) 9 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q4.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Taking input from user 3 | var input_number = input("Enter a number : ", "i") 4 | 5 | // Checking Odd or Even by using Modulo Operator 6 | if (input_number % 2 == 0) { 7 | print("{input_number} is Even!") 8 | } else { 9 | print("{input_number} is Odd!") 10 | } 11 | 12 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q40.simc: -------------------------------------------------------------------------------- 1 | //Compute compound interest 2 | MAIN 3 | var p = input("Input principle amount : ", "f") 4 | var t = input("Input time : ", "f") 5 | var r = input("Input rate : ", "f") 6 | r = r/100 7 | var interest = 1+r 8 | interest = interest^t 9 | var ci= p*interest 10 | print("Compound interest is : {ci}") 11 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q41.simc: -------------------------------------------------------------------------------- 1 | //Question 2 | 3 | //Check if a number is special or not. 4 | //A number is special when sum of factorial of digits of number is equal to that number. 5 | //Example 145 = 1! + 4! + 5! = 145. 6 | 7 | 8 | 9 | MAIN 10 | //Taking input nunmber from user in p(int) 11 | var p = input("enter a nunmber : ", "i") 12 | 13 | // Initializations 14 | //temperory variable : temp 15 | //variable to store sum of factorials : facto 16 | 17 | var temp=p 18 | var facto=0 19 | 20 | 21 | // This is where the real magic happens !! 22 | // The main while loop 23 | 24 | while (temp!=0){ 25 | var facto_cal=1 26 | 27 | var digit=temp%10 28 | 29 | while (digit != 1) 30 | { 31 | facto_cal = facto_cal*digit 32 | digit=digit-1 33 | } 34 | 35 | facto = facto+facto_cal 36 | temp = temp/10 37 | 38 | 39 | } 40 | 41 | //Conditionals to check if the number is special or not 42 | 43 | if ( facto == p){ 44 | print('Special') 45 | } 46 | else{ 47 | print('Not special') 48 | } 49 | 50 | END_MAIN 51 | -------------------------------------------------------------------------------- /simc-codes/q42.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var num = input("Enter a number:\t","i") 3 | var sqr = num * num 4 | var temp = num; 5 | var n = 0; 6 | while(temp>0){ 7 | n = n + 1 8 | temp = temp/10 9 | } 10 | var power = 10 ^n 11 | var split = sqr % power 12 | if(split == num){ 13 | print("Automorphic number\n") 14 | } 15 | else{ 16 | print("Not a Automorphic number\n") 17 | } 18 | END_MAIN 19 | -------------------------------------------------------------------------------- /simc-codes/q43.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var num = input("Enter a number:\t","i") 3 | var count =0 4 | var i =1 5 | var flag =0 6 | while(i<=num){ 7 | if(num % i == 0){ 8 | count = count + 1 9 | } 10 | i = i+1 11 | } 12 | if(count>2){ 13 | flag =1 14 | } 15 | if(flag==1){ 16 | var sumofdigits =0 17 | i = num 18 | while(i!=0){ 19 | sumofdigits = sumofdigits + (i%10) 20 | i = i/10 21 | } 22 | var sumofprime = 0 23 | var prime = 2 24 | i = num 25 | var tempsum = 0 26 | var j 27 | while(i != 1){ 28 | while(i % prime == 0 && prime <= i){ 29 | tempsum = 0 30 | j = prime 31 | while(j!=0){ 32 | tempsum = tempsum + (j%10) 33 | j = j/10 34 | } 35 | sumofprime = sumofprime + tempsum; 36 | i /= prime; 37 | } 38 | prime++; 39 | } 40 | if(sumofdigits==sumofprime){ 41 | print("Smith Number") 42 | } 43 | else{ 44 | print("Not a Smith Number") 45 | } 46 | } 47 | else{ 48 | print("Not a Smith Number") 49 | } 50 | END_MAIN 51 | -------------------------------------------------------------------------------- /simc-codes/q44.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Determines if a number is a Kaprekar number 3 | // A list of Kaprekar numbers can be found here: https://oeis.org/A006886 4 | // First get all of the parameters from the user 5 | print("Kaprekar Number Test\n") 6 | var power = input("Power: ", "i") 7 | var n = input("Number you want to test: ", "i") 8 | 9 | // Next, find the values for the Kaprekar function 10 | var beta_1 = n^2 11 | var beta_2 = (10^power) 12 | var beta = beta_1 % beta_2 13 | var alpha_1 = n^2 - beta 14 | var alpha_2 = 10^power 15 | var alpha = alpha_1/alpha_2 16 | 17 | // Finally, calculate and compare the result 18 | if (alpha+beta == n) { 19 | print(n) 20 | print(" is a ") 21 | print(power) 22 | print("-Kaprekar number\n") 23 | } else { 24 | print(n) 25 | print(" is not a ") 26 | print(power) 27 | print("-Kaprekar number\n") 28 | } 29 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q45.simc: -------------------------------------------------------------------------------- 1 | //To find composite factors of a number 2 | MAIN 3 | //Take input of the number whose factors are to be calculated 4 | var n = input("Input number : ", "i") 5 | print("Composite Factors of {n} are:") 6 | var i = 1 7 | var p = 1 8 | while(i <= n){ 9 | if (n % i == 0){ 10 | var j = 2 11 | while (j < i) { 12 | if (i%j == 0){ 13 | p=0 14 | } 15 | j++ 16 | } 17 | if(p == 0){ 18 | print(" {i}") 19 | } 20 | } 21 | i++ 22 | } 23 | END_MAIN 24 | -------------------------------------------------------------------------------- /simc-codes/q46.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n1 = input("Enter first number : ", "i") 3 | var n2 = input("Enter second number : ", "i") 4 | var max 5 | if (n1 > n2){ 6 | max = n1 7 | } 8 | else { 9 | max = n2 10 | } 11 | while(1){ 12 | if(max % n1 == 0 && max % n2 ==0){ 13 | print("LCM is : {max}") 14 | break 15 | } 16 | max++ 17 | } 18 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q47.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var a = input("Enter first number : ", "i") 3 | var b = input("Enter second number : ", "i") 4 | var c 5 | var max 6 | var min 7 | 8 | // Handle special cases 9 | if (a == 0 && b == 0){ 10 | print("Numbers must not be all zero!") 11 | exit(0) 12 | } 13 | if (a == 0 || b == 0){ 14 | c = a + b 15 | print("GCD = {c}") 16 | exit(0) 17 | } 18 | if (a == b){ 19 | print("GCD = {a}") 20 | exit(0) 21 | } 22 | 23 | //Sort numbers 24 | if (a > b){ 25 | max = a 26 | min = b 27 | } 28 | else{ 29 | max = a 30 | min = b 31 | } 32 | 33 | // Euklidian Algorithm 34 | do { 35 | c = max % min 36 | max = min 37 | min = c 38 | } while (c != 0) 39 | 40 | print("GCD = {max}") 41 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q48.simc: -------------------------------------------------------------------------------- 1 | //To check if a phone number is valid 2 | MAIN 3 | //Take input of the number whose factors are to be calculated 4 | var n = input("Input number : ", "d") 5 | if (n >= 1000000000 && n <= 9999999999) { 6 | print("Valid Phone Number") 7 | } else { 8 | print("Invalid Phone Number") 9 | } 10 | END_MAIN 11 | -------------------------------------------------------------------------------- /simc-codes/q49.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var pi = 3.14 3 | var radius = 4 4 | var height = 2 5 | var volume = pi * radius * radius * height 6 | print("Result = {volume}") 7 | END_MAIN 8 | -------------------------------------------------------------------------------- /simc-codes/q5.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var num = input("Enter a number : ", "i") 3 | 4 | var sum = 0 5 | 6 | var x = num 7 | while(x != 0) 8 | { 9 | var digit = x % 10 10 | sum = sum + digit ^ 3 11 | x = x/10 12 | } 13 | 14 | if(num == sum){ 15 | print("{num} is an Armstrong number") 16 | } 17 | else { 18 | print("{num} is not an Armstrong number") 19 | } 20 | END_MAIN 21 | -------------------------------------------------------------------------------- /simc-codes/q51.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var x1 = input("Enter x coordinate of center of circle 1 ", "i") 3 | var y1 = input("Enter y coordinate of center of circle 1 ", "i") 4 | var r1 = input("Enter radius of circle 1 ","i") 5 | var x2 = input("Enter x coordinate of center of circle 2 ","i") 6 | var y2 = input("Enter y coordinate of center of circle 2 ","i") 7 | var r2 = input("Enter radius of circle 2 ","i") 8 | var diffx = (x1-x2) 9 | var diffy = (y1-y2) 10 | diffx = diffx*diffx 11 | diffy = diffy*diffy 12 | var diff = diffx + diffy 13 | var rad1 = r1*r1 14 | var rad2 = r2*r2 15 | var sum = rad1 + rad2 16 | if(sum==diff){ 17 | print("The circles are orthogonal") 18 | } 19 | else{ 20 | print("The circles are not orthogonal") 21 | } 22 | END_MAIN 23 | -------------------------------------------------------------------------------- /simc-codes/q52.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Get the number and figure out how many digits it has 3 | print("Magic Number Checker\n") 4 | var num = input("Enter a number: ", "i") 5 | var digs = 0 6 | var ismagic = 1 7 | var tmp = num 8 | while (tmp > 0) { 9 | tmp = tmp/10 10 | digs = digs + 1 11 | } 12 | 13 | // Check each digit to see if duplicates exist 14 | var loc1 = 0 // The location of the digit being checked for 15 | var loc2 = 0 // The current digit location 16 | while (loc1 < digs) { 17 | var digit1 = num / (10^loc1) // The digit being checked for 18 | digit1 = digit1 % 10 19 | var digit2 20 | 21 | // Check each location to see if we can find a duplicate of the number 22 | loc2 = 0 23 | while (loc2 < digs) { 24 | digit2 = num / (10^loc2) // The digit we're currently checking digit1 against 25 | digit2 = digit2 % 10 26 | if (digit1==digit2 && loc1!=loc2) { // Notice that we exclude the number from counting itself as a duplicate 27 | ismagic = 0 28 | } 29 | loc2 = loc2 + 1 30 | } 31 | loc1 = loc1 + 1 32 | } 33 | 34 | // Print the result 35 | if (ismagic==1) { 36 | print("This is a magic number!\n") 37 | } else { 38 | print("This is not a magic number!\n") 39 | } 40 | 41 | END_MAIN 42 | -------------------------------------------------------------------------------- /simc-codes/q53.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Compute the area of a rhombus, given its diagonals 3 | // The diagonals are float inputs 4 | 5 | // Get the two diagonals 6 | var p = input("First diagonal : ", "f") 7 | var q = input("Second diagonal : ", "f") 8 | 9 | // Verify that the diagonals are positive 10 | if(p>=0 && q>=0) { 11 | var area = p*q/2 12 | 13 | print("Area of the rhombus ({p}, {q}) is {area}") 14 | } else { 15 | print("Diagonals cannot be negative") 16 | } 17 | END_MAIN 18 | -------------------------------------------------------------------------------- /simc-codes/q54.simc: -------------------------------------------------------------------------------- 1 | //Print Area of Trapezium. 2 | 3 | MAIN 4 | var a = input("Input shorter parallel side length: ", "i") 5 | var b = input("Input larger parallel side length: ", "i") 6 | var h = input("Input perpendicular distance between parallel sides: ", "i") 7 | var area 8 | var num1 9 | 10 | if(h<=0){ 11 | print("Height cannot be 0 or negative") 12 | } 13 | else{ 14 | num1 = (a+b) 15 | area = num1*h/2 16 | print("Area of trapezium is : {area}") 17 | } 18 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q55.simc: -------------------------------------------------------------------------------- 1 | // Check if two numbers are coprime or not. 2 | 3 | MAIN 4 | var num1 = input("Input first number: ", "i") 5 | var num2 = input("Input second number: ", "i") 6 | var hcf = 0 7 | var i = 1 8 | if(num1 <= num2){ 9 | while(i <= num1){ 10 | if(num1%i == 0 && num2%i ==0){ 11 | hcf = i 12 | } 13 | i++ 14 | } 15 | } 16 | else{ 17 | while(i <= num2){ 18 | if(num1%i == 0 && num2%i ==0){ 19 | hcf = i 20 | } 21 | i++ 22 | } 23 | } 24 | if(hcf == 1){ 25 | print("The numbers are Coprime") 26 | } 27 | else{ 28 | print("The numbers are not Coprime") 29 | } 30 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q56.simc: -------------------------------------------------------------------------------- 1 | // Calculate Cost Price when loss percentage and selling price are given 2 | 3 | MAIN 4 | var loss = input("Enter the percentage loss incurred: ", "i") 5 | var sell_price = input("Enter the selling price: ", "i") 6 | var cost_price 7 | var deno 8 | 9 | if(loss >= 100){ 10 | print("Percentage loss cannot be greater than or equal to 100") 11 | } 12 | else{ 13 | deno = 100 - loss 14 | cost_price = 100*sell_price/deno 15 | print("The Cost Price is: {cost_price}") 16 | } 17 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q57.simc: -------------------------------------------------------------------------------- 1 | //Divide two numbers 2 | 3 | MAIN 4 | var num = input("Input numerator: ", "i") 5 | var denom = input("Input denominator: ", "i") 6 | var res 7 | 8 | if(denom != 0) { 9 | res = num / denom 10 | print("The division output is: {res}") 11 | } else { 12 | print("Denominator cannot be zero") 13 | } 14 | 15 | 16 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q58.simc: -------------------------------------------------------------------------------- 1 | // task of this problem to find average of 7 numbers when 2 | // sum of six numbers and seventh number is provided to us 3 | 4 | MAIN 5 | 6 | var avg_of_six_numbers = 45 7 | var seventh_number = 21 8 | 9 | var sum_of_six_numbers = avg_of_six_numbers * 6 // since average of 6 numbers are given ((ie a1+a2+a3+a4+a5+a6) / 6 = 45) therefore sum of 6 numbers is 45 * 6 10 | var sum_of_seven_numbers = sum_of_six_numbers + seventh_number // we can add seventh number to the sum ie(sum of 7 numbers), dividing it with 7 will give us the needed average 11 | var result = sum_of_seven_numbers / 7 12 | print("Area of 7 numbers is {result} ") 13 | 14 | END_MAIN 15 | -------------------------------------------------------------------------------- /simc-codes/q59.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // User input [taking radius as input, declaring pi in the code itself, would be directly imported from math helper class] 3 | var radius = input("Enter a Radius: ", "i") 4 | var pi = 3.14159 5 | 6 | var area = radius * radius * pi // area = (pi * (r ^ 2)) 7 | 8 | print("Area of circle with Radius {radius} is {area} ") 9 | 10 | END_MAIN 11 | -------------------------------------------------------------------------------- /simc-codes/q6.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var i = 0 3 | var n = 10 4 | var prev = 0 5 | var next = 1 6 | while(i=0; j--) 35 | printf("%c",hexaDeciNum[j]); 36 | 37 | END_C 38 | 39 | 40 | END_MAIN 41 | -------------------------------------------------------------------------------- /simc-codes/q65.simc: -------------------------------------------------------------------------------- 1 | //Convert Hexadecimal to Decimal 2 | 3 | MAIN 4 | 5 | var decnum=0 6 | var i=0 7 | var len=0 8 | var rem=0 9 | 10 | //C used to declare and use array for hexadecimal to decimal conversion. 11 | BEGIN_C 12 | char hexnum[20]; 13 | printf("Enter any Hexadecimal Number: "); 14 | scanf("%s", hexnum); 15 | while(hexnum[i]!='\0') 16 | { 17 | len++; 18 | i++; 19 | } 20 | len--; 21 | i=0; 22 | while(len>=0) 23 | { 24 | rem = hexnum[len]; 25 | if(rem>=48 && rem<=57) 26 | rem = rem-48; 27 | else if(rem>=65 && rem<=90) 28 | rem = rem-55; 29 | 30 | decnum = decnum + (rem*pow(16, i)); 31 | len--; 32 | i++; 33 | } 34 | END_C 35 | print("Decimal Value is {decnum}") 36 | 37 | END_MAIN 38 | -------------------------------------------------------------------------------- /simc-codes/q66.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // User input takes a binary number as input 3 | var oct_num = input("Enter a Number in its octal representation: ", "i") 4 | var dec_num = 0 5 | var lsb = 0 6 | var counter = 0 7 | var temp_oct = oct_num // for presentation purpose in print statement 8 | 9 | 10 | // working 11 | // the octal number is converted in a single single bit and is then worked upon (starting from lsb [Least significant bit (rightmost)]) 12 | // the bit is first isolated, converted into decimal by multiplying 8 ^ position of the bit and added to the decimal number 13 | // the binary number is then divided so that the lsb is shifted to right by one position 14 | 15 | while(oct_num > 0) { 16 | lsb = oct_num % 10 17 | if (lsb > 7) { 18 | print("Not a valid Octal Number") 19 | break 20 | } 21 | dec_num = dec_num + lsb * 8 ^ counter 22 | oct_num = oct_num / 10 23 | counter = counter + 1 24 | } 25 | if(lsb < 8 && temp_oct != 0){ 26 | print("{temp_oct} in Octal format is {dec_num}") 27 | } 28 | END_MAIN 29 | -------------------------------------------------------------------------------- /simc-codes/q67.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var decimal_no = input("Enter a number :", "i") 3 | var initial_val = decimal_no //saving initial value for output 4 | var octal_no = 0 5 | var place = 1 6 | while(decimal_no != 0){ 7 | 8 | octal_no += decimal_no % 8*place //digit for consecutive places added 9 | place *= 10 // move to next place 10 | decimal_no /= 8 11 | 12 | } 13 | print("{initial_val} in octal = {octal_no}\n") 14 | END_MAIN 15 | -------------------------------------------------------------------------------- /simc-codes/q68.simc: -------------------------------------------------------------------------------- 1 | //Convert binary number to hexadecimal 2 | MAIN 3 | //Take input as the binary number as a double 4 | var binaryval = input("Input number : ", "i") 5 | var hexadecimalval = 0 6 | var i = 1 7 | var remainder = 0 8 | while (binaryval != 0) { 9 | remainder = binaryval % 10 10 | hexadecimalval = hexadecimalval + remainder * i 11 | i = i * 2 12 | binaryval = binaryval / 10 13 | } 14 | BEGIN_C 15 | printf("Equivalent hexadecimal value: %lX\n", hexadecimalval); 16 | END_C 17 | 18 | END_MAIN 19 | -------------------------------------------------------------------------------- /simc-codes/q69.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // User input takes a binary number as input 3 | var bin_num = input("Enter a Binary Number: ", "i") 4 | var dec_num = 0 5 | var lsb = 0 6 | var counter = 0 7 | var temp_bin = bin_num // for presentation purpose in print statement 8 | 9 | 10 | // working 11 | // the binary number is converted in a single single bit and is then worked upon (starting from lsb [Least significant bit (rightmost)]) 12 | // the bit is first isolated, converted into decimal by multiplying 2 ^ position of the bit and added to the decimal number 13 | // the binary number is then divided so that the lsb is shifted to right by one position 14 | 15 | while(bin_num > 0) { 16 | lsb = bin_num % 10 17 | dec_num = dec_num + lsb * 2 ^ counter 18 | bin_num = bin_num / 10 19 | counter = counter + 1 20 | } 21 | 22 | // working 23 | // this while loop works similar to the above one 24 | // only difference here is the base is changed from 10 to 8 [for octal format] 25 | // and the result is filled from right most position 26 | 27 | var result = 0 28 | counter = 0 29 | while(dec_num > 0) { 30 | result = result + dec_num % 8 * 10 ^ counter 31 | dec_num = dec_num / 8 32 | counter = counter + 1 33 | } 34 | 35 | print("{temp_bin} in Octal format is {result}") 36 | END_MAIN 37 | -------------------------------------------------------------------------------- /simc-codes/q7.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | //Lower left triangle pattern 3 | var rows = 5 4 | var i = 0 5 | var j = 0 6 | while(i<=rows) 7 | { 8 | j = 0 9 | //printing the pattern 10 | while(j number2) { 17 | print("{number1} is greater than {number2}") 18 | } 19 | //Checking that Number1 is less than Number2 20 | else{ 21 | print("{number1} is less than {number2}") 22 | } 23 | END_MAIN 24 | -------------------------------------------------------------------------------- /simc-codes/q71.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // User input taking a valid month input 3 | // uses switch case to check the input and ouputs the month 4 | 5 | var month = input("Enter a number to find the corresponding month: ", "i") 6 | 7 | switch (month) { 8 | case 1 : 9 | print("{month}st Month of the Year is January") 10 | break 11 | case 2 : 12 | print("{month}nd Month of the Year is February") 13 | break 14 | case 3: 15 | print("{month}rd Month of the Year is March") 16 | break 17 | case 4 : 18 | print("{month}th Month of the Year is April") 19 | break 20 | case 5 : 21 | print("{month}th Month of the Year is May") 22 | break 23 | case 6 : 24 | print("{month}th Month of the Year is June") 25 | break 26 | case 7 : 27 | print("{month}th Month of the Year is July") 28 | break 29 | case 8 : 30 | print("{month}th Month of the Year is August") 31 | break 32 | case 9 : 33 | print("{month}th Month of the Year is September") 34 | break 35 | case 10 : 36 | print("{month}th Month of the Year is October") 37 | break 38 | case 11 : 39 | print("{month}th Month of the Year is November") 40 | break 41 | case 12 : 42 | print("{month}th Month of the Year is December") 43 | break 44 | default : 45 | print("{month} is not a valid Month") 46 | break 47 | } 48 | END_MAIN 49 | -------------------------------------------------------------------------------- /simc-codes/q72.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var sides = input("Enter number of sides: ", "i") 3 | 4 | if (sides < 3) { 5 | print("Invalid number of sides.\n") 6 | } else { 7 | var temp = sides - 2.0 8 | var internal_angle = temp * 180 / sides 9 | print("Internal angle is {internal_angle} degrees.\n") 10 | } 11 | END_MAIN 12 | -------------------------------------------------------------------------------- /simc-codes/q73.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | 3 | // Ask for input for radius 4 | var radius = input("Enter the radius of the sphere: ", "f") 5 | 6 | // Using the formula (4/3)(PI)(r^3) compute the area 7 | var volume = 4.0/3 * PI * radius^3 8 | 9 | // Print Output and add units cubed to the end 10 | print("{volume} units cubed") 11 | END_MAIN 12 | -------------------------------------------------------------------------------- /simc-codes/q74.simc: -------------------------------------------------------------------------------- 1 | // Question : 2 | // Calculate and print the Volume of Cone given height and base radius 3 | // The area of the triangle with sides A = 4, B = 13, C = 15 is 24 4 | MAIN 5 | var pi = 3.1415 6 | var height = input("Enter the height of the cone ","i") 7 | var base_radius = input("Enter the radius of the base of the cone ","i") 8 | var volume = 1/3 * pi * base_radius * base_radius * height 9 | print("Volume of the cone is = {volume} units") 10 | END_MAIN 11 | -------------------------------------------------------------------------------- /simc-codes/q75.simc: -------------------------------------------------------------------------------- 1 | // * 2 | // sim-C 3 | // 4 | // Question: 5 | // 6 | // In a class there are 50% students study English, 7 | // 30% study Hindi, 8 | // 25% study foreign language, 9 | // 10% study english with foreign language, 10 | // find the percentage of students who study hindi with foreign language, 11 | // if no one studies all the three subjects at a time 12 | // 13 | // Resolution: 14 | // 15 | // en: only English 16 | // hi: only Hindi 17 | // fl: only foreign language 18 | // no: no language(disjoint from others) 19 | // 20 | // en_hi : English and Hindi 21 | // en_fl : English and foreign 22 | // hi_fl : Hindi and foreign 23 | // 24 | // en_hi_fl : en + hi + fl = 0% 25 | // en_fl : 10% 26 | // 27 | // From the statment: 28 | // 29 | // (1) 100% = en + hi + fl + en_hi + en_fl + hi_fl + no 30 | // (2) 40% = en_hi + en 31 | // (3) 30% = en_hi + hi + hi_fl + hi 32 | // (4) 15% = hi_fl + fl 33 | // 34 | // Put (2) and (4) into (1) 35 | // 100% = (en_hi + en) + (hi_fl + fl) + (en_fl) + hi + no = 40% + 15% + 10% + hi + no 36 | // 37 | // (5) 35% = hi + no 38 | // 39 | // Next follow a trick to discover which students is not studyng any langueges(no) 40 | // 41 | // Suppose n = 100 is an arbitary number of students. Then it is possible distribute the students such that 42 | // the restrictions are satified and conclude then the total students must be 85%. 43 | // 44 | // Note, it does not matter thaat the numbers is correct distributed yet. You can note that this arrange satifies 45 | // the initial restriction and with that we infer quantity of no. 46 | // 47 | // en: 30 48 | // hi: 15 49 | // fl: 20 50 | // no: no language(disjoint from others) 51 | // 52 | // en_hi : 10 53 | // en_fl : 10 54 | // hi_fl : 0 55 | // 56 | // en_hi_fl : 0 57 | // total : 85 58 | // 59 | // no = (n - all students of langues) / n 60 | // 61 | // This says that the total number of students who does not study language is 15%! 62 | // no = (100 - 85) / 100 = 15% 63 | // 64 | // From (5) => hi = 20% 65 | // 66 | // Now, the equations can solve all the unknow variables. 67 | // 68 | // From (3) with (no) => (6) en_hi + fl_hi = 10% 69 | // 70 | // The sum of en + en_fl + en_hi + en_fl + hi + fl + fl_hi= 85 71 | // 72 | // We add en_hi in both sides: 73 | // 74 | // en + en_fl + (2*en_hi + en_fl + hi) + fl + fl_hi = 85 + en_hi 75 | // 76 | // As (6) and (3) fl + 2*en_hi + fl_hi = 25% 77 | // 78 | // So en + en_fl + hi - en_hi = 60 79 | // 80 | // hi and en_fl are know as 20% and 10% 81 | // 82 | // Finally, en - en_hi = 30% 83 | // 84 | // With that, we conclude that 85 | // en + en_hi = 40% 86 | // + 87 | // en - en_hi = 30% 88 | // ----------------- 89 | // en = 35% => en_hi = 5% 90 | // 91 | // en_hi + fl_hi = 10% => fl_hi = 5% 92 | // 93 | // Answer: fl_hi = 5% 94 | // 95 | 96 | MAIN 97 | var n_students = input("Enter number of students : ","i") 98 | var fl_hi = 0.05*n_students 99 | print("The number of students learning Foreign Language and Hindi is {fl_hi}\n") 100 | END_MAIN 101 | 102 | 103 | -------------------------------------------------------------------------------- /simc-codes/q76.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | /* 3 | Given a user input positive integer n between 0 and 9, 4 | print n + nn + nnn 5 | Example: 6 | n = 5 7 | n + nn + nnn = 5 + 55 + 555 = 615 8 | */ 9 | var n1 = input("Enter a positive integer between 0 and 9: ", "i") 10 | var n2 = n1*11 11 | var n3 = n1*111 12 | var ans = n1 + n2 + n3 13 | print("{n1} + {n2} + {n3} = {ans}") 14 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q77.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | 3 | var min = 1 4 | var max = 99 5 | 6 | print("Odd numbers from {min} to {max}:\n") 7 | 8 | var num = min 9 | do { 10 | if (num % 2 != 0) { 11 | print("{num} ") 12 | } 13 | 14 | num += 1 15 | 16 | // Optional: break line every 5 numbers for nicer formatting 17 | if (num % 10 == 0) { 18 | print("\n") 19 | } 20 | 21 | } while(num <= max) 22 | 23 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q78.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | /* 3 | Print numbers in a user provide range that are divisible 4 | by either 3 or 7 but not by both 5 | */ 6 | var left = input("Enter an integer to represent start of range: ", "i") 7 | var right = input("Enter an integer to represent end of range: ", "i") 8 | 9 | for i in left to right by +1 { 10 | if(i%3==0 || i%7==0) { 11 | if(i%21!=0){ 12 | print("{i}\n") 13 | } 14 | } 15 | } 16 | END_MAIN 17 | -------------------------------------------------------------------------------- /simc-codes/q79.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n = 100 3 | n++; 4 | for i in 1 to n by +1{ 5 | if(i%3==0 || i%5==0){ 6 | print("{i}\n") 7 | } 8 | } 9 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q80.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var x = input("Enter first number: ","i") 3 | var y = input("Enter second number: ","i") 4 | var z = input("Enter third number: ","i") 5 | 6 | 7 | if(x+y==z){ 8 | print("{z} is equal to {x} + {y}") 9 | } 10 | else{ 11 | print("{z} is not equal to {x} + {y}") 12 | } 13 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q81.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Initialize our variables 3 | var first_variable = 10 4 | var second_variable = 15 5 | 6 | // Make the first variable equal the sum of the two 7 | first_variable += second_variable 8 | 9 | // Make the second variable equal the first, by subtracting it from the sum 10 | second_variable = first_variable - second_variable 11 | 12 | // Make the first variable be the second, by subtracting the original first which is now second_variable, from itself, the sum 13 | first_variable -= second_variable 14 | 15 | // Print output 16 | print("After the switch the first variable is {first_variable} and the second is {second_variable}") 17 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q82.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var x = input("Enter the number: ","i") 3 | var cnt=0 4 | var i=1 5 | var sqN=(x^0.5) 6 | sqN=sqN+1 7 | for i in 1 to sqN by +1{ 8 | if(x % i == 0){ 9 | if(x / i == i){ 10 | cnt=cnt+1 11 | } 12 | else{ 13 | cnt=cnt+2 14 | } 15 | } 16 | } 17 | print("The total factors of {x} is/ are {cnt}") 18 | END_MAIN 19 | 20 | -------------------------------------------------------------------------------- /simc-codes/q83.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | // Declare and initialize the dividend and divisor, note here I use floats to show that it works with them, but it will work with integers aswell 3 | var dividend = 15.3 4 | var divisor = 3.2 5 | 6 | // Declare and initialize what will be the whole part of the division, in other words the integer quotient 7 | var integer_quotient = 1 8 | 9 | // Since sim-c is dynamically typed, adding the following line would convert integer_quotient to a float, and since sim-c does not have any type casting we must use the built in c type casting. 10 | BEGIN_C 11 | integer_quotient = dividend / divisor; 12 | END_C 13 | 14 | // Now since we have the truncated answer, we simply multiply that by the divisor, and subtract from the dividend 15 | var remainder = dividend - divisor*integer_quotient 16 | 17 | // Print the remainder out 18 | print("{dividend} modulo {divisor} is {remainder}") 19 | END_MAIN 20 | -------------------------------------------------------------------------------- /simc-codes/q84.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var num1 = input("Enter value of first number : ", "i" ) 3 | var num2 = input("Enter value of second number : ", "i" ) 4 | var temp 5 | 6 | //swapping the numbers using a temp varianble 7 | temp = num1 8 | num1 = num2 9 | num2 = temp 10 | 11 | print("After swapping first number is = {num1}") 12 | 13 | print("\nAfter swapping second number is = {num2}") 14 | 15 | END_MAIN 16 | -------------------------------------------------------------------------------- /simc-codes/q85.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n = input("Enter the number : ", "i" ) 3 | var i=1 4 | var j=1 5 | var check=0 6 | for i in 1 to n by +1 { 7 | for j in 1 to n by +1 { 8 | if(i * i + j * j == n){ 9 | check=check+1 10 | } 11 | } 12 | } 13 | 14 | if(check==0){ 15 | print("{n} is scarcely a sum of two whole squares") 16 | } 17 | else{ 18 | print("{n} is a sum of two whole squares") 19 | } 20 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q86.simc: -------------------------------------------------------------------------------- 1 | //to print Fibonacci Series numbers at even places 2 | MAIN 3 | var term1 = 0 4 | var term2 = 1 5 | var nextTerm = 0 6 | var max_term = input("Enter number of terms : ","i") //number of terms to be calculated 7 | print("Fibonacci series :{term2}") 8 | nextTerm = term1+term2 9 | var term_position = 3 10 | while(term_position <= max_term){ 11 | if(term_position % 2 == 0){ 12 | print(", {nextTerm}") 13 | } 14 | term1 = term2 15 | term2 = nextTerm 16 | nextTerm = term1 + term2 17 | term_position += 1 18 | } 19 | print("\n"); 20 | END_MAIN 21 | -------------------------------------------------------------------------------- /simc-codes/q87.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var N = input("Enter the number: ","i") 3 | var i=0 4 | var count=0 5 | while(count 18 && age < 65) { 12 | result = "Yes" 13 | } 14 | print("Age: {age}, Eligible to vote: {result}") 15 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q9.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | var n = 3 3 | var i = 0 4 | var j = 0 5 | while(i,<) and logical(&&) operator to judge the value */ 13 | /* and printing the strings */ 14 | if (n>0 && n<1){ 15 | print("Lies in between 0 and 1") 16 | }else{ 17 | print("Does not lies in between 0 and 1") 18 | } 19 | END_MAIN 20 | -------------------------------------------------------------------------------- /simc-codes/q96.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | /* 3 | Convert given weight in KGs to pounds. 4 | The conversion factor is 2.2046. 5 | Ex. 6 | 1 Kg = 2.2046 pounds 7 | */ 8 | 9 | var value = 2.2046; 10 | var n = input("Enter the weight in Kg:","f"); 11 | 12 | var ans = n * value; 13 | 14 | print("The weight in pounds is {ans} pounds") 15 | 16 | END_MAIN 17 | -------------------------------------------------------------------------------- /simc-codes/q97.simc: -------------------------------------------------------------------------------- 1 | /* 2 | sim-c 3 | 4 | The Aritmetic Progressing is a sequence that start at a1( and each following term is increase by d 5 | 6 | the Sum of an Aritmetic Progressing is given by: 7 | 8 | Sn = n/2(2*a1 + (n-1)*d) 9 | */ 10 | MAIN 11 | 12 | print("Welcome to sim-C, give a range to sum up!\n") 13 | 14 | var init = input("Enter first term of the progression : ","i") // a1 15 | var step = input("Enter step of the progression : ", "i") // d 16 | var n = input("Enter the number of the term: ", "i") // n 17 | var result = 0; 18 | 19 | var prog = step*(n-1) 20 | var range = 0.0 21 | 22 | // the division made in C to cast to double 23 | BEGIN_C 24 | range = n / (double)2; 25 | END_C 26 | 27 | var first = 2*init 28 | 29 | // AP (Aritmetic Progressing) 30 | result = range*(first + prog) 31 | print("The sum of all terms until n = {result}\n") 32 | 33 | END_MAIN -------------------------------------------------------------------------------- /simc-codes/q98.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | 3 | var a = input("Enter value of the first term : ", "f" ) 4 | var r = input("Enter value of the common ratio : ", "f" ) 5 | var n = input("Enter value of total number of terms : ", "f" ) 6 | 7 | var sum=0.0 8 | var power = r^n 9 | r=r-1 10 | sum= power -1 11 | sum = sum* a 12 | sum= sum/r 13 | 14 | print("The final value is {sum}") 15 | 16 | END_MAIN 17 | 18 | -------------------------------------------------------------------------------- /simc-codes/q99.simc: -------------------------------------------------------------------------------- 1 | MAIN 2 | //harmonic mean of two numbers num1 and num2 3 | var num1 = input("Enter the first value: ", "f") 4 | var num2 = input("Enter the second value: ", "f") 5 | 6 | var product = num1*num2 7 | var sum = num1 + num2 8 | 9 | /* 10 | harmonic mean is 2*num1*num2/(num1+num2) 11 | */ 12 | product = 2*product 13 | var ans = product/sum 14 | 15 | print("Harmonic mean of {num1} and {num2} is {ans}") 16 | END_MAIN 17 | -------------------------------------------------------------------------------- /simc/__init__.py: -------------------------------------------------------------------------------- 1 | import simc 2 | 3 | __version__ = "0.1-alpha-4" 4 | -------------------------------------------------------------------------------- /simc/compiler.py: -------------------------------------------------------------------------------- 1 | # Module to import OpCode class 2 | from .op_code import OpCode 3 | 4 | 5 | def check_include(opcodes): 6 | """ 7 | Checks if any opcode requires standard libraries to be included 8 | 9 | Params 10 | ====== 11 | opcodes (list) = List of opcodes 12 | 13 | Returns 14 | ======= 15 | string: The string representation of unique include files 16 | """ 17 | 18 | # List of includes 19 | includes = [] 20 | 21 | # List of math constants 22 | math_func_const = ["M_PI", "M_E", "pow(", "INFINITY", "NAN"] 23 | 24 | # Loop through all opcodes 25 | for opcode in opcodes: 26 | # If opcode is of type print, then it requires stdio.h to be included 27 | if opcode.type == "print": 28 | includes.append("#include ") 29 | 30 | # If there is any boolean assignment opcode then include stdbool.h 31 | if opcode.dtype == "bool": 32 | includes.append("#include ") 33 | 34 | # If the opcode is a statement of type input, then it requires stdio.h to be included 35 | if len(opcode.val.split("---")) >= 3 and len(opcode.val.split('---')[-1]) == 1: 36 | includes.append("#include ") 37 | 38 | if any(math in opcode.val for math in math_func_const): 39 | includes.append("#include ") 40 | 41 | # Return string representation of unique elements of includes list separated by newline characters 42 | return "\n".join(list(set(includes))) 43 | 44 | 45 | def compile_func_main_code(outside_code, ccode, outside_main, code): 46 | """ 47 | Check which code should go in main and which outside of main 48 | 49 | Params 50 | ====== 51 | outside_code (string) = Code to be put outside main function 52 | ccode (string) = Code to be put inside main function 53 | outside_main (bool) = Decides where the code should go (true - outside, false - inside) 54 | code (string) = Compiled code 55 | 56 | Returns 57 | ======= 58 | string, string: The outside and main C code strings 59 | """ 60 | 61 | # If outside_main is true then code goes outside main 62 | if outside_main: 63 | outside_code += code 64 | else: 65 | if code == "}\n": 66 | code = "\t" + code 67 | ccode += code 68 | 69 | # Return code strings 70 | return outside_code, ccode 71 | 72 | 73 | def compile(opcodes, c_filename, table): 74 | """ 75 | Compiles opcodes produced by parser into C code 76 | 77 | Params 78 | ====== 79 | opcodes (list) = List of opcodes 80 | c_filename (string) = Name of C file to write C code into 81 | table (SymbolTable) = Symbol table constructed during lexical analysis and parsing 82 | """ 83 | 84 | # Check for includes 85 | compiled_code = check_include(opcodes) + "\n" 86 | 87 | # Put the code in main function 88 | ccode = "" 89 | 90 | # Function code is compiled into separate list 91 | outside_code = "" 92 | 93 | # Check if function body has started or not 94 | outside_main = True 95 | 96 | # Check if the function has returned or not 97 | has_returned = False 98 | 99 | # Loop through all opcodes 100 | for opcode in opcodes: 101 | code = "" 102 | # If opcode is of type print then generate a printf statement 103 | if opcode.type == "print": 104 | 105 | if ( 106 | opcode.val == '"%s", i' 107 | ): # Temporary solution to the printf( ) statement being used on strings 108 | opcode.val = '"%s", &i' 109 | # Generation of opcode is flawed as it fails to add the reference addess of the string being printed 110 | 111 | code = "\tprintf(%s);\n" % opcode.val 112 | 113 | # If opcode is of type import then generate include statement 114 | if opcode.type == "import": 115 | code = '#include "' + opcode.val + '.h"\n' 116 | 117 | # If opcode is of type var_assign then generate a declaration [/initialization] statement 118 | elif opcode.type == "var_assign": 119 | code = "" 120 | 121 | # val contains - ---, split that into a list 122 | val = opcode.val.split("---") 123 | 124 | # Get the datatye of the variable 125 | dtype = opcode.dtype 126 | if dtype == "declared": 127 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 128 | 129 | # Helper Dictionaries 130 | get_data_type = { 131 | "i": "int", 132 | "s": "char*", 133 | "f": "float", 134 | "d": "double", 135 | "c": "char", 136 | } 137 | get_placeholder = {"i": "d", "s": "s", "f": "f", "d": "lf", "c": "c"} 138 | 139 | # If it is of string type then change it to char [] 140 | if dtype == "string": 141 | dtype = "char*" 142 | # Check if the statement is of type input or not 143 | if len(val) < 3: 144 | code += "\t" + dtype + " " + str(val[0]) + " = " + str(val[1]) + ";\n" 145 | else: 146 | # If the statement is of type input - 147 | dtype = get_data_type[val[2]] 148 | placeholder = get_placeholder[val[2]] 149 | code += "\t" + dtype + " " + str(val[0]) + ";\n" 150 | if val[1] != "": 151 | code += "\t" + 'printf("' + str(val[1]) + '");\n' 152 | code += "\t" + 'scanf("%' + placeholder 153 | 154 | if dtype == "char*": 155 | # If the datatype is character array, we need to pass in the reference address into scanf( ) 156 | code += '", &' + str(val[0]) + ");\n" 157 | elif "*" in dtype: 158 | code += '", ' + str(val[0]) + ");\n" 159 | else: 160 | code += '", &' + str(val[0]) + ");\n" 161 | # If opcode is of type ptr_assign then generate a declarative statement 162 | elif opcode.type == "ptr_assign": 163 | code = "" 164 | 165 | # val contains - ------, split that into a list 166 | val = opcode.val.split("---") 167 | 168 | # Get the datatye of the variable 169 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 170 | 171 | # Helper Dictionaries 172 | get_data_type = { 173 | "i": "int", 174 | "s": "char*", 175 | "f": "float", 176 | "d": "double", 177 | "c": "char", 178 | } 179 | get_placeholder = {"i": "d", "s": "s", "f": "f", "d": "lf", "c": "c"} 180 | 181 | # If it is of string type then change it to char [] 182 | if dtype == "string": 183 | dtype = "char*" 184 | code += ( 185 | "\t" 186 | + dtype 187 | + " " 188 | + "*" * int(val[2]) 189 | + str(val[0]) 190 | + " = " 191 | + str(val[1]) 192 | + ";\n" 193 | ) 194 | 195 | # If opcode is of type var_no_assign then generate a declaration statement 196 | elif opcode.type == "var_no_assign": 197 | # val contains - ---, split that into a list 198 | val = opcode.val.split("---") 199 | 200 | # Get the datatye of the variable 201 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 202 | # Check if dtype could be inferred or not 203 | opcode.dtype = str(dtype) if dtype is not None else "not_known" 204 | code += "\t" + opcode.dtype + " " + str(opcode.val) + ";\n" 205 | elif opcode.type == "array_no_assign": 206 | # val contains - ---, split that into a list 207 | val = opcode.val.split("---") 208 | # Get the datatye of the variable 209 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 210 | # Check if dtype could be inferred or not 211 | opcode.dtype = str(dtype) if dtype is not None else "not_known" 212 | code += "\t" + opcode.dtype + " *" + str(val[0]) + ";\n" 213 | elif opcode.type == "array_assign": 214 | # val contains - ---, split that into a list 215 | val = opcode.val.split("---") 216 | # Get the datatye of the variable 217 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 218 | # Check if dtype could be inferred or not 219 | opcode.dtype = str(dtype) if dtype is not None else "not_known" 220 | code += ( 221 | "\t" 222 | + opcode.dtype 223 | + " " 224 | + str(val[0]) 225 | + "[" 226 | + (val[1]) 227 | + "]" 228 | + " = " 229 | + val[2] 230 | + ";\n" 231 | ) 232 | elif opcode.type == "array_only_assign": 233 | # val contains - ---=( []), split that into a list 234 | val = opcode.val.split("---") 235 | 236 | # val[0] contains identifier and val[1] contains =( []) 237 | code += "\t" + val[0] + val[1] + ";\n" 238 | # If opcode is of type ptr_no_assign then generate declaration statement 239 | elif opcode.type == "ptr_no_assign": 240 | val = opcode.val.split("---") 241 | # Get the datatye of the variable 242 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 243 | # Check if dtype could be inferred or not 244 | opcode.dtype = str(dtype) if dtype is not None else "not_known" 245 | if opcode.dtype == "string": 246 | opcode.dtype = "char" 247 | code += "\t" + opcode.dtype + " *" + str(opcode.val) + ";\n" 248 | 249 | # If opcode is of type assign then generate an assignment statement 250 | elif opcode.type == "assign": 251 | # val contains - ---, split that into a list 252 | val = opcode.val.split("---") 253 | # Helper Dictionaries 254 | get_data_type = { 255 | "i": "int", 256 | "s": "char *", 257 | "f": "float", 258 | "d": "double", 259 | "c": "char", 260 | } 261 | get_placeholder = {"i": "d", "s": "s", "f": "f", "d": "lf", "c": "c"} 262 | # Check if the statement is of type input or not 263 | if len(val) == 3: 264 | code += "\t" + val[0] + " " + val[1] + " " + val[2] + ";\n" 265 | else: 266 | # If the statement is of type input 267 | dtype = get_data_type[val[3]] 268 | placeholder = get_placeholder[val[3]] 269 | if val[2] != "": 270 | code += "\t" + 'printf("' + str(val[2]) + '");\n' 271 | code += "\t" + 'scanf("%' + placeholder + '", &' + str(val[0]) + ");\n" 272 | 273 | # If opcode is of type ptr_only_assign then generate an assignment statement 274 | elif opcode.type == "ptr_only_assign": 275 | # val contains - ------, split that into a list 276 | val = opcode.val.split("---") 277 | code += "\t" + int(val[3]) * "*" + val[0] + " = " + val[2] + ";\n" 278 | 279 | # If opcode is of type unary then generate an uanry statement 280 | elif opcode.type == "unary": 281 | # val contains - ---, split that into a list 282 | val = opcode.val.split("---") 283 | print_val = "" 284 | for i in val: 285 | i = i.replace(" ", "") 286 | print_val += str(i) 287 | code += "\t" + print_val + ";\n" 288 | # If opcode is of type func_decl then generate function declaration statement 289 | elif opcode.type == "func_decl": 290 | # val contains - ---, split that into list 291 | val = opcode.val.split("---") 292 | 293 | # Check if function has params 294 | params = val[1].split("&&&") if len(val[1]) > 0 else [] 295 | 296 | # Get the return type of the function 297 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(val[0])) 298 | dtype = dtype if dtype != "var" else "void" 299 | 300 | # Append the function return type and name to code 301 | code += "\n" + dtype + " " + val[0] + "(" 302 | 303 | # Compile the formal params 304 | has_param = False 305 | for i in range(len(params)): 306 | if len(params[i]) > 0: 307 | has_param = True 308 | _, dtype, _, _, _ = table.get_by_id(table.get_by_symbol(params[i])) 309 | dtype = dtype if dtype != "var" else "not_known" 310 | dtype = "char*" if dtype == "string" else dtype 311 | code += dtype + " " + params[i] + ", " 312 | if has_param: 313 | code = code[:-2] 314 | else: 315 | code += "void" 316 | 317 | # Finally add opening brace to start the function body 318 | code += ") " 319 | # If the opcode is of type func_call then generate function calling statement 320 | elif opcode.type == "func_call": 321 | # val contains - ---, split that into list 322 | val = opcode.val.split("---") 323 | 324 | # Check if function has params 325 | params = val[1].split("&&&") if len(val[1]) > 0 else [] 326 | 327 | # Compile function name 328 | code = "\t" + val[0] + "(" 329 | 330 | # Compile the actual params 331 | has_param = False 332 | for param in params: 333 | if len(params) > 0: 334 | has_param = True 335 | code += param + ", " 336 | if has_param: 337 | code = code[:-2] 338 | 339 | # Finally add opening brace to start the function body 340 | code += ");\n" 341 | # If opcode is of type struct_decl then generate structure declaration statement 342 | elif opcode.type == "struct_decl": 343 | # extracting struct name from val 344 | struct_name = opcode.val 345 | 346 | # append the struct keyword and structure nameto the code 347 | code += "\n" + "struct" + " " + struct_name + " " 348 | # If opcode is of type struct_instantiate then generate structure instantiation statement 349 | elif opcode.type == "struct_instantiate": 350 | # Extract the identifier name of instance variable 351 | struct_name, instance_var_name = opcode.val.split("---") 352 | 353 | code += ( 354 | "\t" 355 | + "struct " 356 | + struct_name.strip() 357 | + " " 358 | + instance_var_name.strip() 359 | + ";\n" 360 | ) 361 | # If opcode is of type scope_begin then generate open brace statement 362 | elif opcode.type == "scope_begin": 363 | code += "\t{\n" 364 | # If opcode is of type scope_over then generate closing brace statement 365 | elif opcode.type == "scope_over": 366 | code += "}\n" 367 | # If opcode is of type struct_scope_over then generate closing brace, name of struct instance (if any) and add a semi-colon 368 | elif opcode.type == "struct_scope_over": 369 | code += "} " + opcode.val + ";\n" 370 | # If opcode is of type scope_over then generate closing brace statement 371 | elif opcode.type == "MAIN": 372 | code += "\nint main() {\n" 373 | outside_main = False 374 | has_returned = False 375 | # If opcode is of type scope_over then generate closing brace statement 376 | elif opcode.type == "END_MAIN": 377 | if not has_returned: 378 | code += "\n\treturn 0;" 379 | code += "\n}\n" 380 | outside_code, ccode = compile_func_main_code( 381 | outside_code, ccode, outside_main, code 382 | ) 383 | outside_main = True 384 | continue 385 | # If opcode is of type for 386 | elif opcode.type == "for": 387 | val = opcode.val.split("&&&") 388 | code += ( 389 | "\tfor(int " 390 | + val[0] 391 | + " = " 392 | + val[1] 393 | + "; " 394 | + val[0] 395 | + " " 396 | + val[4] 397 | + " " 398 | + val[2] 399 | + "; " 400 | + val[0] 401 | + val[3] 402 | + "=" 403 | + val[5] 404 | + ") " 405 | ) 406 | # If opcode is of type while then generate while loop statement 407 | elif opcode.type == "while": 408 | code = "\twhile(%s) " % opcode.val 409 | # If opcode is of type do then generate do statement 410 | elif opcode.type == "do": 411 | code = "\tdo " 412 | # If opcode is of type while_do then generate while for do-while statement 413 | elif opcode.type == "while_do": 414 | code = "\twhile(%s);" % opcode.val 415 | # If opcode is of type if then generate if statement 416 | elif opcode.type == "if": 417 | code = "\tif(%s) " % opcode.val 418 | # If opcode is of type exit then generate exit statement 419 | elif opcode.type == "exit": 420 | code = "\texit(%s);\n" % opcode.val 421 | # If opcode is of type else_if then generate else if statement 422 | elif opcode.type == "else_if": 423 | code = "\telse if(%s) " % opcode.val 424 | # If opcode is of type else then generate else statement 425 | elif opcode.type == "else": 426 | code = "\telse " 427 | # If opcode is of type return then generate return statement 428 | elif opcode.type == "return": 429 | code += "\n\treturn " + opcode.val + ";\n" 430 | has_returned = True 431 | # If opcode is of type break then generate break statement 432 | elif opcode.type == "break": 433 | code += "\tbreak;\n" 434 | # If opcode is of type continue then generate continue statement 435 | elif opcode.type == "continue": 436 | code += "\tcontinue;\n" 437 | # If opcode is of type single_line_comment the generate single comment line 438 | elif opcode.type == "single_line_comment": 439 | code += "\t// %s \n" % opcode.val 440 | # If opcode is of type multi_line_comment the generate single comment line 441 | elif opcode.type == "multi_line_comment": 442 | code += "/* %s*/\n" % opcode.val 443 | # If opcode is of type switch then generate switch statement 444 | elif opcode.type == "switch": 445 | code += "\tswitch(" + opcode.val + ") " 446 | # If opcode is of type case then generate case statement 447 | elif opcode.type == "case": 448 | code += "\tcase " + opcode.val + ":\n" 449 | # If opcode is of type default then generate default statement 450 | elif opcode.type == "default": 451 | code += "\tdefault:\n" 452 | # If opcode is of type RAW_c, simpaly copy the value 453 | elif opcode.type == "raw": 454 | code += opcode.val + "\n" 455 | 456 | outside_code, ccode = compile_func_main_code( 457 | outside_code, ccode, outside_main, code 458 | ) 459 | 460 | # Add return 0 to the end of code 461 | compiled_code += outside_code + ccode 462 | 463 | # Write generated code into C file 464 | with open(c_filename, "w") as file: 465 | file.write(compiled_code) 466 | -------------------------------------------------------------------------------- /simc/global_helpers.py: -------------------------------------------------------------------------------- 1 | # Library to exit code when error occurs 2 | import sys 3 | 4 | 5 | def check_if(got_type, should_be_types, error_msg, line_num): 6 | """ 7 | Check if type matches what it should be otherwise throw an error and exit 8 | 9 | Params 10 | ====== 11 | given_type (string) = Type of token to be checked 12 | should_be_types (string/list) = Type(s) to be compared with 13 | msg (string) = Error message to print in case some case fails 14 | line_num (int) = Line number 15 | """ 16 | 17 | # Convert to list if type is string 18 | if type(should_be_types) == str: 19 | should_be_types = [should_be_types] 20 | 21 | # If the given_type is not part of should_be_types then throw error and exit 22 | if got_type not in should_be_types: 23 | error(error_msg, line_num) 24 | 25 | 26 | def error(msg, line_num): 27 | """ 28 | Shows error message in red color and exits the current process 29 | 30 | Params 31 | ====== 32 | msg (string) = The message to be shown as error message 33 | line_num (int) = Line number 34 | """ 35 | 36 | # Prints the error to screen in red color and then exits tokenizer 37 | print("\033[91m[Line %d] Error: %s" % (line_num, msg), end=" ") 38 | print(" \033[m") 39 | sys.exit() 40 | 41 | 42 | def is_digit(char): 43 | """ 44 | Checks if character is digit or not, includes 0-9 and . 45 | 46 | Params 47 | ====== 48 | char (string) = Single character mostly part of a longer string 49 | 50 | Returns 51 | ======= 52 | bool: Checks whether the character is number or not 53 | """ 54 | 55 | return char in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] 56 | 57 | 58 | def is_alpha(char): 59 | """ 60 | Checks if character is alphabet or not, includes a-z and _ 61 | 62 | Params 63 | ====== 64 | char (string) = Single character mostly part of a longer string 65 | 66 | Returns 67 | ======= 68 | bool: Checks whether the character is alphabet or not 69 | """ 70 | 71 | return char.isalpha() or char == "_" 72 | 73 | 74 | def is_alnum(char): 75 | """ 76 | Checks if character is alphabet or digit or none, checks if character is in a-z, 0-9, _, and . for alphanumeric character 77 | 78 | Params 79 | ====== 80 | char (string) = Single character mostly part of a longer string 81 | 82 | Returns 83 | ======= 84 | bool: Checks whether the character is alphabet/digit not 85 | """ 86 | 87 | return ( 88 | char.isalpha() 89 | or char == "_" 90 | or char in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] 91 | ) 92 | -------------------------------------------------------------------------------- /simc/op_code.py: -------------------------------------------------------------------------------- 1 | class OpCode: 2 | """ 3 | OpCode class is responsible for creating opcodes 4 | """ 5 | 6 | def __init__(self, opcode, val, dtype=None): 7 | """ 8 | Initializer of OpCode class 9 | 10 | Params 11 | ====== 12 | opcode (string) = Type of opcode as string 13 | val (string) = Value stored at opcode 14 | dtype (string) = Datatype of opcode 15 | """ 16 | 17 | self.type = opcode 18 | self.val = val 19 | self.dtype = dtype 20 | 21 | def __str__(self): 22 | """ 23 | Returns string representation of OpCode 24 | 25 | Returns 26 | ======= 27 | string: The string representation of OpCode object, which can be used to print the opcodes 28 | """ 29 | 30 | return "OpCode('%s', '%s', '%s')" % (self.type, self.val, self.dtype) 31 | 32 | def __eq__(self, other): 33 | """ 34 | Check for equality of opcodes 35 | 36 | Returns 37 | ======= 38 | bool: Whether a token object is equal to another or not 39 | """ 40 | 41 | if ( 42 | self.type == other.type 43 | and self.val == other.val 44 | and self.dtype == other.dtype 45 | ): 46 | return True 47 | 48 | return False 49 | -------------------------------------------------------------------------------- /simc/package-index: -------------------------------------------------------------------------------- 1 | geometry - https://raw.githubusercontent.com/frankhart2018/geometry/master/geometry.simc -------------------------------------------------------------------------------- /simc/parser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cimplec/sim-c/64f96d92c5a58abeb7656160ab38c8386c0d3bc9/simc/parser/__init__.py -------------------------------------------------------------------------------- /simc/parser/array_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def array_initializer(tokens, i, table, size_of_array, msg, func_ret_type): 7 | """ 8 | Parse array initializer list 9 | 10 | Params 11 | ====== 12 | tokens (list) = List of tokens 13 | i (string/list) = Current index in list of tokens 14 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 15 | size_of_array (number) = Number of fileds expected to fill 16 | msg (string) = Error message to print in case some case fails 17 | 18 | Returns 19 | ======= 20 | string, string, int: The expression, datatype of the expression and the current index in source 21 | code after parsing 22 | """ 23 | from .simc_parser import expression 24 | from .function_parser import function_call_statement 25 | 26 | # Initial values 27 | op_value = "" 28 | op_type = -1 29 | 30 | # Mapping for precedence checking (double > float > int) 31 | type_to_prec = {"int": 3, "float": 4, "double": 5} 32 | 33 | # Mapping simc constant name to c constant name 34 | math_constants = {"PI": "M_PI", "E": "M_E", "inf": "INFINITY", "NaN": "NAN"} 35 | 36 | # Number of values initialized 37 | initialized_value_counts = 0 38 | 39 | # Predicted type of variable 40 | type_of_id = "" 41 | 42 | # Mark if comma if need 43 | expected_comma = False 44 | 45 | # Check if left brace follows assignment operator 46 | check_if( 47 | got_type=tokens[i].type, 48 | should_be_types="left_brace", 49 | error_msg="Expected {", 50 | line_num=tokens[i].line_num, 51 | ) 52 | 53 | # Begin array initializer 54 | op_value += "{" 55 | 56 | # Maximum possible length of array 57 | max_length_array = 2 ** 32 58 | 59 | # If size is not empty then update max_length_array to that size 60 | if size_of_array != "": 61 | max_length_array = int(size_of_array) 62 | 63 | # Loop until right brace 64 | while i < len(tokens) - 1: 65 | 66 | # Check end of expression, stop loop 67 | if tokens[i].type == "right_brace": 68 | op_value += "}" 69 | break 70 | 71 | # The values overflow size of declared array 72 | if initialized_value_counts > max_length_array: 73 | error("Too many initializers ", tokens[i].line_num) 74 | 75 | # If is a new line, go to next 76 | if tokens[i].type == "newline": 77 | op_value += "\n" 78 | i += 1 79 | continue 80 | 81 | # Check for comma before next element 82 | if expected_comma and tokens[i].type == "comma": 83 | expected_comma = False 84 | op_value += "," 85 | i += 1 86 | continue 87 | elif expected_comma or (expected_comma is False and tokens[i].type == "comma"): 88 | error( 89 | "Expected values to be separated by comma in initializer list", 90 | tokens[i].line_num, 91 | ) 92 | 93 | # If token is identifier or constant 94 | if tokens[i].type in ["number", "string", "id"]: 95 | # Fetch information from symbol table 96 | value, type_, typedata, _, _ = table.get_by_id(tokens[i].val) 97 | 98 | if type_ == "var": 99 | error("Variable %s used before declaration" % value, tokens[i].line_num) 100 | 101 | # Check if there is more than one type in initializers 102 | if initialized_value_counts > 1 and type_ != type_of_id: 103 | error("Too many unique types in initializers", tokens[i].line_num) 104 | else: 105 | type_of_id = type_ 106 | 107 | error_message = "Array Initializer parsed incorrectly" 108 | op_value_temp, op_type, i_temp, func_ret_type = expression( 109 | tokens, 110 | i, 111 | table, 112 | error_message, 113 | block_type_promotion=True, 114 | func_ret_type=func_ret_type, 115 | ) 116 | op_value += op_value_temp 117 | 118 | # If after splitting by comma there are more than one empty field then throw error 119 | # One is allowed since there can be one comma at the end like - {1, 2, } 120 | split_by_comma = op_value_temp.split(",") 121 | if split_by_comma.count('') > 1: 122 | error("Too many commas at the end of initializer list", line_num=tokens[i].line_num) 123 | 124 | # If the size of the array is defined, and if the number of tokens parsed is not equal to 125 | # what it should be, then display error 126 | if ( 127 | size_of_array != "" 128 | and (i_temp - i != int(size_of_array) * 2 - 1) 129 | and tokens[i_temp - 1].type != "comma" 130 | ): 131 | 132 | # Number of elements in parsed array is equal to the 133 | # number of tokens parsed in expression minus the number of commas 134 | number_of_elements = (i_temp - i) - int((i_temp - i - 1) / 2) 135 | error_message = ( 136 | f"Expected {size_of_array} entries, got {number_of_elements}" 137 | " entries instead." 138 | ) 139 | 140 | error(error_message, tokens[i].line_num) 141 | 142 | # We need to update the total number of tokens parsed (i) according to the number of tokens 143 | # parsed in expression( ), which depends on if the second last token is a comma or not. 144 | if size_of_array == "": 145 | # If the size of the array is not mentioned, number of tokens parsed = i_temp - 1 146 | i = i_temp - 1 147 | 148 | elif tokens[i_temp - 1].type == "comma": 149 | # If the token following the last element inserted is a comma, then we will skip the following tokens. 150 | # For example, int arr[2] = { 1,2, } 151 | # 3 Skipped Tokens after the first element (We need to account for 2 commas and 1 element) 152 | i += int(size_of_array) * 2 - 1 153 | else: 154 | # Same logic as before, but in this case, the last element inserted has no 155 | # comma at the end, which means that we will have to skip 1 less token from before. For example, 156 | # int arr[2] = { 1,2 } 157 | # 2 Skipped Tokens after the first element (We need to account for 1 comma and 1 element) 158 | i += int(size_of_array) * 2 - 2 159 | 160 | # Expected comma 161 | expected_comma = True 162 | 163 | initialized_value_counts += 1 164 | i += 1 165 | 166 | # one comma after expression is allowed 167 | if tokens[i].type == "comma": 168 | i += 1 169 | 170 | # Check if ending right brace is present or not 171 | check_if( 172 | got_type=tokens[i].type, 173 | should_be_types="right_brace", 174 | error_msg="Expected }", 175 | line_num=tokens[i].line_num, 176 | ) 177 | 178 | return op_value, op_type, i + 1 179 | -------------------------------------------------------------------------------- /simc/parser/conditional_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def if_statement(tokens, i, table, func_ret_type): 7 | """ 8 | Parse if statement 9 | 10 | Params 11 | ====== 12 | tokens (list) = List of tokens 13 | i (int) = Current index in token 14 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 15 | func_ret_type (dict) = Dict of functions whose return type could not be resolved immediately 16 | 17 | Returns 18 | ======= 19 | OpCode, int: The opcode for the assign code and the index after parsing if statement 20 | """ 21 | 22 | from .simc_parser import expression, skip_all_nextlines 23 | 24 | # Check if ( follows if statement 25 | check_if( 26 | got_type=tokens[i].type, 27 | should_be_types="left_paren", 28 | error_msg="Expected ( after if statement", 29 | line_num=tokens[i].line_num, 30 | ) 31 | 32 | # check if expression follows ( in if statement 33 | op_value, op_type, i, func_ret_type = expression( 34 | tokens, 35 | i, 36 | table, 37 | "Expected expression inside if statement", 38 | func_ret_type=func_ret_type, 39 | ) 40 | 41 | # check if ) follows expression in if statement 42 | check_if( 43 | got_type=tokens[i - 1].type, 44 | should_be_types="right_paren", 45 | error_msg="Expected ) after expression in if statement", 46 | line_num=tokens[i - 1].line_num, 47 | ) 48 | 49 | # If \n follows ) then skip all the \n characters 50 | if tokens[i + 1].type == "newline": 51 | i = skip_all_nextlines(tokens, i) 52 | i -= 1 53 | 54 | # Token index to be returned 55 | ret_idx = i 56 | 57 | if tokens[i].type == "newline": 58 | ret_idx = i + 1 59 | 60 | if tokens[i + 1].type == "left_brace": 61 | # Loop until } is reached 62 | i += 1 63 | ret_idx = i 64 | found_right_brace = False 65 | while i < len(tokens) and tokens[i].type != "right_brace": 66 | i += 1 67 | 68 | # If right brace found at end 69 | if i != len(tokens) and tokens[i].type == "right_brace": 70 | found_right_brace = True 71 | 72 | return OpCode("if", op_value[1:-1]), ret_idx - 1, func_ret_type 73 | 74 | 75 | def switch_statement(tokens, i, table, func_ret_type): 76 | """ 77 | Parse switch statement 78 | 79 | Params 80 | ====== 81 | tokens (list) = List of tokens 82 | i (int) = Current index in token 83 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 84 | func_ret_type (dict) = Dict of functions whose return type could not be resolved immediately 85 | 86 | Returns 87 | ======= 88 | OpCode, int: The opcode for the assign code and the index after parsing switch statement 89 | """ 90 | 91 | from .simc_parser import expression, skip_all_nextlines 92 | 93 | # Check if ( is present after switch keyword 94 | check_if( 95 | got_type=tokens[i].type, 96 | should_be_types="left_paren", 97 | error_msg="Expected ( after switch", 98 | line_num=tokens[i].line_num, 99 | ) 100 | 101 | # Expected expression after ( in switch 102 | op_value, _, i, func_ret_type = expression( 103 | tokens, 104 | i, 105 | table, 106 | "Expected expression inside switch statement", 107 | func_ret_type=func_ret_type, 108 | ) 109 | 110 | # Check if ) is present after expression in switch 111 | check_if( 112 | got_type=tokens[i - 1].type, 113 | should_be_types="right_paren", 114 | error_msg="Expected ) after expression in switch", 115 | line_num=tokens[i - 1].line_num, 116 | ) 117 | 118 | # Skip all next lines before { 119 | if tokens[i + 1].type == "newline": 120 | i = skip_all_nextlines(tokens, i) 121 | i -= 1 122 | 123 | # Check if opening { is present, as switch cannot be single line 124 | check_if( 125 | got_type=tokens[i + 1].type, 126 | should_be_types="left_brace", 127 | error_msg="Expected { after switch statement", 128 | line_num=tokens[i + 1].line_num, 129 | ) 130 | 131 | return OpCode("switch", op_value[1:-1], ""), i, func_ret_type 132 | 133 | 134 | def case_statement(tokens, i, table, func_ret_type): 135 | """ 136 | Parse case statement 137 | 138 | Params 139 | ====== 140 | tokens (list) = List of tokens 141 | i (int) = Current index in token 142 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 143 | func_ret_type (dict) = Dict of functions whose return type could not be resolved immediately 144 | 145 | Returns 146 | ======= 147 | OpCode, int: The opcode for the assign code and the index after parsing case statement 148 | """ 149 | 150 | from .simc_parser import expression 151 | 152 | # Expected expression after case keyword 153 | op_value, _, i, func_ret_type = expression( 154 | tokens, 155 | i, 156 | table, 157 | "Expected expected expression after case", 158 | expect_paren=False, 159 | func_ret_type=func_ret_type, 160 | ) 161 | 162 | # Check if expression is followed by : (colon) in case statement 163 | check_if( 164 | got_type=tokens[i].type, 165 | should_be_types="colon", 166 | error_msg="Expected : after case in switch statement", 167 | line_num=tokens[i].line_num, 168 | ) 169 | 170 | return OpCode("case", op_value, ""), i + 1, func_ret_type 171 | -------------------------------------------------------------------------------- /simc/parser/function_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def function_call_statement(tokens, i, table, func_ret_type): 7 | """ 8 | Parse function calling statement 9 | 10 | Params 11 | ====== 12 | tokens (list) = List of tokens 13 | i (int) = Current index in token 14 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 15 | func_ret_type (dict) = If return type of function is not figured yet 16 | 17 | Returns 18 | ======= 19 | OpCode, int, dict: The opcode for the assign code, index after parsing function calling statement and function return type 20 | """ 21 | 22 | from .simc_parser import expression 23 | 24 | # Store the beginning index for function call from imported libraries 25 | beg_idx = i 26 | 27 | # Get information about the function from symbol table 28 | func_info = table.get_by_id(tokens[i].val) 29 | func_id = tokens[i].val 30 | func_name = func_info[0] 31 | metadata = func_info[2] 32 | 33 | if metadata == "variable": 34 | error(f"No definition found for function {func_name}", tokens[i].line_num) 35 | 36 | # Get all parameter ids (default and non-default) and the default values (if any) 37 | params, default_values = extract_func_typedata(metadata, table) 38 | num_formal_params = len(params) 39 | num_required_args = num_formal_params - len(default_values) 40 | 41 | params_start_idx = i + 1 42 | 43 | # Parse the arguments 44 | op_value, op_type, i, func_ret_type = expression( 45 | tokens, 46 | i + 1, 47 | table, 48 | "", 49 | accept_empty_expression=True, 50 | expect_paren=True, 51 | func_ret_type=func_ret_type, 52 | ) 53 | 54 | params_end_idx = i 55 | actual_param_tokens = [] 56 | 57 | for i in range(params_start_idx, params_end_idx): 58 | if tokens[i].type == "id": 59 | actual_param_tokens.append(tokens[i]) 60 | 61 | # op_value start in 1 because it should start with "params)" not "(params)" 62 | op_value = op_value[1:] 63 | op_value_list = op_value.replace(" ", "").split(",") 64 | op_value_list = ( 65 | op_value_list if len(op_value_list) > 0 and len(op_value_list[0]) > 0 else [] 66 | ) 67 | num_actual_params = len(op_value_list) if op_value_list != [")"] else 0 68 | 69 | # Check if number of actual and formal parameters match 70 | if num_actual_params != num_required_args: 71 | error( 72 | "Expected {} arguments but got {} in function {}".format( 73 | num_required_args, num_actual_params, func_name 74 | ), 75 | tokens[i].line_num, 76 | ) 77 | 78 | # Fill the missing values in function call with default values 79 | op_value_list = fill_missing_args_with_defaults( 80 | op_value_list, default_values, num_actual_params, num_formal_params 81 | ) 82 | 83 | # Assign datatype to formal parameters 84 | for j in range(len(params)): 85 | # If parameter list is empty 86 | if params[j] == ")": 87 | continue 88 | 89 | # Fetch the datatype of corresponding actual parameter from symbol table 90 | _, dtype, _, _, _ = table.get_by_id( 91 | actual_param_tokens[j].val 92 | if (len(actual_param_tokens) > 0 and j < len(actual_param_tokens)) 93 | else table.get_by_symbol(op_value_list[j].replace(")", "")) 94 | ) 95 | 96 | # The id of the formal parameter will always be greater than the function's identifier in symbol table 97 | param_id = table.get_by_symbol(params[j], id_greater_than=func_id) 98 | 99 | # Set the datatype of the formal parameter 100 | table.symbol_table[param_id][1] = dtype 101 | 102 | # Resolve pendenting infer types 103 | table.resolve_dependency(tokens, i, param_id) 104 | 105 | use_module_tokens = False 106 | 107 | # If it an imported function the type of the function will be a list containing tokens from module's lexing results 108 | # Push all the function names and the corresponding position from where to parse 109 | if func_info != -1 and type(func_info[1][2]) == list: 110 | func_ret_type[func_name] = func_info[1][1] 111 | use_module_tokens = True 112 | 113 | # Handles delayed inference of return types, this can occur in two situations 114 | # 1 - When the function is part of third party module, 2 - When the function's parameter are contained in return expression 115 | if func_name in func_ret_type.keys(): 116 | # Case 1 117 | if use_module_tokens: 118 | # Parse the tokens which will help in deciding on the return type 119 | _, op_type, _, _ = expression( 120 | func_info[1][2], 121 | func_ret_type[func_name], 122 | table, 123 | "", 124 | func_ret_type=func_ret_type, 125 | ) 126 | 127 | # Case 2 128 | else: 129 | _, op_type, _, _ = expression( 130 | tokens, func_ret_type[func_name], table, "", func_ret_type=func_ret_type 131 | ) 132 | 133 | # Map datatype to appropriate datatype in C 134 | prec_to_type = { 135 | -1: "declared", 136 | 0: "char*", 137 | 1: "char*", 138 | 2: "char", 139 | 3: "int", 140 | 4: "float", 141 | 5: "double", 142 | 6: "bool", 143 | } 144 | 145 | table.symbol_table[table.get_by_symbol(func_name)][1] = prec_to_type[op_type] 146 | del func_ret_type[func_name] 147 | 148 | return ( 149 | OpCode("func_call", func_name + "---" + "&&&".join(op_value_list)[:-1], ""), 150 | i + 1, 151 | func_ret_type, 152 | ) 153 | 154 | 155 | def extract_func_typedata(typedata, table): 156 | """ 157 | Extract typedata of function 158 | 159 | Params 160 | ====== 161 | typedata (string) = Typedata of function in format "function---param1---param2---...&&&default_val1&&&... 162 | table (SymbolTable) = Symbol table 163 | 164 | Returns 165 | ======= 166 | parameters (list) = Parameter names 167 | default_values (list) = Default values 168 | """ 169 | 170 | func_typedata_split = typedata.split("&&&") 171 | 172 | param_segment = func_typedata_split[0] 173 | 174 | # Ignore the first index as it contains function's name 175 | parameters = param_segment.split("---")[1:] 176 | 177 | default_values = [] 178 | for seg in func_typedata_split[1:]: 179 | default_value, _, _, _, _ = table.get_by_id(int(seg)) 180 | default_values.append(default_value) 181 | 182 | return parameters, default_values 183 | 184 | 185 | def fill_missing_args_with_defaults( 186 | op_value_list, default_values, num_actual_params, num_formal_params 187 | ): 188 | 189 | # Compute the offset of default values according to the missing values count 190 | offset = len(default_values) - num_formal_params + num_actual_params 191 | default_values = default_values[offset:] 192 | 193 | # If there are not default values to be filled 194 | if not default_values: 195 | return op_value_list 196 | 197 | args = [] 198 | for op_value in op_value_list: 199 | arg = op_value.replace(")", "") 200 | if arg: 201 | args.append(arg) 202 | args += default_values 203 | args[-1] = args[-1] + ")" 204 | 205 | return args 206 | 207 | 208 | def function_definition_statement(tokens, i, table, func_ret_type): 209 | """ 210 | Parse function definition statement 211 | Params 212 | ====== 213 | tokens (list) = List of tokens 214 | i (int) = Current index in token 215 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 216 | func_ret_type (string) = Function return type 217 | Returns 218 | ======= 219 | OpCodes, int, string: The opcodes for the assign code, the index, and the name of the function after 220 | parsing function calling statement 221 | Grammar 222 | ======= 223 | function_definition_statement -> fun id([formal_param,]*) { body } 224 | formal_params -> id ('=' default_value) 225 | default_value -> number || string 226 | body -> statement 227 | id -> [a-zA-Z_]?[a-zA-Z0-9_]* 228 | """ 229 | 230 | from .simc_parser import skip_all_nextlines 231 | 232 | # Check if identifier follows fun 233 | check_if( 234 | got_type=tokens[i].type, 235 | should_be_types="id", 236 | error_msg="Expected function name", 237 | line_num=tokens[i].line_num, 238 | ) 239 | 240 | # Store the id of function name in symbol table 241 | func_idx = tokens[i].val 242 | 243 | # Get function name 244 | func_name, _, _, _, _ = table.get_by_id(func_idx) 245 | 246 | # Check if ( follows id in function 247 | check_if( 248 | got_type=tokens[i + 1].type, 249 | should_be_types="left_paren", 250 | error_msg="Expected ( after function name", 251 | line_num=tokens[i + 1].line_num, 252 | ) 253 | 254 | # Get the function parameter [and default value] tuples 255 | parameters, i = function_parameters(tokens, i + 2, table) 256 | 257 | # Check if ) follows expression in function 258 | check_if( 259 | got_type=tokens[i - 1].type, 260 | should_be_types="right_paren", 261 | error_msg="Expected ) after function params list", 262 | line_num=tokens[i - 1].line_num, 263 | ) 264 | 265 | # If \n follows ) then skip all the \n characters 266 | if tokens[i + 1].type == "newline": 267 | i = skip_all_nextlines(tokens, i) 268 | i -= 1 269 | 270 | op_codes = [] 271 | 272 | # Index to be returned to main parsing loop 273 | ret_idx = i 274 | 275 | if tokens[i].type == "newline": 276 | ret_idx = i + 1 277 | 278 | if tokens[i + 1].type == "left_brace": 279 | # Loop until } is reached 280 | i += 1 281 | ret_idx = i 282 | found_right_brace = False 283 | 284 | while i < len(tokens) and tokens[i].type != "right_brace": 285 | i += 1 286 | 287 | # If right brace found at end 288 | if i != len(tokens) and tokens[i].type == "right_brace": 289 | found_right_brace = True 290 | 291 | # If right brace is not found then produce error 292 | if not found_right_brace: 293 | error("Expected } after function body", tokens[i].line_num) 294 | 295 | else: 296 | op_codes.append(OpCode("scope_begin", "", "")) 297 | 298 | # Add the identifier types to function's typedata 299 | parameter_names = [parameter[0] for parameter in parameters] 300 | default_values = [ 301 | str(parameter[1]) for parameter in parameters if parameter[1] is not None 302 | ] 303 | 304 | func_typedata = "function" 305 | if parameter_names: 306 | func_typedata += "---" + "---".join(parameter_names) 307 | if default_values: 308 | func_typedata += "&&&" + "&&&".join(default_values) 309 | 310 | table.symbol_table[func_idx][2] = func_typedata 311 | 312 | op_codes.append( 313 | OpCode("func_decl", func_name + "---" + "&&&".join(parameter_names), "") 314 | ) 315 | 316 | # The order now is scope_begin followed by func_decl, but the compiler expects the opposite order 317 | op_codes.reverse() 318 | 319 | return ( 320 | op_codes, 321 | ret_idx - 1, 322 | func_name, 323 | func_ret_type, 324 | ) 325 | 326 | 327 | def function_parameters(tokens, i, table): 328 | """ 329 | Parse function parameters 330 | Params 331 | ====== 332 | tokens (list) = List of tokens 333 | i (int) = Current index in list of tokens 334 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 335 | Returns 336 | ======= 337 | parameters (list) = List of parameters (= list of (ids, default)) 338 | i (int) = Current index in list of tokens 339 | """ 340 | if tokens[i].type == "right_paren": 341 | 342 | i += 1 343 | 344 | return [], i 345 | 346 | parameters = [] 347 | default_val_required = False 348 | 349 | # Get the first parameter [and default value] 350 | param_info, i = function_parameter(tokens, i, table, default_val_required) 351 | 352 | # If there are parameters 353 | if param_info is not None: 354 | 355 | parameters.append(param_info) 356 | _, default_val = param_info 357 | default_val_required = default_val is not None 358 | 359 | # Continue parsing until comma tokens are encountered 360 | while tokens[i].type == "comma": 361 | # Skip comma token 362 | i += 1 363 | 364 | # Get parameter [and default value] 365 | param_info, i = function_parameter(tokens, i, table, default_val_required) 366 | 367 | if param_info is not None: 368 | parameters.append(param_info) 369 | if not default_val_required: 370 | _, default_val = param_info 371 | default_val_required = default_val is not None 372 | else: 373 | error("Parameter expected after comma", tokens[i].line_num) 374 | 375 | check_if( 376 | got_type=tokens[i].type, 377 | should_be_types="right_paren", 378 | error_msg="Right parentheses expected", 379 | line_num=tokens[i].line_num, 380 | ) 381 | 382 | # Skip right parantheses 383 | i += 1 384 | 385 | else: 386 | error("Function parameters must be identifiers", tokens[i].line_num) 387 | 388 | return parameters, i 389 | 390 | 391 | def function_parameter(tokens, i, table, default_val_required): 392 | """ 393 | Parse function parameter 394 | Params 395 | ====== 396 | tokens (list) = List of tokens 397 | i (int) = Current index in list of tokens 398 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 399 | default_val_required (bool) = Default value is required 400 | Returns 401 | ======= 402 | (parameter, default_val_id?) (tuple?) = Parameter and optional default value id or none 403 | i (int) = Current index in list of tokens 404 | """ 405 | if tokens[i].type != "id": 406 | return None, i 407 | 408 | # Get the parameter from symbol table id stored in token 409 | parameter, _, _, _, _ = table.get_by_id(tokens[i].val) 410 | i += 1 411 | 412 | default_val = None 413 | 414 | # To handle the case when a parameter on left has default value and the current one does not 415 | if default_val_required: 416 | check_if( 417 | got_type=tokens[i].type, 418 | should_be_types="assignment", 419 | error_msg="Default value expected for parameter {}".format(parameter), 420 | line_num=tokens[i].line_num, 421 | ) 422 | 423 | # Skip the assignment operator 424 | i += 1 425 | 426 | # Default parameter values can be number or string only as of now 427 | if tokens[i].type in ["number", "string"]: 428 | default_val = tokens[i].val 429 | i += 1 430 | else: 431 | error( 432 | "Only numbers and strings are allowed as default arguments", 433 | tokens[i].line_num, 434 | ) 435 | elif tokens[i].type == "assignment": 436 | i += 1 437 | if tokens[i].type in ["number", "string"]: 438 | default_val = tokens[i].val 439 | i += 1 440 | else: 441 | error( 442 | "Only numbers and strings are allowed as default arguments", 443 | tokens[i].line_num, 444 | ) 445 | 446 | return (parameter, default_val), i 447 | -------------------------------------------------------------------------------- /simc/parser/loop_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def for_statement(tokens, i, table, func_ret_type): 7 | """ 8 | Parse for for_loop 9 | Params 10 | ====== 11 | tokens (list) = List of tokens 12 | i (int) = Current index in token 13 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 14 | Returns 15 | ======= 16 | OpCode, int: The opcode for the for loop code and the index after parsing for loop 17 | Grammar 18 | ======= 19 | for_loop -> for id in number to number by operator number 20 | number -> [0-9]+ 21 | id -> [a-zA-Z_]?[a-zA-Z0-9_]* 22 | operator -> + | - | * | / 23 | """ 24 | from .simc_parser import expression 25 | 26 | # Check if identifier follows for keyword 27 | check_if( 28 | got_type=tokens[i].type, 29 | should_be_types="id", 30 | error_msg="Expected variable name", 31 | line_num=tokens[i].line_num, 32 | ) 33 | 34 | # Check if in follows identifier 35 | check_if( 36 | got_type=tokens[i + 1].type, 37 | should_be_types="in", 38 | error_msg="Expected in keyword", 39 | line_num=tokens[i + 1].line_num, 40 | ) 41 | 42 | # Check if number follows in keyword 43 | expression(tokens, i + 2, table, "Expected starting value", expect_paren=False) 44 | 45 | # Check if to keyword follows number 46 | check_if( 47 | got_type=tokens[i + 3].type, 48 | should_be_types="to", 49 | error_msg="Expected to keyword", 50 | line_num=tokens[i + 3].line_num, 51 | ) 52 | 53 | # Check if number follows in keyword 54 | expression(tokens, i + 4, table, "Expected ending value", expect_paren=False) 55 | 56 | # Check if by keyword follows number 57 | check_if( 58 | got_type=tokens[i + 5].type, 59 | should_be_types="by", 60 | error_msg="Expected by keyword", 61 | line_num=tokens[i + 5].line_num, 62 | ) 63 | 64 | word_to_op = {"plus": "+", "minus": "-", "multiply": "*", "divide": "/"} 65 | 66 | # Check if number follows operator 67 | expression(tokens, i + 7, table, "Expected value for change", expect_paren=False) 68 | 69 | # Get required values 70 | var_name, _, _, _, _ = table.get_by_id(tokens[i].val) 71 | 72 | # Set the value 73 | table.symbol_table[tokens[i].val][1] = "int" 74 | 75 | starting_val, _, _, _, _ = table.get_by_id(tokens[i + 2].val) 76 | ending_val, _, _, _, _ = table.get_by_id(tokens[i + 4].val) 77 | operator_type = word_to_op[tokens[i + 6].type] 78 | change_val, _, _, _, _ = table.get_by_id(tokens[i + 7].val) 79 | 80 | # To determine the > or < sign 81 | if starting_val > ending_val: 82 | sign_needed = ">" 83 | else: 84 | sign_needed = "<" 85 | 86 | # Return the opcode and i+1 (the token after for loop statement) 87 | return ( 88 | OpCode( 89 | "for", 90 | str(var_name) 91 | + "&&&" 92 | + str(starting_val) 93 | + "&&&" 94 | + str(ending_val) 95 | + "&&&" 96 | + str(operator_type) 97 | + "&&&" 98 | + sign_needed 99 | + "&&&" 100 | + str(change_val), 101 | ), 102 | i + 1, 103 | func_ret_type, 104 | ) 105 | 106 | 107 | def while_statement(tokens, i, table, in_do, func_ret_type): 108 | """ 109 | Parse while statement 110 | Params 111 | ====== 112 | tokens (list) = List of tokens 113 | i (int) = Current index in token 114 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 115 | in_do (bool) = While is part of do-while or is a separate while 116 | Returns 117 | ======= 118 | OpCode, int: The opcode for the assign code and the index after parsing while statement 119 | Grammar 120 | ======= 121 | while_statement -> while(condition) { body } 122 | condition -> expr 123 | expr -> string | number | id | operator 124 | string -> quote [a-zA-Z0-9`~!@#$%^&*()_-+={[]}:;,.?/|\]+ quote 125 | quote -> " 126 | number -> [0-9]+ 127 | id -> [a-zA-Z_]?[a-zA-Z0-9_]* 128 | operator -> + | - | * | / 129 | """ 130 | from .simc_parser import expression, skip_all_nextlines 131 | 132 | # Check if ( follows while statement 133 | check_if( 134 | got_type=tokens[i].type, 135 | should_be_types="left_paren", 136 | error_msg="Expected ( after while statement", 137 | line_num=tokens[i].line_num, 138 | ) 139 | 140 | # check if expression follows ( in while statement 141 | op_value, _, i, func_ret_type = expression( 142 | tokens, 143 | i, 144 | table, 145 | "Expected expression inside while statement", 146 | func_ret_type=func_ret_type, 147 | ) 148 | 149 | # check if ) follows expression in while statement 150 | check_if( 151 | got_type=tokens[i - 1].type, 152 | should_be_types="right_paren", 153 | error_msg="Expected ) after expression in while statement", 154 | line_num=tokens[i - 1].line_num, 155 | ) 156 | 157 | # If while is not part of do-while 158 | if not in_do: 159 | # If \n follows ) then skip all the \n characters 160 | if tokens[i + 1].type == "newline": 161 | i = skip_all_nextlines(tokens, i) 162 | i -= 1 163 | 164 | ret_idx = i 165 | if tokens[i].type == "newline": 166 | ret_idx = i + 1 167 | if tokens[i + 1].type == "left_brace": 168 | # Loop until } is reached 169 | i += 1 170 | ret_idx = i 171 | found_right_brace = False 172 | 173 | while i < len(tokens) and tokens[i].type != "right_brace": 174 | i += 1 175 | 176 | # If right brace found at end 177 | if i != len(tokens) and tokens[i].type == "right_brace": 178 | found_right_brace = True 179 | 180 | # If right brace is not found then produce error 181 | if not found_right_brace: 182 | error("Expected } after while loop body", tokens[i].line_num) 183 | 184 | return OpCode("while", op_value[1:-1]), ret_idx - 1, func_ret_type 185 | else: 186 | return OpCode("while_do", op_value[1:-1]), i + 1, func_ret_type 187 | -------------------------------------------------------------------------------- /simc/parser/parser_constants.py: -------------------------------------------------------------------------------- 1 | OP_TOKENS = [ 2 | "number", 3 | "input", 4 | "string", 5 | "id", 6 | "plus", 7 | "minus", 8 | "multiply", 9 | "power", 10 | "divide", 11 | "bitwise_and", 12 | "bitwise_xor", 13 | "bitwise_or", 14 | "bitwise_and_equal", 15 | "bitwise_xor_equal", 16 | "bitwise_or_equal", 17 | "comma", 18 | "equal", 19 | "not_equal", 20 | "greater_than", 21 | "less_than", 22 | "greater_than_equal", 23 | "less_than_equal", 24 | "modulus", 25 | "increment", 26 | "decrement", 27 | "plus_equal", 28 | "minus_equal", 29 | "multiply_equal", 30 | "divide_equal", 31 | "modulus_equal", 32 | "power_equal", 33 | "and", 34 | "or", 35 | "left_paren", 36 | "left_bracket", 37 | "exit", 38 | "right_paren", 39 | "right_bracket", 40 | "newline", 41 | "call_end", 42 | "address_of", 43 | "right_shift", 44 | "left_shift", 45 | "bool", 46 | "type_cast", 47 | "size", 48 | "type", 49 | ] 50 | 51 | WORD_TO_OP = { 52 | "plus": " + ", 53 | "minus": " - ", 54 | "multiply": " * ", 55 | "divide": " / ", 56 | " comma ": ", ", 57 | "equal": " == ", 58 | "not_equal": " != ", 59 | "greater_than": " > ", 60 | "less_than": " < ", 61 | "greater_than_equal": " >= ", 62 | "less_than_equal": " <= ", 63 | "input": " scanf ", 64 | "modulus": " % ", 65 | "increment": " ++ ", 66 | "decrement": " -- ", 67 | "plus_equal": " += ", 68 | "minus_equal": " -= ", 69 | "multiply_equal": " *= ", 70 | "divide_equal": " /= ", 71 | "modulus_equal": " %= ", 72 | "and": " && ", 73 | "or": " || ", 74 | "bitwise_and": " & ", 75 | "bitwise_or": " | ", 76 | "bitwise_xor": " ^ ", 77 | "bitwise_and_equal": " &= ", 78 | "bitwise_or_equal": " |= ", 79 | "bitwise_xor_equal": " ^= ", 80 | "comma": ",", 81 | "left_bracket": "[", 82 | "right_bracket": "]", 83 | "left_paren": "(", 84 | "right_paren": ")", 85 | "address_of": "&", 86 | "left_shift": " << ", 87 | "right_shift": " >> ", 88 | "power": "", 89 | } 90 | -------------------------------------------------------------------------------- /simc/parser/struct_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def initializate_struct(tokens, i, table, instance_var_name, var_list): 7 | """ 8 | Initialization of a struction when the variable instantiate is type of a declared struct 9 | Params 10 | ====== 11 | tokens (list) = List of tokens 12 | i (int) = Current index in token 13 | table (SymbolTable) = Symbol Table constructed holding information about identifiers and constans 14 | instance_var_name (String) = Name of the instance of the struct 15 | var_list (String) = List of if variable declared inside struct 16 | """ 17 | # Initializate the child variable of struct 18 | var_ids = var_list.split("-")[1:] 19 | 20 | # Load var and copy to struct initilization 21 | for var_id in var_ids: 22 | 23 | # Find the child variable of struct 24 | var_name, type_, metatype_, _, _ = table.get_by_id(int(var_id)) 25 | new_var_name = instance_var_name + "." + var_name 26 | 27 | # Check if variable already exist 28 | new_var_id = table.get_by_symbol(new_var_name) 29 | # If it not exist, then create a new 30 | if new_var_id is -1: 31 | table.entry(instance_var_name + "." + var_name, type_, metatype_, "") 32 | # Otherwise, Modify datatype of the identifier 33 | else: 34 | table.symbol_table[new_var_id][1] = type_ 35 | table.symbol_table[new_var_id][3] += "-" + var_id 36 | 37 | 38 | def struct_declaration_statement(tokens, i, table): 39 | """ 40 | Parse structure declaration statement 41 | Params 42 | ====== 43 | tokens (list) = List of tokens 44 | i (int) = Current index in token 45 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 46 | Returns 47 | ======= 48 | OpCode, int, string: The opcode for the assign code, the index, and the name of the function after 49 | parsing function calling statement 50 | """ 51 | 52 | from .simc_parser import skip_all_nextlines 53 | 54 | # Check if identifier follows struct 55 | check_if( 56 | got_type=tokens[i].type, 57 | should_be_types="id", 58 | error_msg="Expected structure name", 59 | line_num=tokens[i].line_num, 60 | ) 61 | 62 | # Store the id of strcuture name in symbol table 63 | struct_idx = tokens[i].val 64 | 65 | # Update type to hold struct_var instead of var 66 | table.symbol_table[struct_idx][1] = "struct_var" 67 | 68 | # Get struct name 69 | struct_name, _, _, _, _ = table.get_by_id(struct_idx) 70 | 71 | # If \n follows struct name then skip all the \n characters 72 | if tokens[i + 1].type == "newline": 73 | i = skip_all_nextlines() 74 | i -= 1 75 | 76 | # Check if { follows the structure name 77 | check_if( 78 | got_type=tokens[i + 1].type, 79 | should_be_types="left_brace", 80 | error_msg="Expected { after structure name body", 81 | line_num=tokens[i + 1].line_num, 82 | ) 83 | 84 | # Loop until } is reached 85 | i += 2 86 | ret_idx = i 87 | found_right_brace = False 88 | while i < len(tokens) and tokens[i].type != "right_brace": 89 | i += 1 90 | 91 | # If right brace found at end 92 | if i != len(tokens) and tokens[i].type == "right_brace": 93 | found_right_brace = True 94 | 95 | # If right brace is not found then produce error 96 | if not found_right_brace: 97 | error("Expected } after structure body", tokens[i].line_num) 98 | 99 | return (OpCode("struct_decl", struct_name, ""), ret_idx - 1, struct_name) 100 | -------------------------------------------------------------------------------- /simc/parser/variable_parser.py: -------------------------------------------------------------------------------- 1 | from ..global_helpers import error, check_if 2 | 3 | from ..op_code import OpCode 4 | 5 | 6 | def check_ptr(tokens, i): 7 | # Check if a pointer is being declared 8 | is_ptr = False 9 | 10 | # Count the depth of pointer 11 | count_ast = 0 12 | 13 | if tokens[i].type == "multiply": 14 | asterisk_count = 0 15 | 16 | # Accumulate count of * in j 17 | while tokens[i + asterisk_count].type == "multiply": 18 | asterisk_count += 1 19 | 20 | # Add asterisk count to token index to get index of token after all asterisks 21 | i += asterisk_count 22 | 23 | is_ptr = True 24 | return is_ptr, asterisk_count, i 25 | else: 26 | return False, 0, i 27 | 28 | 29 | def var_statement(tokens, i, table, func_ret_type): 30 | """ 31 | Parse variable and array declaration [/initialization] statement 32 | Params 33 | ====== 34 | tokens (list) = List of tokens 35 | i (int) = Current index in token 36 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 37 | func_ret_type (string) = Function return type 38 | Returns 39 | ======= 40 | OpCode, int: The opcode for the var_assign/var_no_assign code and the index after parsing var statement 41 | Grammar 42 | ======= 43 | var_statement -> var id [= expr]? 44 | expr -> string | number | id | operator 45 | string -> quote [a-zA-Z0-9`~!@#$%^&*()_-+={[]}:;,.?/|\]+ quote 46 | quote -> " 47 | number -> [0-9]+ 48 | id -> [a-zA-Z_]?[a-zA-Z0-9_]* 49 | operator -> + | - | * | / 50 | """ 51 | from .array_parser import array_initializer 52 | from .simc_parser import expression 53 | 54 | # Check if the variable is a pointer, and if it is then get the depth of pointer 55 | is_ptr, asterisk_count, i = check_ptr(tokens, i) 56 | 57 | # Check if identifier is present after var 58 | check_if( 59 | got_type=tokens[i].type, 60 | should_be_types="id", 61 | error_msg="Expected id after var keyword", 62 | line_num=tokens[i].line_num, 63 | ) 64 | 65 | # Tokens that are not accepted after declaration of a variable 66 | invalid_tokens = [ 67 | # Shortcut arithmetic assignments 68 | "plus_equal", 69 | "minus_equal", 70 | "multiply_equal", 71 | "divide_equal", 72 | "modulus_equal", 73 | # Arithmetic operators 74 | "plus", 75 | "minus", 76 | "multiply", 77 | "divide", 78 | "modulus", 79 | # Bitwise operators 80 | "bitwise_and", 81 | "bitwise_or", 82 | "bitwise_xor", 83 | # Shortcut bitwise assignments 84 | "bitwise_and_equal", 85 | "bitwise_or_equal", 86 | "bitwise_xor_equal", 87 | # Relational operators 88 | "equal", 89 | "not_equal", 90 | ] 91 | 92 | # Map datatype to appropriate datatype in C 93 | prec_to_type = { 94 | -1: "declared", 95 | 0: "string", 96 | 1: "char*", 97 | 2: "char", 98 | 3: "int", 99 | 4: "float", 100 | 5: "double", 101 | 6: "bool", 102 | } 103 | 104 | # Check if it is an array declaration (+ initializer list) 105 | if tokens[i + 1].type == "left_bracket": 106 | 107 | # Size of array 108 | size_of_array = "" 109 | 110 | # Store the index of identifier 111 | id_idx = i 112 | 113 | # If the next token after [ is a number 114 | if tokens[i + 2].type == "number": 115 | # Fetch information from symbol table 116 | value, type_, _, _, _ = table.get_by_id(tokens[i + 2].val) 117 | 118 | if type_ == "int": 119 | size_of_array = value 120 | else: 121 | error( 122 | f"Expected integer size of array but got {type_}", 123 | tokens[i + 2].line_num, 124 | ) 125 | 126 | # Check if array statement has closing ] (right_bracket) 127 | check_if( 128 | got_type=tokens[i + 3].type, 129 | should_be_types="right_bracket", 130 | error_msg="Expected ] after expression in array statement", 131 | line_num=tokens[i + 3].line_num, 132 | ) 133 | 134 | # Move token index to end of array declaration (right bracket) 135 | i += 3 136 | elif tokens[i + 2].type == "right_bracket": 137 | # Size of array is not known 138 | size_of_array = "" 139 | 140 | # Move token index to end of array declaration (right bracket) 141 | i += 2 142 | 143 | # Check if array is initialized as var [] = {1, 2, ...} 144 | if i + 1 < len(tokens) and tokens[i + 1].type == "assignment": 145 | # Check if expression follows = in array statement 146 | op_value, op_type, i = array_initializer( 147 | tokens, 148 | i + 2, 149 | table, 150 | size_of_array, 151 | "Required expression after assignment operator", 152 | func_ret_type=func_ret_type, 153 | ) 154 | i += 1 155 | 156 | # Modify datatype of the identifier 157 | table.symbol_table[tokens[id_idx].val][1] = prec_to_type[op_type] 158 | 159 | # Add the size of array to metadata (typedata) in symbol table 160 | table.symbol_table[tokens[id_idx].val][2] = ( 161 | size_of_array if size_of_array != "" else -1 162 | ) 163 | 164 | # Return the opcode and i (the token after var statement) 165 | return ( 166 | OpCode( 167 | "array_assign", 168 | table.symbol_table[tokens[id_idx].val][0] 169 | + "---" 170 | + str(size_of_array) 171 | + "---" 172 | + op_value, 173 | prec_to_type[op_type], 174 | ), 175 | i, 176 | func_ret_type, 177 | ) 178 | elif i + 1 < len(tokens) and tokens[i + 1].type in invalid_tokens: 179 | error("Invalid Syntax for declaration", tokens[i].line_num) 180 | else: 181 | # Get the value from symbol table by id 182 | value, type_, _, _, _ = table.get_by_id(tokens[id_idx].val) 183 | 184 | # If already declared then throw error 185 | if type_ in [ 186 | "declared", 187 | "int", 188 | "char", 189 | "float", 190 | "double", 191 | "string", 192 | "char *", 193 | "char*", 194 | ]: 195 | error("Variable %s already declared" % value, tokens[i].line_num) 196 | 197 | # Set type to declared 198 | table.symbol_table[tokens[id_idx].val][1] = "arr_declared" 199 | 200 | # Check if size of array has been determined or not, it isn't then throw error 201 | # Since for later assignment size needs to be known 202 | if size_of_array == "": 203 | error( 204 | "Size of array needs to be known if assignment is not done while" 205 | " declaration", 206 | tokens[i].line_num, 207 | ) 208 | else: 209 | table.symbol_table[tokens[id_idx].val][2] = size_of_array 210 | return ( 211 | OpCode("array_no_assign", value + "---" + str(size_of_array)), 212 | i, 213 | func_ret_type, 214 | ) 215 | 216 | # Check if variable is assigned with declaration 217 | elif i + 1 < len(tokens) and tokens[i + 1].type == "assignment": 218 | # Store the index of identifier 219 | id_idx = i 220 | 221 | # Check if expression follows = in var statement 222 | op_value, op_type, i, func_ret_type = expression( 223 | tokens, 224 | i + 2, 225 | table, 226 | "Required expression after assignment operator", 227 | expect_paren=False, 228 | func_ret_type=func_ret_type, 229 | ) 230 | 231 | # Modify datatype of the identifier 232 | table.symbol_table[tokens[id_idx].val][1] = prec_to_type[op_type] 233 | 234 | if is_ptr: 235 | return ( 236 | OpCode( 237 | "ptr_assign", 238 | table.symbol_table[tokens[id_idx].val][0] 239 | + "---" 240 | + op_value 241 | + "---" 242 | + str(asterisk_count), 243 | prec_to_type[op_type], 244 | ), 245 | i, 246 | func_ret_type, 247 | ) 248 | else: 249 | # Return the opcode and i (the token after var statement) 250 | return ( 251 | OpCode( 252 | "var_assign", 253 | table.symbol_table[tokens[id_idx].val][0] + "---" + op_value, 254 | prec_to_type[op_type], 255 | ), 256 | i, 257 | func_ret_type, 258 | ) 259 | elif i + 1 < len(tokens) and tokens[i + 1].type in invalid_tokens: 260 | error("Invalid Syntax for declaration", tokens[i].line_num) 261 | 262 | # If it is of pointer or variable type but has no value yet 263 | else: 264 | # Get the value from symbol table by id 265 | value, type, _, _, _ = table.get_by_id(tokens[i].val) 266 | 267 | # If already declared then throw error 268 | if type in [ 269 | "declared", 270 | "int", 271 | "char", 272 | "float", 273 | "double", 274 | "string", 275 | "char *", 276 | "char*", 277 | "bool", 278 | ]: 279 | error("Variable %s already declared" % value, tokens[i].line_num) 280 | 281 | # Set declared 282 | table.symbol_table[tokens[i].val][1] = "declared" 283 | 284 | # Return the opcode and i+1 (the token after var statement) 285 | if is_ptr: 286 | return OpCode("ptr_no_assign", value), i + 1, func_ret_type 287 | 288 | return OpCode("var_no_assign", value), i + 1, func_ret_type 289 | 290 | 291 | def assign_statement(tokens, i, table, func_ret_type): 292 | """ 293 | Parse assignment statement 294 | Params 295 | ====== 296 | tokens (list) = List of tokens 297 | i (int) = Current index in token 298 | table (SymbolTable) = Symbol table constructed holding information about identifiers and constants 299 | Returns 300 | ======= 301 | OpCode, int: The opcode for the assign code and the index after parsing assign statement 302 | Grammar 303 | ======= 304 | var_statement -> var id [= expr]? 305 | expr -> string | number | id | operator 306 | string -> quote [a-zA-Z0-9`~!@#$%^&*()_-+={[]}:;,.?/|\]+ quote 307 | quote -> " 308 | number -> [0-9]+ 309 | id -> [a-zA-Z_]?[a-zA-Z0-9_]* 310 | operator -> + | - | * | / 311 | """ 312 | from .simc_parser import expression 313 | from .array_parser import array_initializer 314 | 315 | # Map datatype to appropriate datatype in C 316 | prec_to_type = { 317 | -1: "declared", 318 | 0: "string", 319 | 1: "char*", 320 | 2: "char", 321 | 3: "int", 322 | 4: "float", 323 | 5: "double", 324 | 6: "bool", 325 | } 326 | 327 | # Check if the identifier is a pointer 328 | is_ptr = False 329 | # count depth of pointer 330 | count_ast = 0 331 | 332 | if tokens[i - 2].type == "multiply": 333 | j = -2 334 | while tokens[j + i].type == "multiply": 335 | j -= 1 336 | count_ast = -1 * j - 2 337 | is_ptr = True 338 | 339 | # Check if variable is declared or not 340 | var_name, type_, _, _, scope = table.get_by_id(tokens[i - 1].val) 341 | 342 | # If - is not in scope then it wasn't declared, otherwise its scope would have been resolved by now 343 | # and it would have the form -- as the scope 344 | if type_ == "var" and "-" not in scope: 345 | error("Variable %s used before declaration" % var_name, tokens[i - 1].line_num) 346 | 347 | # Index of assignment in array 348 | op_value_idx = "" 349 | 350 | # Store the index of identifier 351 | id_idx = i - 1 352 | 353 | # Store the id of variable in Symbol Table 354 | var_id = tokens[id_idx].val 355 | 356 | # Check if is a array indexing case 357 | if tokens[i].type == "left_bracket": 358 | if tokens[i + 1].type == "number": 359 | # Fetch information from symbol table 360 | value, type_, _, _, _ = table.get_by_id(tokens[i + 1].val) 361 | 362 | if type_ == "int": 363 | if int(value) >= int(table.symbol_table[tokens[id_idx].val][2]): 364 | error( 365 | f"Index {value} out of bounds for array {var_name}", 366 | tokens[i].line_num, 367 | ) 368 | else: 369 | error( 370 | "Expected integer value or expression in array idexing", 371 | tokens[i].line_num, 372 | ) 373 | 374 | op_value_idx, op_type_idx, i, func_ret_type = expression( 375 | tokens, 376 | i, 377 | table, 378 | "Expected integer an index for array", 379 | block_type_promotion=True, 380 | expect_paren=False, 381 | func_ret_type=func_ret_type, 382 | ) 383 | 384 | # Type 3 is for integer expressions 385 | if op_type_idx != 3: 386 | error( 387 | "Expected integer value or expression in array idexing", 388 | tokens[i].line_num, 389 | ) 390 | 391 | # Dictionary to convert tokens to their corresponding assignment types 392 | assignment_type = { 393 | "assignment": "=", 394 | "plus_equal": "+=", 395 | "minus_equal": "-=", 396 | "multiply_equal": "*=", 397 | "divide_equal": "/=", 398 | "modulus_equal": "%=", 399 | "bitwise_and_equal": "&=", 400 | "bitwise_xor_equal": "^=", 401 | "bitwise_or_equal": "|=", 402 | } 403 | 404 | check_if( 405 | got_type=tokens[i].type, 406 | should_be_types=[ 407 | "assignment", 408 | "plus_equal", 409 | "minus_equal", 410 | "multiply_equal", 411 | "divide_equal", 412 | "modulus_equal", 413 | "bitwise_and_equal", 414 | "bitwise_xor_equal", 415 | "bitwise_or_equal", 416 | ], 417 | error_msg="Expected assignment operator after identifier", 418 | line_num=tokens[i].line_num, 419 | ) 420 | 421 | # Convert the token to respective symbol 422 | converted_type = assignment_type[tokens[i].type] 423 | 424 | # Get the symbol table entry for the identifier 425 | id_table_entry = table.symbol_table[tokens[id_idx].val] 426 | type_ = id_table_entry[1] 427 | 428 | # Flag to check array assignment 429 | is_arr = False 430 | 431 | # Check if assignment is an array initializer or a simple expression type 432 | if tokens[i + 1].type == "left_brace": 433 | is_arr = True 434 | if type_ != "arr_declared": 435 | error("Cannot assign an initializer list to a variable", tokens[i].line_num) 436 | 437 | size_of_array = id_table_entry[2] 438 | 439 | op_value, op_type, i = array_initializer( 440 | tokens, 441 | i + 1, 442 | table, 443 | size_of_array, 444 | "Required expression after assignment operator", 445 | func_ret_type=func_ret_type, 446 | ) 447 | 448 | # Modify datatype of the identifier 449 | table.symbol_table[var_id][1] = prec_to_type[op_type] 450 | 451 | else: 452 | if type_ == "arr_declared" and tokens[id_idx + 1].type != "left_bracket": 453 | error( 454 | "Array assignment requires initializer list, cannot assign expression", 455 | tokens[i].line_num, 456 | ) 457 | 458 | # Check if expression follows = in assign statement 459 | op_value, op_type, i, func_ret_type = expression( 460 | tokens, 461 | i + 1, 462 | table, 463 | "Required expression after assignment operator", 464 | expect_paren=False, 465 | func_ret_type=func_ret_type, 466 | ) 467 | 468 | op_value = converted_type + "---" + op_value 469 | 470 | if table.symbol_table[var_id][1] in ["var", "declared"]: 471 | # Modify datatype of the identifier 472 | table.symbol_table[var_id][1] = prec_to_type[op_type] 473 | 474 | # Check if a pointer is being assigned 475 | if is_ptr: 476 | return ( 477 | OpCode( 478 | "ptr_only_assign", 479 | table.symbol_table[var_id][0] 480 | + op_value_idx 481 | + "---" 482 | + op_value 483 | + "---" 484 | + str(count_ast), 485 | "", 486 | ), 487 | i, 488 | func_ret_type, 489 | ) 490 | 491 | # Resolve pendenting infer types 492 | table.resolve_dependency(tokens, i, var_id) 493 | 494 | # If it is an array then generate array_only_assign 495 | if is_arr: 496 | # Add ( []) to op_value 497 | op_value = ( 498 | " " 499 | + op_value.split("---")[0] 500 | + " (" 501 | + prec_to_type[op_type] 502 | + " [" 503 | + size_of_array 504 | + "])" 505 | + op_value.split("---")[1] 506 | ) 507 | return ( 508 | OpCode( 509 | "array_only_assign", 510 | table.symbol_table[var_id][0] + "---" + op_value, 511 | "", 512 | ), 513 | i, 514 | func_ret_type, 515 | ) 516 | 517 | # Return the opcode and i (the token after assign statement) 518 | return ( 519 | OpCode("assign", var_name + op_value_idx + "---" + op_value, ""), 520 | i, 521 | func_ret_type, 522 | ) 523 | -------------------------------------------------------------------------------- /simc/scope_resolve.py: -------------------------------------------------------------------------------- 1 | from .token_class import Token 2 | 3 | 4 | class ScopeResolver: 5 | def __init__(self, tokens_list, symbol_table): 6 | self.__tokens_list = tokens_list 7 | self.__symbol_table = symbol_table 8 | self.__scope_stack = [] 9 | 10 | def __push_to_scope_stack(self, val): 11 | self.__scope_stack.append(val) 12 | 13 | def __pop_from_scope_stack(self): 14 | return self.__scope_stack.pop() 15 | 16 | def resolve_scope(self, module_name): 17 | final_line = 0 18 | id_usage_to_resolve = [] 19 | function_started = False 20 | 21 | for i, token in enumerate(self.__tokens_list): 22 | if i > 0 and self.__tokens_list[i - 1].type == "fun" and token.type == "id": 23 | self.__push_to_scope_stack(Token("left_brace", "", token.line_num)) 24 | function_started = True 25 | elif ( 26 | i > 0 and self.__tokens_list[i - 1].type == "var" and token.type == "id" 27 | ): 28 | self.__push_to_scope_stack(token) 29 | elif token.type == "id" and function_started: 30 | self.__push_to_scope_stack(token) 31 | elif token.type == "call_end" and function_started: 32 | function_started = False 33 | elif token.type == "id": 34 | id_usage_to_resolve.append(i) 35 | elif ( 36 | i > 0 37 | and token.type == "left_brace" 38 | and self.__tokens_list[i - 1].type != "call_end" 39 | ): 40 | self.__push_to_scope_stack(token) 41 | elif token.type == "right_brace": 42 | while len(self.__scope_stack) != 0: 43 | top_token = self.__pop_from_scope_stack() 44 | 45 | if top_token.type == "id": 46 | top_token_id = top_token.val 47 | self.__symbol_table.symbol_table[top_token_id][-1] += ( 48 | "-" + str(token.line_num) + "-" + module_name 49 | ) 50 | elif top_token.type == "left_brace": 51 | break 52 | 53 | final_line = token.line_num 54 | 55 | while len(self.__scope_stack) != 0: 56 | top_token = self.__pop_from_scope_stack() 57 | 58 | if top_token.type == "id": 59 | top_token_id = top_token.val 60 | self.__symbol_table.symbol_table[top_token_id][-1] += ( 61 | "-" + str(final_line) + "-" + module_name 62 | ) 63 | 64 | for id_ in id_usage_to_resolve: 65 | resolved_id = self.__symbol_table.resolve_scope_for_id( 66 | token=self.__tokens_list[id_], module_name=module_name 67 | ) 68 | self.__tokens_list[id_].val = ( 69 | resolved_id if resolved_id != None else self.__tokens_list[id_].val 70 | ) 71 | 72 | return self.__tokens_list, self.__symbol_table 73 | 74 | def swap_tokens_and_table(self, tokens_list, table): 75 | self.__tokens_list = tokens_list 76 | self.__symbol_table = table 77 | -------------------------------------------------------------------------------- /simc/simc.py: -------------------------------------------------------------------------------- 1 | # Import sys, os and pprint module 2 | import sys 3 | import os 4 | import pprint 5 | 6 | # Module to import global helpers 7 | from .global_helpers import error 8 | 9 | # Module to import Symbol Table class 10 | from .symbol_table import SymbolTable 11 | 12 | # Module for using lexical analyzer 13 | from .lexical_analyzer import LexicalAnalyzer 14 | 15 | # Module for using parser 16 | from .parser.simc_parser import parse 17 | 18 | # Module for using compiler 19 | from .compiler import compile 20 | 21 | from .scope_resolve import ScopeResolver 22 | 23 | 24 | def run(): 25 | filename = "" 26 | 27 | pretty_printer = pprint.PrettyPrinter(indent=4) 28 | 29 | # Check if filepath is provided or not 30 | if len(sys.argv) >= 2: 31 | filename = sys.argv[1] 32 | 33 | # Check if extension of file is correct or not 34 | if "." not in filename or filename.split(".")[-1] != "simc": 35 | error("Incorrect file extension", -1) 36 | else: 37 | error("Please provide simc file path", -1) 38 | 39 | # Get the filename of c file to be generated 40 | c_filename = "".join(filename.split(".")[:-1]) + ".c" 41 | 42 | # Create symbol table 43 | table = SymbolTable() 44 | 45 | # Get tokens and list of modules from source code 46 | lexical_analyzer = LexicalAnalyzer(filename, table) 47 | tokens, module_source_paths = lexical_analyzer.lexical_analyze() 48 | 49 | scope_resolver = ScopeResolver(tokens_list=tokens, symbol_table=table) 50 | tokens, table = scope_resolver.resolve_scope(module_name="main") 51 | 52 | # Get tokens for modules 53 | all_module_tokens = {} 54 | if len(module_source_paths) > 0: 55 | for module_source_path in module_source_paths: 56 | module_name = os.path.basename(module_source_path).split(".")[0] 57 | 58 | lexical_analyzer.update_filename(module_source_path) 59 | all_module_tokens[module_name], _ = lexical_analyzer.lexical_analyze() 60 | 61 | scope_resolver.swap_tokens_and_table( 62 | tokens_list=all_module_tokens[module_name], table=table 63 | ) 64 | all_module_tokens[module_name], table = scope_resolver.resolve_scope( 65 | module_name=module_name 66 | ) 67 | 68 | # Option to check out tokens 69 | if len(sys.argv) > 2 and sys.argv[2] == "token": 70 | # Print source code tokens 71 | for token in tokens: 72 | print(token) 73 | 74 | # Print module tokens 75 | for module_name, module_tokens in all_module_tokens.items(): 76 | print("\n---Tokens for module " + module_name + "---") 77 | for token in module_tokens: 78 | print(token) 79 | 80 | # Option to check symbol table after lexical analysis 81 | if len(sys.argv) > 2 and sys.argv[2] == "table_after_lexing": 82 | # print(table) 83 | pretty_printer.pprint(table.symbol_table) 84 | 85 | # Parse the modules first as these function definitions will be important during source parsing 86 | all_module_opcodes = {} 87 | 88 | for module_name, module_tokens in all_module_tokens.items(): 89 | all_module_opcodes[module_name] = parse(module_tokens, table) 90 | 91 | # Get opcodes for source code from parser 92 | op_codes = parse(tokens, table) 93 | 94 | # Remove opcodes of unused functions from modules 95 | all_module_opcodes_pruned = {} 96 | for module_name, module_opcodes in all_module_opcodes.items(): 97 | all_module_opcodes_pruned[module_name] = [] 98 | i = 0 99 | 100 | # Loops through all the opcodes of specific module and checks for functions which weren't called from source code 101 | while i < len(module_opcodes): 102 | if module_opcodes[i].type == "func_decl": 103 | func_name = module_opcodes[i].val.split("---")[0].strip() 104 | func_symbol_table_val = table.symbol_table.get( 105 | table.get_by_symbol(func_name) 106 | ) 107 | func_ret_type = func_symbol_table_val[1] 108 | 109 | # Skip all functions whose return type is not_known meaning they weren't called 110 | if func_ret_type == "not_known" or type(func_ret_type) == list: 111 | beg_idx = i 112 | while module_opcodes[i].type != "scope_over": 113 | i += 1 114 | else: 115 | all_module_opcodes_pruned[module_name].append(module_opcodes[i]) 116 | else: 117 | all_module_opcodes_pruned[module_name].append(module_opcodes[i]) 118 | i += 1 119 | 120 | # Option to check out opcodes 121 | if len(sys.argv) > 2 and sys.argv[2] == "opcode": 122 | # Print source code opcodes 123 | for op_code in op_codes: 124 | print(op_code) 125 | 126 | # Print module opcodes 127 | for module_name, module_opcodes in all_module_opcodes_pruned.items(): 128 | print("\n---OpCodes for module " + module_name + "---") 129 | for op_code in module_opcodes: 130 | print(op_code) 131 | 132 | # Option to check symbol table after parsing 133 | if len(sys.argv) > 2 and sys.argv[2] == "table_after_parsing": 134 | # print(table) 135 | pretty_printer.pprint(table.symbol_table) 136 | 137 | # Compile to C code 138 | compile(op_codes, c_filename, table) 139 | 140 | # Compile the module functions, this can be done in any order 141 | for module_name, module_opcodes in all_module_opcodes_pruned.items(): 142 | module_c_filename = module_name + ".h" 143 | 144 | compile(module_opcodes, module_c_filename, table) 145 | 146 | print("\033[92mC code generated at %s!" % c_filename, end="") 147 | print(" \033[m") 148 | -------------------------------------------------------------------------------- /simc/simpack.py: -------------------------------------------------------------------------------- 1 | # simpack (short for simC Packages) is the official package manager for simC 2 | 3 | # Import libraries 4 | import requests 5 | import argparse 6 | import os 7 | 8 | # Import error from global helpers 9 | from .global_helpers import error 10 | 11 | 12 | def get_package(): 13 | # Get path to local simc installation 14 | simc_path = os.path.dirname(__file__) 15 | 16 | # Get path for package-index which has link to download simc modules 17 | index_path = os.path.join(simc_path, "package-index") 18 | 19 | # Open the path and read all the package names with corresponding links 20 | with open(index_path, "r") as file: 21 | index = file.read().split("\n") 22 | package_index = {} 23 | for i in range(len(index)): 24 | name_link = index[i].split("-") 25 | package_index[name_link[0].strip()] = name_link[1].strip() 26 | 27 | # Command line argument parser 28 | parser = argparse.ArgumentParser(description="simC Packages") 29 | parser.add_argument("--name", help="Enter name of package") 30 | 31 | args = parser.parse_args() 32 | 33 | # Find the link for the package name 34 | requested_name = args.name 35 | requested_link = package_index.get(requested_name, "Unknown") 36 | 37 | # If the package is not listed in package-index then throw an error 38 | if requested_link == "Unknown": 39 | error("Unable to find package with name " + requested_name, -1) 40 | 41 | # All modules go inside modules directory in local simc installation 42 | module_dir = os.path.join(simc_path, "modules") 43 | module_path = os.path.join(module_dir, requested_name + ".simc") 44 | 45 | # If module directory does not exist (user did not install anything yet) then create the directory 46 | if not os.path.exists(module_dir): 47 | os.mkdir(module_dir) 48 | 49 | # If the simc file is already present in modules directory then the package is already installed 50 | if os.path.exists(module_path): 51 | print(requested_name + " is already installed!") 52 | 53 | # Otherwise fetch the simc module from the corresponding link 54 | else: 55 | print("Fetching package " + requested_name + " from " + requested_link) 56 | r = requests.get(requested_link) 57 | 58 | # Dump module code into modules/.simc 59 | open(module_path, "wb").write(r.content) 60 | print(requested_name + " is now available for use!") 61 | -------------------------------------------------------------------------------- /simc/symbol_table.py: -------------------------------------------------------------------------------- 1 | class SymbolTable: 2 | """ 3 | SymbolTable class is responsible for storing information about identifiers and constants 4 | """ 5 | 6 | def __init__(self): 7 | """ 8 | Initializer of SymbolTable class 9 | """ 10 | 11 | self.id = 1 12 | self.symbol_table = {} 13 | 14 | def __str__(self): 15 | """ 16 | String representation of SymbolTable 17 | 18 | Returns 19 | ======= 20 | string: The string representation of SymbolTable object - used for pretty printing the table 21 | """ 22 | 23 | table_dict = self.symbol_table 24 | 25 | # Maximum length when all strings in the lists are compared 26 | max_length = max( 27 | [len(i) for dict_list in table_dict.values() for i in dict_list] 28 | ) 29 | 30 | table_string = "" 31 | 32 | # To solve spacing issue for when lines exceed some power of 10 (like from line 9 to 10, 99 to 100 etc. ) 33 | spaces_after_integer = len(str(len(table_dict))) 34 | 35 | # Keeps track of the lengths of each line (To account for alignment, when structures are involved) 36 | line_lengths = [] 37 | 38 | for i in range(1, len(table_dict) + 1): 39 | 40 | line = "| " + str(i) + " " 41 | 42 | # Without this line, as the number of elements in symbol table exceeds some power of 10, 43 | # there will be some distortion in table rows. For example, between row 99 and 100. 44 | line += " " * (spaces_after_integer - len(str(i))) 45 | 46 | dict_list = table_dict[i] # Dictionary to be printed in tabular form 47 | 48 | for j in range(len(dict_list)): 49 | 50 | line += dict_list[j] 51 | if j < len(dict_list) - 2: # To add space between columns 52 | line += " " * (max_length - len(dict_list[j]) + 2) 53 | 54 | line_lengths.append(len(line)) 55 | table_string += line + "\n" 56 | 57 | symbol_table_string = "" # Final string which will be displayed 58 | max_line_len = max(line_lengths) 59 | line_len = 0 60 | 61 | for character in table_string: 62 | 63 | if character == "\n": # If a newline is detected, add necessary spaces 64 | symbol_table_string += " " * (max_line_len - line_len) + " |\n" 65 | line_len = 0 66 | else: 67 | symbol_table_string += character 68 | line_len += 1 69 | 70 | horizontal_bar = "|" + "-" * (max_line_len) + "|\n" 71 | symbol_table_string = horizontal_bar + symbol_table_string + horizontal_bar 72 | 73 | return symbol_table_string 74 | 75 | def entry(self, value, type, typedata, dependency="", scope=""): 76 | """ 77 | Returns id in symbol table after making an entry 78 | 79 | Params 80 | ====== 81 | value (string) = Value to be stored in symbol table (identifier/constant) 82 | type (string) = Datatype of symbol 83 | typedata (string) = Type of data (constant/variable) 84 | dependency (string) = List of token ids of dependent variables 85 | scope (string) = Scope of entry 86 | 87 | Returns 88 | ======= 89 | int: The id of the current entry in symbol table 90 | """ 91 | 92 | self.symbol_table[self.id] = [value, type, typedata, dependency, scope] 93 | self.id += 1 94 | return self.id - 1 95 | 96 | def get_by_id(self, id): 97 | """ 98 | Returns symbol table entry by integer unique id 99 | 100 | Params 101 | ====== 102 | id (id) = Integer unique id of a symbol in the table 103 | 104 | Returns 105 | ======= 106 | list: Table entry 107 | """ 108 | 109 | return self.symbol_table.get(id, [None, None, None, None, None]) 110 | 111 | def get_by_symbol(self, value, id_greater_than=None): 112 | """ 113 | Returns unique id of a given value 114 | 115 | Params 116 | ====== 117 | value (string) = Value to be searched in the symbol table 118 | consider_scope (bool) = Should consider scope or not while getting by symbol 119 | current_scope (string) = If scope is to be considered then which scope is to be searched for 120 | 121 | Returns 122 | ======= 123 | int: The unique id of the entry in symbol table 124 | """ 125 | 126 | id = -1 127 | for ids, value_list in self.symbol_table.items(): 128 | if value_list[0] == value: 129 | if id_greater_than == None: 130 | return ids 131 | else: 132 | if ids < id_greater_than: 133 | continue 134 | else: 135 | return ids 136 | 137 | return id 138 | 139 | def resolve_scope_for_id(self, token, module_name): 140 | min_distance = None 141 | min_id = None 142 | 143 | token_line_num = token.line_num 144 | token_symbol = self.get_by_id(token.val)[0] 145 | 146 | for id_, value_list in self.symbol_table.items(): 147 | if value_list[0] == token_symbol and "-" in value_list[-1]: 148 | ( 149 | scope_start_line_num, 150 | scope_end_line_num, 151 | scope_module_name, 152 | ) = value_list[-1].split("-") 153 | 154 | if scope_module_name != module_name: 155 | continue 156 | 157 | distance_line_num = token_line_num - int(scope_start_line_num) 158 | if distance_line_num < 0: 159 | continue 160 | 161 | if min_distance == None or ( 162 | distance_line_num < min_distance 163 | and token_line_num < int(scope_end_line_num) 164 | ): 165 | min_distance = distance_line_num 166 | min_id = id_ 167 | 168 | return min_id 169 | 170 | def add_dependency(self, var_father_id, var_child_id): 171 | """ 172 | Adds a relation of dependecy beetween two variables 173 | 174 | It is used when the variable is assigned to other varible before it is type had been defined 175 | When the type of the varible is discovered, use the function resolve_dependency to update the child variables 176 | 177 | Params 178 | ====== 179 | var_father_id (int) = ID of parent identifier in SymbolTable 180 | var_child_id (int) = ID of child identifier in SymbolTable 181 | """ 182 | 183 | # Add the variable to list in the expression:: "<-ID>" 184 | self.symbol_table[var_father_id][3] += "-" + str(var_child_id) 185 | 186 | def resolve_dependency(self, tokens, i, var_id): 187 | """ 188 | Resolves the dependency relation between variables 189 | 190 | This is a recursive function, it is used when the parser discovers the type of a varible which has been 191 | assign to another one, then the type of the assigned one dependes on this 192 | 193 | Params 194 | ====== 195 | tokens (list) = List of tokens 196 | i (int) = Current index in token 197 | var_id (int) = ID in Symbol table where the function will look at for child dependencies 198 | 199 | Returns 200 | ======= 201 | bool: Whether it is possible to resolve the dependency or not 202 | """ 203 | # Extract the type of variable and the list of variable which dependies on it 204 | _, type_, _, list_dependency, _ = self.symbol_table[var_id] 205 | 206 | # Nothing to do 207 | if type_ == "var": 208 | return 209 | 210 | # Clear the dependencies 211 | self.symbol_table[var_id][3] = "" 212 | 213 | # Split the list "ID-ID-...-ID" => ['ID', 'ID', ..., 'ID'] 214 | list_dependency = [ 215 | int(child_var_id) 216 | for child_var_id in list_dependency.split("-") 217 | if child_var_id != "" 218 | ] 219 | 220 | is_allowed = True 221 | 222 | # For each child variable assign the new type and check up for its dependencies. 223 | for var_child_id in list_dependency: 224 | 225 | if is_allowed is False: 226 | break 227 | 228 | # Extract the current type of child variable 229 | child_type = self.symbol_table[var_child_id][1] 230 | 231 | # If the type is not defined 232 | if child_type == "declared": 233 | if type_ == "string": 234 | type_ = "char*" 235 | self.symbol_table[var_child_id][1] = type_ 236 | is_allowed = self.resolve_dependency(tokens, i, var_child_id) 237 | 238 | # If the type is defined, it cannot downgrade 239 | elif child_type > type_: 240 | self.symbol_table[var_child_id][1] = type_ 241 | 242 | # If the type is defined and the type of child is greater or equal than the father 243 | elif child_type < type_: 244 | is_allowed = False 245 | 246 | return is_allowed 247 | -------------------------------------------------------------------------------- /simc/token_class.py: -------------------------------------------------------------------------------- 1 | class Token: 2 | """ 3 | Token class is responsible for creating tokens 4 | """ 5 | 6 | def __init__(self, type, val, line_num, scope=None): 7 | """ 8 | Class initializer 9 | 10 | Params 11 | ====== 12 | type (string) = Type of token as string 13 | val (string) = Value stored at token 14 | line_num (int) = Line number 15 | scope (string) = Scope of token 16 | """ 17 | 18 | self.type = type 19 | self.val = val 20 | self.line_num = line_num 21 | 22 | def __str__(self): 23 | """ 24 | String representation of a Token 25 | 26 | Returns 27 | ======= 28 | string: The string representation of Token object, which can be used to print the tokens 29 | """ 30 | 31 | return "Token(%s, %s, %s)" % (self.type, self.val, self.line_num) 32 | 33 | def __eq__(self, other): 34 | """ 35 | Check for equality of tokens 36 | 37 | Returns 38 | ======= 39 | bool: Whether a token object is equal to another or not 40 | """ 41 | 42 | if ( 43 | self.type == other.type 44 | and self.val == other.val 45 | and self.line_num == other.line_num 46 | ): 47 | return True 48 | 49 | return False 50 | --------------------------------------------------------------------------------