-1
#include <fortran.h>

real function f() code
    return 0.0;
endfunction

program(main)
    if 3 == 3 then
        print(*) "Your PC is fine.";
    elseif 3 == 4 then
        print(*) "Your PC is broken.";
    else
        print(*) "Your PC is trash.";
    endif

    write(*, "(I)") 5);
end

I get the error expected unqualified-id before 'else' in line number 10. I don't know why.

And in line number 16, the program should write '5' on the screen, but I get a runtime error.

Also, C++ is a case sensitive language, is there a way not to make C++ case sensitive?

FORTRAN.H is:

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#define IF if(
#define THEN ){
#define ELSEIF } else if(
#define ELSE }else{
#define ENDIF }
#define if IF
#define then THEN
#define elseif ELSEIF
#define else ELSE
#define endif ENDIF
#define PROGRAM(x) main(){
#define program PROGRAM
#define END }
#define end END
#define STOP exit(0);
#define stop STOP
#define call
#define subroutine
#define recursive
#define function
#define FOR for(
#define for FOR
#define LOOP ){
#define loop LOOP
#define ENDFOR }
#define endfor ENDFOR
#define WHILE while(
#define DO ){
#define ENDDO }
#define enddo ENDDO
#define PRINT(t) std::cout<<
#define _ <<
#define READ std::cin>>
#define $ >>
#define Read READ
#define read READ
#define Print PRINT
#define print PRINT
#define selectcase(x) switch(x){
#define endselectcase }
#define endfunction }
#define code {
typedef char character;
typedef int integer;
typedef double doubleprecision;
typedef float real;

char* function __FORTRAN_WRITE_ARGS(const char* f) code
    integer i;
    std::__cxx11::string arg = "";

    if f[0] != '(' || f[strlen(f)-1] != ')' then
        return "";
    endif

    for i = 0; i < strlen(f); i++ loop
        selectcase(f[i])
            case ' ':
                continue;
                break;
            case '(':
                continue;
                break;
            case ')':
                continue;
                break;
            case ',':
                continue;
                break;
            case 'I':
                if f[i+1] >= 48 && f[i+1] <= 57 then
                    arg += "%";
                    arg += f[i+1];
                    arg += "d";
                else
                    arg += "%d";
                endif

                break;
            default:
                continue;
        endselectcase
    endfor
    char retval[arg.length()] = "";
    strcat(retval, arg.c_str());
    return retval;
endfunction
#define write(t, f) printf(__FORTRAN_WRITE_ARGS(f),
#define endwrite )
#define WRITE write
#define precision

Is there any way to fix this issue or this error?

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • 3
    You can run preprocessor only on your code and see what is generated by the preprocessor: [Can gcc output C code after preprocessing?](https://stackoverflow.com/questions/4900870/can-gcc-output-c-code-after-preprocessing) (similar options should be available for other compilers) – Yksisarvinen Oct 18 '19 at 07:51
  • 1
    Unfortunately the C++ language is case sensitive by definition, as many other languages. See this [link](https://stackoverflow.com/questions/503218/why-are-many-languages-case-sensitive) for more info. You simply must overcome this barrier if you want to become a multi-language programmer. – sɐunıɔןɐqɐp Oct 18 '19 at 08:10

1 Answers1

0

While I like the idea of the project, the implementation is currently flawed and I am unsure you will ever be able to get a 100% conversion. fortran.h uses some old, deprecated practices and contains two actual compile errors.

The main issue (why you asked the question) is plain to see when you run the code through the pre-processor.

int main(){
    if( 3 == 3 ){
        std::cout<< "Your PC is fine.";
    } }else{ if(( 3 == 4 ){  // *** The issue you're having ***
        std::cout<< "Your PC is broken.";
    }else{
        std::cout<< "Your PC is trash.";
    }

    printf(__FORTRAN_WRITE_ARGS("(I)"), 5);
}

The ELSEIF (I eliminated most lowercase variations) gets substituted, but not the way you want. ELSEIF makes its substitution, but then you had done #define else ELSE and #define if IF. That obviously clashes with real C++ and you were making double substitutions which were creating broken code.

Below is my modified fortran.h and main.cpp. It will be worth running a diff on my fortran.h to see exactly what changes I made. It now compiles, but it's still broken. It prints garbage after saying that my computer is fine. I poked around on your WRITE function, but in order to preserve your syntax (which might be incorrect, I don't know Fortran but the '()' don't match up), I couldn't come up with anything reasonable. It will likely need nested macro calling. One to generate the string, and another to actually substitute the string into the printf statement. In figuring this out, the pre-processor only flag, -E, will be your friend to see if the substitutions you are attempting are working.

fortran.h

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>

#define IF if(
#define THEN ){
#define ELSEIF } else if(
#define ELSE }else{
#define ENDIF }
#define PROGRAM(x) int main(){
#define program PROGRAM
#define END }
#define end END
#define STOP exit(0);
#define stop STOP
#define call
#define subroutine
#define recursive
#define function
#define FOR for(
#define LOOP ){
#define ENDFOR }
#define WHILE while(
#define DO ){
#define ENDDO }
#define PRINT(t) std::cout<<
#define _ <<
#define READ std::cin>>
#define $ >>
#define selectcase(x) switch(x){
#define endselectcase }
#define endfunction }
#define CODE {
typedef char character;
typedef int integer;
typedef double doubleprecision;
typedef float real;

char* function __FORTRAN_WRITE_ARGS(const char* f) CODE
    integer i;
    std::string arg = "";  // Removed __cx11, not needed

    IF f[0] != '(' || f[strlen(f)-1] != ')' THEN
        return "";
    ENDIF

    FOR i = 0; i < strlen(f); i++ LOOP
        selectcase(f[i])
            case ' ':
            case '(':
            case ')':
            case ',':
                continue;
                break;
            case 'I':
                IF f[i+1] >= 48 && f[i+1] <= 57 THEN
                    arg += "%";
                    arg += f[i+1];
                    arg += "d";
                ELSE
                    arg += "%d";
                ENDIF

                break;
            default:
                continue;
        endselectcase
    ENDFOR
    char retval[arg.length() + 1];  // Removed pointless initialization, fixed size
    for (auto& I : retail) i = '\0';  // null character initialization
    strncpy(retval, arg.c_str(), arg.length());
    return retval;
endfunction
#define write(t, f) printf(__FORTRAN_WRITE_ARGS(f),
#define endwrite )
#define WRITE write
#define precision

main

#include "fortran.h"  // Not a system include for me, so changed to " "

real function f() CODE
    return 0.0;
endfunction

program(main)
    IF 3 == 3 THEN
        PRINT(*) "Your PC is fine.";
    ELSEIF 3 == 4 THEN
        PRINT(*) "Your PC is broken.";
    ELSE
        PRINT(*) "Your PC is trash.";
    ENDIF

    write(*, "(I)") 5);
END

If the end-goal is to legitimately write C++ code using fortran syntax for something other than novelty, I'd say abandon that idea quickly and just learn C++.

sweenish
  • 4,793
  • 3
  • 12
  • 23
  • 1
    On "using fortran syntax for something other than novelty" it's possibly worth noting that the code of the question is far from being Fortran syntax. The only non-blank lines which are match Fortran syntax are those with `else`, `endif`, `endfunction` and `end`. – francescalus Oct 21 '19 at 12:48
  • Yeah, good to know. I don't know Fortran at all, and don't see myself ever needing to learn it. If I ever did, though, I would just use Fortran. – sweenish Oct 21 '19 at 16:40