Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build_nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build, Test and provide Nightly (Ubuntu + MSYS1)

on:
pull_request:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
push:
workflow_dispatch:

Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ibm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ name: IBM Power & Z

on:
pull_request:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
push:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
# manual run in actions tab - for all branches
workflow_dispatch:

jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: MacOS Workflow

on:
pull_request:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
push:
workflow_dispatch:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Windows MSVC Workflow

on:
pull_request:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
push:
workflow_dispatch:

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-msys2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Windows MSYS2 Workflow

on:
pull_request:
branches: [ gitside-gnucobol-3.x ]
branches: [ gitside-gnucobol-3.x, oo4gnucobol-3.x ]
push:
workflow_dispatch:

Expand Down
15 changes: 15 additions & 0 deletions cobc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
* field.c (warn_pic_for_numeric_value_implied): Added fix to print
Implied PIC warning only when needed

2026-06-11 Saurabh Kumar <developer.saurabh@outlook.com>

* parser.y, reserved.c: add support for parsing class attributes - AS literal,
IS FINAL, INHERITS FROM {class-name ...}, USING {param-name ...}
with unimplemented warning; also support MF extensions IS STATIC, IS ABSTRACT,
IS PARTIAL, IS PUBLIC, IS INTERNAL
* tree.h, common.h: add COB_MODULE_TYPE_CLASS and bit masks for all
object-oriented class attributes

2026-06-08 Nicolas Berthier <nicolas.berthier@ocamlpro.com>

* tree.h, parser.y: change type of cobc_cs_check flags to permit
Expand All @@ -45,6 +54,12 @@
at that position
* pplex.c,cobc.c: use the new type of cb_tab_width

2026-04-08 Saurabh Kumar <developer.saurabh@outlook.com>

* scanner.l: add support for scanning class names and "END CLASS" token.
* parser.y, reserved.c (class_definition): support parsing an "empty"
CLASS-ID paragraph with no contained paragraphs and divisions.

2025-12-29 Roger Bowler <rbowler@snipix.net>

* tree.c (finalize_file): if file is EXTFH enabled then don't warn for
Expand Down
176 changes: 169 additions & 7 deletions cobc/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
#define EVAL_DEPTH 32
#define PROG_DEPTH 16


/* Global variables */

struct cb_program *current_program = NULL; /* program in parse/syntax check/codegen */
Expand Down Expand Up @@ -1287,10 +1288,17 @@ begin_scope_of_program_name (struct cb_program *program)
elt_name);
return;
} else if (strcmp (prog_id, elt_id) == 0) {
cb_error_x (CB_TREE(program),
_("redefinition of program ID '%s'"),
elt_id);
return;
if (program->prog_type == COB_MODULE_TYPE_PROGRAM) {
cb_error_x (CB_TREE(program),
_("redefinition of program ID '%s'"),
elt_id);
return;
} else if (program->prog_type == COB_MODULE_TYPE_CLASS) {
cb_error_x (CB_TREE(program),
_("redefinition of class ID '%s'"),
elt_id);
return;
}
}
}

Expand Down Expand Up @@ -1471,7 +1479,7 @@ setup_program (cb_tree id, cb_tree as_literal, const enum cob_module_type type,
main_flag_set = 1;
current_program->flag_main = !!cobc_flag_main;
}
} else { /* COB_MODULE_TYPE_FUNCTION */
} else if (type == COB_MODULE_TYPE_FUNCTION) {
current_program->flag_recursive = 1;
}

Expand Down Expand Up @@ -1515,8 +1523,13 @@ decrement_depth (const char *name, const unsigned char type)
}

if (depth != d) {
cb_error (_("END PROGRAM '%s' is different from PROGRAM-ID '%s'"),
name, stack_progid[depth]);
if (type == COB_MODULE_TYPE_PROGRAM) {
cb_error (_("END PROGRAM '%s' is different from PROGRAM-ID '%s'"),
name, stack_progid[depth]);
} else if (type == COB_MODULE_TYPE_CLASS) {
cb_error (_("END CLASS '%s' is different from CLASS-ID '%s'"),
name, stack_progid[depth]);
}
}
}

Expand Down Expand Up @@ -2548,12 +2561,24 @@ set_record_size (cb_tree min, cb_tree max)
}
}

/* Object-oriented class */

static COB_INLINE void
set_oo_class_attr(enum cb_oo_class_attribute attr, const char* attr_name)
{
if (current_program->oo_class_attributes & attr) {
emit_duplicate_clause_message (attr_name);
}
current_program->oo_class_attributes |= attr;
}

%}

%token TOKEN_EOF 0 "end of file"

