//! @file decide.c
//! @author J. Marcel van der Veer
//
//! @section Copyright
//
// This file is part of VIF - vintage FORTRAN compiler.
// Copyright 2020-2025 J. Marcel van der Veer <algol68g@xs4all.nl>.
//
//! @section License
//
// This program is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation; either version 3 of the License, or 
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
// more details. You should have received a copy of the GNU General Public 
// License along with this program. If not, see <http://www.gnu.org/licenses/>.

//! @section Synopsis
//!
//! Decide statement type.

#include <vif.h>

int_4 statement_type (void)
{
// FORTRAN allowed to use a keyword as variable name.
// The meaning of a keyword thus depended on its use.
// Most code does not use this feature, presumably for portability reasons.
// Sometimes code uses IF, SAVE or DATA as variable name.
// Below code determines whether a line is either
//
//   1. An ASSIGNMENT, for instance DATA = 1 or IF (1) = 0
//   2. A MACRO_DECLARATION, for instance SAVE (X) = SIN(X * PI / 180.0)
//   3. A STATEMENT, that is, neither (1) nor (2).
//
  SAVE_POS (1);
  NEW_RECORD (name);
  RECCPY (name, curlex);
  int_4 rc = scan (NULL);
  if (TOKEN ("=")) {
    RESTORE_POS (1);
    return ASSIGNMENT;
  } else if (TOKEN ("(")) {
    int_4 nest = 1;
    while (TRUE) {
      rc = scan (NULL);
      if (rc == END_OF_LINE || rc == END_OF_MODULE) {
        RESTORE_POS (1);
        return NOT_ASSIGNMENT;
      } else if (TOKEN ("(")) {
        nest++;
      } else if (TOKEN (")")) {
        nest--;
        if (nest == 0) {
          rc = scan (NULL);
          if (TOKEN ("=")) {
            MODE mode;
            IDENT *idf = find_local (name, &mode);
            if (idf == NO_IDENT || (!idf->external && !idf->parm && !IS_ROW (idf->mode))) {
              RESTORE_POS (1);
              return MACRO_DECLARATION;
            } else {
              RESTORE_POS (1);
              return ASSIGNMENT;
            }
          } else {
            RESTORE_POS (1);
            return NOT_ASSIGNMENT;
          }
        }
      }
    } 
  } else {
    RESTORE_POS (1);
    return NOT_ASSIGNMENT;
  }
}
