From 45bee27824348cb6bdd312526b97af56d7ad3347 Mon Sep 17 00:00:00 2001 From: RedoC-github Date: Fri, 20 Oct 2023 00:11:48 +0900 Subject: [PATCH] misc: prettier --- .clang-format | 2 +- .github/workflows/trunk-check.yaml | 2 +- .github/workflows/ubuntu.yml | 53 +- CONTRIBUTING.md | 29 +- README.md | 20 +- build.sh | 33 +- doc/README.md | 6 +- doc/grammar.md | 110 +- doc/howto.md | 12 +- include/basis.h | 8 +- include/dlfcn.c | 90 +- include/dlfcn.h | 18 +- lib/functions.md | 12 +- lib/library.cpp | 112 +- src/error/signal.h | 333 ++--- src/import_/eexec_.cpp | 61 +- src/import_/eexec_.h | 7 +- src/interpreter.cpp | 93 +- src/parser/parse.cpp | 2007 ++++++++++++++-------------- src/parser/parse.h | 11 +- src/runtime/AST.h | 873 ++++++------ src/type/object.h | 165 +-- src/type/operator.h | 39 +- src/type/variable.h | 504 +++---- 24 files changed, 2247 insertions(+), 2353 deletions(-) diff --git a/.clang-format b/.clang-format index ad95135..9b1fd4a 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ BasedOnStyle: Google -ColumnLimit: 100 +ColumnLimit: 400 --- Language: Cpp DerivePointerAlignment: false diff --git a/.github/workflows/trunk-check.yaml b/.github/workflows/trunk-check.yaml index d740fea..e35b91c 100644 --- a/.github/workflows/trunk-check.yaml +++ b/.github/workflows/trunk-check.yaml @@ -19,4 +19,4 @@ jobs: uses: actions/checkout@v3 - name: Trunk Check - uses: trunk-io/trunk-action@v1 \ No newline at end of file + uses: trunk-io/trunk-action@v1 diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 3bf03b9..410e959 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -9,51 +9,52 @@ name: CI - Ubuntu OS on: push: - branches: [ main, lab ] + branches: [main, lab] pull_request: - branches: [ main, lab ] + branches: [main, lab] + +permissions: read-all jobs: Build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: make - run: mkdir sample/lib; make CI-TEST-Wopslang; + - uses: actions/checkout@v2 + - name: make + run: mkdir sample/lib; make CI-TEST-Wopslang; Fizzbuzz: needs: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: make - run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; - - name: run - run: cd sample; ./Wopslang fizzbuzz.wops debug > out; + - uses: actions/checkout@v2 + - name: make + run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; + - name: run + run: cd sample; ./Wopslang fizzbuzz.wops debug > out; Hailstone_Sequence: needs: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: make - run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; - - name: run - run: cd sample; tree; ./Wopslang hailstone_sequence.wops debug > out; + - uses: actions/checkout@v2 + - name: make + run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; + - name: run + run: cd sample; tree; ./Wopslang hailstone_sequence.wops debug > out; Hello_Wopslang: needs: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: make - run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; - - name: run - run: cd sample; tree; ./Wopslang hello_wopslang.wops debug > out; + - uses: actions/checkout@v2 + - name: make + run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; + - name: run + run: cd sample; tree; ./Wopslang hello_wopslang.wops debug > out; Multiline: needs: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: make - run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; - - name: run - run: cd sample; echo "1" > input; tree; ./Wopslang multiline.wops debug < input > out; - \ No newline at end of file + - uses: actions/checkout@v2 + - name: make + run: mkdir sample/lib; make CI-TEST-Wopslang; mv Wopslang sample/; + - name: run + run: cd sample; echo "1" > input; tree; ./Wopslang multiline.wops debug < input > out; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 71c1bf8..ad5e081 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,14 @@ # :page_with_curl: Contribute Guideline -## :wave: Welcome, new Wopers +## :wave: Welcome, new Wopers First off, thank you for considering contributing to Wopslang. Wopslang could be existed because of many devoted Wopers like you. @@ -30,13 +30,13 @@ If you already have a solution for it, please make a PR. If you already have a solution for it, PR suits you. Code style should satisfy these checklist. -- [ ] [Google C++ Coding Style Guide #General Naming Rules](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules) -- [ ] K&R Indentation Style -- [ ] Use Boilerplate Code : +- [ ] [Google C++ Coding Style Guide #General Naming Rules](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules) +- [ ] K&R Indentation Style +- [ ] Use Boilerplate Code : ```c++ /* - * + * * * * , Wops Team @@ -52,11 +52,12 @@ Code style should satisfy these checklist. ``` All commit messages should satisfy these checklist. + - [ ] Description Starts with Lowercase Character - [ ] No Emoji - [ ] Use Boilerplate Code : -``` +```text : ``` @@ -69,21 +70,21 @@ Also, your PR can be rejected by these reasons: Finally, your PR branch's name should be in one of these forms: - `patch-[username]-[number]` -- *`dev-[username]-[number]`: only for inside Wopers* +- _`dev-[username]-[number]`: only for inside Wopers_ - `docs-[username]-[number]` ### :speech_balloon: Being the Wopslang Manager -Wopslang managers mediate the overheated community, review the issues and pull requests, and lead the development of Wopslang. Of course, this job requires not only deep knowledge of Wopslang, but also conversation skill. Also, Wopslang managers should be in Wops team; Wopslang managers should be inside Wopers. +Wopslang managers mediate the overheated community, review the issues and pull requests, and lead the development of Wopslang. Of course, this job requires not only deep knowledge of Wopslang, but also conversation skill. Also, Wopslang managers should be in Wops team; Wopslang managers should be inside Wopers. We're not recruiting the Wopslang manager for now. #### Wopslang manager list -|Github Username|Slack Username| -|---|---| -|@RedoC-github|@RedoC-github| -|@rdxxer|@codenstory| -|@pokmui|@pokmui| +| Github Username | Slack Username | +| --------------- | -------------- | +| @RedoC-github | @RedoC-github | +| @rdxxer | @codenstory | +| @pokmui | @pokmui | 2023, Wops Team diff --git a/README.md b/README.md index 4f8d9be..d1c48ee 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ func Wopslang = {contributors, { ``` ### `#LanguageForAlgorithm` `#WorkingPseudo` + _**Wopslang**_ is for every computer scientist who needs a **pseudocode-like**, but **working** programming language. _**Simple grammar**_ will highlight your logical ideas. _**Fast-runtime**_ will give you immediate feedback to forward. _Be with our project, using ⭐_ - ## Infomation Version: **Wopslang v0.1 alpha** @@ -54,16 +54,16 @@ Check [howto.md](doc/howto.md) for more detail See [sample folder](./sample) :sparkles: -## Credit +## Credit -|Github Username|Slack Username|Role| -|---|---|---| -|**@RedoC-github**|**@RedoC**|**Lead Programmer of Interpreter**| -|**@pokmui**|**@pokmui**|**Programmer of Interpreter, Admin of Slack**| -|@byunjaewoo|@byunjaewoo|Lead Programmer of Data Structure -|@happybean4|@khanjhy|Planner of Grammar| -|**@rdxxer**|**@codenstory**|**Programmer of Interpreter**| -|@dddddd1234-creator|@dddddd|Lead Programmer of Builtin Function| +| Github Username | Slack Username | Role | +| ------------------- | --------------- | --------------------------------------------- | +| **@RedoC-github** | **@RedoC** | **Lead Programmer of Interpreter** | +| **@pokmui** | **@pokmui** | **Programmer of Interpreter, Admin of Slack** | +| @byunjaewoo | @byunjaewoo | Lead Programmer of Data Structure | +| @happybean4 | @khanjhy | Planner of Grammar | +| **@rdxxer** | **@codenstory** | **Programmer of Interpreter** | +| @dddddd1234-creator | @dddddd | Lead Programmer of Builtin Function | **Bold user** is the Wopslang manager. Special Thanks to @jhhan128 diff --git a/build.sh b/build.sh index 6d486e7..181137f 100644 --- a/build.sh +++ b/build.sh @@ -10,21 +10,20 @@ echo -e "✨ \033[1mWopslang v0.1 alpha Builder\033[m" echo -e "\033[91mWarning: This is alpha version. Some critical issues might be appeared.\033[m" echo -e -n "- make install..." make clean -LOG=`make` -RESULT=`echo $?` +LOG=$(make) +RESULT=$(echo $?) -if [ $RESULT -ne 0 ] -then - echo -e "\033[91mError occured while building Wopslang.\033[m" - echo -e "\033[91m┌─────────────── How to Fix ───────────────┐\033[m" - echo -e "\033[91m│ │\033[m" - echo -e "\033[91m│ 1. Check the error message fix your │\033[m" - echo -e "\033[91m│ environment setting (or installation) │\033[m" - echo -e "\033[91m│ │\033[m" - echo -e "\033[91m│ 2. Ask help to the Wops Community │\033[m" - echo -e "\033[91m│ - github.com/Wopslang/Wops/discussions │\033[m" - echo -e "\033[91m│ │\033[m" - echo -e "\033[91m└──────────────────────────────────────────┘\033[m" -else - echo -e "\033[94mDone! Happy coding with Wopslang :)\033[m" -fi \ No newline at end of file +if [[ ${RESULT} -ne 0 ]]; then + echo -e "\033[91mError occured while building Wopslang.\033[m" + echo -e "\033[91m┌─────────────── How to Fix ───────────────┐\033[m" + echo -e "\033[91m│ │\033[m" + echo -e "\033[91m│ 1. Check the error message fix your │\033[m" + echo -e "\033[91m│ environment setting (or installation) │\033[m" + echo -e "\033[91m│ │\033[m" + echo -e "\033[91m│ 2. Ask help to the Wops Community │\033[m" + echo -e "\033[91m│ - github.com/Wopslang/Wops/discussions │\033[m" + echo -e "\033[91m│ │\033[m" + echo -e "\033[91m└──────────────────────────────────────────┘\033[m" +else + echo -e "\033[94mDone! Happy coding with Wopslang :)\033[m" +fi diff --git a/doc/README.md b/doc/README.md index 9fa7896..aab1a83 100644 --- a/doc/README.md +++ b/doc/README.md @@ -10,14 +10,14 @@ func Documentation = {question, { ## 📜 Language Reference -*[Official Reference for v0.1](grammar.md)* +_[Official Reference for v0.1](grammar.md)_ ## ⚡️ Built-in Function -*[Wopslang Builtin Functions for v0.1](../lib/functions.md)* +_[Wopslang Builtin Functions for v0.1](../lib/functions.md)_ ## 📓 Guidebook -*[How to install and launch Wopslang](howto.md)* +_[How to install and launch Wopslang](howto.md)_ 2023, Wops Team diff --git a/doc/grammar.md b/doc/grammar.md index 5a78ed5..769cdcb 100644 --- a/doc/grammar.md +++ b/doc/grammar.md @@ -1,7 +1,7 @@ @@ -26,7 +26,6 @@ - [Floating-point Literal] - [Rune Literal] - [String Literal] - - [Boolean Literal] - [Types] - [Variables] - [Expressions] @@ -55,7 +54,7 @@ So, make sure to check this page when you updated Wopslang to the newest version > Our language is based on an idea: simple, but powerful. > And because our grammar was also designed with this idea, we developed only the most important expressions. -> However, we know that our standard of *importance* can be different from your standard. +> However, we know that our standard of _importance_ can be different from your standard. > So, please tell us your idea of what to put into Wopslang. > We would love to hear your voice. @@ -88,7 +87,7 @@ digit = "0" ... "9" . ### Comments -Comments can be represented with a form: +Comments can be represented with a form: - comments start with `//` and stop at the end of the line. @@ -110,7 +109,7 @@ out(":(") ### Tokens -Token is the word which can be used in Wopslang. There are four types: *Identifiers, Keywords, Operators, Punctuation, and Literals*. White space, formed from spaces (U+0020), horizontal tabs (U+0009), carriage returns (U+000D), and newlines (U+000A), is ignored except as it separates tokens that would otherwise combine into a single token. +Token is the word which can be used in Wopslang. There are four types: _Identifiers, Keywords, Operators, Punctuation, and Literals_. White space, formed from spaces (U+0020), horizontal tabs (U+0009), carriage returns (U+000D), and newlines (U+000A), is ignored except as it separates tokens that would otherwise combine into a single token. ### Identifiers @@ -140,6 +139,8 @@ break const continue for if in ``` +also, all type identifiers could not be used as identifiers too. + ### Operators and Punctuation The following character sequences represent operators (including assignment operators) and punctuation. @@ -178,7 +179,7 @@ a56bc // (x) ### Boolean Literal -boolean literal is a bit representing boolean constant: *true `1`, and false `0`*. +boolean literal is a bit representing boolean constant: _true `1`, and false `0`_. If you assign other integer on a boolean literal, it will be stored as `1`. Also, the operation between a boolean and an integer is regarded as one between integers but will end up as `1` unless the result is `0`. Any operation between a boolean and a floating-point or assigning a floating-point to a boolean is prohibited (same with string). @@ -213,18 +214,18 @@ A rune literal represents a rune constant, an integer value identifying a Unicod After a backslash, certain single-character escapes represent special values: -|Literal|Unicode|Description| -|---|---|--| -|`\a`|U+0007|alert or bell| -|`\b`|U+0008|backspace| -|`\f`|U+000C|form feed| -|`\n`|U+000A|line feed or newline| -|`\r`|U+0007|carriage return| -|`\t`|U+0007|horizontal tab| -|`\v`|U+0007|vertical tab| -|`\\`|U+0007|backslash| -|`\'`|U+0007|single quote| -|`\"`|U+0007|double quote| +| Literal | Unicode | Description | +| ------- | ------- | -------------------- | +| `\a` | U+0007 | alert or bell | +| `\b` | U+0008 | backspace | +| `\f` | U+000C | form feed | +| `\n` | U+000A | line feed or newline | +| `\r` | U+0007 | carriage return | +| `\t` | U+0007 | horizontal tab | +| `\v` | U+0007 | vertical tab | +| `\\` | U+0007 | backslash | +| `\'` | U+0007 | single quote | +| `\"` | U+0007 | double quote | ```ebnf rune_lit = "'" uni_value "'" . @@ -253,14 +254,14 @@ Example: ## Types A data type or simply type is an attribute which notate a particular kind of data item. -There are four kind of type: *Integer, Floating-Point, String, and Boolean*. And it can be notated with these [predeclared identifiers][Predeclared Identifiers]: +There are four kind of type: _Integer, Floating-Point, String, and Boolean_. And it can be notated with these identifiers: -|Identifier|Matching Type|Description| -|---|---|--| -|`int`|Integer|signed 32-bit integers (-2147483648 ~ 2147483647)| -|`double`|Floating-Point|IEEE-754 64-bit floating-point numbers| -|`string`|String|[same with string literal][String Literal]| -|`bool`|Boolean|[same with boolean literal][Boolean Literal]| +| Identifier | Matching Type | Description | +| ---------- | -------------- | ------------------------------------------------- | +| `int` | Integer | signed 32-bit integers (-2147483648 ~ 2147483647) | +| `double` | Floating-Point | IEEE-754 64-bit floating-point numbers | +| `string` | String | [same with string literal][String Literal] | +| `bool` | Boolean | [same with boolean literal][Boolean Literal] | ```ebnf Type = "int" | "double" | "string" | "bool" . @@ -269,7 +270,7 @@ Type = "int" | "double" | "string" | "bool" . ## Variables A variable is a storage for holding a value. The set of available values is determined by the variable's [type][Types]. -There are two types of variable which can be used in Wopslang v0.1: *constant variable, modifiable variable*. You can declare constant variable as adding const keyword in variable declare expression. Also, you should add initial value to declare constant variable and you won't be able to reassign its value. Interpreter can emit the error if value's representing type doesn't match with variable's type. +There are two types of variable which can be used in Wopslang v0.1: _constant variable, modifiable variable_. You can declare constant variable as adding const keyword in variable declare expression. Also, you should add initial value to declare constant variable and you won't be able to reassign its value. Interpreter can emit the error if value's representing type doesn't match with variable's type. ```go int woo = toint(in()) @@ -307,7 +308,7 @@ out("Hello, ", ### Declarations -A declaration bind *identifiers* and *value* to a constant or [variable][Variables]. +A declaration bind _identifiers_ and _value_ to a constant or [variable][Variables]. Every identifier in a program must be declared, and no identifier may be declared twice in the same block. See [Variables] to get more information. ```ebnf @@ -320,7 +321,7 @@ To find syntax defination of `Expression`, see [Operators] for more. ### Operands -Operands represent the elementary values in an expression. It can be a *literal*, a *function*, or a *variable*. +Operands represent the elementary values in an expression. It can be a _literal_, a _function_, or a _variable_. ```ebnf Operand = Literal | OpndName | "(" Expression ")" . @@ -380,13 +381,13 @@ unary_op = "!" | "+" | "-" . Each operator has a different priority for parsing. For instance, unary operators have the highest priority. -|Priority|Operators| -|--------|---------| -|5|`*`, `/`, `%`| -|4|`+`, `-`| -|3|`==`, `!=`, `<`, `<=`, `>`, `>=`| -|2|`&&`| -|1|`\|\|`| +| Priority | Operators | +| -------- | -------------------------------- | +| 5 | `*`, `/`, `%` | +| 4 | `+`, `-` | +| 3 | `==`, `!=`, `<`, `<=`, `>`, `>=` | +| 2 | `&&` | +| 1 | `\|\|` | The leftmost operator in the same priority has a higher priority. For instance, `a+b-c` is the same with `(a+b)-c`. @@ -394,15 +395,15 @@ Also, the unary operator `+` and `-` is different from the binary operator `+` a ### Arithmetic Operators -|Operator|Matching Literals| -|--------|-----------------| -|`+`|integer, float, string| -|`-`|integer, float| -|`*`|integer, float| -|`/`|integer, float| -|`%`|integer| +| Operator | Matching Literals | +| -------- | ---------------------- | +| `+` | integer, float, string | +| `-` | integer, float | +| `*` | integer, float | +| `/` | integer, float | +| `%` | integer | -If you divide by zero(`A/0` or `A%0`, A:expression), interpreter will emit the error. Also, ***If you divide with integers, the result will be integer, too.*** +If you divide by zero(`A/0` or `A%0`, A:expression), interpreter will emit the error. Also, **_If you divide with integers, the result will be integer, too._** ### Conversion @@ -449,7 +450,7 @@ c = 0.5 - 1.3 ### If Statement -*If* statements specify the conditional execution of more than two branches according to the value of a boolean expression. If value is true, `if` branches will be executed, otherwise, highest `elif` branches will be executed. If every `if` and `elif` branches' expression is false, `else` branch will be executed. +_If_ statements specify the conditional execution of more than two branches according to the value of a boolean expression. If value is true, `if` branches will be executed, otherwise, highest `elif` branches will be executed. If every `if` and `elif` branches' expression is false, `else` branch will be executed. For example: @@ -475,8 +476,8 @@ IfStmt = "if" Expression IfBlock ### For Statement -*For* statement represents repeating execution of a block. -There are two types of for statement: *using a single condition*, and *using an array*. +_For_ statement represents repeating execution of a block. +There are two types of for statement: _using a single condition_, and _using an array_. ```ebnf ForStmt = "for" ( Expression | ForClause ) ForBlock . @@ -484,7 +485,7 @@ ForStmt = "for" ( Expression | ForClause ) ForBlock . #### For statement with single condition -A *for* statement with single condition represents repeating execution of a block as long as a boolean condition evaluates to true. The condition is evaluated before each iteration. +A _for_ statement with single condition represents repeating execution of a block as long as a boolean condition evaluates to true. The condition is evaluated before each iteration. ```go for a % 2 $ @@ -494,12 +495,12 @@ for a % 2 $ #### For statement with for clause -A *for* statement with for clause use special operator `~` to denote a sequence. +A _for_ statement with for clause use special operator `~` to denote a sequence. Special operator (only available in for clause) `~` denotes the arithmetic integer sequence. Basicaly, `a~b` denotes a sequence from `a` to `b-1` with interval `1`. You can also decide specific interval c using `a~b~c`. Operator `~` has the lowest priority in the whole operators. -Finally, *for* statement repeat execution of a block with that sequence. +Finally, _for_ statement repeat execution of a block with that sequence. ```ebnf ForClause = identifiers "in" Expression "~" Expression [ "~" Expression ]. @@ -521,7 +522,7 @@ Output: ### Break and Continue Statement -A *break* or *continue* statement terminates or passes execution of innermost `for` statement. +A _break_ or _continue_ statement terminates or passes execution of innermost `for` statement. ```ebnf BreakStmt = "break" . @@ -535,29 +536,23 @@ ContinueStmt = "continue" . Redirect to [here][ext-link-1] + [Introduction]: #introduction [Notation]: #notation [Source Code Representation]: #source-code-representation [Lexical Elements]: #lexical-elements [Types]: #types [Variables]: #variables -[Containers]: #containers -[Objects]: #objects -[Object Types]: #object-types -[Defining Object]: #defining-object -[Declaring Object]: #declaring-object [Expressions]: #expressions [Statements]: #statements [If Statement]: #if-statement [For Statement]: #for-statement [Builtin functions]: #builtin-functions [Tokens]: #tokens -[Predeclared Identifiers]: #predeclared-identifiers [UTF-8]: https://en.wikipedia.org/wiki/UTF-8 [Characters]: #characters [Letter and Digits]: #letter-and-digits [Comments]: #comments -[Semicolons]: #semicolons [Identifiers]: #identifiers [Keywords]: #keywords [Operators and Punctuation]: #operators-and-punctuation @@ -566,7 +561,6 @@ Redirect to [here][ext-link-1] [Floating-point Literal]: #floating-point-literal [Rune Literal]: #rune-literal [String Literal]: #string-literal -[Boolean Literal]: #boolean-literal [Blocks]: #blocks [Parenthesis]: #parenthesis [Declarations]: #declarations diff --git a/doc/howto.md b/doc/howto.md index 3ff11f0..11cec68 100644 --- a/doc/howto.md +++ b/doc/howto.md @@ -1,7 +1,7 @@ @@ -22,6 +22,7 @@ It is a document containing how to install Wops. If you find an unexpected error sudo apt install g++ sudo apt install make ``` + 3. Clone our project repository ```bash @@ -39,19 +40,22 @@ It is a document containing how to install Wops. If you find an unexpected error Done! ## Windows OS + 1. Install Git Bash + - English: https://git-scm.com/downloads - Korean: https://xangmin.tistory.com/102 2. Install gcc + - English: https://dev.to/gamegods3/how-to-install-gcc-in-windows-10-the-easier-way-422j - - Korean: https://jeunna.tistory.com/entry/Windows-gcc-g-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-MinGW - if "the file has been downloaded incorrectly" error occurred, check [this website](https://suji-choi.tistory.com/34) 3. Install make + - English: https://www.stanleyulili.com/git/how-to-install-git-bash-on-windows/ - Korean: https://ndb796.tistory.com/381 @@ -60,7 +64,7 @@ Done! ```bash git clone https://github.com/Wopslang/Wops.git - ``` + ``` 5. Use this command in Git Bash to build and make executable interpreter: @@ -76,7 +80,7 @@ Done! The library file(`library.so`) should be placed in the path `${ExecutableFilePath}/lib/library.so`. -``` +```bash ./Wopslang .wops ``` diff --git a/include/basis.h b/include/basis.h index 5258114..c252f17 100644 --- a/include/basis.h +++ b/include/basis.h @@ -8,9 +8,9 @@ #ifndef WOPSLANG_BASIS_H #define WOPSLANG_BASIS_H -using Int=signed int; -using Double=double; -using String=std::string; -using Bool=bool; +using Int = signed int; +using Double = double; +using String = std::string; +using Bool = bool; #endif \ No newline at end of file diff --git a/include/dlfcn.c b/include/dlfcn.c index bae3573..b834ae0 100644 --- a/include/dlfcn.c +++ b/include/dlfcn.c @@ -5,73 +5,65 @@ * 2023, Wops Team * */ +#include "dlfcn.h" + #include #include #include #include #include -#include "dlfcn.h" -typedef struct CACHE_DLFCN{ - long lasterror; - const char *err_rutin; +typedef struct CACHE_DLFCN { + long lasterror; + const char* err_rutin; } CACHE_DLFCN; -CACHE_DLFCN cache = { - 0, - NULL -}; +CACHE_DLFCN cache = {0, NULL}; -void *dlopen(const char *filename, int flags) { - HINSTANCE h_instance; +void* dlopen(const char* filename, int flags) { + HINSTANCE h_instance; - h_instance = LoadLibrary(filename); - if (h_instance == NULL) { - cache.lasterror = GetLastError(); - cache.err_rutin = "dlopen"; - } - return h_instance; + h_instance = LoadLibrary(filename); + if (h_instance == NULL) { + cache.lasterror = GetLastError(); + cache.err_rutin = "dlopen"; + } + return h_instance; } -int dlclose(void *handle) { - BOOL status; - int return_code = 0; +int dlclose(void* handle) { + BOOL status; + int return_code = 0; - status = FreeLibrary( - (HINSTANCE)handle - ); + status = FreeLibrary((HINSTANCE)handle); - if (!status) { - cache.lasterror = GetLastError(); - cache.err_rutin = "dlclose"; - return_code = -1; - } + if (!status) { + cache.lasterror = GetLastError(); + cache.err_rutin = "dlclose"; + return_code = -1; + } - return return_code; + return return_code; } -void *dlsym(void *handle, const char *name) { - FARPROC func_ptr; +void* dlsym(void* handle, const char* name) { + FARPROC func_ptr; - func_ptr = GetProcAddress( - (HINSTANCE)handle, - name - ); - - if (!func_ptr) { - cache.lasterror = GetLastError(); - cache.err_rutin = "dlsym"; - } - return (void *)(intptr_t) func_ptr; -} + func_ptr = GetProcAddress((HINSTANCE)handle, name); -const char *dlerror(void) { - static char* errstr; - if (cache.lasterror) { - sprintf(errstr, "%s error (%ld)", cache.err_rutin, cache.lasterror); - return errstr; - } else { - return NULL; - } + if (!func_ptr) { + cache.lasterror = GetLastError(); + cache.err_rutin = "dlsym"; + } + return (void*)(intptr_t)func_ptr; } +const char* dlerror(void) { + static char* errstr; + if (cache.lasterror) { + sprintf(errstr, "%s error (%ld)", cache.err_rutin, cache.lasterror); + return errstr; + } else { + return NULL; + } +} \ No newline at end of file diff --git a/include/dlfcn.h b/include/dlfcn.h index 42e085b..2c0ba95 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -1,6 +1,6 @@ /* * include/dlfcn.h - * Wopslang DLFCN-WIN headerfile + * Wopslang DLFCN-WIN headerfile * * 2023, Wops Team * */ @@ -10,21 +10,21 @@ // Redefine the plag #define RTLD_GLOBAL 0x100 -#define RTLD_LOCAL 0x000 -#define RTLD_LAZY 0x000 -#define RTLD_NOW 0x001 +#define RTLD_LOCAL 0x000 +#define RTLD_LAZY 0x000 +#define RTLD_NOW 0x001 #ifdef __cplusplus extern "C" { #endif - void *dlopen (const char *filename, int flag); - int dlclose (void *handle); - void *dlsym (void *handle, const char *name); - const char *dlerror (void); +void* dlopen(const char* filename, int flag); +int dlclose(void* handle); +void* dlsym(void* handle, const char* name); +const char* dlerror(void); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/lib/functions.md b/lib/functions.md index 70cade4..72e5daf 100644 --- a/lib/functions.md +++ b/lib/functions.md @@ -1,10 +1,10 @@ # 📔 Wopslang Builtin Functions `v0.1` -|Name|Brief Summary|Parameter|Return| -|----|-------------|---------|------| -|out|Standard output|[any s]|none| -|in|Standard input|none|string s| -|toint|Change datatype to integer|any s|int r| -|tostring|Change datatype to string|any s|string r| +| Name | Brief Summary | Parameter | Return | +| -------- | -------------------------- | --------- | -------- | +| out | Standard output | [any s] | none | +| in | Standard input | none | string s | +| toint | Change datatype to integer | any s | int r | +| tostring | Change datatype to string | any s | string r | 2023, Wops Team diff --git a/lib/library.cpp b/lib/library.cpp index 4fd15b3..0acdcb6 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -6,88 +6,86 @@ * --- * We'll put only I/O functions in Ver 0.1 alpha. * Built-in function development is on the way. Stay tuned. - * + * * 2023, Wops Team * */ -#include -#include #include +#include #include +#include + #include "../src/type/object.h" #include "../src/type/variable.h" // Standard I/O Functions /** -* @brief out([any s]): Standard output -* @name out -* @param [any s] -* @return none -*/ + * @brief out([any s]): Standard output + * @name out + * @param [any s] + * @return none + */ extern "C" Object out(Object s) { - for (Object e: s.GetContainer()) { - if (e.GetBase().GetValue() == "") continue; - if (e.dim) - return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; - if (e.GetBase()._t == STRING) - std::cout << e.GetBase().trim(e.GetBase().GetValue()); - else - std::cout << e.GetBase().GetValue(); - } - return {"_", {}, {}, {}, 0, -1, OK}; + for (Object e : s.GetContainer()) { + if (e.GetBase().GetValue() == "") continue; + if (e.dim) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; + if (e.GetBase()._t == STRING) + std::cout << e.GetBase().trim(e.GetBase().GetValue()); + else + std::cout << e.GetBase().GetValue(); + } + return {"_", {}, {}, {}, 0, -1, OK}; } /** -* @brief string in(): Standard input -* @name in -* @param none -* @return string s -* Terminates inputting when space or new line character is entered -*/ -extern "C" Object in(Object _) { - std::string s; std::cin >> s; - return {"_", {}, {}, Variable("_", "\""+s+"\"", STRING), 0, -1, OK}; + * @brief string in(): Standard input + * @name in + * @param none + * @return string s + * Terminates inputting when space or new line character is entered + */ +extern "C" Object in(Object _) { + std::string s; + std::cin >> s; + return {"_", {}, {}, Variable("_", "\"" + s + "\"", STRING), 0, -1, OK}; } // Type Function /** -* @brief int toint(any s): Change datatype to integer -* @name toint -* @param any s -* @return int r -*/ -extern "C" Object toint(Object s) { - if (s.dim != 1 || s.size[0] != 1) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; + * @brief int toint(any s): Change datatype to integer + * @name toint + * @param any s + * @return int r + */ +extern "C" Object toint(Object s) { + if (s.dim != 1 || s.size[0] != 1) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; - Object cont = s.GetContainer()[0]; - if (cont.dim) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; + Object cont = s.GetContainer()[0]; + if (cont.dim) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; - Variable e = cont.GetBase(); - if (e._t == STRING) { - if (e.GetValue()[0] != '"' - || e.GetValue()[e.value.length()-1] != '"' - || e.value.length() < 2 - || std::regex_match(e.trim(e.value), std::regex("/[+-]?\\d+"))) { - return {"_", {}, {}, {}, 0, -1, OBJECT_NOT_MATCHING_DATA}; - } - return {"_", {}, {}, Variable("_", std::to_string(std::stoi(e.trim(e.value)))), 0, -1, OK}; + Variable e = cont.GetBase(); + if (e._t == STRING) { + if (e.GetValue()[0] != '"' || e.GetValue()[e.value.length() - 1] != '"' || e.value.length() < 2 || std::regex_match(e.trim(e.value), std::regex("/[+-]?\\d+"))) { + return {"_", {}, {}, {}, 0, -1, OBJECT_NOT_MATCHING_DATA}; } - return {"_", {}, {}, Variable("_", std::to_string(std::stoi(e.value)), INT), 0, -1, OK}; + return {"_", {}, {}, Variable("_", std::to_string(std::stoi(e.trim(e.value)))), 0, -1, OK}; + } + return {"_", {}, {}, Variable("_", std::to_string(std::stoi(e.value)), INT), 0, -1, OK}; } /** -* @brief string tostring(any s): Change datatype to string -* @name tostring -* @param any s -* @return string r -*/ -extern "C" Object tostring(Object s) { - if (s.dim != 1 || s.size[0] != 1) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; + * @brief string tostring(any s): Change datatype to string + * @name tostring + * @param any s + * @return string r + */ +extern "C" Object tostring(Object s) { + if (s.dim != 1 || s.size[0] != 1) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; - Object cont = s.GetContainer()[0]; - if (cont.dim) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; + Object cont = s.GetContainer()[0]; + if (cont.dim) return {"_", {}, {}, {}, 0, -1, TOO_HIGH_DIMENSION}; - Variable e = cont.GetBase(); - return {"_", {}, {}, Variable("_", "\""+e.GetValue()+"\"", STRING), 0, -1, OK}; + Variable e = cont.GetBase(); + return {"_", {}, {}, Variable("_", "\"" + e.GetValue() + "\"", STRING), 0, -1, OK}; } \ No newline at end of file diff --git a/src/error/signal.h b/src/error/signal.h index 4ab77a3..843486c 100644 --- a/src/error/signal.h +++ b/src/error/signal.h @@ -10,179 +10,182 @@ #include #include + #include "../../include/basis.h" // enum Err // Enumeration of error types enum Err { - OK, - ERROR, - INTERPRETER_CANNOT_OPEN_FILE, - BLANK_VARIABLE_NAME, - BLANK_OPERAND, - BLANK_PARAMETER, - NO_IDENTIFIER_AFTER_OPERATOR, - NO_OPERATION_MATCHING_TYPE, - NO_OPERATION_MATCHING_TYPE_UNARY, - NO_MATCHING_UNARY_OPERATION_FORM, - NO_MATCHING_SYNTAX_EXPRESSION, - NO_MATCHING_SYNTAX_FOR, - NO_MATCHING_SYNTAX_IF, - NO_MATCHING_SYNTAX_ELIF, - NO_MATCHING_STRUCTURE_IF, - NO_MATCHING_SYNTAX_BREAK, - NO_MATCHING_SYNTAX_CONTINUE, - NOT_MATCHING_TYPE_WITH_DEF, - NOT_MATCHING_TYPE_WHEN_COMP, - NOT_CLOSED_BLOCK, - VARIABLE_HAS_NOT_DECLARED, - VARIABLE_REDECLARE, - ERROR_OCCURED_WHILE_CALLING_FUNCTION, - BREAK_CONTINUE_ONLY_ALLOWED_FOR, - ASSIGN_ON_CONSTANT, - ASSIGN_ON_UNKNOWN, - IF_NO_BOOLEAN_CONDITION, - ELIF_NO_BOOLEAN_CONDITION, - FOR_NO_BOOLEAN_CONDITION, - CANNOT_LOAD_LIBRARY, - CANNOT_LOAD_SYMBOL, - OBJECT_OVERFLOW, - OBJECT_NOT_MATCHING_DATA, - OBJECT_WRONG_DIMENSION, - TOO_HIGH_DIMENSION, - UNMATCHED_PARENTHESIS, - OPERATION_ONLY_BINARY, - DIVIDING_WITH_ZERO, + OK, + ERROR, + INTERPRETER_CANNOT_OPEN_FILE, + BLANK_VARIABLE_NAME, + BLANK_OPERAND, + BLANK_PARAMETER, + NO_IDENTIFIER_AFTER_OPERATOR, + NO_OPERATION_MATCHING_TYPE, + NO_OPERATION_MATCHING_TYPE_UNARY, + NO_MATCHING_UNARY_OPERATION_FORM, + NO_MATCHING_SYNTAX_EXPRESSION, + NO_MATCHING_SYNTAX_FOR, + NO_MATCHING_SYNTAX_IF, + NO_MATCHING_SYNTAX_ELIF, + NO_MATCHING_STRUCTURE_IF, + NO_MATCHING_SYNTAX_BREAK, + NO_MATCHING_SYNTAX_CONTINUE, + NOT_MATCHING_TYPE_WITH_DEF, + NOT_MATCHING_TYPE_WHEN_COMP, + NOT_CLOSED_BLOCK, + VARIABLE_HAS_NOT_DECLARED, + VARIABLE_REDECLARE, + ERROR_OCCURED_WHILE_CALLING_FUNCTION, + BREAK_CONTINUE_ONLY_ALLOWED_FOR, + ASSIGN_ON_CONSTANT, + ASSIGN_ON_UNKNOWN, + IF_NO_BOOLEAN_CONDITION, + ELIF_NO_BOOLEAN_CONDITION, + FOR_NO_BOOLEAN_CONDITION, + CANNOT_LOAD_LIBRARY, + CANNOT_LOAD_SYMBOL, + OBJECT_OVERFLOW, + OBJECT_NOT_MATCHING_DATA, + OBJECT_WRONG_DIMENSION, + TOO_HIGH_DIMENSION, + UNMATCHED_PARENTHESIS, + OPERATION_ONLY_BINARY, + DIVIDING_WITH_ZERO, }; class ErrHandler { - public: - void CallErr(int error_pos, Err errtype, std::vector arg) { - std::string errmsg; - switch (errtype) { - case OK: - errmsg = "OKAY"; - break; - case ERROR: - errmsg = "ERROR"; - break; - case INTERPRETER_CANNOT_OPEN_FILE: - errmsg = "From Interpreter: cannot open the file"; - break; - case BLANK_VARIABLE_NAME: - errmsg = "Name of variable should not be blank"; - break; - case BLANK_OPERAND: - errmsg = "Operand should not be blank"; - break; - case BLANK_PARAMETER: - errmsg = "Parameter should not be blank"; - break; - case NO_IDENTIFIER_AFTER_OPERATOR: - errmsg = "Operator " + arg[0] + " cannot appear after identifer"; - break; - case NO_OPERATION_MATCHING_TYPE: - errmsg = "Operator " + arg[0] + " doesn't have operation between " + arg[1] + " and " + arg[2]; - break; - case NO_OPERATION_MATCHING_TYPE_UNARY: - errmsg = "Operator " + arg[0] + " doesn't have operation with " + arg[1]; - break; - case NO_MATCHING_UNARY_OPERATION_FORM: - errmsg = "No matching unary operation form: " + arg[0]; - break; - case NO_MATCHING_SYNTAX_EXPRESSION: - errmsg = "No matching syntax: expression"; - break; - case NO_MATCHING_SYNTAX_FOR: - errmsg = "No matching syntax: for"; - break; - case NO_MATCHING_SYNTAX_IF: - errmsg = "No matching syntax: if"; - break; - case NO_MATCHING_SYNTAX_ELIF: - errmsg = "No matching syntax: elif"; - break; - case NO_MATCHING_STRUCTURE_IF: - errmsg = "No matching structure: if-elif-else"; - break; - case NO_MATCHING_SYNTAX_BREAK: - errmsg = "No matching syntax: break"; - break; - case NO_MATCHING_SYNTAX_CONTINUE: - errmsg = "No matching syntax: continue"; - break; - case NOT_MATCHING_TYPE_WITH_DEF: - errmsg = "Type of " + arg[0] + " doesn't match with definition, " + arg[1]; - break; - case NOT_MATCHING_TYPE_WHEN_COMP: - errmsg = "Comparing with different type variables is not allowed (" + arg[0] + ", " + arg[1] + ")"; - break; - case NOT_CLOSED_BLOCK: - errmsg = "Block is not closed"; - break; - case VARIABLE_HAS_NOT_DECLARED: - errmsg = arg[0] + " has not declared yet"; - break; - case VARIABLE_REDECLARE: - errmsg = "Redeclared variable " + arg[0] + ""; - break; - case ERROR_OCCURED_WHILE_CALLING_FUNCTION: - errmsg = "Error occured while calling " + arg[0] + ""; - break; - case BREAK_CONTINUE_ONLY_ALLOWED_FOR: - errmsg = "break and continue statement only allowed to be used in for statements"; - break; - case ASSIGN_ON_CONSTANT: - errmsg = arg[0] + " is constant"; - break; - case ASSIGN_ON_UNKNOWN: - errmsg = "Variable " + arg[0] + " hasn't declared yet"; - break; - case IF_NO_BOOLEAN_CONDITION: - errmsg = "If Statement allows only boolean condition expression"; - break; - case ELIF_NO_BOOLEAN_CONDITION: - errmsg = "Elif Statement allows only boolean condition expression"; - break; - case FOR_NO_BOOLEAN_CONDITION: - errmsg = "For Statement allows only boolean condition expression"; - break; - case CANNOT_LOAD_LIBRARY: - errmsg = "Cannot load library: " + arg[0] + ""; - break; - case CANNOT_LOAD_SYMBOL: - errmsg = "Cannot load symbol: " + arg[0] + ""; - break; - case OBJECT_OVERFLOW: - errmsg = "Size of object " + arg[0] + " is over than limit"; - break; - case OBJECT_NOT_MATCHING_DATA: - errmsg = "Data of object " + arg[0] + " does not match with declaration"; - break; - case OBJECT_WRONG_DIMENSION: - errmsg = "Object " + arg[0] + " has wrong dimension (Expected " + arg[1] + ", Found " + arg[2] + ")"; - break; - case TOO_HIGH_DIMENSION: - errmsg = arg[0] + " has too high dimension for job (Expected " + arg[1] + ", Found " + arg[2] + ")"; - break; - case UNMATCHED_PARENTHESIS: - errmsg = "Unmatched parenthesis"; - break; - case OPERATION_ONLY_BINARY: - errmsg = "Operation " + arg[0] + " cannot be unary"; - break; - case DIVIDING_WITH_ZERO: - errmsg = "Dividing with zero is not allowed"; - break; - } - if (error_pos != -1) { - std::cout << "\e[31m"<< "line " << error_pos << ": " << errmsg << "\e[m."; - exit(1); - } - std::cout << "\e[31m"<< "runtime: " << errmsg << "\e[m."; - exit(1); - return; + public: + void CallErr(int error_pos, Err errtype, std::vector arg) { + std::string errmsg; + switch (errtype) { + case OK: + errmsg = "OKAY"; + break; + case ERROR: + errmsg = "ERROR"; + break; + case INTERPRETER_CANNOT_OPEN_FILE: + errmsg = "From Interpreter: cannot open the file"; + break; + case BLANK_VARIABLE_NAME: + errmsg = "Name of variable should not be blank"; + break; + case BLANK_OPERAND: + errmsg = "Operand should not be blank"; + break; + case BLANK_PARAMETER: + errmsg = "Parameter should not be blank"; + break; + case NO_IDENTIFIER_AFTER_OPERATOR: + errmsg = "Operator " + arg[0] + " cannot appear after identifer"; + break; + case NO_OPERATION_MATCHING_TYPE: + errmsg = "Operator " + arg[0] + " doesn't have operation between " + arg[1] + " and " + arg[2]; + break; + case NO_OPERATION_MATCHING_TYPE_UNARY: + errmsg = "Operator " + arg[0] + " doesn't have operation with " + arg[1]; + break; + case NO_MATCHING_UNARY_OPERATION_FORM: + errmsg = "No matching unary operation form: " + arg[0]; + break; + case NO_MATCHING_SYNTAX_EXPRESSION: + errmsg = "No matching syntax: expression"; + break; + case NO_MATCHING_SYNTAX_FOR: + errmsg = "No matching syntax: for"; + break; + case NO_MATCHING_SYNTAX_IF: + errmsg = "No matching syntax: if"; + break; + case NO_MATCHING_SYNTAX_ELIF: + errmsg = "No matching syntax: elif"; + break; + case NO_MATCHING_STRUCTURE_IF: + errmsg = "No matching structure: if-elif-else"; + break; + case NO_MATCHING_SYNTAX_BREAK: + errmsg = "No matching syntax: break"; + break; + case NO_MATCHING_SYNTAX_CONTINUE: + errmsg = "No matching syntax: continue"; + break; + case NOT_MATCHING_TYPE_WITH_DEF: + errmsg = "Type of " + arg[0] + " doesn't match with definition, " + arg[1]; + break; + case NOT_MATCHING_TYPE_WHEN_COMP: + errmsg = "Comparing with different type variables is not allowed (" + arg[0] + ", " + arg[1] + ")"; + break; + case NOT_CLOSED_BLOCK: + errmsg = "Block is not closed"; + break; + case VARIABLE_HAS_NOT_DECLARED: + errmsg = arg[0] + " has not declared yet"; + break; + case VARIABLE_REDECLARE: + errmsg = "Redeclared variable " + arg[0] + ""; + break; + case ERROR_OCCURED_WHILE_CALLING_FUNCTION: + errmsg = "Error occured while calling " + arg[0] + ""; + break; + case BREAK_CONTINUE_ONLY_ALLOWED_FOR: + errmsg = "break and continue statement only allowed to be used in for statements"; + break; + case ASSIGN_ON_CONSTANT: + errmsg = arg[0] + " is constant"; + break; + case ASSIGN_ON_UNKNOWN: + errmsg = "Variable " + arg[0] + " hasn't declared yet"; + break; + case IF_NO_BOOLEAN_CONDITION: + errmsg = "If Statement allows only boolean condition expression"; + break; + case ELIF_NO_BOOLEAN_CONDITION: + errmsg = "Elif Statement allows only boolean condition expression"; + break; + case FOR_NO_BOOLEAN_CONDITION: + errmsg = "For Statement allows only boolean condition expression"; + break; + case CANNOT_LOAD_LIBRARY: + errmsg = "Cannot load library: " + arg[0] + ""; + break; + case CANNOT_LOAD_SYMBOL: + errmsg = "Cannot load symbol: " + arg[0] + ""; + break; + case OBJECT_OVERFLOW: + errmsg = "Size of object " + arg[0] + " is over than limit"; + break; + case OBJECT_NOT_MATCHING_DATA: + errmsg = "Data of object " + arg[0] + " does not match with declaration"; + break; + case OBJECT_WRONG_DIMENSION: + errmsg = "Object " + arg[0] + " has wrong dimension (Expected " + arg[1] + ", Found " + arg[2] + ")"; + break; + case TOO_HIGH_DIMENSION: + errmsg = arg[0] + " has too high dimension for job (Expected " + arg[1] + ", Found " + arg[2] + ")"; + break; + case UNMATCHED_PARENTHESIS: + errmsg = "Unmatched parenthesis"; + break; + case OPERATION_ONLY_BINARY: + errmsg = "Operation " + arg[0] + " cannot be unary"; + break; + case DIVIDING_WITH_ZERO: + errmsg = "Dividing with zero is not allowed"; + break; + } + if (error_pos != -1) { + std::cout << "\e[31m" + << "line " << error_pos << ": " << errmsg << "\e[m."; + exit(1); } + std::cout << "\e[31m" + << "runtime: " << errmsg << "\e[m."; + exit(1); + return; + } }; -#endif +#endif \ No newline at end of file diff --git a/src/import_/eexec_.cpp b/src/import_/eexec_.cpp index 5fdcdf8..ed132e1 100644 --- a/src/import_/eexec_.cpp +++ b/src/import_/eexec_.cpp @@ -5,40 +5,39 @@ * 2023, Wops Team * */ - #include "eexec_.h" // Object EExecFunc(std::string func, Object argv) // Calls a function with argv as a parameter and func as a name. Object EExecFunc(std::string func, Object argv) { - // EMPTY VARIABLE - Object null("_", {}, {}, Variable("_", "", INT), 0); - - void* handle = dlopen("lib/library.so", RTLD_LAZY); - - if (!handle) { - ErrHandler().CallErr(-1, CANNOT_LOAD_LIBRARY, {std::string(dlerror())}); - null.errvalue = CANNOT_LOAD_LIBRARY; - return null; - } - - // function pointer - typedef Object (*t)(Object); - - // reset errors - dlerror(); - - std::string exfunc(func); - t fptr = (t) dlsym(handle, exfunc.c_str()); - const char *dlsym_error = dlerror(); - if (dlsym_error) { - ErrHandler().CallErr(-1, CANNOT_LOAD_SYMBOL, {func}); - dlclose(handle); - null.errvalue = CANNOT_LOAD_SYMBOL; - return null; - } - - Object ret = fptr(argv); + // EMPTY VARIABLE + Object null("_", {}, {}, Variable("_", "", INT), 0); + + void* handle = dlopen("lib/library.so", RTLD_LAZY); + + if (!handle) { + ErrHandler().CallErr(-1, CANNOT_LOAD_LIBRARY, {std::string(dlerror())}); + null.errvalue = CANNOT_LOAD_LIBRARY; + return null; + } + + // function pointer + typedef Object (*t)(Object); + + // reset errors + dlerror(); + + std::string exfunc(func); + t fptr = (t)dlsym(handle, exfunc.c_str()); + const char* dlsym_error = dlerror(); + if (dlsym_error) { + ErrHandler().CallErr(-1, CANNOT_LOAD_SYMBOL, {func}); dlclose(handle); - return ret; -} + null.errvalue = CANNOT_LOAD_SYMBOL; + return null; + } + + Object ret = fptr(argv); + dlclose(handle); + return ret; +} \ No newline at end of file diff --git a/src/import_/eexec_.h b/src/import_/eexec_.h index 95a600b..f48b9ca 100644 --- a/src/import_/eexec_.h +++ b/src/import_/eexec_.h @@ -13,9 +13,10 @@ #include #include -#include "../type/variable.h" -#include "../type/object.h" + #include "../error/signal.h" +#include "../type/object.h" +#include "../type/variable.h" #ifndef WOPS_EEXEC_H #define WOPS_EEXEC_H @@ -26,4 +27,4 @@ Calls a function with argv as a parameter and func as a name. */ Object EExecFunc(std::string func, Object argv); -#endif +#endif \ No newline at end of file diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 2c21c12..c44b308 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -6,51 +6,56 @@ * * */ -#include #include -#include "runtime/AST.h" +#include + #include "parser/parse.h" +#include "runtime/AST.h" + +int main(int argc, char** argv) { + std::cout << "\e[31m" + << "Warning: This is alpha version. Some critical issues might be appeared." + << "\e[m\n"; + if (argc == 2 || (argc == 3 && String(argv[2]) == "debug") || (argc == 3 && String(argv[2]) == "check")) { + std::ifstream handler(String(argv[1]).data()); + if (!handler.is_open()) ErrHandler().CallErr(-1, INTERPRETER_CANNOT_OPEN_FILE, {}); + + String codeline; + std::vector code; -int main(int argc, char **argv) { - std::cout << "\e[31m" << "Warning: This is alpha version. Some critical issues might be appeared." << "\e[m\n"; - if (argc == 2 || (argc == 3 && String(argv[2]) == "debug") || (argc == 3 && String(argv[2]) == "check")) { - std::ifstream handler(String(argv[1]).data()); - if (!handler.is_open()) - ErrHandler().CallErr(-1, INTERPRETER_CANNOT_OPEN_FILE, {}); - - String codeline; - std::vector code; - - while (std::getline(handler, codeline)) { - code.push_back(codeline); - } - - handler.close(); - - // interpret - std::vector stor; - std::vector Token_storage; - std::vector> token_table; - - for (String s: code) token_table.push_back(GetTokenTable(s)); - stor.push_back(Storage()); - AST main(Main, {}, {}, 1); - - if (argc == 3 && String(argv[2]) == "debug") { - std::clock_t end, start = clock(); - Parse(main, token_table, 0, 0, Token_storage); - main.Execute(stor); - end = clock(); - std::cout << "\n=== DEBUG ===\n\e[32m" << "Running Time(ms): " << (double)(end-start) * 1000 / CLOCKS_PER_SEC << "\e[m\n"; - return 0; - } - if (argc == 3 && String(argv[2]) == "check") { - Parse(main, token_table, 0, 0, Token_storage); - return 0; - } - Parse(main, token_table, 0, 0, Token_storage); - main.Execute(stor); - } else { - std::cout << "\e[93m" << "Incorrect command structure. Use command 'Wopslang '" << "\e[m\n"; + while (std::getline(handler, codeline)) { + code.push_back(codeline); + } + + handler.close(); + + // interpret + std::vector stor; + std::vector Token_storage; + std::vector> token_table; + + for (String s : code) token_table.push_back(GetTokenTable(s)); + stor.push_back(Storage()); + AST main(Main, {}, {}, 1); + + if (argc == 3 && String(argv[2]) == "debug") { + std::clock_t end, start = clock(); + Parse(main, token_table, 0, 0, Token_storage); + main.Execute(stor); + end = clock(); + std::cout << "\n=== DEBUG ===\n\e[32m" + << "Running Time(ms): " << (double)(end - start) * 1000 / CLOCKS_PER_SEC << "\e[m\n"; + return 0; + } + if (argc == 3 && String(argv[2]) == "check") { + Parse(main, token_table, 0, 0, Token_storage); + return 0; } -} + Parse(main, token_table, 0, 0, Token_storage); + main.Execute(stor); + } else { + std::cout << "\e[93m" + << "Incorrect command structure. Use command 'Wopslang '" + << "\e[m\n"; + } +} \ No newline at end of file diff --git a/src/parser/parse.cpp b/src/parser/parse.cpp index a65f3b0..9aeaef2 100644 --- a/src/parser/parse.cpp +++ b/src/parser/parse.cpp @@ -12,16 +12,12 @@ std::vector oprs{ '+', '-', '*', '/', '%', '=', '>', '<', '!', '&', '|', '(', ')', '[', ']', ';', ',', '?', '$', '~', }; -std::vector operators{ - "+", "-", "*", "/", "%", "=", "==", "!=", ">", "<", ">=", "<=", "!", "&&", "||", "//" -}; +std::vector operators{"+", "-", "*", "/", "%", "=", "==", "!=", ">", "<", ">=", "<=", "!", "&&", "||", "//"}; -std::vector> runes{ - {"\a", "a"}, {"\b", "b"}, {"\f", "f"}, {"\n", "n"}, {"\r", "r"}, {"\t", "t"}, {"\v", "v"}, {"\\", "\\"}, {"\'", "'"}, {"\"", "\""} -}; +std::vector> runes{{"\a", "a"}, {"\b", "b"}, {"\f", "f"}, {"\n", "n"}, {"\r", "r"}, {"\t", "t"}, {"\v", "v"}, {"\\", "\\"}, {"\'", "'"}, {"\"", "\""}}; // TODO: improve library system -std::vector funcs {"in", "out", "tostring", "toint"}; +std::vector funcs{"in", "out", "tostring", "toint"}; // TODO: develop this function // Expr ParseExpr(std::vector tokens, int parsing_line) @@ -34,1091 +30,1048 @@ std::vector funcs {"in", "out", "tostring", "toint"}; // Deprecated Expr ParseExpr(std::vector tokens, int parsing_line) { - Expr head({0,0,0}, - Object("_", {}, {}, Variable("_", "", OPERATOR), 0, parsing_line, OK), parsing_line); - - if (tokens.size() == 0) ErrHandler().CallErr(parsing_line, BLANK_OPERAND, {}); - - if (tokens.size() >= 3 && std::find(funcs.begin(), funcs.end(), tokens[0]) != funcs.end() && - tokens[1] == "(" && tokens[tokens.size()-1] == ")") { - int level = 0; bool isSuitable = 1; - for (int idx = 1; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (token == "(") level++; - else if (token == ")") level--; - else if (!level) isSuitable = 0; - } - if (isSuitable) { - head = Expr({0,0,1}, Object("_", {}, {}, Variable("_", tokens[0], OPERATOR), 0, parsing_line, OK), parsing_line); - std::vector parameter; - for (int idx = 2; idx < tokens.size()-1; idx++) { - if (tokens[idx] == ",") { - if (parameter.size() == 0) ErrHandler().CallErr(parsing_line, BLANK_PARAMETER, {}); - head.AddChild(ParseExpr(parameter, parsing_line)); - parameter.clear(); - continue; - } - parameter.push_back(tokens[idx]); - } - if (parameter.size() != 0) - head.AddChild(ParseExpr(parameter, parsing_line)); - return head; - } - } + Expr head({0, 0, 0}, Object("_", {}, {}, Variable("_", "", OPERATOR), 0, parsing_line, OK), parsing_line); - if (tokens[0] == "(" && tokens[tokens.size()-1] == ")") { - int level = 0; bool isSuitable = 1; - for (int idx = 0; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (token == "(") level++; - else if (token == ")") level--; - else if (!level) isSuitable = 0; - } - if (isSuitable) - tokens = std::vector(tokens.begin()+1, tokens.end()-1); - } + if (tokens.size() == 0) ErrHandler().CallErr(parsing_line, BLANK_OPERAND, {}); - if (tokens.size() == 1) { - if (std::regex_match(tokens[0], std::regex("[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], INT), 0, parsing_line), parsing_line); - } else if (std::regex_match(tokens[0], std::regex("[0-9]+.[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], DOUBLE), 0, parsing_line), parsing_line); - } else if (tokens[0][0] == '\"' && tokens[0][tokens[0].length()-1] == '\"') { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], STRING), 0, parsing_line), parsing_line); - } else { - head = Expr({0, 1, 0}, Object("_", {}, {}, Variable("_", tokens[0], OPERATOR), 0, parsing_line), parsing_line); + if (tokens.size() >= 3 && std::find(funcs.begin(), funcs.end(), tokens[0]) != funcs.end() && tokens[1] == "(" && tokens[tokens.size() - 1] == ")") { + int level = 0; + bool isSuitable = 1; + for (int idx = 1; idx < tokens.size(); idx++) { + String token = tokens[idx]; + if (token == "(") + level++; + else if (token == ")") + level--; + else if (!level) + isSuitable = 0; + } + if (isSuitable) { + head = Expr({0, 0, 1}, Object("_", {}, {}, Variable("_", tokens[0], OPERATOR), 0, parsing_line, OK), parsing_line); + std::vector parameter; + for (int idx = 2; idx < tokens.size() - 1; idx++) { + if (tokens[idx] == ",") { + if (parameter.size() == 0) ErrHandler().CallErr(parsing_line, BLANK_PARAMETER, {}); + head.AddChild(ParseExpr(parameter, parsing_line)); + parameter.clear(); + continue; } - return head; + parameter.push_back(tokens[idx]); + } + if (parameter.size() != 0) head.AddChild(ParseExpr(parameter, parsing_line)); + return head; } + } - std::vector isTarget(tokens.size(), 0); + if (tokens[0] == "(" && tokens[tokens.size() - 1] == ")") { int level = 0; + bool isSuitable = 1; for (int idx = 0; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (token == "(") level++; - else if (token == ")") level--; - else if (!level) isTarget[idx] = 1; + String token = tokens[idx]; + if (token == "(") + level++; + else if (token == ")") + level--; + else if (!level) + isSuitable = 0; } - if (level != 0) ErrHandler().CallErr(parsing_line, UNMATCHED_PARENTHESIS, {}); - - // priority 1 - for (int idx = 0; idx < tokens.size(); idx++) { - if (!isTarget[idx]) continue; - String token = tokens[idx]; - if (token == "||") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"||"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "||", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } + if (isSuitable) tokens = std::vector(tokens.begin() + 1, tokens.end() - 1); + } + + if (tokens.size() == 1) { + if (std::regex_match(tokens[0], std::regex("[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], INT), 0, parsing_line), parsing_line); + } else if (std::regex_match(tokens[0], std::regex("[0-9]+.[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], DOUBLE), 0, parsing_line), parsing_line); + } else if (tokens[0][0] == '\"' && tokens[0][tokens[0].length() - 1] == '\"') { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[0], STRING), 0, parsing_line), parsing_line); + } else { + head = Expr({0, 1, 0}, Object("_", {}, {}, Variable("_", tokens[0], OPERATOR), 0, parsing_line), parsing_line); } - - // priority 2 - for (int idx = 0; idx < tokens.size(); idx++) { - if (!isTarget[idx]) continue; - String token = tokens[idx]; - if (token == "&&") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"&&"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "&&", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } + return head; + } + + std::vector isTarget(tokens.size(), 0); + int level = 0; + for (int idx = 0; idx < tokens.size(); idx++) { + String token = tokens[idx]; + if (token == "(") + level++; + else if (token == ")") + level--; + else if (!level) + isTarget[idx] = 1; + } + if (level != 0) ErrHandler().CallErr(parsing_line, UNMATCHED_PARENTHESIS, {}); + + // priority 1 + for (int idx = 0; idx < tokens.size(); idx++) { + if (!isTarget[idx]) continue; + String token = tokens[idx]; + if (token == "||") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"||"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "||", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; } - - // priority 3 - for (int idx = 0; idx < tokens.size(); idx++) { - if (!isTarget[idx]) continue; - String token = tokens[idx]; - if (token == "==") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"=="}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "==", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "!=") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"!="}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "!=", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "<") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"<"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "<", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "<=") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"<="}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "<=", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == ">") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {">"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", ">", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == ">=") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {">="}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", ">=", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - } - - // priority 4 - for (int idx = 0; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (!isTarget[idx]) continue; - if (token == "+") { - if (idx != 0 && std::find(operators.begin(), operators.end(), tokens[idx - 1]) != operators.end()) - continue; - if (idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"+"}); - if (idx == 0) { - if (tokens.size() != 2) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"+"}); - if (std::regex_match(tokens[1], std::regex("[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[1], INT), 0, parsing_line), parsing_line); - } else if (std::regex_match(tokens[1], std::regex("[0-9]+.[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[1], DOUBLE), 0, parsing_line), parsing_line); - } else if (tokens[1][0] == '\"' && tokens[1][tokens[1].length()-1] == '\"') { - ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"+", "string"}); - } else { - ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"+", "lvalue"}); - } - return head; - } - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "+", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "-") { - if (idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"-"}); - if (std::find(operators.begin(), operators.end(), tokens[idx - 1]) != operators.end()) - continue; - if (idx == 0) { - if (tokens.size() != 2) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"-"}); - if (std::regex_match(tokens[1], std::regex("[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", "-" + tokens[1], INT), 0, parsing_line), parsing_line); - } else if (std::regex_match(tokens[1], std::regex("[0-9]+.[0-9]+"))) { - head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", "-" + tokens[1], DOUBLE), 0, parsing_line), parsing_line); - } else if (tokens[1][0] == '\"' && tokens[1][tokens[1].length()-1] == '\"') { - ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"string"}); - } else { - ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"lvalue"}); - } - return head; - } - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "-", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } + } + + // priority 2 + for (int idx = 0; idx < tokens.size(); idx++) { + if (!isTarget[idx]) continue; + String token = tokens[idx]; + if (token == "&&") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"&&"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "&&", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; } - - // priority 5 - for (int idx = 0; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (!isTarget[idx]) continue; - if (token == "*") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"*"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "*", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "/") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"/"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "/", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; - } - if (token == "%") { - if (idx == 0 || idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"%"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "%", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr(std::vector(tokens.begin(), tokens.begin()+idx), parsing_line), - ParseExpr(std::vector(tokens.begin()+idx+1, tokens.end()), parsing_line) - }); - return head; + } + + // priority 3 + for (int idx = 0; idx < tokens.size(); idx++) { + if (!isTarget[idx]) continue; + String token = tokens[idx]; + if (token == "==") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"=="}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "==", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == "!=") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"!="}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "!=", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == "<") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"<"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "<", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == "<=") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"<="}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "<=", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == ">") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {">"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", ">", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == ">=") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {">="}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", ">=", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + } + + // priority 4 + for (int idx = 0; idx < tokens.size(); idx++) { + String token = tokens[idx]; + if (!isTarget[idx]) continue; + if (token == "+") { + if (idx != 0 && std::find(operators.begin(), operators.end(), tokens[idx - 1]) != operators.end()) continue; + if (idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"+"}); + if (idx == 0) { + if (tokens.size() != 2) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"+"}); + if (std::regex_match(tokens[1], std::regex("[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[1], INT), 0, parsing_line), parsing_line); + } else if (std::regex_match(tokens[1], std::regex("[0-9]+.[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", tokens[1], DOUBLE), 0, parsing_line), parsing_line); + } else if (tokens[1][0] == '\"' && tokens[1][tokens[1].length() - 1] == '\"') { + ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"+", "string"}); + } else { + ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"+", "lvalue"}); } + return head; + } + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "+", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; } - - // priority 6 - for (int idx = 0; idx < tokens.size(); idx++) { - String token = tokens[idx]; - if (!isTarget[idx]) continue; - if (token == "!") { - if (idx == tokens.size()-1) ErrHandler().CallErr(parsing_line, NO_IDENTIFIER_AFTER_OPERATOR, {"!"}); - head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "!", OPERATOR), 0, parsing_line), parsing_line); - head.SetChildren({ - ParseExpr({tokens[idx+1]}, parsing_line) - }); - return head; + if (token == "-") { + if (idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, OPERATION_ONLY_BINARY, {"-"}); + if (std::find(operators.begin(), operators.end(), tokens[idx - 1]) != operators.end()) continue; + if (idx == 0) { + if (tokens.size() != 2) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"-"}); + if (std::regex_match(tokens[1], std::regex("[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", "-" + tokens[1], INT), 0, parsing_line), parsing_line); + } else if (std::regex_match(tokens[1], std::regex("[0-9]+.[0-9]+"))) { + head = Expr({1, 0, 0}, Object("_", {}, {}, Variable("_", "-" + tokens[1], DOUBLE), 0, parsing_line), parsing_line); + } else if (tokens[1][0] == '\"' && tokens[1][tokens[1].length() - 1] == '\"') { + ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"string"}); + } else { + ErrHandler().CallErr(parsing_line, NO_OPERATION_MATCHING_TYPE_UNARY, {"lvalue"}); } + return head; + } + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "-", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + } + + // priority 5 + for (int idx = 0; idx < tokens.size(); idx++) { + String token = tokens[idx]; + if (!isTarget[idx]) continue; + if (token == "*") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"*"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "*", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == "/") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"/"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "/", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + if (token == "%") { + if (idx == 0 || idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_UNARY_OPERATION_FORM, {"%"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "%", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr(std::vector(tokens.begin(), tokens.begin() + idx), parsing_line), ParseExpr(std::vector(tokens.begin() + idx + 1, tokens.end()), parsing_line)}); + return head; + } + } + + // priority 6 + for (int idx = 0; idx < tokens.size(); idx++) { + String token = tokens[idx]; + if (!isTarget[idx]) continue; + if (token == "!") { + if (idx == tokens.size() - 1) ErrHandler().CallErr(parsing_line, NO_IDENTIFIER_AFTER_OPERATOR, {"!"}); + head = Expr({0, 0, 0}, Object("_", {}, {}, Variable("_", "!", OPERATOR), 0, parsing_line), parsing_line); + head.SetChildren({ParseExpr({tokens[idx + 1]}, parsing_line)}); + return head; } + } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); } // std::vector GetTokenTable(String code) // get token table from the string code (a single code line) std::vector GetTokenTable(String code) { - bool is_searching_string = false; - bool is_searching_blank = false; - std::vector token_table; - for (int idx = 0; idx < code.length(); idx++) { - if (code[idx] == ' ' && !is_searching_string) { - if (is_searching_blank) { - code.erase(code.begin()+idx); idx--; - continue; - } - is_searching_blank = true; + bool is_searching_string = false; + bool is_searching_blank = false; + std::vector token_table; + for (int idx = 0; idx < code.length(); idx++) { + if (code[idx] == ' ' && !is_searching_string) { + if (is_searching_blank) { + code.erase(code.begin() + idx); + idx--; + continue; + } + is_searching_blank = true; + + String token; + token.resize(idx); + + if (idx != 0) { + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); + } + + code.erase(0, idx + 1); + idx = -1; + continue; + } else + is_searching_blank = false; + if (code[idx] == '"') { + is_searching_string = !(is_searching_string); + if (!is_searching_string) { + String token; + token.resize(idx + 1); + std::copy(code.begin(), code.begin() + idx + 1, token.begin()); + + // rune exception + for (std::pair rune : runes) { + while (token.find("\\" + rune.second) != String::npos) { + token.replace(token.find("\\" + rune.second), 2, rune.first); + } + } + token_table.push_back(token); - String token; token.resize(idx); + code.erase(0, idx + 1); + idx = -1; + } + continue; + } + if (std::find(oprs.begin(), oprs.end(), code[idx]) != oprs.end() && !is_searching_string) { + bool alreadyChecked = false; + switch (code[idx]) { + case '=': + case '!': + case '<': + case '>': { + if (code.length() > idx + 1 && code[idx + 1] == '=') { + String token; + token.resize(idx); if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); } - code.erase(0, idx+1); + token.resize(2); + std::copy(code.begin() + idx, code.begin() + idx + 2, token.begin()); + token_table.push_back(token); + + code.erase(0, idx + 2); idx = -1; - continue; - } else is_searching_blank = false; - if (code[idx] == '"') { - is_searching_string = !(is_searching_string); - if (!is_searching_string) { - String token; token.resize(idx+1); - std::copy(code.begin(), code.begin()+idx+1, token.begin()); - - // rune exception - for (std::pair rune: runes) { - while (token.find("\\" + rune.second) != String::npos) { - token.replace(token.find("\\" + rune.second), 2, rune.first); - } - } - token_table.push_back(token); + alreadyChecked = true; + } + break; + } + case '&': { + if (code.length() > idx + 1 && code[idx + 1] == '&') { + String token; + token.resize(idx); - code.erase(0, idx+1); - idx = -1; + if (idx != 0) { + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); } - continue; + + token.resize(2); + std::copy(code.begin() + idx, code.begin() + idx + 2, token.begin()); + token_table.push_back(token); + + code.erase(0, idx + 2); + idx = -1; + alreadyChecked = true; + } + break; } - if (std::find(oprs.begin(), oprs.end(), code[idx]) != oprs.end() && !is_searching_string) { - bool alreadyChecked = false; - switch (code[idx]) { - case '=': - case '!': - case '<': - case '>': { - if (code.length() > idx+1 && code[idx+1] == '=') { - String token; token.resize(idx); - - if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); - } - - token.resize(2); std::copy(code.begin()+idx, code.begin()+idx+2, token.begin()); - token_table.push_back(token); - - code.erase(0, idx+2); - idx = -1; - alreadyChecked = true; - } - break; - } - case '&': { - if (code.length() > idx+1 && code[idx+1] == '&') { - String token; token.resize(idx); - - if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); - } - - token.resize(2); std::copy(code.begin()+idx, code.begin()+idx+2, token.begin()); - token_table.push_back(token); - - code.erase(0, idx+2); - idx = -1; - alreadyChecked = true; - } - break; - } - case '|': { - if (code.length() > idx+1 && code[idx+1] == '|') { - String token; token.resize(idx); - - if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); - } - - token.resize(2); std::copy(code.begin()+idx, code.begin()+idx+2, token.begin()); - token_table.push_back(token); - - code.erase(0, idx+2); - idx = -1; - alreadyChecked = true; - } - break; - } - case '/': { - if (code.length() > idx+1 && code[idx+1] == '/') { - String token; token.resize(idx); - - if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); - } - - token.resize(2); std::copy(code.begin()+idx, code.begin()+idx+2, token.begin()); - token_table.push_back(token); - - code.erase(0, idx+2); - idx = -1; - alreadyChecked = true; - } - break; - } + case '|': { + if (code.length() > idx + 1 && code[idx + 1] == '|') { + String token; + token.resize(idx); + + if (idx != 0) { + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); } - if (alreadyChecked) continue; - - String token; token.resize(idx); + + token.resize(2); + std::copy(code.begin() + idx, code.begin() + idx + 2, token.begin()); + token_table.push_back(token); + + code.erase(0, idx + 2); + idx = -1; + alreadyChecked = true; + } + break; + } + case '/': { + if (code.length() > idx + 1 && code[idx + 1] == '/') { + String token; + token.resize(idx); if (idx != 0) { - std::copy(code.begin(), code.begin()+idx, token.begin()); - token_table.push_back(token); + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); } - - token = code[idx]; + + token.resize(2); + std::copy(code.begin() + idx, code.begin() + idx + 2, token.begin()); token_table.push_back(token); - - code.erase(0, idx+1); + + code.erase(0, idx + 2); idx = -1; - continue; + alreadyChecked = true; + } + break; } + } + if (alreadyChecked) continue; + + String token; + token.resize(idx); + + if (idx != 0) { + std::copy(code.begin(), code.begin() + idx, token.begin()); + token_table.push_back(token); + } + + token = code[idx]; + token_table.push_back(token); + + code.erase(0, idx + 1); + idx = -1; + continue; } - if (code.length()) token_table.push_back(code); - return token_table; + } + if (code.length()) token_table.push_back(code); + return token_table; } // int Parse(AST& head, std::vector> Token_table, int parse_start, int arg_idx, std::vector& token_storage) // ** return value is a pair of the end of line of parsing block and parsing index ** std::pair Parse(AST& head, std::vector> Token_table, int parse_start, int arg_idx, std::vector& token_storage) { - int parsing_line = head.codeline; // base parsing line = 1 - StmtType prev_stmt = Main; - for (; parsing_line <= Token_table.size(); parsing_line++) { - std::vector token_table = Token_table[parsing_line-1]; + int parsing_line = head.codeline; // base parsing line = 1 + StmtType prev_stmt = Main; + for (; parsing_line <= Token_table.size(); parsing_line++) { + std::vector token_table = Token_table[parsing_line - 1]; + + for (int idx = parse_start; idx < token_table.size(); idx++) { + if (token_table[idx] == "//") break; + if (token_table[idx] == "(") { + // BracketBlock is only for adding bracket-inside tokens into token_table. + // Thus, bracket_block isn't added in AST + AST bracket_block(BracketBlock, {}, {}, parsing_line); + token_storage.push_back("("); + + std::pair res = Parse(bracket_block, Token_table, idx + 1, 0, token_storage); + + parsing_line = res.first; + idx = res.second; + token_table = Token_table[parsing_line - 1]; + continue; + } + if (token_table[idx] == ")") { + token_storage.push_back(")"); + return {parsing_line, idx}; + } + switch (head.GetStmt()) { + case Main: { + // if-family statement + if (token_table[idx] == "if") { + AST if_block(IfStmt, {}, {}, parsing_line); + std::pair res = Parse(if_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(if_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = IfStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } - for (int idx = parse_start; idx < token_table.size(); idx++) { - if (token_table[idx] == "//") break; - if (token_table[idx] == "(") { - // BracketBlock is only for adding bracket-inside tokens into token_table. - // Thus, bracket_block isn't added in AST - AST bracket_block(BracketBlock, {}, {}, parsing_line); - token_storage.push_back("("); + if (token_table[idx] == "?") { + if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { + if (token_storage.empty()) { // else + AST else_block(ElseStmt, {}, {}, parsing_line); + std::pair res = Parse(else_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(else_block); - std::pair res = Parse(bracket_block, Token_table, idx+1, 0, token_storage); + parsing_line = res.first; + idx = res.second; + prev_stmt = ElseStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } else { // elif + AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + token_storage = {}; + std::pair res = Parse(elif_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(elif_block); parsing_line = res.first; idx = res.second; - token_table = Token_table[parsing_line-1]; + prev_stmt = ElifStmt; + token_storage = {}; // if not need -> remove + token_table = Token_table[parsing_line - 1]; continue; + } + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + } + + // for statement + if (token_table[idx] == "for") { + AST for_block(ForStmt, {}, {}, parsing_line); + std::pair res = Parse(for_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(for_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ForStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + + if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + + if (token_table[idx] == "=") { + if (token_storage.size() == 1) { // assignment + AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(assignment, Token_table, idx + 1, 1, token_storage); + head.AddChild(assignment); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; } - if (token_table[idx] == ")") { - token_storage.push_back(")"); - return {parsing_line, idx}; + if (token_storage.size() == 2) { // declaration + AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(var_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(var_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; } - switch (head.GetStmt()) { - case Main: { - // if-family statement - if (token_table[idx] == "if") { - AST if_block(IfStmt, {}, {}, parsing_line); - std::pair res = Parse(if_block, Token_table, idx+1, 1, token_storage); - head.AddChild(if_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = IfStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "?") { - if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { - if (token_storage.empty()) { // else - AST else_block(ElseStmt, {}, {}, parsing_line); - std::pair res = Parse(else_block, Token_table, idx+1, 0, token_storage); - head.AddChild(else_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElseStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } else { // elif - AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - token_storage = {}; - std::pair res = Parse(elif_block, Token_table, idx+1, 0, token_storage); - head.AddChild(elif_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElifStmt; - token_storage = {}; // if not need -> remove - token_table = Token_table[parsing_line-1]; - continue; - } - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - } - - // for statement - if (token_table[idx] == "for") { - AST for_block(ForStmt, {}, {}, parsing_line); - std::pair res = Parse(for_block, Token_table, idx+1, 1, token_storage); - head.AddChild(for_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ForStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - - if (token_table[idx] == "=") { - if (token_storage.size() == 1) { // assignment - AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(assignment, Token_table, idx+1, 1, token_storage); - head.AddChild(assignment); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - if (token_storage.size() == 2) { // declaration - AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(var_del, Token_table, idx+1, 1, token_storage); - head.AddChild(var_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - } - - // const variable declaration - if (token_table[idx] == "const") { - AST const_del(ConstDel, {}, {}, parsing_line); - std::pair res = Parse(const_del, Token_table, idx+1, 1, token_storage); - head.AddChild(const_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ConstDel; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - - // break statement - if (token_table[idx] == "break") { - AST break_stmt(BreakStmt, {}, {}, parsing_line); - head.AddChild(break_stmt); - prev_stmt = BreakStmt; - } - - // continue statement - if (token_table[idx] == "continue") { - AST continue_stmt(ContinueStmt, {}, {}, parsing_line); - head.AddChild(continue_stmt); - prev_stmt = ContinueStmt; - } - break; - } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + } + + // const variable declaration + if (token_table[idx] == "const") { + AST const_del(ConstDel, {}, {}, parsing_line); + std::pair res = Parse(const_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(const_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ConstDel; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + + // break statement + if (token_table[idx] == "break") { + AST break_stmt(BreakStmt, {}, {}, parsing_line); + head.AddChild(break_stmt); + prev_stmt = BreakStmt; + } + + // continue statement + if (token_table[idx] == "continue") { + AST continue_stmt(ContinueStmt, {}, {}, parsing_line); + head.AddChild(continue_stmt); + prev_stmt = ContinueStmt; + } + break; + } - // if-family statement - case IfStmt: { - // if-family statement - if (token_table[idx] == "if") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - AST if_block(IfStmt, {}, {}, parsing_line); - std::pair res = Parse(if_block, Token_table, idx+1, 1, token_storage); - head.AddChild(if_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = IfStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "?") { - if (arg_idx == 1) { - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - token_storage = {}; - head.codeline = parsing_line; - return Parse(head, Token_table, idx+1, 2, token_storage); - } else { - if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { - if (token_storage.empty()) { // else - AST else_block(ElseStmt, {}, {}, parsing_line); - std::pair res = Parse(else_block, Token_table, idx+1, 0, token_storage); - head.AddChild(else_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElseStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } else { // elif - AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - token_storage = {}; - std::pair res = Parse(elif_block, Token_table, idx+1, 0, token_storage); - head.AddChild(elif_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElifStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - } - } - - // for statement - if (token_table[idx] == "for") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); - AST for_block(ForStmt, {}, {}, parsing_line); - std::pair res = Parse(for_block, Token_table, idx+1, 1, token_storage); - head.AddChild(for_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ForStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - - if (token_table[idx] == "=") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); - if (token_storage.size() == 1) { // assignment - AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(assignment, Token_table, idx+1, 1, token_storage); - head.AddChild(assignment); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - if (token_storage.size() == 2) { // declaration - AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(var_del, Token_table, idx+1, 1, token_storage); - head.AddChild(var_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - } - - // const variable declaration - if (token_table[idx] == "const") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); - AST const_del(ConstDel, {}, {}, parsing_line); - std::pair res = Parse(const_del, Token_table, idx+1, 1, token_storage); - head.AddChild(const_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ConstDel; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - - // break statement - if (token_table[idx] == "break") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); - AST break_stmt(BreakStmt, {}, {}, parsing_line); - head.AddChild(break_stmt); - } - - // continue statement - if (token_table[idx] == "continue") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); - AST continue_stmt(ContinueStmt, {}, {}, parsing_line); - head.AddChild(continue_stmt); - } - - if (token_table[idx] == ";") { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - if (token_storage.size() != 0) { - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); - } - return {parsing_line, idx}; - } - break; - } - - case ElifStmt: - case ElseStmt: { - // if-family statement - if (token_table[idx] == "if") { - AST if_block(IfStmt, {}, {}, parsing_line); - std::pair res = Parse(if_block, Token_table, idx+1, 1, token_storage); - head.AddChild(if_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = IfStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "?") { - if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { - if (token_storage.empty()) { // else - AST else_block(ElseStmt, {}, {}, parsing_line); - std::pair res = Parse(else_block, Token_table, idx+1, 0, token_storage); - head.AddChild(else_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElseStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } else { // elif - AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - token_storage = {}; - std::pair res = Parse(elif_block, Token_table, idx+1, 0, token_storage); - head.AddChild(elif_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElifStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - } - - // for statement - if (token_table[idx] == "for") { - AST for_block(ForStmt, {}, {}, parsing_line); - std::pair res = Parse(for_block, Token_table, idx+1, 1, token_storage); - head.AddChild(for_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ForStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - - if (token_table[idx] == "=") { - if (token_storage.size() == 1) { // assignment - AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(assignment, Token_table, idx+1, 1, token_storage); - head.AddChild(assignment); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - if (token_storage.size() == 2) { // declaration - AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(var_del, Token_table, idx+1, 1, token_storage); - head.AddChild(var_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - } - - // const variable declaration - if (token_table[idx] == "const") { - AST const_del(ConstDel, {}, {}, parsing_line); - std::pair res = Parse(const_del, Token_table, idx+1, 1, token_storage); - head.AddChild(const_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ConstDel; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - - // break statement - if (token_table[idx] == "break") { - AST break_stmt(BreakStmt, {}, {}, parsing_line); - head.AddChild(break_stmt); - } - - // continue statement - if (token_table[idx] == "continue") { - AST continue_stmt(ContinueStmt, {}, {}, parsing_line); - head.AddChild(continue_stmt); - } - - if (token_table[idx] == ";") { - if (token_storage.size() != 0) { - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); - } - return {parsing_line, idx}; - } - break; + // if-family statement + case IfStmt: { + // if-family statement + if (token_table[idx] == "if") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + AST if_block(IfStmt, {}, {}, parsing_line); + std::pair res = Parse(if_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(if_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = IfStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + + if (token_table[idx] == "?") { + if (arg_idx == 1) { + head.AddExpr(ParseExpr(token_storage, parsing_line)); + token_storage = {}; + head.codeline = parsing_line; + return Parse(head, Token_table, idx + 1, 2, token_storage); + } else { + if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { + if (token_storage.empty()) { // else + AST else_block(ElseStmt, {}, {}, parsing_line); + std::pair res = Parse(else_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(else_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElseStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } else { // elif + AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + token_storage = {}; + std::pair res = Parse(elif_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(elif_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElifStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; } + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + } + } + + // for statement + if (token_table[idx] == "for") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); + AST for_block(ForStmt, {}, {}, parsing_line); + std::pair res = Parse(for_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(for_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ForStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } - // for statement - case ForStmt: { - // if-family statement - if (token_table[idx] == "if") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - AST if_block(IfStmt, {}, {}, parsing_line); - std::pair res = Parse(if_block, Token_table, idx+1, 1, token_storage); - head.AddChild(if_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = IfStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - - if (token_table[idx] == "?") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { - if (token_storage.empty()) { // else - AST else_block(ElseStmt, {}, {}, parsing_line); - std::pair res = Parse(else_block, Token_table, idx+1, 0, token_storage); - head.AddChild(else_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElseStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } else { // elif - AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - token_storage = {}; - std::pair res = Parse(elif_block, Token_table, idx+1, 0, token_storage); - head.AddChild(elif_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ElifStmt; - token_table = Token_table[parsing_line-1]; - token_storage = {}; // if not need -> remove - continue; - } - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - } - - // for statement - if (token_table[idx] == "for") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - AST for_block(ForStmt, {}, {}, parsing_line); - std::pair res = Parse(for_block, Token_table, idx+1, 1, token_storage); - head.AddChild(for_block); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ForStmt; - token_storage = {}; // if not need -> remove - token_table = Token_table[parsing_line-1]; - continue; - } - - if (token_table[idx] == "=") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - if (token_storage.size() == 1) { // assignment - AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(assignment, Token_table, idx+1, 1, token_storage); - head.AddChild(assignment); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - if (token_storage.size() == 2) { // declaration - AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); - token_storage = {}; - - std::pair res = Parse(var_del, Token_table, idx+1, 1, token_storage); - head.AddChild(var_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = Assignment; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - } - - // const variable declaration - if (token_table[idx] == "const") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - AST const_del(ConstDel, {}, {}, parsing_line); - std::pair res = Parse(const_del, Token_table, idx+1, 1, token_storage); - head.AddChild(const_del); - - parsing_line = res.first; - idx = res.second; - prev_stmt = ConstDel; - token_table = Token_table[parsing_line-1]; - token_storage = {}; - continue; - } - - // break statement - if (token_table[idx] == "break") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - AST break_stmt(BreakStmt, {}, {}, parsing_line); - head.AddChild(break_stmt); - } - - // continue statement - if (token_table[idx] == "continue") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - AST continue_stmt(ContinueStmt, {}, {}, parsing_line); - head.AddChild(continue_stmt); - } - if (token_table[idx] == "in") { - if (arg_idx != 1 || token_storage.size() != 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - head.AddArg(Object("_", {}, {}, {"_", "C"}, 0, parsing_line)); - head.AddArg(Object("_", {}, {}, {"_", token_storage[0]}, 0, parsing_line)); - token_storage = {}; - return Parse(head, Token_table, idx+1, 2, token_storage); - } - if (token_table[idx] == "~") { - if (arg_idx == 2 | arg_idx == 3) { - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - token_storage = {}; - return Parse(head, Token_table, idx+1, arg_idx+1, token_storage); - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - } - if (token_table[idx] == "$") { - if (arg_idx == 1) { - head.AddArg(Object("_", {}, {}, {"_", "S"}, 0, parsing_line)); - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - token_storage = {}; - head.codeline = parsing_line; - return Parse(head, Token_table, idx+1, 5, token_storage); - } - if (arg_idx == 3) { // omission of - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - head.AddExpr(Expr({1, 0, 0}, Object("_", {}, {}, {"_", "1", INT}), parsing_line)); - token_storage = {}; - head.codeline = parsing_line; - return Parse(head, Token_table, idx+1, 5, token_storage); - } - if (arg_idx == 4) { - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - token_storage = {}; - head.codeline = parsing_line; - return Parse(head, Token_table, idx+1, 5, token_storage); - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - } - if (token_table[idx] == ";") { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - if (token_storage.size() != 0) { - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); - } - return {parsing_line, idx}; - } - break; - } - - // const variable declaration - case ConstDel: { - if (token_table[idx] == "if" || token_table[idx] == "?" || - token_table[idx] == "for" || token_table[idx] == "continue" || - token_table[idx] == "const" || token_table[idx] == "break" || token_table[idx] == "$" || token_table[idx] == ";") - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - if (token_table[idx] == "=") { - if (token_storage.size() == 2) { // declaration - head.AddArg( - Object("_", {}, {}, {"_", token_storage[0]}) - ); - head.AddArg( - Object("_", {}, {}, {"_", token_storage[1]}) - ); - token_storage = {}; - - return Parse(head, Token_table, idx+1, 2, token_storage); - } - ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); - } - } + if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + + if (token_table[idx] == "=") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); + if (token_storage.size() == 1) { // assignment + AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(assignment, Token_table, idx + 1, 1, token_storage); + head.AddChild(assignment); + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; } - token_storage.push_back(token_table[idx]); + if (token_storage.size() == 2) { // declaration + AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(var_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(var_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + } + + // const variable declaration + if (token_table[idx] == "const") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); + AST const_del(ConstDel, {}, {}, parsing_line); + std::pair res = Parse(const_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(const_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ConstDel; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + + // break statement + if (token_table[idx] == "break") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); + AST break_stmt(BreakStmt, {}, {}, parsing_line); + head.AddChild(break_stmt); + } + + // continue statement + if (token_table[idx] == "continue") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_IF, {}); + AST continue_stmt(ContinueStmt, {}, {}, parsing_line); + head.AddChild(continue_stmt); + } + + if (token_table[idx] == ";") { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + if (token_storage.size() != 0) { + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); + } + return {parsing_line, idx}; + } + break; } - - parse_start = 0; - switch (head.GetStmt()) { - case ElifStmt: - case ElseStmt: - case Main: { - if (token_storage.size() == 0) continue; - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); + + case ElifStmt: + case ElseStmt: { + // if-family statement + if (token_table[idx] == "if") { + AST if_block(IfStmt, {}, {}, parsing_line); + std::pair res = Parse(if_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(if_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = IfStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + + if (token_table[idx] == "?") { + if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { + if (token_storage.empty()) { // else + AST else_block(ElseStmt, {}, {}, parsing_line); + std::pair res = Parse(else_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(else_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElseStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } else { // elif + AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); token_storage = {}; - break; + std::pair res = Parse(elif_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(elif_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElifStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } } - case IfStmt: { - if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); - if (token_storage.size() == 0) continue; - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); - token_storage = {}; - break; + ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + } + + // for statement + if (token_table[idx] == "for") { + AST for_block(ForStmt, {}, {}, parsing_line); + std::pair res = Parse(for_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(for_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ForStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + + if (token_table[idx] == "$") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + + if (token_table[idx] == "=") { + if (token_storage.size() == 1) { // assignment + AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(assignment, Token_table, idx + 1, 1, token_storage); + head.AddChild(assignment); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + if (token_storage.size() == 2) { // declaration + AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(var_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(var_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; } - case ForStmt: { - if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); - if (token_storage.size() == 0) continue; - AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); - head.AddChild(expression); + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + } + + // const variable declaration + if (token_table[idx] == "const") { + AST const_del(ConstDel, {}, {}, parsing_line); + std::pair res = Parse(const_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(const_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ConstDel; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + + // break statement + if (token_table[idx] == "break") { + AST break_stmt(BreakStmt, {}, {}, parsing_line); + head.AddChild(break_stmt); + } + + // continue statement + if (token_table[idx] == "continue") { + AST continue_stmt(ContinueStmt, {}, {}, parsing_line); + head.AddChild(continue_stmt); + } + + if (token_table[idx] == ";") { + if (token_storage.size() != 0) { + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); + } + return {parsing_line, idx}; + } + break; + } + + // for statement + case ForStmt: { + // if-family statement + if (token_table[idx] == "if") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + AST if_block(IfStmt, {}, {}, parsing_line); + std::pair res = Parse(if_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(if_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = IfStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + + if (token_table[idx] == "?") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + if (prev_stmt == IfStmt || prev_stmt == ElifStmt) { + if (token_storage.empty()) { // else + AST else_block(ElseStmt, {}, {}, parsing_line); + std::pair res = Parse(else_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(else_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElseStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } else { // elif + AST elif_block(ElifStmt, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); token_storage = {}; - break; + std::pair res = Parse(elif_block, Token_table, idx + 1, 0, token_storage); + head.AddChild(elif_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ElifStmt; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; // if not need -> remove + continue; + } + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + } + + // for statement + if (token_table[idx] == "for") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + AST for_block(ForStmt, {}, {}, parsing_line); + std::pair res = Parse(for_block, Token_table, idx + 1, 1, token_storage); + head.AddChild(for_block); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ForStmt; + token_storage = {}; // if not need -> remove + token_table = Token_table[parsing_line - 1]; + continue; + } + + if (token_table[idx] == "=") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + if (token_storage.size() == 1) { // assignment + AST assignment(Assignment, {Object("_", {}, {}, {"_", token_storage[0]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(assignment, Token_table, idx + 1, 1, token_storage); + head.AddChild(assignment); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + if (token_storage.size() == 2) { // declaration + AST var_del(VarDel, {Object("_", {}, {}, {"_", token_storage[0]}), Object("_", {}, {}, {"_", token_storage[1]})}, {}, parsing_line); + token_storage = {}; + + std::pair res = Parse(var_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(var_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = Assignment; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + } + + // const variable declaration + if (token_table[idx] == "const") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + AST const_del(ConstDel, {}, {}, parsing_line); + std::pair res = Parse(const_del, Token_table, idx + 1, 1, token_storage); + head.AddChild(const_del); + + parsing_line = res.first; + idx = res.second; + prev_stmt = ConstDel; + token_table = Token_table[parsing_line - 1]; + token_storage = {}; + continue; + } + + // break statement + if (token_table[idx] == "break") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + AST break_stmt(BreakStmt, {}, {}, parsing_line); + head.AddChild(break_stmt); + } + + // continue statement + if (token_table[idx] == "continue") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + AST continue_stmt(ContinueStmt, {}, {}, parsing_line); + head.AddChild(continue_stmt); + } + if (token_table[idx] == "in") { + if (arg_idx != 1 || token_storage.size() != 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + head.AddArg(Object("_", {}, {}, {"_", "C"}, 0, parsing_line)); + head.AddArg(Object("_", {}, {}, {"_", token_storage[0]}, 0, parsing_line)); + token_storage = {}; + return Parse(head, Token_table, idx + 1, 2, token_storage); + } + if (token_table[idx] == "~") { + if (arg_idx == 2 | arg_idx == 3) { + head.AddExpr(ParseExpr(token_storage, parsing_line)); + token_storage = {}; + return Parse(head, Token_table, idx + 1, arg_idx + 1, token_storage); + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + } + if (token_table[idx] == "$") { + if (arg_idx == 1) { + head.AddArg(Object("_", {}, {}, {"_", "S"}, 0, parsing_line)); + head.AddExpr(ParseExpr(token_storage, parsing_line)); + token_storage = {}; + head.codeline = parsing_line; + return Parse(head, Token_table, idx + 1, 5, token_storage); + } + if (arg_idx == 3) { // omission of + head.AddExpr(ParseExpr(token_storage, parsing_line)); + head.AddExpr(Expr({1, 0, 0}, Object("_", {}, {}, {"_", "1", INT}), parsing_line)); + token_storage = {}; + head.codeline = parsing_line; + return Parse(head, Token_table, idx + 1, 5, token_storage); + } + if (arg_idx == 4) { + head.AddExpr(ParseExpr(token_storage, parsing_line)); + token_storage = {}; + head.codeline = parsing_line; + return Parse(head, Token_table, idx + 1, 5, token_storage); + } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + } + if (token_table[idx] == ";") { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + if (token_storage.size() != 0) { + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); } - case VarDel: - case ConstDel: - case Assignment: { - head.AddExpr( - ParseExpr(token_storage, parsing_line) - ); - return {parsing_line, token_table.size()}; + return {parsing_line, idx}; + } + break; + } + + // const variable declaration + case ConstDel: { + if (token_table[idx] == "if" || token_table[idx] == "?" || token_table[idx] == "for" || token_table[idx] == "continue" || token_table[idx] == "const" || token_table[idx] == "break" || token_table[idx] == "$" || token_table[idx] == ";") ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + if (token_table[idx] == "=") { + if (token_storage.size() == 2) { // declaration + head.AddArg(Object("_", {}, {}, {"_", token_storage[0]})); + head.AddArg(Object("_", {}, {}, {"_", token_storage[1]})); + token_storage = {}; + + return Parse(head, Token_table, idx + 1, 2, token_storage); } + ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_EXPRESSION, {}); + } } - prev_stmt = Expression; + } + token_storage.push_back(token_table[idx]); } + + parse_start = 0; switch (head.GetStmt()) { - case BracketBlock: - ErrHandler().CallErr(parsing_line, UNMATCHED_PARENTHESIS, {}); - break; - case IfStmt: - case ElifStmt: - case ElseStmt: - ErrHandler().CallErr(parsing_line, NOT_CLOSED_BLOCK, {}); - break; + case ElifStmt: + case ElseStmt: + case Main: { + if (token_storage.size() == 0) continue; + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); + token_storage = {}; + break; + } + case IfStmt: { + if (arg_idx == 1) ErrHandler().CallErr(parsing_line, NO_MATCHING_STRUCTURE_IF, {}); + if (token_storage.size() == 0) continue; + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); + token_storage = {}; + break; + } + case ForStmt: { + if (arg_idx != 5) ErrHandler().CallErr(parsing_line, NO_MATCHING_SYNTAX_FOR, {}); + if (token_storage.size() == 0) continue; + AST expression(Expression, {}, {ParseExpr(token_storage, parsing_line)}, parsing_line); + head.AddChild(expression); + token_storage = {}; + break; + } + case VarDel: + case ConstDel: + case Assignment: { + head.AddExpr(ParseExpr(token_storage, parsing_line)); + return {parsing_line, token_table.size()}; + } } + prev_stmt = Expression; + } + switch (head.GetStmt()) { + case BracketBlock: + ErrHandler().CallErr(parsing_line, UNMATCHED_PARENTHESIS, {}); + break; + case IfStmt: + case ElifStmt: + case ElseStmt: + ErrHandler().CallErr(parsing_line, NOT_CLOSED_BLOCK, {}); + break; + } } \ No newline at end of file diff --git a/src/parser/parse.h b/src/parser/parse.h index d98675f..c983481 100644 --- a/src/parser/parse.h +++ b/src/parser/parse.h @@ -6,13 +6,14 @@ * */ #include +#include +#include +#include #include #include -#include -#include -#include -#include "../runtime/AST.h" + #include "../error/signal.h" +#include "../runtime/AST.h" #ifndef WOPS_PARSE_H #define WOPS_PARSE_H @@ -21,4 +22,4 @@ std::pair Parse(AST& head, std::vector> Token_tabl Expr ParseExpr(std::vector tokens, int parsing_line); std::vector GetTokenTable(String code); -#endif +#endif \ No newline at end of file diff --git a/src/runtime/AST.h b/src/runtime/AST.h index 7c372d3..78a0bbb 100644 --- a/src/runtime/AST.h +++ b/src/runtime/AST.h @@ -8,30 +8,31 @@ #ifndef WOPS_AST_H #define WOPS_AST_H -#include #include #include #include +#include + #include "../import_/eexec_.h" -#include "../type/variable.h" #include "../type/object.h" #include "../type/operator.h" +#include "../type/variable.h" // enum TYPE {...} // Enumeration of statement types enum StmtType { - Main, - ConstDel, - VarDel, - Expression, - Assignment, - BreakStmt, - ContinueStmt, - IfStmt, - ElifStmt, - ElseStmt, - ForStmt, - BracketBlock, // () + Main, + ConstDel, + VarDel, + Expression, + Assignment, + BreakStmt, + ContinueStmt, + IfStmt, + ElifStmt, + ElseStmt, + ForStmt, + BracketBlock, // () }; typedef std::unordered_map Storage; @@ -39,187 +40,167 @@ typedef std::unordered_map Storage; /** * class Expr * Expression Syntax Tree class - * + * * Structure - * + * * private * - bool constant, variable, call (token's type) * - Variable token - * - std::vector children + * - std::vector children * - int codeline */ class Expr { - private: - bool constant = 0, variable = 0, call = 0; - Object token; // base object (variable) - std::vector children; - int codeline; - - public: - // constructor - Expr(std::vector t, Object tkn, int _codeline) { - token = tkn, constant = t[0], variable = t[1], call = t[2], codeline = _codeline; - } - - void SetChildren(std::vector rplcment) { - children = rplcment; - } - - void AddChild(Expr child) { - children.push_back(child); - } - - // execute from the tree root - Object Execute(std::vector& storages) { - std::string tkn = token.GetBase().GetValue(); - - if (variable) { - auto iter = storages[0].find(tkn); - bool wasErrorOccured = true; - Object ret; - for (Storage storage: storages) { - iter = storage.find(tkn); - if (iter != storage.end()) { - ret = iter->second; - wasErrorOccured = false; - break; - } - } - if (wasErrorOccured) // has variable declared? - ErrHandler().CallErr(codeline, VARIABLE_HAS_NOT_DECLARED, {tkn}); - - ret.runtime_codeline = codeline; - return ret; - } - if (constant) { - return Object("_", {}, {}, token.GetBase(), 0, codeline, OK); - } - if (call) { - Object arg; - std::vector container; - for (Expr child: children) { - container.push_back(child.Execute(storages)); - } - arg.runtime_codeline = codeline; - arg.dim = 1; arg.ReplaceContainer(container); arg.size = { (Int)container.size() }; - Object res = EExecFunc(tkn, arg); - if (res.errvalue != OK) - ErrHandler().CallErr(codeline, res.errvalue, {tkn}); - - return res; - } - - // Binary Operation - if (tkn == "+") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() + operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "-") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() - operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "*") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() * operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "/") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() / operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "%") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() % operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "==") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() == operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "!=") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() != operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == ">") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() > operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == ">=") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() >= operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "<") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() < operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "<=") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() <= operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "||") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() || operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - if (tkn == "&&") { - Object value = children[0].Execute(storages), operand = children[1].Execute(storages); - if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); - if (value.dim == 0) - return Object("_", {}, {}, value.GetBase() && operand.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); - } - - // Unary Operation - if (tkn == "!") { - Object value = children[0].Execute(storages); - if (value.dim == 0) - return Object("_", {}, {}, !value.GetBase(), 0, codeline, OK); - ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(value.dim)}); - } - } + private: + bool constant = 0, variable = 0, call = 0; + Object token; // base object (variable) + std::vector children; + int codeline; + + public: + // constructor + Expr(std::vector t, Object tkn, int _codeline) { token = tkn, constant = t[0], variable = t[1], call = t[2], codeline = _codeline; } + + void SetChildren(std::vector rplcment) { children = rplcment; } + + void AddChild(Expr child) { children.push_back(child); } + + // execute from the tree root + Object Execute(std::vector& storages) { + std::string tkn = token.GetBase().GetValue(); + + if (variable) { + auto iter = storages[0].find(tkn); + bool wasErrorOccured = true; + Object ret; + for (Storage storage : storages) { + iter = storage.find(tkn); + if (iter != storage.end()) { + ret = iter->second; + wasErrorOccured = false; + break; + } + } + if (wasErrorOccured) // has variable declared? + ErrHandler().CallErr(codeline, VARIABLE_HAS_NOT_DECLARED, {tkn}); + + ret.runtime_codeline = codeline; + return ret; + } + if (constant) { + return Object("_", {}, {}, token.GetBase(), 0, codeline, OK); + } + if (call) { + Object arg; + std::vector container; + for (Expr child : children) { + container.push_back(child.Execute(storages)); + } + arg.runtime_codeline = codeline; + arg.dim = 1; + arg.ReplaceContainer(container); + arg.size = {(Int)container.size()}; + Object res = EExecFunc(tkn, arg); + if (res.errvalue != OK) ErrHandler().CallErr(codeline, res.errvalue, {tkn}); + + return res; + } + + // Binary Operation + if (tkn == "+") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() + operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "-") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() - operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "*") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() * operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "/") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() / operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "%") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() % operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "==") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() == operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "!=") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() != operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == ">") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() > operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == ">=") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() >= operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "<") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() < operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "<=") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() <= operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "||") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() || operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + if (tkn == "&&") { + Object value = children[0].Execute(storages), operand = children[1].Execute(storages); + if (value.dim != operand.dim) ErrHandler().CallErr(codeline, OBJECT_WRONG_DIMENSION, {tkn, std::to_string(value.dim), std::to_string(operand.dim)}); + if (value.dim == 0) return Object("_", {}, {}, value.GetBase() && operand.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(operand.dim)}); + } + + // Unary Operation + if (tkn == "!") { + Object value = children[0].Execute(storages); + if (value.dim == 0) return Object("_", {}, {}, !value.GetBase(), 0, codeline, OK); + ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {tkn, "0", std::to_string(value.dim)}); + } + } }; - /** - * class AST + * class AST * Abstract Syntax Tree class - * + * * Structure - * + * * private * - StmtType _t * - std::vector childStmt @@ -227,9 +208,9 @@ class Expr { * - std::vector argument * public * - int codeline - * + * * expression - * + * * if AST's type is one of these: * - ConstDel * - VarDel @@ -240,298 +221,256 @@ class Expr { * - ElseStmt * - ForClauseStmt * - ForSCStmt - * + * * expression will not be blank. (length 1) - * + * * argument - * + * * argument can have different formation. * - _t = ConstDel or VarDel: argument[2] = {TYPE, IDENTIFIER} * - _t = Assignment: argument[1] = {IDENTIFIER} * - _t = ForClauseStmt: argument[1] = {VARIABLE} (+ START, STOP, STEP expr) * - others: argument[0] = {} - * + * * every argument's type(Variable::_t) should be OPERATOR. */ class AST { - private: - StmtType _t; - std::vector childStmt; - std::vector expression; - std::vector argument; - - public: - int codeline; - - // constructor - AST(StmtType t, std::vector argv, std::vector expr, int _codeline) { - _t = t, argument = argv, expression = expr, codeline = _codeline; - } - - void SetChildren(std::vector rplcment) { - childStmt = rplcment; - } - - void AddChild(AST child) { - childStmt.push_back(child); - } - - void SetExpr(std::vector rplcment) { - expression = rplcment; - } - - void AddExpr(Expr expr) { - expression.push_back(expr); - } - - void SetArg(std::vector argv) { - argument = argv; - } - - void AddArg(Object argv) { - argument.push_back(argv); - } - - StmtType GetStmt() { return _t; } - - // storages: smaller index, inner variable - std::pair Execute(std::vector& storages) { - switch (_t) { - case Main: { - bool ignoreif = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - - std::pair res = ast.Execute(storages); - if (res.first >= 1) - ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); - - if (res.second) { - ignoreif = 1; - continue; - } - } - break; - } - - case ConstDel: { - Object v_type = argument[0], v_identifier = argument[1]; - if (v_type.dim != 0 && v_identifier.dim != 0) ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {"Expression", "0", std::to_string(v_type.dim)}); - for (Storage& storage: storages) { - if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) - ErrHandler().CallErr(codeline, VARIABLE_REDECLARE, {v_identifier.GetBase().GetValue()}); - } - - TYPE v_t = v_type.GetBase().GetValue() == "int" ? INT : ( - v_type.GetBase().GetValue() == "bool" ? BOOL : ( - v_type.GetBase().GetValue() == "string" ? STRING : DOUBLE - ) - ); - - storages[0].insert({v_identifier.GetBase().GetValue(), {v_identifier.GetBase().GetValue(), {}, {}, - Variable( - v_identifier.GetBase().GetValue(), - expression[0].Execute(storages).GetBase().GetValue(), - v_t, - true) - , 0, codeline, OK}}); - - break; - } - - case VarDel: { - Object v_type = argument[0], v_identifier = argument[1]; - for (Storage& storage: storages) { - if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) - ErrHandler().CallErr(codeline, VARIABLE_REDECLARE, {v_identifier.GetBase().GetValue()}); - } - - TYPE v_t = v_type.GetBase().GetValue() == "int" ? INT : ( - v_type.GetBase().GetValue() == "bool" ? BOOL : ( - v_type.GetBase().GetValue() == "string" ? STRING : DOUBLE - ) - ); - - storages[0].insert({v_identifier.GetBase().GetValue(), {v_identifier.GetBase().GetValue(), {}, {}, - Variable( - v_identifier.GetBase().GetValue(), - expression[0].Execute(storages).GetBase().GetValue(), - v_t, - false) - , 0, codeline, OK}}); - break; - } - - case Expression: - expression[0].Execute(storages); - break; - - case Assignment: { - Object v_identifier = argument[0]; - bool wasErrorOccured = true; - for (Storage& storage: storages) - if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) { - if (storage[v_identifier.GetBase().GetValue()].GetBase().constant) - ErrHandler().CallErr(codeline, ASSIGN_ON_CONSTANT, {v_identifier.GetBase().GetValue()}); - storage[v_identifier.GetBase().GetValue()].GetBase().Substitute(expression[0].Execute(storages).GetBase().GetValue()); - wasErrorOccured = false; - break; - } - if (wasErrorOccured) - ErrHandler().CallErr(codeline, ASSIGN_ON_UNKNOWN, {v_identifier.GetBase().GetValue()}); - break; - } - - case BreakStmt: - return {2, false}; - - case ContinueStmt: - return {1, false}; - - case IfStmt: { - storages.insert(storages.begin(), Storage()); - Object condition = expression[0].Execute(storages); - if (condition.GetBase()._t != BOOL) - ErrHandler().CallErr(codeline, IF_NO_BOOLEAN_CONDITION, {}); - if (condition.GetBase().GetValue() == "0") { - return {0, false}; - } - bool ignoreif = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - std::pair res = ast.Execute(storages); - if (res.first >= 1) { - return {res.first, res.second}; - ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); - } - if (res.second) { - ignoreif = 1; - continue; - } - } - storages.erase(storages.begin()); - return {0, true}; - } - - case ElifStmt: { - storages.insert(storages.begin(), Storage()); - Object condition = expression[0].Execute(storages); - if (condition.GetBase()._t != BOOL) - ErrHandler().CallErr(codeline, ELIF_NO_BOOLEAN_CONDITION, {}); - if (condition.GetBase().GetValue() == "0") { - return {0, false}; - } - bool ignoreif = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - std::pair res = ast.Execute(storages); - if (res.first >= 1) { - return {res.first, res.second}; - ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); - } - if (res.second) { - ignoreif = 1; - continue; - } - } - storages.erase(storages.begin()); - return {0, true}; - } - - case ElseStmt: { - storages.insert(storages.begin(), Storage()); - bool ignoreif = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - std::pair res = ast.Execute(storages); - if (res.first >= 1) { - return {res.first, res.second}; - ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); - } - if (res.second) { - ignoreif = 1; - continue; - } - } - storages.erase(storages.begin()); - return {0, true}; - } - - case ForStmt: { - if (argument.size() >= 1) { - if (argument[0].GetBase().GetValue() == "C" && argument.size() == 2) { // for clause - for (int idx = std::stoi(expression[0].Execute(storages).GetBase().GetValue()); idx < std::stoi(expression[1].Execute(storages).GetBase().GetValue()); idx += std::stoi(expression[2].Execute(storages).GetBase().GetValue())) { - storages.insert(storages.begin(), Storage()); - storages[0][argument[1].GetBase().GetValue()] = Object(argument[1].GetBase().GetValue(), {}, {}, Variable(argument[1].GetBase().GetValue(), std::to_string(idx), INT), 0, codeline, OK); - bool ignoreif = 0; - bool flowstmt = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - std::pair res = ast.Execute(storages); - if (res.first == 2) { - flowstmt = 1; - break; - } - if (res.first == 1) break; - if (res.second) { - ignoreif = 1; - continue; - } - } - storages.erase(storages.begin()); - if (flowstmt) break; - } - } else { // single condition - while (1) { - storages.insert(storages.begin(), Storage()); - Object condition = expression[0].Execute(storages); - if (condition.GetBase()._t != BOOL) - ErrHandler().CallErr(codeline, FOR_NO_BOOLEAN_CONDITION, {}); - if (condition.GetBase().GetValue() == "0") break; - - bool ignoreif = 0; - bool flowstmt = 0; - for (AST ast: childStmt) { - if (ignoreif) { - if (ast._t == ElifStmt || ast._t == ElseStmt) continue; - ignoreif = 0; - } - std::pair res = ast.Execute(storages); - if (res.first == 2) { - flowstmt = 1; - break; - } - if (res.first == 1) break; - if (res.second) { - ignoreif = 1; - continue; - } - } - storages.erase(storages.begin()); - if (flowstmt) break; - } - } - break; - } - } - } - return {0, false}; - } + private: + StmtType _t; + std::vector childStmt; + std::vector expression; + std::vector argument; + + public: + int codeline; + + // constructor + AST(StmtType t, std::vector argv, std::vector expr, int _codeline) { _t = t, argument = argv, expression = expr, codeline = _codeline; } + + void SetChildren(std::vector rplcment) { childStmt = rplcment; } + + void AddChild(AST child) { childStmt.push_back(child); } + + void SetExpr(std::vector rplcment) { expression = rplcment; } + + void AddExpr(Expr expr) { expression.push_back(expr); } + + void SetArg(std::vector argv) { argument = argv; } + + void AddArg(Object argv) { argument.push_back(argv); } + + StmtType GetStmt() { return _t; } + + // storages: smaller index, inner variable + std::pair Execute(std::vector& storages) { + switch (_t) { + case Main: { + bool ignoreif = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + + std::pair res = ast.Execute(storages); + if (res.first >= 1) ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); + + if (res.second) { + ignoreif = 1; + continue; + } + } + break; + } + + case ConstDel: { + Object v_type = argument[0], v_identifier = argument[1]; + if (v_type.dim != 0 && v_identifier.dim != 0) ErrHandler().CallErr(codeline, TOO_HIGH_DIMENSION, {"Expression", "0", std::to_string(v_type.dim)}); + for (Storage& storage : storages) { + if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) ErrHandler().CallErr(codeline, VARIABLE_REDECLARE, {v_identifier.GetBase().GetValue()}); + } + + TYPE v_t = v_type.GetBase().GetValue() == "int" ? INT : (v_type.GetBase().GetValue() == "bool" ? BOOL : (v_type.GetBase().GetValue() == "string" ? STRING : DOUBLE)); + + storages[0].insert({v_identifier.GetBase().GetValue(), {v_identifier.GetBase().GetValue(), {}, {}, Variable(v_identifier.GetBase().GetValue(), expression[0].Execute(storages).GetBase().GetValue(), v_t, true), 0, codeline, OK}}); + + break; + } + + case VarDel: { + Object v_type = argument[0], v_identifier = argument[1]; + for (Storage& storage : storages) { + if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) ErrHandler().CallErr(codeline, VARIABLE_REDECLARE, {v_identifier.GetBase().GetValue()}); + } + + TYPE v_t = v_type.GetBase().GetValue() == "int" ? INT : (v_type.GetBase().GetValue() == "bool" ? BOOL : (v_type.GetBase().GetValue() == "string" ? STRING : DOUBLE)); + + storages[0].insert({v_identifier.GetBase().GetValue(), {v_identifier.GetBase().GetValue(), {}, {}, Variable(v_identifier.GetBase().GetValue(), expression[0].Execute(storages).GetBase().GetValue(), v_t, false), 0, codeline, OK}}); + break; + } + + case Expression: + expression[0].Execute(storages); + break; + + case Assignment: { + Object v_identifier = argument[0]; + bool wasErrorOccured = true; + for (Storage& storage : storages) + if (storage.find(v_identifier.GetBase().GetValue()) != storage.end()) { + if (storage[v_identifier.GetBase().GetValue()].GetBase().constant) ErrHandler().CallErr(codeline, ASSIGN_ON_CONSTANT, {v_identifier.GetBase().GetValue()}); + storage[v_identifier.GetBase().GetValue()].GetBase().Substitute(expression[0].Execute(storages).GetBase().GetValue()); + wasErrorOccured = false; + break; + } + if (wasErrorOccured) ErrHandler().CallErr(codeline, ASSIGN_ON_UNKNOWN, {v_identifier.GetBase().GetValue()}); + break; + } + + case BreakStmt: + return {2, false}; + + case ContinueStmt: + return {1, false}; + + case IfStmt: { + storages.insert(storages.begin(), Storage()); + Object condition = expression[0].Execute(storages); + if (condition.GetBase()._t != BOOL) ErrHandler().CallErr(codeline, IF_NO_BOOLEAN_CONDITION, {}); + if (condition.GetBase().GetValue() == "0") { + return {0, false}; + } + bool ignoreif = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + std::pair res = ast.Execute(storages); + if (res.first >= 1) { + return {res.first, res.second}; + ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); + } + if (res.second) { + ignoreif = 1; + continue; + } + } + storages.erase(storages.begin()); + return {0, true}; + } + + case ElifStmt: { + storages.insert(storages.begin(), Storage()); + Object condition = expression[0].Execute(storages); + if (condition.GetBase()._t != BOOL) ErrHandler().CallErr(codeline, ELIF_NO_BOOLEAN_CONDITION, {}); + if (condition.GetBase().GetValue() == "0") { + return {0, false}; + } + bool ignoreif = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + std::pair res = ast.Execute(storages); + if (res.first >= 1) { + return {res.first, res.second}; + ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); + } + if (res.second) { + ignoreif = 1; + continue; + } + } + storages.erase(storages.begin()); + return {0, true}; + } + + case ElseStmt: { + storages.insert(storages.begin(), Storage()); + bool ignoreif = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + std::pair res = ast.Execute(storages); + if (res.first >= 1) { + return {res.first, res.second}; + ErrHandler().CallErr(codeline, BREAK_CONTINUE_ONLY_ALLOWED_FOR, {}); + } + if (res.second) { + ignoreif = 1; + continue; + } + } + storages.erase(storages.begin()); + return {0, true}; + } + + case ForStmt: { + if (argument.size() >= 1) { + if (argument[0].GetBase().GetValue() == "C" && argument.size() == 2) { // for clause + for (int idx = std::stoi(expression[0].Execute(storages).GetBase().GetValue()); idx < std::stoi(expression[1].Execute(storages).GetBase().GetValue()); idx += std::stoi(expression[2].Execute(storages).GetBase().GetValue())) { + storages.insert(storages.begin(), Storage()); + storages[0][argument[1].GetBase().GetValue()] = Object(argument[1].GetBase().GetValue(), {}, {}, Variable(argument[1].GetBase().GetValue(), std::to_string(idx), INT), 0, codeline, OK); + bool ignoreif = 0; + bool flowstmt = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + std::pair res = ast.Execute(storages); + if (res.first == 2) { + flowstmt = 1; + break; + } + if (res.first == 1) break; + if (res.second) { + ignoreif = 1; + continue; + } + } + storages.erase(storages.begin()); + if (flowstmt) break; + } + } else { // single condition + while (1) { + storages.insert(storages.begin(), Storage()); + Object condition = expression[0].Execute(storages); + if (condition.GetBase()._t != BOOL) ErrHandler().CallErr(codeline, FOR_NO_BOOLEAN_CONDITION, {}); + if (condition.GetBase().GetValue() == "0") break; + + bool ignoreif = 0; + bool flowstmt = 0; + for (AST ast : childStmt) { + if (ignoreif) { + if (ast._t == ElifStmt || ast._t == ElseStmt) continue; + ignoreif = 0; + } + std::pair res = ast.Execute(storages); + if (res.first == 2) { + flowstmt = 1; + break; + } + if (res.first == 1) break; + if (res.second) { + ignoreif = 1; + continue; + } + } + storages.erase(storages.begin()); + if (flowstmt) break; + } + } + break; + } + } + } + return {0, false}; + } }; -#endif +#endif \ No newline at end of file diff --git a/src/type/object.h b/src/type/object.h index 26c7d9d..728d9c8 100644 --- a/src/type/object.h +++ b/src/type/object.h @@ -7,113 +7,116 @@ #ifndef WOPS_OBJECT_H #define WOPS_OBJECT_H -#include "variable.h" #include +#include "variable.h" + /** - * class Object + * class Object * Wopslang Object Class * * Structure * * Private * - data - * Public - * - size + * Public + * - size * - precalc_size * - dim * - runtime_codeline - * - token + * - token * - errvalue -*/ + */ class Object { - private: - std::vector data; // for base, data = {} - Variable base; // base (0-dim) + private: + std::vector data; // for base, data = {} + Variable base; // base (0-dim) - public: - // a[100][200][300] -> size = {100, 200, 300}, dim = 3 - // single variable -> dim = 0 - std::vector size; // multiplication of all size <= 10^9 - std::vector precalc_size; - Int dim; - Int runtime_codeline; // for error analyzing - String token; - Err errvalue; // special variable: only used to deliver error code + public: + // a[100][200][300] -> size = {100, 200, 300}, dim = 3 + // single variable -> dim = 0 + std::vector size; // multiplication of all size <= 10^9 + std::vector precalc_size; + Int dim; + Int runtime_codeline; // for error analyzing + String token; + Err errvalue; // special variable: only used to deliver error code - // constructor - Object(String objname = "_", std::vector objdata = {}, std::vector objsize = {}, Variable objbase = {}, Int objdim = 0, Int codeline = -1, Err err = OK) { - token = objname; - data = objdata; - base = objbase; - size = objsize; - dim = objdim; - runtime_codeline = codeline; - errvalue = err; - Prepare(); - } + // constructor + Object(String objname = "_", std::vector objdata = {}, std::vector objsize = {}, Variable objbase = {}, Int objdim = 0, Int codeline = -1, Err err = OK) { + token = objname; + data = objdata; + base = objbase; + size = objsize; + dim = objdim; + runtime_codeline = codeline; + errvalue = err; + Prepare(); + } - // void Prepare() - // Prerequisite Job - void Prepare() { - if (!dim) return; - if (dim != size.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(size.size())}); + // void Prepare() + // Prerequisite Job + void Prepare() { + if (!dim) return; + if (dim != size.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(size.size())}); - precalc_size.resize(dim); - precalc_size[dim-1] = 1; - for (int idx = dim-2; idx >= 0; idx--) { - Int *checker; *checker = precalc_size[idx+1]*size[idx+1]; - if (precalc_size[idx+1] > 0 && size[idx+1] > 0 && *checker < 0) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); - if (precalc_size[idx+1] < 0 && size[idx+1] < 0 && *checker > 0) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); - if (precalc_size[idx+1]*size[idx+1] > 1000000000) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); - precalc_size[idx] = precalc_size[idx+1]*size[idx+1]; - } - if (precalc_size[0]*size[0] != data.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_NOT_MATCHING_DATA, {token}); + precalc_size.resize(dim); + precalc_size[dim - 1] = 1; + for (int idx = dim - 2; idx >= 0; idx--) { + Int* checker; + *checker = precalc_size[idx + 1] * size[idx + 1]; + if (precalc_size[idx + 1] > 0 && size[idx + 1] > 0 && *checker < 0) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); + if (precalc_size[idx + 1] < 0 && size[idx + 1] < 0 && *checker > 0) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); + if (precalc_size[idx + 1] * size[idx + 1] > 1000000000) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); + precalc_size[idx] = precalc_size[idx + 1] * size[idx + 1]; } + if (precalc_size[0] * size[0] != data.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_NOT_MATCHING_DATA, {token}); + } - // Object At(std::vector dimidx) - // Get the data addressed by dimidx - Object At(std::vector dimidx) { - if (!dim) return Object("_", {}, {}, base); - if (dim != dimidx.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(dimidx.size())}); + // Object At(std::vector dimidx) + // Get the data addressed by dimidx + Object At(std::vector dimidx) { + if (!dim) return Object("_", {}, {}, base); + if (dim != dimidx.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(dimidx.size())}); - Int idx = IdxFinder(dimidx); - if (idx >= data.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); - return data[IdxFinder(dimidx)]; - } + Int idx = IdxFinder(dimidx); + if (idx >= data.size()) ErrHandler().CallErr(runtime_codeline, OBJECT_OVERFLOW, {token}); + return data[IdxFinder(dimidx)]; + } - // void Replace(std::vector dimidx, Object newdata) - // Replace the data addressed by dimidx with newdata - void Replace(std::vector dimidx, Object newdata) { - if (dim != newdata.dim) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(newdata.dim)}); - if (dimidx.size() != dim) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(dimidx.size())}); - if (!dim) { base = newdata.base; return; } - data[IdxFinder(dimidx)] = newdata; + // void Replace(std::vector dimidx, Object newdata) + // Replace the data addressed by dimidx with newdata + void Replace(std::vector dimidx, Object newdata) { + if (dim != newdata.dim) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(newdata.dim)}); + if (dimidx.size() != dim) ErrHandler().CallErr(runtime_codeline, OBJECT_WRONG_DIMENSION, {token, std::to_string(dim), std::to_string(dimidx.size())}); + if (!dim) { + base = newdata.base; + return; } + data[IdxFinder(dimidx)] = newdata; + } - // void ReplaceContainer(std::vector container) - // Replace whole data with container - void ReplaceContainer(std::vector container) { - data = container; - } + // void ReplaceContainer(std::vector container) + // Replace whole data with container + void ReplaceContainer(std::vector container) { data = container; } - // std::vector GetContainer() - // Getter function for data - std::vector GetContainer() { return data; } + // std::vector GetContainer() + // Getter function for data + std::vector GetContainer() { return data; } - // Variable GetBase() - // Getter function for base - Variable& GetBase() { - if (dim) ErrHandler().CallErr(runtime_codeline, TOO_HIGH_DIMENSION, {token, "0", std::to_string(dim)}); - return base; - } + // Variable GetBase() + // Getter function for base + Variable& GetBase() { + if (dim) ErrHandler().CallErr(runtime_codeline, TOO_HIGH_DIMENSION, {token, "0", std::to_string(dim)}); + return base; + } - // Int IdxFinder(std::vector dimidx) - Int IdxFinder(std::vector dimidx) { - Int cur = 0; - for (int idx = 0; idx < dim; idx++) cur += dimidx[idx]*precalc_size[idx]; - return cur; - } + // Int IdxFinder(std::vector dimidx) + Int IdxFinder(std::vector dimidx) { + Int cur = 0; + for (int idx = 0; idx < dim; idx++) cur += dimidx[idx] * precalc_size[idx]; + return cur; + } }; -#endif +#endif \ No newline at end of file diff --git a/src/type/operator.h b/src/type/operator.h index b331b58..274787b 100644 --- a/src/type/operator.h +++ b/src/type/operator.h @@ -8,28 +8,29 @@ #ifndef WOPS_OPERATOR_H #define WOPS_OPERATOR_H #include + #include "variable.h" enum op_ { - // Arithmetic - PLU, // + - MIN, // - - MUL, // * - DIV, // / - MOD, // % - ASSIGN, // = + // Arithmetic + PLU, // + + MIN, // - + MUL, // * + DIV, // / + MOD, // % + ASSIGN, // = - // Relational - EQ, // == - NEQ, // != - LG, // > - SM, // < - LGE, // >= - SME, // <= + // Relational + EQ, // == + NEQ, // != + LG, // > + SM, // < + LGE, // >= + SME, // <= - // Logical - LNOT, // ! - LAND, // && - LOR, // || + // Logical + LNOT, // ! + LAND, // && + LOR, // || }; -#endif +#endif \ No newline at end of file diff --git a/src/type/variable.h b/src/type/variable.h index 0df6b61..83be31c 100644 --- a/src/type/variable.h +++ b/src/type/variable.h @@ -8,16 +8,17 @@ #ifndef WOPS_VARIABLE_H #define WOPS_VARIABLE_H #include + #include "../error/signal.h" // enum TYPE {INT, DOUBLE, STRING, BOOL, OPERATOR} // Enumeration of data types enum TYPE { - INT, - DOUBLE, - STRING, - BOOL, - OPERATOR // +, -, *, ... + INT, + DOUBLE, + STRING, + BOOL, + OPERATOR // +, -, *, ... }; const std::string type_strname[] = {"INT", "DOUBLE", "STRING", "BOOL", "OPERATOR"}; @@ -31,294 +32,293 @@ const std::string type_strname[] = {"INT", "DOUBLE", "STRING", "BOOL", "OPERATOR * - value * - token (=variable name) * - type -*/ + */ class Variable { - private: - public: - String value; - String token; - bool constant = 0; - int runtime_codeline; // for error analyzing - TYPE _t; - - // constructor - Variable(String varname = "_", String val = "", TYPE t = OPERATOR, int _runtime_codeline = -1, bool con = 0) { - runtime_codeline = _runtime_codeline; - _t = t; - token = varname; - constant = con; - - if (varname == "") ErrHandler().CallErr(runtime_codeline, BLANK_VARIABLE_NAME, {}); - if (Substitute(val) == ERROR) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WITH_DEF, {varname, type_strname[t]}); + private: + public: + String value; + String token; + bool constant = 0; + int runtime_codeline; // for error analyzing + TYPE _t; + + // constructor + Variable(String varname = "_", String val = "", TYPE t = OPERATOR, int _runtime_codeline = -1, bool con = 0) { + runtime_codeline = _runtime_codeline; + _t = t; + token = varname; + constant = con; + + if (varname == "") ErrHandler().CallErr(runtime_codeline, BLANK_VARIABLE_NAME, {}); + if (Substitute(val) == ERROR) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WITH_DEF, {varname, type_strname[t]}); + } + + // operation + Variable operator+(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", _t); + + switch (_t) { + case BOOL: + if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "boolean", type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(value) + std::stoi(operand.value) != 0)); + break; + case INT: + if (operand._t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "int", "string"}); + if (operand._t == DOUBLE) + res.Substitute(std::to_string((Int)(std::stoi(value) + std::stod(operand.value)))); + else + res.Substitute(std::to_string(std::stoi(value) + std::stoi(operand.value))); + break; + case DOUBLE: + if (operand._t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "double", "string"}); + if (operand._t == DOUBLE) + res.Substitute(std::to_string(std::stod(value) + std::stod(operand.value))); + else + res.Substitute(std::to_string(std::stod(value) + std::stoi(operand.value))); + break; + case STRING: + if (operand._t != STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "string", type_strname[operand._t]}); + res.Substitute("\"" + trim(value) + trim(operand.value) + "\""); + break; } - - // operation - Variable operator + (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", _t); - - switch (_t) { - case BOOL: - if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "boolean", type_strname[operand._t]}); - res.Substitute(std::to_string(std::stoi(value)+std::stoi(operand.value) != 0)); - break; - case INT: - if (operand._t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "int", "string"}); - if (operand._t == DOUBLE) - res.Substitute(std::to_string((Int)(std::stoi(value)+std::stod(operand.value)))); - else - res.Substitute(std::to_string(std::stoi(value)+std::stoi(operand.value))); - break; - case DOUBLE: - if (operand._t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "double", "string"}); - if (operand._t == DOUBLE) - res.Substitute(std::to_string(std::stod(value)+std::stod(operand.value))); - else - res.Substitute(std::to_string(std::stod(value)+std::stoi(operand.value))); - break; - case STRING: - if (operand._t != STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"+", "string", type_strname[operand._t]}); - res.Substitute("\""+trim(value)+trim(operand.value)+"\""); - break; - } - return res; + return res; + } + + Variable operator-(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", _t); + + if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"-", type_strname[_t], type_strname[operand._t]}); + switch (_t) { + case BOOL: + if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"-", "boolean", type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(value) - std::stoi(operand.value) != 0)); + break; + case INT: + if (operand._t == DOUBLE) + res.Substitute(std::to_string((Int)(std::stoi(value) - std::stod(operand.value)))); + else + res.Substitute(std::to_string(std::stoi(value) - std::stoi(operand.value))); + break; + case DOUBLE: + if (operand._t == DOUBLE) + res.Substitute(std::to_string(std::stod(value) - std::stod(operand.value))); + else + res.Substitute(std::to_string(std::stod(value) - std::stoi(operand.value))); + break; } - - Variable operator - (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", _t); - - if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"-", type_strname[_t], type_strname[operand._t]}); - switch (_t) { - case BOOL: - if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"-", "boolean", type_strname[operand._t]}); - res.Substitute(std::to_string(std::stoi(value)-std::stoi(operand.value) != 0)); - break; - case INT: - if (operand._t == DOUBLE) - res.Substitute(std::to_string((Int)(std::stoi(value)-std::stod(operand.value)))); - else - res.Substitute(std::to_string(std::stoi(value)-std::stoi(operand.value))); - break; - case DOUBLE: - if (operand._t == DOUBLE) - res.Substitute(std::to_string(std::stod(value)-std::stod(operand.value))); - else - res.Substitute(std::to_string(std::stod(value)-std::stoi(operand.value))); - break; - } - return res; + return res; + } + + Variable operator*(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", _t); + + if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"*", type_strname[_t], type_strname[operand._t]}); + switch (_t) { + case BOOL: + if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"*", "boolean", type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(value) * std::stoi(operand.value) != 0)); + break; + case INT: + if (operand._t == DOUBLE) + res.Substitute(std::to_string((Int)(std::stoi(value) * std::stod(operand.value)))); + else + res.Substitute(std::to_string(std::stoi(value) * std::stoi(operand.value))); + break; + case DOUBLE: + if (operand._t == DOUBLE) + res.Substitute(std::to_string(std::stod(value) * std::stod(operand.value))); + else + res.Substitute(std::to_string(std::stod(value) * std::stoi(operand.value))); + break; } - - Variable operator * (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", _t); - - if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"*", type_strname[_t], type_strname[operand._t]}); - switch (_t) { - case BOOL: - if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"*", "boolean", type_strname[operand._t]}); - res.Substitute(std::to_string(std::stoi(value)*std::stoi(operand.value) != 0)); - break; - case INT: - if (operand._t == DOUBLE) - res.Substitute(std::to_string((Int)(std::stoi(value)*std::stod(operand.value)))); - else - res.Substitute(std::to_string(std::stoi(value)*std::stoi(operand.value))); - break; - case DOUBLE: - if (operand._t == DOUBLE) - res.Substitute(std::to_string(std::stod(value)*std::stod(operand.value))); - else - res.Substitute(std::to_string(std::stod(value)*std::stoi(operand.value))); - break; - } - return res; + return res; + } + + Variable operator/(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", _t); + + if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"/", type_strname[_t], type_strname[operand._t]}); + if (operand.GetValue() == "0") ErrHandler().CallErr(runtime_codeline, DIVIDING_WITH_ZERO, {}); + switch (_t) { + case BOOL: + if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"/", "boolean", type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(value) / std::stoi(operand.value) != 0)); + break; + case INT: + if (operand._t == DOUBLE) + res.Substitute(std::to_string((Int)(std::stoi(value) / std::stod(operand.value)))); + else + res.Substitute(std::to_string(std::stoi(value) / std::stoi(operand.value))); + break; + case DOUBLE: + if (operand._t == DOUBLE) + res.Substitute(std::to_string(std::stod(value) / std::stod(operand.value))); + else + res.Substitute(std::to_string(std::stod(value) / std::stoi(operand.value))); + break; } - - Variable operator / (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", _t); - - if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"/", type_strname[_t], type_strname[operand._t]}); - if (operand.GetValue() == "0") ErrHandler().CallErr(runtime_codeline, DIVIDING_WITH_ZERO, {}); - switch (_t) { - case BOOL: - if (operand._t == STRING || operand._t == DOUBLE) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"/", "boolean", type_strname[operand._t]}); - res.Substitute(std::to_string(std::stoi(value)/std::stoi(operand.value) != 0)); - break; - case INT: - if (operand._t == DOUBLE) - res.Substitute(std::to_string((Int)(std::stoi(value)/std::stod(operand.value)))); - else - res.Substitute(std::to_string(std::stoi(value)/std::stoi(operand.value))); - break; - case DOUBLE: - if (operand._t == DOUBLE) - res.Substitute(std::to_string(std::stod(value)/std::stod(operand.value))); - else - res.Substitute(std::to_string(std::stod(value)/std::stoi(operand.value))); - break; - } - return res; + return res; + } + + Variable operator%(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", _t); + + if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"%", type_strname[_t], type_strname[operand._t]}); + if (operand.GetValue() == "0") ErrHandler().CallErr(runtime_codeline, DIVIDING_WITH_ZERO, {}); + switch (_t) { + case INT: + res.Substitute(std::to_string(std::stoi(value) % std::stoi(operand.value))); + break; } + return res; + } - Variable operator % (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", _t); + Variable operator==(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - if (operand._t == STRING || _t == STRING) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"%", type_strname[_t], type_strname[operand._t]}); - if (operand.GetValue() == "0") ErrHandler().CallErr(runtime_codeline, DIVIDING_WITH_ZERO, {}); - switch (_t) { - case INT: - res.Substitute(std::to_string(std::stoi(value)%std::stoi(operand.value))); - break; - } - return res; - } + if (operand._t != _t) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WHEN_COMP, {type_strname[_t], type_strname[operand._t]}); + res.Substitute(std::to_string(operand.GetValue() == GetValue())); - Variable operator == (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - if (operand._t != _t) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WHEN_COMP, {type_strname[_t], type_strname[operand._t]}); - res.Substitute(std::to_string(operand.GetValue()==GetValue())); + Variable operator!=(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - return res; - } + if (operand._t != _t) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WHEN_COMP, {type_strname[_t], type_strname[operand._t]}); + res.Substitute(std::to_string(operand.GetValue() != GetValue())); - Variable operator != (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - if (operand._t != _t) ErrHandler().CallErr(runtime_codeline, NOT_MATCHING_TYPE_WHEN_COMP, {type_strname[_t], type_strname[operand._t]}); - res.Substitute(std::to_string(operand.GetValue()!=GetValue())); + Variable operator>(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - return res; + try { + res.Substitute(std::to_string(operand.GetValue() > GetValue())); + } catch (const std::exception& e) { + ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {">"}); } - Variable operator > (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - try { - res.Substitute(std::to_string(operand.GetValue()>GetValue())); - } - catch(const std::exception& e) { - ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {">"}); - } + Variable operator<(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - return res; + try { + res.Substitute(std::to_string(operand.GetValue() < GetValue())); + } catch (const std::exception& e) { + ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {"<"}); } - Variable operator < (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - try { - res.Substitute(std::to_string(operand.GetValue()=(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - return res; + try { + res.Substitute(std::to_string(operand.GetValue() >= GetValue())); + } catch (const std::exception& e) { + ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {">="}); } - Variable operator >= (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - try { - res.Substitute(std::to_string(operand.GetValue()>=GetValue())); - } - catch(const std::exception& e) { - ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {">="}); - } + Variable operator<=(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); - return res; + try { + res.Substitute(std::to_string(operand.GetValue() <= GetValue())); + } catch (const std::exception& e) { + ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {"<="}); } - Variable operator <= (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); + return res; + } - try { - res.Substitute(std::to_string(operand.GetValue()<=GetValue())); - } - catch(const std::exception& e) { - ErrHandler().CallErr(runtime_codeline, ERROR_OCCURED_WHILE_CALLING_FUNCTION, {"<="}); - } + Variable operator!() { + Variable res = Variable("_", "", BOOL); - return res; - } + if (_t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE_UNARY, {"!"}); + res.Substitute(std::to_string(!(std::stoi(GetValue())))); + return res; + } - Variable operator ! () { - Variable res = Variable("_", "", BOOL); + Variable operator&&(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); + if (_t != BOOL || operand._t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"&&", type_strname[_t], type_strname[operand._t]}); - if (_t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE_UNARY, {"!"}); - res.Substitute(std::to_string( - !(std::stoi(GetValue())) - )); - return res; - } - - Variable operator && (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); - if (_t != BOOL || operand._t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"&&", type_strname[_t], type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(operand.GetValue()) && std::stoi(GetValue()))); - res.Substitute(std::to_string(std::stoi(operand.GetValue())&&std::stoi(GetValue()))); + return res; + } - return res; - } + Variable operator||(Variable operand) { + if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); + Variable res = Variable("_", "", BOOL); + if (_t != BOOL || operand._t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"||", type_strname[_t], type_strname[operand._t]}); - Variable operator || (Variable operand) { - if (operand.GetValue() == "" || GetValue() == "") ErrHandler().CallErr(runtime_codeline, BLANK_OPERAND, {}); - Variable res = Variable("_", "", BOOL); - if (_t != BOOL || operand._t != BOOL) ErrHandler().CallErr(runtime_codeline, NO_OPERATION_MATCHING_TYPE, {"||", type_strname[_t], type_strname[operand._t]}); + res.Substitute(std::to_string(std::stoi(operand.GetValue()) || std::stoi(GetValue()))); - res.Substitute(std::to_string(std::stoi(operand.GetValue())||std::stoi(GetValue()))); + return res; + } - return res; - } + // management + inline Err Substitute(String newval); // substitute + inline String GetValue(); // extract - // management - inline Err Substitute(String newval); // substitute - inline String GetValue(); // extract - - // utility - inline String trim(String s) { s = s.erase(0,1); return s.erase(s.length()-1, 1); } + // utility + inline String trim(String s) { + s = s.erase(0, 1); + return s.erase(s.length() - 1, 1); + } }; inline Err Variable::Substitute(String newval) { - if (newval == "") return OK; - try { - switch (_t) { - case INT: - value = std::to_string(std::stoi(newval)); - break; - case DOUBLE: - value = std::to_string(std::stod(newval)); - break; - case BOOL: - value = std::to_string(std::stoi(newval)); - break; - case STRING: - if (newval == "") {value = newval; break;} - if (newval[0] != '"' || newval[newval.length()-1] != '"' || newval.length() < 2) return ERROR; - value = newval; - break; - case OPERATOR: - value = newval; - break; + if (newval == "") return OK; + try { + switch (_t) { + case INT: + value = std::to_string(std::stoi(newval)); + break; + case DOUBLE: + value = std::to_string(std::stod(newval)); + break; + case BOOL: + value = std::to_string(std::stoi(newval)); + break; + case STRING: + if (newval == "") { + value = newval; + break; } + if (newval[0] != '"' || newval[newval.length() - 1] != '"' || newval.length() < 2) return ERROR; + value = newval; + break; + case OPERATOR: + value = newval; + break; } - catch(const std::exception& e) { - return ERROR; - } + } catch (const std::exception& e) { + return ERROR; + } - return OK; + return OK; } inline String Variable::GetValue() { return value; } @@ -326,8 +326,8 @@ inline String Variable::GetValue() { return value; } // struct VariableWithCode // Has Variable class and Err enum as elements. struct VariableWithCode { - Variable var; - Err error; + Variable var; + Err error; }; -#endif +#endif \ No newline at end of file