%token THREEDIMENSIONAL "3D"
%token ABSENT
%token ABSTRACT
%token ACCEPT
%token ACCESS
%token ACTIVEX "ACTIVE-X"
Expand Down Expand Up @@ -2676,6 +2701,7 @@ set_record_size (cb_tree min, cb_tree max)
%token CHARACTERS
%token CHECK_BOX "CHECK-BOX"
%token CLASS
%token CLASS_ID "CLASS-ID"
%token CLASSIFICATION
%token CLASS_NAME "class-name"
%token CLEAR_SELECTION "CLEAR-SELECTION"
Expand Down Expand Up @@ -2825,6 +2851,7 @@ set_record_size (cb_tree min, cb_tree max)
%token END_MULTIPLY "END-MULTIPLY"
%token END_PERFORM "END-PERFORM"
%token END_PROGRAM "END PROGRAM"
%token END_CLASS "END CLASS"
%token END_READ "END-READ"
%token END_RECEIVE "END-RECEIVE"
%token END_RETURN "END-RETURN"
Expand Down Expand Up @@ -2968,6 +2995,7 @@ set_record_size (cb_tree min, cb_tree max)
%token INDEX
%token INDEXED
%token INDICATE
%token INHERITS
%token INITIALIZE
%token INITIALIZED
%token INITIATE
Expand All @@ -2979,6 +3007,7 @@ set_record_size (cb_tree min, cb_tree max)
%token INSPECT
%token INSTALLATION /* remark: not used here */
%token INTERMEDIATE
%token INTERNAL
%token INTO
%token INTRINSIC
%token INVALID /* remark: not used here */
Expand Down Expand Up @@ -3165,6 +3194,7 @@ set_record_size (cb_tree min, cb_tree max)
%token PARAGRAPH
%token PARENT
%token PARSE
%token PARTIAL
%token PASSWORD
%token PERFORM
%token PERMANENT
Expand Down Expand Up @@ -3207,6 +3237,7 @@ set_record_size (cb_tree min, cb_tree max)
%token PROPERTY
%token PROTECTED
%token PROTOTYPE
%token PUBLIC
%token PURGE
%token PUSH_BUTTON "PUSH-BUTTON"
%token QUERY_INDEX "QUERY-INDEX"
Expand Down Expand Up @@ -3714,6 +3745,7 @@ source_element_list:

source_element:
program_definition
| class_definition
| function_definition
| program_prototype
| function_prototype
Expand Down Expand Up @@ -3742,6 +3774,13 @@ program_definition:
*/
;

class_definition:
_identification_header
class_id_paragraph
/* TODO: _program_body */
end_class
;

function_definition:
_identification_header
function_id_paragraph
Expand Down Expand Up @@ -3776,6 +3815,19 @@ end_program:
}
;

end_class:
END_CLASS
{
last_source_line = cb_source_line;
check_area_a_of ("END CLASS");
}
end_class_name _dot
{
clean_up_program ($3, COB_MODULE_TYPE_CLASS);
}

;

end_function:
END_FUNCTION
{
Expand Down Expand Up @@ -3950,6 +4002,116 @@ _default_display_clause:
}
;

/* CLASS */

class_id_header:
CLASS_ID
{
cobc_in_id = 1;
}
;

class_id_name:
CLASS_NAME { $$ = $1; }
| LITERAL
{
cb_trim_program_id ($1);
}
;

parent_class_name:
WORD
{
current_program->class_inheritance_list =
cb_list_add(current_program->class_inheritance_list, $1);
}
;

parent_class_name_list:
parent_class_name
| parent_class_name_list parent_class_name
;

/* Parameterized classes not supported for now. */
class_param_list:
WORD
| class_param_list WORD
;

_inherits_phrase:
/* empty */
| INHERITS _from parent_class_name_list
;

_using_phrase:
/* empty */
| USING class_param_list
;

class_attribute:
_is STATIC { set_oo_class_attr(CB_OO_CLASS_ATTR_STATIC, "STATIC"); }
| _is PARTIAL { set_oo_class_attr(CB_OO_CLASS_ATTR_PARTIAL, "PARTIAL"); }
| _is FINAL { set_oo_class_attr(CB_OO_CLASS_ATTR_FINAL, "FINAL"); }
| _is ABSTRACT { set_oo_class_attr(CB_OO_CLASS_ATTR_ABSTRACT, "ABSTRACT"); }
| _is PUBLIC { set_oo_class_attr(CB_OO_CLASS_ATTR_PUBLIC, "PUBLIC"); }
| _is INTERNAL { set_oo_class_attr(CB_OO_CLASS_ATTR_INTERNAL, "INTERNAL"); }
;

_class_attributes:
/* empty */ { current_program->oo_class_attributes = CB_OO_CLASS_ATTR_NONE; }
| _class_attributes class_attribute
;

/*
* CLASS-ID paragraph syntax is:
*
* CLASS-ID. object-class-name-1 [ AS literal-1 ] [ IS STATIC ]
* [ IS { PARTIAL, FINAL, ABSTRACT } ... ] [ IS { PUBLIC, INTERNAL } ]
* [ INHERITS FROM { object-class-name-2 } ... ]
* [ USING { parameter-name-1 } ... ] .
*
*/

class_id_paragraph:
class_id_header TOK_DOT class_id_name _as_literal
{
if (setup_program ($3, $4, COB_MODULE_TYPE_CLASS, 1)) {
YYABORT;
}

__CS_CLEAR_ALL();
cobc_in_id = 0;

CB_UNSUPPORTED ("object-oriented COBOL");
}
_inherits_phrase
_class_attributes
_using_phrase
TOK_DOT
{
/* check consistency of current attribues */
if (current_program->oo_class_attributes & CB_OO_CLASS_ATTR_FINAL
&& current_program->oo_class_attributes & CB_OO_CLASS_ATTR_ABSTRACT) {
emit_conflicting_clause_message ("FINAL", "ABSTRACT");
current_program->oo_class_attributes &= ~CB_OO_CLASS_ATTR_FINAL;
}
if (current_program->oo_class_attributes & CB_OO_CLASS_ATTR_INTERNAL
&& current_program->oo_class_attributes & CB_OO_CLASS_ATTR_PUBLIC) {
emit_conflicting_clause_message ("INTERNAL", "PUBLIC");
current_program->oo_class_attributes &= ~CB_OO_CLASS_ATTR_INTERNAL;
}
}
;

end_class_name:
CLASS_NAME
| LITERAL
{
cb_trim_program_id ($1);
}
;


/* PROGRAM body */

_program_body:
Expand Down
Loading
Loading