From 5bb9d5189f9150af3e8c761f41d7ff3006848e4d Mon Sep 17 00:00:00 2001 From: Lartu <11744462+Lartu@users.noreply.github.com> Date: Sat, 29 Jun 2024 20:35:37 -0300 Subject: [PATCH] Add % to in ... solve and < / > / <> / >= / <= / = ops --- src/aux/aux_c_format.cpp | 39 ++++- src/aux/aux_line_like.cpp | 298 ++++++++++++++++++++++++-------------- src/aux/aux_typecheck.cpp | 58 +++++--- 3 files changed, 262 insertions(+), 133 deletions(-) diff --git a/src/aux/aux_c_format.cpp b/src/aux/aux_c_format.cpp index f3d7abb..2d515e6 100644 --- a/src/aux/aux_c_format.cpp +++ b/src/aux/aux_c_format.cpp @@ -5,6 +5,8 @@ // | TODO: comment and format this file properly | // +---------------------------------------------+ +#include "../ldpl.h" + // Given a full variable (with accesses and everything, like foo:0:'hi there' or // bar) returns the C++ representation of said variable in order to be accessed. string get_c_variable(compiler_state &state, string &variable) @@ -103,9 +105,12 @@ string get_c_condition(compiler_state &state, vector tokens, string second_value; string rel_op; ct++; // We validate the token after we get the second value - if (tokens[ct] == "IS") + if (tokens[ct] == "IS" || tokens[ct] == "=" || tokens[ct] == "<>" || tokens[ct] == "<" || tokens[ct] == ">" || tokens[ct] == "<=" || tokens[ct] == ">=") { - MATCH("IS"); + if (tokens[ct] == "IS") + { + MATCH("IS"); + } if (tokens[ct] == "EQUAL") { MATCH("EQUAL"); @@ -155,6 +160,36 @@ string get_c_condition(compiler_state &state, vector tokens, rel_op = "LESS THAN"; } } + else if (tokens[ct] == "<") + { + MATCH("<"); + rel_op = "LESS THAN"; + } + else if (tokens[ct] == "<=") + { + MATCH("<="); + rel_op = "LESS THAN OR EQUAL TO"; + } + else if (tokens[ct] == ">") + { + MATCH(">"); + rel_op = "GREATER THAN"; + } + else if (tokens[ct] == ">=") + { + MATCH(">="); + rel_op = "GREATER THAN OR EQUAL TO"; + } + else if (tokens[ct] == "=") + { + MATCH("="); + rel_op = "EQUAL TO"; + } + else if (tokens[ct] == "<>") + { + MATCH("<>"); + rel_op = "NOT EQUAL TO"; + } else { return "[ERROR]"; diff --git a/src/aux/aux_line_like.cpp b/src/aux/aux_line_like.cpp index b02ecf6..9ba8f5e 100644 --- a/src/aux/aux_line_like.cpp +++ b/src/aux/aux_line_like.cpp @@ -4,149 +4,222 @@ // | TODO: comment and format this file properly | // +---------------------------------------------+ +#include "../ldpl.h" + // Check if the tokens of a line passed are like the ones of a model line bool line_like(string model_line, vector &tokens, - compiler_state &state) { + compiler_state &state) +{ // Tokenize model line vector model_tokens; tokenize(model_line, model_tokens, state.where, false, ' '); // Check that tokens match between line and model line - if (tokens.size() < model_tokens.size()) return false; + if (tokens.size() < model_tokens.size()) + return false; unsigned int i = 0; unsigned int j = 0; - for (; i < model_tokens.size(); ++i) { - if (model_tokens[i] == "$name") // $name is a valid identifier for a - // variable or a sub-procedure + for (; i < model_tokens.size(); ++i) + { + if (model_tokens[i] == "$name") // $name is a valid identifier for a + // variable or a sub-procedure { for (char letter : tokens[j]) - if (letter == ':') return false; + if (letter == ':') + return false; for (char letter : tokens[j]) - if (letter == '\"') return false; + if (letter == '\"') + return false; for (char letter : tokens[j]) - if (letter == '(') return false; + if (letter == '(') + return false; for (char letter : tokens[j]) - if (letter == ')') return false; - if (is_number(tokens[j])) return false; - if (tokens[j] == "+") return false; - if (tokens[j] == "-") return false; - if (tokens[j] == "*") return false; - if (tokens[j] == "/") return false; - } else if (model_tokens[i] == "$num-var") // $num-var is NUMBER variable - { - if (!is_num_var(tokens[j], state)) return false; - } else if (model_tokens[i] == "$str-var") // $str-var is TEXT variable - { - if (!is_txt_var(tokens[j], state)) return false; - } else if (model_tokens[i] == - "$var") // $var is either a NUMBER variable or a TEXT variable - { - if (!is_scalar_variable(tokens[j], state)) return false; - } else if (model_tokens[i] == "$anyVar") // $anyVar is any variable - { - if (!variable_exists(tokens[j], state)) return false; - } else if (model_tokens[i] == - "$scalar-map") { // $scalar-map is TEXT MAP, NUMBER MAP - if (!is_scalar_map(tokens[j], state)) return false; - } else if (model_tokens[i] == "$num-vec") // $num-vec is NUMBER vector - { - if (!is_num_map(tokens[j], state)) return false; - } else if (model_tokens[i] == "$str-vec") // $str-vec is TEXT vector - { - if (!is_txt_map(tokens[j], state)) return false; - } else if (model_tokens[i] == "$list") { // $list is a LIST - if (variable_type(tokens[j], state).back() != 3) return false; - } else if (model_tokens[i] == "$map") { // $map is a MAP - if (variable_type(tokens[j], state).back() != 4) return false; - } else if (model_tokens[i] == - "$scalar-list") { // $scalar-list is a LIST of scalar values - if (!is_scalar_list(tokens[j], state)) return false; - } else if (model_tokens[i] == "$num-list") // $num-vec is NUMBER list - { - if (!is_num_list(tokens[j], state)) return false; - } else if (model_tokens[i] == "$str-list") // $str-vec is TEXT list - { - if (!is_txt_list(tokens[j], state)) return false; - } else if (model_tokens[i] == "$list-list") // $str-vec is a LIST of LISTs - { - if (!is_list_list(tokens[j], state)) return false; - } else if (model_tokens[i] == "$map-list") // $str-vec is LIST of MAPs - { - if (!is_map_list(tokens[j], state)) return false; - } else if (model_tokens[i] == - "$collection") // $collection is either a MAP or a LIST + if (letter == ')') + return false; + if (is_number(tokens[j])) + return false; + if (tokens[j] == "+") + return false; + if (tokens[j] == "-") + return false; + if (tokens[j] == "*") + return false; + if (tokens[j] == "/") + return false; + if (tokens[j] == "%") + return false; + } + else if (model_tokens[i] == "$num-var") // $num-var is NUMBER variable + { + if (!is_num_var(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$str-var") // $str-var is TEXT variable + { + if (!is_txt_var(tokens[j], state)) + return false; + } + // $var is either a NUMBER variable or a TEXT variable + else if (model_tokens[i] == "$var") + { + if (!is_scalar_variable(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$anyVar") // $anyVar is any variable + { + if (!variable_exists(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$scalar-map") + { // $scalar-map is TEXT MAP, NUMBER MAP + if (!is_scalar_map(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$num-vec") // $num-vec is NUMBER vector + { + if (!is_num_map(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$str-vec") // $str-vec is TEXT vector + { + if (!is_txt_map(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$list") + { // $list is a LIST + if (variable_type(tokens[j], state).back() != 3) + return false; + } + else if (model_tokens[i] == "$map") + { // $map is a MAP + if (variable_type(tokens[j], state).back() != 4) + return false; + } + else if (model_tokens[i] == "$scalar-list") + { // $scalar-list is a LIST of scalar values + if (!is_scalar_list(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$num-list") // $num-vec is NUMBER list + { + if (!is_num_list(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$str-list") // $str-vec is TEXT list + { + if (!is_txt_list(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$list-list") // $str-vec is a LIST of LISTs + { + if (!is_list_list(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$map-list") // $str-vec is LIST of MAPs + { + if (!is_map_list(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$collection") // $collection is either a MAP or a LIST { // if(!is_scalar_map(tokens[j], state) && !is_scalar_list(tokens[j], // state) && (variable_type(tokens[j], state).size() < 2)) return false; - if (variable_type(tokens[j], state).size() < 2) return false; - } else if (model_tokens[i] == - "$literal") // $literal is either a NUMBER or a TEXT - { - if (!is_string(tokens[j]) && !is_number(tokens[j])) return false; - } else if (model_tokens[i] == "$string") // $string is a TEXT literal - { - if (!is_string(tokens[j])) return false; - } else if (model_tokens[i] == "$number") // $number is a NUMBER literal - { - if (!is_number(tokens[j])) return false; - } else if (model_tokens[i] == "$expression") // $expression is NUMBER, - // TEXT, TEXT-VAR, NUMBER-VAR - { - if (!is_expression(tokens[j], state)) return false; - } else if (model_tokens[i] == - "$str-expr") // $str-expr is either a TEXT or a TEXT variable - { - if (!is_txt_expr(tokens[j], state)) return false; - } else if (model_tokens[i] == "$num-expr") // $num-expr is either a NUMBER - // or a NUMBER variable - { - if (!is_num_expr(tokens[j], state)) return false; - } else if (model_tokens[i].find("$var-type-") == - 0) // variable with a given type number + if (variable_type(tokens[j], state).size() < 2) + return false; + } + else if (model_tokens[i] == "$literal") // $literal is either a NUMBER or a TEXT + { + if (!is_string(tokens[j]) && !is_number(tokens[j])) + return false; + } + else if (model_tokens[i] == "$string") // $string is a TEXT literal + { + if (!is_string(tokens[j])) + return false; + } + else if (model_tokens[i] == "$number") // $number is a NUMBER literal + { + if (!is_number(tokens[j])) + return false; + } + else if (model_tokens[i] == "$expression") // $expression is NUMBER, + // TEXT, TEXT-VAR, NUMBER-VAR + { + if (!is_expression(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$str-expr") // $str-expr is either a TEXT or a TEXT variable + { + if (!is_txt_expr(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$num-expr") // $num-expr is either a NUMBER + // or a NUMBER variable + { + if (!is_num_expr(tokens[j], state)) + return false; + } + else if (model_tokens[i].find("$var-type-") == 0) // variable with a given type number { vector actual_type = variable_type(tokens[j], state); string expected_type = model_tokens[i].substr(10); - if (actual_type.size() != expected_type.length()) return false; - for (size_t t = 0; t < actual_type.size(); ++t) { - if ((int)actual_type[t] != expected_type[t] - '0') return false; + if (actual_type.size() != expected_type.length()) + return false; + for (size_t t = 0; t < actual_type.size(); ++t) + { + if ((int)actual_type[t] != expected_type[t] - '0') + return false; } - } else if (model_tokens[i] == - "$natural") // $natural is an integer greater than 0 + } + else if (model_tokens[i] == "$natural") // $natural is an integer greater than 0 { - if (!is_natural(tokens[j])) return false; - } else if (model_tokens[i] == - "$display") // multiple NUMBER, TEXT, TEXT-VAR, NUMBER-VAR + if (!is_natural(tokens[j])) + return false; + } + else if (model_tokens[i] == "$display") // multiple NUMBER, TEXT, TEXT-VAR, NUMBER-VAR { - for (; j < tokens.size(); ++j) { - if (!is_expression(tokens[j], state)) return false; + for (; j < tokens.size(); ++j) + { + if (!is_expression(tokens[j], state)) + return false; } - } else if (model_tokens[i] == - "$subprocedure") // $subprocedure is a SUB-PROCEDURE + } + else if (model_tokens[i] == "$subprocedure") // $subprocedure is a SUB-PROCEDURE { - if (!is_subprocedure(tokens[j], state)) return false; - } else if (model_tokens[i] == - "$external") // $external is a C++ function defined elsewhere + if (!is_subprocedure(tokens[j], state)) + return false; + } + else if (model_tokens[i] == "$external") // $external is a C++ function defined elsewhere { return !is_subprocedure(tokens[j], state) && !is_expression(tokens[j], state); - } else if (model_tokens[i] == "$label") // $label is a GOTO label + } + else if (model_tokens[i] == "$label") // $label is a GOTO label { return is_label(tokens[j]); - } else if (model_tokens[i] == "$math") // $math is a math expression + } + else if (model_tokens[i] == "$math") // $math is a math expression { - vector maths; // further tokenize math expressions + vector maths; // further tokenize math expressions string math_token = ""; - for (; j < tokens.size(); ++j) { - for (unsigned int z = 0; z < tokens[j].size(); ++z) { - if (tokens[j][z] == '(' || tokens[j][z] == ')') { - if (!math_token.empty()) maths.push_back(math_token); + for (; j < tokens.size(); ++j) + { + for (unsigned int z = 0; z < tokens[j].size(); ++z) + { + if (tokens[j][z] == '(' || tokens[j][z] == ')') + { + if (!math_token.empty()) + maths.push_back(math_token); math_token = tokens[j][z]; maths.push_back(math_token); math_token = ""; - } else { + } + else + { math_token += tokens[j][z]; } } - if (!math_token.empty()) maths.push_back(math_token); + if (!math_token.empty()) + maths.push_back(math_token); math_token = ""; } // replace LDPL line tokens with new math tokens @@ -154,24 +227,27 @@ bool line_like(string model_line, vector &tokens, tokens.insert(tokens.end(), maths.begin(), maths.end()); // validate the new tokens - for (unsigned int z = i; z < tokens.size(); ++z) { + for (unsigned int z = i; z < tokens.size(); ++z) + { if (!is_math_symbol(tokens[z]) && !is_expression(tokens[z], state)) return false; } return true; - } else if (model_tokens[i] == - "$condition") // $condition is a IF/WHILE condition + } + else if (model_tokens[i] == "$condition") // $condition is a IF/WHILE condition { // Skip to the last token (THEN/DO), // the condition is validated in get_c_condition j = tokens.size() - 1; continue; - } else if (model_tokens[i] == "$anything") + } + else if (model_tokens[i] == "$anything") return true; else if (model_tokens[i] != tokens[j]) return false; ++j; } - if (j < tokens.size()) return false; + if (j < tokens.size()) + return false; return true; } \ No newline at end of file diff --git a/src/aux/aux_typecheck.cpp b/src/aux/aux_typecheck.cpp index 8cdb8cb..817d437 100644 --- a/src/aux/aux_typecheck.cpp +++ b/src/aux/aux_typecheck.cpp @@ -1,24 +1,30 @@ /* This file contains auxiliary functions to check data type compliance */ +#include "../ldpl.h" -bool is_number(string &number) { +bool is_number(string &number) +{ // -- Checks if a string is a valid real number -- unsigned int firstchar = 0; - if (number[0] == '-') firstchar = 1; + if (number[0] == '-') + firstchar = 1; if (number[firstchar] == '.') - return false; // .12 is not a valid decimal in LDPL, 0.12 is. + return false; // .12 is not a valid decimal in LDPL, 0.12 is. if (number[firstchar] == '+') - return false; // +5 is not a valid decimal in LDPL, 5 is. + return false; // +5 is not a valid decimal in LDPL, 5 is. istringstream iss(number); double f; iss >> f; bool isNumber = iss.eof() && !iss.fail(); // If it is a number, it might be an octal literal (e.g. 025, 067, 003 etc) // so we proceed to fix the original number to make it decimal. - if (isNumber) { + if (isNumber) + { string f_number = ""; unsigned int i; - for (i = 1; i < number.length(); ++i) { - if (number[i - 1] != '0') { + for (i = 1; i < number.length(); ++i) + { + if (number[i - 1] != '0') + { // If prev char not 0 if (number[i - 1] == '-') // if prev char is -, continue check @@ -26,46 +32,58 @@ bool is_number(string &number) { else // if prev char is number, break break; - } else if (number[i] == '.') + } + else if (number[i] == '.') // If prev number is 0 f_number += '0'; } f_number += number.substr(i - 1); number = f_number; return true; - } else + } + else return false; } -bool is_natural(string number) { +bool is_natural(string number) +{ // -- Checks if a string is a valid natural number -- - if (!is_number(number)) return false; - if (stod(number) <= 0) return false; + if (!is_number(number)) + return false; + if (stod(number) <= 0) + return false; for (char l : number) - if (l == '.') return false; + if (l == '.') + return false; return true; } -bool is_label(string &token) { +bool is_label(string &token) +{ // -- Checks if a string is a valid label -- for (char letter : token) - if (letter == '\"') return false; + if (letter == '\"') + return false; return true; } -bool is_math_symbol(string &token) { +bool is_math_symbol(string &token) +{ // -- Checks if a string is a valid math symbol -- - string syms = "+-*/()"; + string syms = "+-*/()%"; return token.size() == 1 && syms.find(token[0]) != string::npos; } -bool is_string(string &token) { +bool is_string(string &token) +{ // -- Checks if a string is a valid LDPL string -- if (token.size() < 2 || token[0] != '"' || token[token.size() - 1] != '"') return false; // Check for unescaped quotes - for (unsigned int i = 1; i < token.size() - 1; ++i) { - if (token[i] == '\"' && token[i - 1] != '\\') return false; + for (unsigned int i = 1; i < token.size() - 1; ++i) + { + if (token[i] == '\"' && token[i - 1] != '\\') + return false; } return true; } \ No newline at end of file