https://gcc.gnu.org/g:c22afe03826072098a3dc0c258a57d34579f3c24

commit r17-1784-gc22afe03826072098a3dc0c258a57d34579f3c24
Author: James K. Lowden <[email protected]>
Date:   Tue Jun 23 12:00:25 2026 -0400

    cobol: Elevate keyword priority.
    
    Move keyword patterns higher in the lexer file, giving them higher
    priority than user-defined names. Fix tests that allowed keywords for
    Program-ID, which must be a user-defined name. Fixes PR 119933.
    
    gcc/cobol/ChangeLog:
    
            * parse.y: Restrict Program-ID as name to top-level.
            * scan.l: Elevate keyword priority in lexer.

Diff:
---
 gcc/cobol/parse.y |   9 +-
 gcc/cobol/scan.l  | 927 +++++++++++++++++++++++++++---------------------------
 2 files changed, 473 insertions(+), 463 deletions(-)

diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index 04a6c966c7a1..73b8ff6ace3a 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -1685,7 +1685,14 @@ dot:            %empty
         |       '.'
                 ;
 program_as:     %empty     { static const literal_t empty {}; $$ = empty; }
-        |       AS LITERAL { $$ = $2; }
+        |       AS LITERAL
+                { // program-id not yet parsed, so top-level is 0
+                  if( 0 != current.program_level() ) {
+                    error_msg(@$, "AS %qs valid only for top-level programs",
+                              $LITERAL.data);
+                  }
+                  $$ = $2;
+                }
                 ;
 
 function_id:    FUNCTION dot  NAME program_as program_attrs[attr] '.'
diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l
index 534754848012..5255cf48b32c 100644
--- a/gcc/cobol/scan.l
+++ b/gcc/cobol/scan.l
@@ -205,7 +205,7 @@ LINE_DIRECTIVE ^[#]line{SPC}[[:alnum:]]+{SPC}[""''].+\n
 
 %option debug noyywrap stack yylineno case-insensitive
 %%
-   /* CDF */
+  /* CDF */
 <bool_state>{
   [''""]/[01]
   [01]+/[''""]         { if( copy_state == YY_START ) {
@@ -1376,6 +1376,24 @@ USE({SPC}FOR)?           { return USE; }
   [=]{2}                { yy_push_state(quoteq); }
 }
 
+<date_state>{
+  ^[[:blank:]]+
+  {BLANK_EOL}
+
+  DATE                { pop_return DATE; }
+  DAY                 { pop_return DAY; }
+  DATE/[[:blank:]]+Y  {                 return DATE; }
+  DAY/[[:blank:]]+Y   {                 return DAY; }
+  TIME                { pop_return TIME; }
+
+  YYYYMMDD            { yy_pop_state();
+                        yylval.string = xstrdup(yytext); return YYYYMMDD; }
+  YYYYDDD             { yy_pop_state();
+                        yylval.string = xstrdup(yytext); return YYYYDDD; }
+  DAY-OF-WEEK         { yy_pop_state();
+                        yylval.string = xstrdup(yytext); return DAY_OF_WEEK; }
+}
+
 <quoteq>{
   [^=]+[=]/[^=]       { tmpstring_append(yyleng); }
   [^=]+/[=]{2}        { yylval.string = xstrdup(tmpstring_append(yyleng));
@@ -1419,188 +1437,467 @@ USE({SPC}FOR)?                { return USE; }
                         tmpstring = NULL; pop_return LITERAL; }
 }
 
+    /* ISO Reserved Words */
 <*>{
+  ACCEPT       { return ACCEPT; }
+  ACCESS       { return ACCESS; }
+  ADD          { return ADD; }
+  ADDRESS      { return ADDRESS; }
+  ADVANCING    { return ADVANCING; }
+  AFTER                { return AFTER; }
+  ALL          { return ALL; }
+  ALLOCATE     { return ALLOCATE; }
+  ALPHABET     { return ALPHABET; }
+  ALPHABETIC   { return ALPHABETIC; }
+  ALPHABETIC-LOWER     { return ALPHABETIC_LOWER; }
+  ALPHABETIC-UPPER     { return ALPHABETIC_UPPER; }
+  ALPHANUMERIC         { return ALPHANUMERIC; }
+  ALPHANUMERIC-EDITED  { return ALPHANUMERIC_EDITED; }
+  ALSO         { return ALSO; }
+  ALTERNATE    { return ALTERNATE; }
+  AND          { return AND; }
+  ANY          { return ANY; }
+  ANYCASE      { return ANYCASE; }
+  ARE          { return ARE; }
+  AREA         { return AREA; }
+  AREAS                { return AREAS; }
   AS           { return AS; }
+  ASCENDING    { return ASCENDING; }
+  ASSIGN               { return ASSIGN; }
+  AT           { return AT; }
+  BASED                { return BASED; }
+  BEFORE       { return BEFORE; }
+  BINARY       { return BINARY; }
+  BIT          { return BIT; }
+  BLANK                { return BLANK; }
+  BLOCK                { return BLOCK_kw; }
+  BOTTOM       { return BOTTOM; }
+  BY           { return BY; }
+  CALL         { return CALL; }
+  CANCEL       { return CANCEL; }
+  CF           { return CF; }
+  CH           { return CH; }
+  CHARACTER    { return CHARACTER; }
+  CHARACTERS   { return CHARACTERS; }
+  CLASS                { return CLASS; }
+  CLOSE                { return CLOSE; }
+  CODE         { return CODE; }
+  COMMA                { return COMMA; }
+  COMMIT       { return COMMIT; }
+  COMMON       { return COMMON; }
+  COMPUTE      { return COMPUTE; }
+  CONDITION    { return CONDITION; }
   CONSTANT     { return CONSTANT; }
-  (IS{SPC})?DEFINED    { ydflval.boolean = true;  return DEFINED; }
-  {ISNT}{SPC}DEFINED   { ydflval.boolean = false; return DEFINED; }
-  OFF          { return OFF; }
-}
-
-<cdf_state>{
-  [+-]?{INTEGERZ}       { int value;
-                         if( is_integer_token(&value) ) {
-                           ydflval.number = value;
-                           return cdf::parser::token::YDF_NUMBER;
-                         }
-                         dbgmsg("%s not an integer = %d",
-                                  yytext, value);
-                         return NO_CONDITION;
-                       }
-
-  {NAME}{SPC}AS        { char *s = xstrdup(yytext);
-                         char *p = strchr(s, 0x20);
-                         gcc_assert(p); // just found via regex
-                         *p = '\0';
-                         ydflval.string = yylval.string = s;
-                         return NAME;
-                       }
-  {NAME}               { ydflval.string = yylval.string = xstrdup(yytext);
-                         return NAME;
-                       }
-  %EBCDIC-MODE         { ydflval.number = feature_internal_ebcdic_e;
-                         return FEATURE; }
-  %64-BIT-POINTER      { ydflval.number = feature_embiggen_e;
-                         return FEATURE; }
-  [[:blank:]]+
-  {BLANK_EOL}
-  .                    { myless(0); yy_pop_state(); } // not a CDF token
-}
-
-<program_id_state>{
-  {BLANK_OEOL}
-  (IS)?[[:space:]]
-  AS/{SPC}     { myless(0); yy_pop_state(); } /* => ident_state */
+  CONTAINS     { return CONTAINS; }
+  CONTENT      { return CONTENT; }
+  CONTINUE     { return CONTINUE; }
+  CONTROL      { return CONTROL; }
+  CONTROLS     { return CONTROLS; }
+  CONVERTING   { return CONVERTING; }
+  COPY         { return COPY; }
+  COUNT                { return COUNT; }
+  CURRENCY     { return CURRENCY; }
+  DATA         { return DATA; }
+  DATE         { return DATE; }
+  DAY          { return DAY; }
+  DAY-OF-WEEK  { return DAY_OF_WEEK; }
+  DE           { return DE; }
+  DECIMAL-POINT        { return DECIMAL_POINT; }
+  DECLARATIVES { return DECLARATIVES; }
+  DEFAULT      { yylval.number = 'D'; return DEFAULT; }
+  DELETE       { return DELETE; }
+  DELIMITED    { return DELIMITED; }
+  DELIMITER    { return DELIMITER; }
+  DEPENDING    { return DEPENDING; }
+  DESCENDING   { return DESCENDING; }
+  DETAIL       { return DETAIL; }
+  DISPLAY      { return DISPLAY; }
+  DIVIDE       { return DIVIDE; }
+  DOWN         { return DOWN; }
+  DUPLICATES   { return DUPLICATES; }
+  DYNAMIC      { return DYNAMIC; }
+  EC           { return EC; }
+  ELSE         { return ELSE; }
+  END          { return END; }
+  END-ACCEPT   { return END_ACCEPT; }
+  END-ADD      { return END_ADD; }
+  END-CALL     { return END_CALL; }
+  END-DELETE   { return END_DELETE; }
+  END-DISPLAY  { return END_DISPLAY; }
+  END-DIVIDE   { return END_DIVIDE; }
+  END-EVALUATE { return END_EVALUATE; }
+  END-IF       { return END_IF; }
+  END-MULTIPLY { return END_MULTIPLY; }
+  END-PERFORM  { return END_PERFORM; }
+  END-READ     { return END_READ; }
+  END-RETURN   { return END_RETURN; }
+  END-REWRITE  { return END_REWRITE; }
+  END-SEARCH   { return END_SEARCH; }
+  END-SUBTRACT { return END_SUBTRACT; }
+  END-WRITE    { return END_WRITE; }
+  ENVIRONMENT  { return ENVIRONMENT; }
+  EQUAL                { ydflval.string = yylval.string = xstrdup(yytext);
+                 return EQ; }
+  ERROR                { return ERROR; }
+  EVALUATE     { return EVALUATE; }
+  /* EXCEPTION special handling */
+  EXIT         { return EXIT; }
+  EXTEND       { return EXTEND; }
+  EXTERNAL     { return EXTERNAL; }
 
+  FD           { return FD; }
+  FINAL                { return FINAL; }
+  FINALLY      { return FINALLY; }
+  FIRST                { return FIRST; }
+  FOOTING      { return FOOTING; }
+  FOR          { return FOR; }
+  FREE         { return FREE; }
+  FROM         { return FROM; }
+  /* FUNCTION  special handling */
+  GENERATE     { return GENERATE; }
+  GIVING       { return GIVING; }
+  GLOBAL       { return GLOBAL; }
+  GO           { return GO; }
+  GOBACK       { return GOBACK; }
+  GROUP                { return GROUP; }
+  HEADING      { return HEADING; }
+  IF           { return IF; }
+  IN           { return IN; }
+  INDEX                { return INDEX; }
+  INDEXED      { return INDEXED; }
+  INDICATE     { return INDICATE; }
   INITIAL      { return INITIAL_kw; }
-  COMMON       { return COMMON; }
-  RECURSIVE    { return RECURSIVE; }
-  PROGRAM      { return PROGRAM_kw; }
-
-  {DOTSEP}     { pop_return '.'; }
-}
-
-<name_state>{           /* Either pop from here, or let the quoted state pop */
-  {BLANK_OEOL}
-
-  {NAME}               { yy_pop_state();
-                         yylval.string = xstrdup(yytext);
-                         return NAME; 
-                       }
-  {PREFIX}?['']                { yylval.literal.set_prefix(yytext, yyleng-1);
-                         BEGIN(quoted1); }
-  {PREFIX}?[""]                { yylval.literal.set_prefix(yytext, yyleng-1);
-                         BEGIN(quoted2); }
-
-  .                    { myless(0); yy_pop_state();
-                         /* Should not happen for valid inputs. */ }
-}
-<dot_state>{
-  [[:blank:]]*[.][[:blank:].]+{EOL}    { pop_return '.'; }
-  [[:blank:]]*[.]+                     { pop_return '.'; }
-}
-
-<date_state>{
-  ^[[:blank:]]+
-  {BLANK_EOL}
-
-  DATE                { pop_return DATE; }
-  DAY                 { pop_return DAY; }
-  DATE/[[:blank:]]+Y  {                 return DATE; }
-  DAY/[[:blank:]]+Y   {                 return DAY; }
-  TIME                { pop_return TIME; }
-
-  YYYYMMDD            { yy_pop_state();
-                        yylval.string = xstrdup(yytext); return YYYYMMDD; }
-  YYYYDDD             { yy_pop_state();
-                        yylval.string = xstrdup(yytext); return YYYYDDD; }
-  DAY-OF-WEEK         { yy_pop_state();
-                        yylval.string = xstrdup(yytext); return DAY_OF_WEEK; }
-}
-
-<INITIAL,procedure_div,copy_state>{
-  NOT{SPC}B/{boolseq}  { is_not = true;  yy_push_state(bool_state); }
-    B/{boolseq}                        { is_not = false; 
yy_push_state(bool_state); }
-  N?X/{hexseq}                 { yylval.literal.set_prefix(yytext, yyleng);
-                                 yy_push_state(hex_state); }
-  N?X{nonseq}          { dbgmsg("invalid hexadecimal value: %s", yytext);
-                         return NO_CONDITION; }
-
-  BX/{hexseq}                  { yylval.numstr.radix = hexadecimal_e;
-                                 yy_push_state(numstr_state); }
-
-  {PREFIX}?['']                   { yylval.literal.set_prefix(yytext, 
yyleng-1);
-                            yy_push_state(quoted1); }
-  {PREFIX}?[""]                   { yylval.literal.set_prefix(yytext, 
yyleng-1);
-                            yy_push_state(quoted2); }
-  {PREFIX}?[""]/{STRING}[""]      { yylval.literal.set_prefix(yytext, 
yyleng-1);
-                            yy_push_state(quoted2); }
-
-  {INTEGERZ}/[[:punct:]][[:space:]]{BLANK_OEOL} { return numstr_of(yytext); }
-  {dfc}/[[:blank:][:punct:]]                   { return numstr_of(yytext); }
-
-  [+-]?({dfc}|{dseq})([.,][[:digit:]])* { auto eotext = yytext + yyleng - 1;
-                                      if( *eotext == '.' ) {
-                                        myless(yyleng - 1);
-                                        *eotext = '\0';
-                                      }
-                                      return numstr_of(yytext); }
-
-  UPSI-[0-7]                 { char *p = yytext + yyleng - 1;
-                               ydflval.string = yylval.string = xstrdup(p);
-                               return UPSI; }
-}
-
-    /*
-     * "The decimal point can appear anywhere within the literal except as the
-     * rightmost character."
-     */
-<numeric_state>{
-  [[:blank:]]+
-  {BLANK_EOL}
+  INITIALIZE   { return INITIALIZE; }
+  INITIATE     { return INITIATE; }
+  INPUT                { return INPUT; }
+  INSPECT      { return INSPECT; }
+  INTERFACE    { return INTERFACE; }
+  INTO         { return INTO; }
+  INVOKE       { return INVOKE; }
+  IS           { return IS; }
+  KEY          { return KEY; }
+  LAST         { return LAST; }
+  LEADING      { return LEADING; }
+  LEFT         { return LEFT; }
+  LENGTH       { return LENGTH; }
+  LIMIT                { return LIMIT; }
+  LIMITS       { return LIMITS; }
+  LINAGE       { return LINAGE; }
+  LINE         { return LINE; }
+  LINE-COUNTER { return LINE_COUNTER; }
+  LINES                { return LINES; }
+  LINKAGE      { return LINKAGE; }
+  LOCAL-STORAGE        { return LOCAL_STORAGE; }
+  LOCALE       { return LOCALE; }
+  LOCATION     { return LOCATION; }
+  LOCK         { return LOCK; }
+  MERGE                { return MERGE; }
+  MODE         { return MODE; }
+  MOVE         { return MOVE; }
+  MULTIPLY     { return MULTIPLY; }
+  NATIONAL     { return NATIONAL; }
+  NATIONAL-EDITED      { return NATIONAL_EDITED; }
+  NATIVE       { return NATIVE; }
+  NEGATIVE     { return NEGATIVE; }
+  NESTED       { return NESTED; }
+  NEXT         { return NEXT; }
+  NO           { return NO; }
+  NOT          { return NOT; }
+  NUMBER       { return NUMBER; }
+  NUMERIC      { return NUMERIC; }
+  NUMERIC-EDITED       { return NUMERIC_EDITED; }
+  OCCURS       { return OCCURS; }
+  OF           { return OF; }
+  OFF          { return OFF; }
+  OMITTED      { return OMITTED; }
+  ON           { return ON; }
+  OPEN         { return OPEN; }
+  OPTIONAL     { return OPTIONAL; }
+  OPTIONS      { return OPTIONS; }
+  OR           { return OR; }
+  ORDER                { return ORDER; }
+  ORGANI[SZ]ATION      { return ORGANIZATION; }
+  OTHER                { return OTHER; }
+  OUTPUT       { return OUTPUT; }
+  /* OVERFLOW  special handling */
+  OVERRIDE     { return OVERRIDE; }
+  PACKED-DECIMAL       { return PACKED_DECIMAL; }
+  PAGE         { return PAGE; }
+  PAGE-COUNTER { return PAGE_COUNTER; }
+  PERFORM      { return PERFORM; }
+  PF           { return PF; }
+  PH           { return PH; }
+  PIC          { return PIC; }
+  PICTURE      { return PICTURE; }
+  PLUS         { return PLUS; }
+  POINTER      { return POINTER; }
+  POSITIVE     { return POSITIVE; }
+  PROCEDURE    { return PROCEDURE; }
+  PROGRAM      { return PROGRAM_kw; }
+  PROGRAM-ID   { return PROGRAM_ID; }
+  PROPERTY     { return PROPERTY; }
+  PROTOTYPE    { return PROTOTYPE; }
+  QUOTES       { return QUOTES; }
+  RAISE                { return RAISE; }
+  RAISING      { return RAISING; }
+  /* RANDOM    special handling */
+  RD           { return RD; }
+  READ         { return READ; }
+  RECORD       { return RECORD; }
+  RECORDS      { return RECORDS; }
+  REDEFINES    { return REDEFINES; }
+  REEL         { return REEL; }
+  REFERENCE    { return REFERENCE; }
+  RELATIVE     { return RELATIVE; }
+  RELEASE      { return RELEASE; }
+  REMAINDER    { return REMAINDER; }
+  REMOVAL      { return REMOVAL; }
+  RENAMES      { return RENAMES; }
+  REPLACE      { return REPLACE; }
+  REPLACING    { return REPLACING; }
+  REPORT       { return REPORT; }
+  REPORTING    { return REPORTING; }
+  REPORTS      { return REPORTS; }
+  REPOSITORY   { return REPOSITORY; }
+  RESERVE      { return RESERVE; }
+  RESET                { return RESET; }
+  RESUME       { return RESUME; }
+  RETURN       { return RETURN; }
+  RETURNING    { return RETURNING; }
+  REWIND       { return REWIND; }
+  REWRITE      { return REWRITE; }
+  RF           { return RF; }
+  RH           { return RH; }
+  RIGHT                { return RIGHT; }
+  ROUNDED      { return ROUNDED; }
+  RUN          { return RUN; }
+  SAME         { return SAME; }
+  SCREEN       { return SCREEN; }
+  SD           { return SD; }
+  SEARCH       { return SEARCH; }
+  SECTION      { yylval.string = NULL; return SECTION; }
+  SELECT       { return SELECT; }
+  SENTENCE     { return SENTENCE; }
+  SEPARATE     { return SEPARATE; }
+  SEQUENCE     { return SEQUENCE; }
+  SEQUENTIAL   { return SEQUENTIAL; }
+  SET          { return SET; }
+  SHARING      { return SHARING; }
+  SIGN         { return SIGN; }
+  SIZE         { return SIZE; }
+  SORT         { return SORT; }
+  SORT-MERGE   { return SORT_MERGE; }
+  SOURCE       { return SOURCE; }
+  SPACE                { return SPACE; }
+  SPACES       { return SPACES; }
+  SPECIAL-NAMES        { return SPECIAL_NAMES; }
+  STANDARD     { return STANDARD; }
+  STANDARD-1   { return STANDARD_1; }
+  START                { return START; }
+  STATUS       { return STATUS; }
+  STOP         { return STOP; }
+  SUBTRACT     { return SUBTRACT; }
+  SUM          { return SUM; }
+  SUPPRESS     { return SUPPRESS; }
+  SYMBOLIC     { return SYMBOLIC; }
+  TALLYING     { return TALLYING; }
+  TERMINATE    { return TERMINATE; }
+  TEST         { return TEST; }
+  THAN         { return THAN; }
+  THEN         { return THEN; }
+  THRU         { return THRU; }
+  TIME         { return TIME; }
+  TIMES                { return TIMES; }
+  TO           { return TO; }
+  TOP          { return TOP; }
+  TRAILING     { return TRAILING; }
 
-  [+-]?{INTEGERZ} {            pop_return numstr_of(yytext); }
-  [+-]?{dfc}([.][[:digit:]])*  {
-                               char *s = xstrdup(yytext);
-                               char *p = strchr(s, '.');
-                               if( p && strlen(p) == 1 ) {
-                                 *p = '\0';
-                                 myless(p - s);
-                               }
-                               numstr_of(s); free(s);
-                               pop_return NUMSTR;
-                            }
+  TYPE         { return TYPE; }
+  TYPEDEF      { return TYPEDEF; }
+  UNIT         { return UNIT; }
+  UNTIL                { return UNTIL; }
+  UP           { return UP; }
+  UPON         { return UPON; }
+  USAGE                { return USAGE; }
+  USE          { return USE; }
+  USING                { return USING; }
+  VALUE                { return VALUE; }
+  VARYING      { return VARYING; }
+  WHEN         { return WHEN; }
+  WITH         { return WITH; }
+  WORKING-STORAGE      { return WORKING_STORAGE; }
+  WRITE                { return WRITE; }
+
+  ZERO |
+  ZEROES       |
+  ZEROS                { return ZERO; }
 }
 
-<procedure_div>{
-  (ID|IDENTIFICATION|ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION  {
-                                 myless(0); BEGIN(INITIAL); }
-  PROGRAM-ID{OSPC}{DOTSEP}     { myless(0); BEGIN(INITIAL); }
+<*>{
+  AS           { return AS; }
+  CONSTANT     { return CONSTANT; }
+  (IS{SPC})?DEFINED    { ydflval.boolean = true;  return DEFINED; }
+  {ISNT}{SPC}DEFINED   { ydflval.boolean = false; return DEFINED; }
+  OFF          { return OFF; }
+}
 
-  EXIT{SPC}/(PROGRAM|SECTION|PARAGRAPH|PERFORM) {
-                         return EXIT; }
-  EXIT{OSPC}/{DOTSEP}  { return SIMPLE_EXIT; }
-  EXIT                         { return EXIT; } // 
(PROGRAM|SECTION|PARAGRAPH|PERFORM)
-  RETURNING             { return RETURNING; }
+<cdf_state>{
+  [+-]?{INTEGERZ}       { int value;
+                         if( is_integer_token(&value) ) {
+                           ydflval.number = value;
+                           return cdf::parser::token::YDF_NUMBER;
+                         }
+                         dbgmsg("%s not an integer = %d",
+                                  yytext, value);
+                         return NO_CONDITION;
+                       }
 
-  ACTIVATING            { return ACTIVATING; }
-  CURRENT               { return CURRENT; }
-  NESTED                { return NESTED; }
-  STACK                 { return STACK; }
-  TOP-LEVEL             { return TOP_LEVEL; }
+  {NAME}{SPC}AS        { char *s = xstrdup(yytext);
+                         char *p = strchr(s, 0x20);
+                         gcc_assert(p); // just found via regex
+                         *p = '\0';
+                         ydflval.string = yylval.string = s;
+                         return NAME;
+                       }
+  {NAME}               { ydflval.string = yylval.string = xstrdup(yytext);
+                         return NAME;
+                       }
+  %EBCDIC-MODE         { ydflval.number = feature_internal_ebcdic_e;
+                         return FEATURE; }
+  %64-BIT-POINTER      { ydflval.number = feature_embiggen_e;
+                         return FEATURE; }
+  [[:blank:]]+
+  {BLANK_EOL}
+  .                    { myless(0); yy_pop_state(); } // not a CDF token
+}
 
-  {NAME}/{SPC}SECTION{OSPC}{DOTSEP} {
-                                   yylval.string = xstrdup(yytext);
-                                   return NAME; }
+<program_id_state>{
+  {BLANK_OEOL}
+  (IS)?[[:space:]]
+  AS/{SPC}     { myless(0); yy_pop_state(); } /* => ident_state */
 
-  (IS{SPC})?POSITIVE/[[:space:]]  { yylval.number =  IS; return POSITIVE; }
-  (IS{SPC})?NEGATIVE/[[:space:]]  { yylval.number =  IS; return NEGATIVE; }
-  (IS{SPC})?ZERO/[[:space:]]      { yylval.number =  IS; return ZERO; }
+  INITIAL      { return INITIAL_kw; }
+  COMMON       { return COMMON; }
+  RECURSIVE    { return RECURSIVE; }
+  PROGRAM      { return PROGRAM_kw; }
 
-  {ISNT}{SPC}POSITIVE/[[:space:]] { yylval.number = NOT; return POSITIVE; }
-  {ISNT}{SPC}NEGATIVE/[[:space:]] { yylval.number = NOT; return NEGATIVE; }
-  {ISNT}{SPC}ZERO/[[:space:]]     { yylval.number = NOT; return ZERO; }
+  {DOTSEP}     { pop_return '.'; }
+}
 
-  {ISNT}{SPC}/OMITTED { return NOT; }
+<name_state>{           /* Either pop from here, or let the quoted state pop */
+  {BLANK_OEOL}
 
-  [(:)]                        { return *yytext; }
-  [(]/[^(:)""'']*[:][^)]*[)]   { return LPAREN; /* parentheses around a colon 
*/ }
-  [(][^:""''\n]*[:][^)]*[)]    { // does not match foo(bar)\n:  :-(  
-                                  int tok = is_refmod(yytext, yytext + yyleng)?
-                                      int(LPAREN) : '(';
-                                  myless(1);
-                                  return tok; 
-                                }
+  {NAME}               { yy_pop_state();
+                         yylval.string = xstrdup(yytext);
+                         return NAME; 
+                       }
+  {PREFIX}?['']                { yylval.literal.set_prefix(yytext, yyleng-1);
+                         BEGIN(quoted1); }
+  {PREFIX}?[""]                { yylval.literal.set_prefix(yytext, yyleng-1);
+                         BEGIN(quoted2); }
+
+  .                    { myless(0); yy_pop_state();
+                         /* Should not happen for valid inputs. */ }
+}
+<dot_state>{
+  [[:blank:]]*[.][[:blank:].]+{EOL}    { pop_return '.'; }
+  [[:blank:]]*[.]+                     { pop_return '.'; }
+}
+
+<INITIAL,procedure_div,copy_state>{
+  NOT{SPC}B/{boolseq}  { is_not = true;  yy_push_state(bool_state); }
+    B/{boolseq}                        { is_not = false; 
yy_push_state(bool_state); }
+  N?X/{hexseq}                 { yylval.literal.set_prefix(yytext, yyleng);
+                                 yy_push_state(hex_state); }
+  N?X{nonseq}          { dbgmsg("invalid hexadecimal value: %s", yytext);
+                         return NO_CONDITION; }
+
+  BX/{hexseq}                  { yylval.numstr.radix = hexadecimal_e;
+                                 yy_push_state(numstr_state); }
+
+  {PREFIX}?['']                   { yylval.literal.set_prefix(yytext, 
yyleng-1);
+                            yy_push_state(quoted1); }
+  {PREFIX}?[""]                   { yylval.literal.set_prefix(yytext, 
yyleng-1);
+                            yy_push_state(quoted2); }
+  {PREFIX}?[""]/{STRING}[""]      { yylval.literal.set_prefix(yytext, 
yyleng-1);
+                            yy_push_state(quoted2); }
+
+  {INTEGERZ}/[[:punct:]][[:space:]]{BLANK_OEOL} { return numstr_of(yytext); }
+  {dfc}/[[:blank:][:punct:]]                   { return numstr_of(yytext); }
+
+  [+-]?({dfc}|{dseq})([.,][[:digit:]])* { auto eotext = yytext + yyleng - 1;
+                                      if( *eotext == '.' ) {
+                                        myless(yyleng - 1);
+                                        *eotext = '\0';
+                                      }
+                                      return numstr_of(yytext); }
+
+  UPSI-[0-7]                 { char *p = yytext + yyleng - 1;
+                               ydflval.string = yylval.string = xstrdup(p);
+                               return UPSI; }
+}
+
+    /*
+     * "The decimal point can appear anywhere within the literal except as the
+     * rightmost character."
+     */
+<numeric_state>{
+  [[:blank:]]+
+  {BLANK_EOL}
+
+  [+-]?{INTEGERZ} {            pop_return numstr_of(yytext); }
+  [+-]?{dfc}([.][[:digit:]])*  {
+                               char *s = xstrdup(yytext);
+                               char *p = strchr(s, '.');
+                               if( p && strlen(p) == 1 ) {
+                                 *p = '\0';
+                                 myless(p - s);
+                               }
+                               int token = numstr_of(s);
+                              free(s);
+                               pop_return token;
+                            }
+}
+
+<procedure_div>{
+  (ID|IDENTIFICATION|ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION  {
+                                 myless(0); BEGIN(INITIAL); }
+  PROGRAM-ID{OSPC}{DOTSEP}     { myless(0); BEGIN(INITIAL); }
+
+  EXIT{SPC}/(PROGRAM|SECTION|PARAGRAPH|PERFORM) {
+                         return EXIT; }
+  EXIT{OSPC}/{DOTSEP}  { return SIMPLE_EXIT; }
+  EXIT                         { return EXIT; } // 
(PROGRAM|SECTION|PARAGRAPH|PERFORM)
+  RETURNING             { return RETURNING; }
+
+  ACTIVATING            { return ACTIVATING; }
+  CURRENT               { return CURRENT; }
+  NESTED                { return NESTED; }
+  STACK                 { return STACK; }
+  TOP-LEVEL             { return TOP_LEVEL; }
+
+  {NAME}/{SPC}SECTION{OSPC}{DOTSEP} {
+                                   yylval.string = xstrdup(yytext);
+                                   return NAME; }
+
+  (IS{SPC})?POSITIVE/[[:space:]]  { yylval.number =  IS; return POSITIVE; }
+  (IS{SPC})?NEGATIVE/[[:space:]]  { yylval.number =  IS; return NEGATIVE; }
+  (IS{SPC})?ZERO/[[:space:]]      { yylval.number =  IS; return ZERO; }
+
+  {ISNT}{SPC}POSITIVE/[[:space:]] { yylval.number = NOT; return POSITIVE; }
+  {ISNT}{SPC}NEGATIVE/[[:space:]] { yylval.number = NOT; return NEGATIVE; }
+  {ISNT}{SPC}ZERO/[[:space:]]     { yylval.number = NOT; return ZERO; }
+
+  {ISNT}{SPC}/OMITTED { return NOT; }
+
+  [(:)]                        { return *yytext; }
+  [(]/[^(:)""'']*[:][^)]*[)]   { return LPAREN; /* parentheses around a colon 
*/ }
+  [(][^:""''\n]*[:][^)]*[)]    { // does not match foo(bar)\n:  :-(  
+                                  int tok = is_refmod(yytext, yytext + yyleng)?
+                                      int(LPAREN) : '(';
+                                  myless(1);
+                                  return tok; 
+                                }
 
   FILLER                       { return FILLER_kw; }
   INVALID                      { yylval.number = INVALID; return INVALID; }
@@ -2210,300 +2507,6 @@ BASIS           { yy_push_state(basis); return BASIS; }
   ^{TITLE}
 }
 
-<*>{
-  ACCEPT       { return ACCEPT; }
-  ACCESS       { return ACCESS; }
-  ADD          { return ADD; }
-  ADDRESS      { return ADDRESS; }
-  ADVANCING    { return ADVANCING; }
-  AFTER                { return AFTER; }
-  ALL          { return ALL; }
-  ALLOCATE     { return ALLOCATE; }
-  ALPHABET     { return ALPHABET; }
-  ALPHABETIC   { return ALPHABETIC; }
-  ALPHABETIC-LOWER     { return ALPHABETIC_LOWER; }
-  ALPHABETIC-UPPER     { return ALPHABETIC_UPPER; }
-  ALPHANUMERIC         { return ALPHANUMERIC; }
-  ALPHANUMERIC-EDITED  { return ALPHANUMERIC_EDITED; }
-  ALSO         { return ALSO; }
-  ALTERNATE    { return ALTERNATE; }
-  AND          { return AND; }
-  ANY          { return ANY; }
-  ANYCASE      { return ANYCASE; }
-  ARE          { return ARE; }
-  AREA         { return AREA; }
-  AREAS                { return AREAS; }
-  AS           { return AS; }
-  ASCENDING    { return ASCENDING; }
-  ASSIGN               { return ASSIGN; }
-  AT           { return AT; }
-  BASED                { return BASED; }
-  BEFORE       { return BEFORE; }
-  BINARY       { return BINARY; }
-  BIT          { return BIT; }
-  BLANK                { return BLANK; }
-  BLOCK                { return BLOCK_kw; }
-  BOTTOM       { return BOTTOM; }
-  BY           { return BY; }
-  CALL         { return CALL; }
-  CANCEL       { return CANCEL; }
-  CF           { return CF; }
-  CH           { return CH; }
-  CHARACTER    { return CHARACTER; }
-  CHARACTERS   { return CHARACTERS; }
-  CLASS                { return CLASS; }
-  CLOSE                { return CLOSE; }
-  CODE         { return CODE; }
-  COMMA                { return COMMA; }
-  COMMIT       { return COMMIT; }
-  COMMON       { return COMMON; }
-  CONDITION    { return CONDITION; }
-  CONSTANT     { return CONSTANT; }
-  CONTAINS     { return CONTAINS; }
-  CONTENT      { return CONTENT; }
-  CONTINUE     { return CONTINUE; }
-  CONTROL      { return CONTROL; }
-  CONTROLS     { return CONTROLS; }
-  CONVERTING   { return CONVERTING; }
-  COPY         { return COPY; }
-  COUNT                { return COUNT; }
-  CURRENCY     { return CURRENCY; }
-  DATA         { return DATA; }
-  DATE         { return DATE; }
-  DAY          { return DAY; }
-  DAY-OF-WEEK  { return DAY_OF_WEEK; }
-  DE           { return DE; }
-  DECIMAL-POINT        { return DECIMAL_POINT; }
-  DECLARATIVES { return DECLARATIVES; }
-  DEFAULT      { yylval.number = 'D'; return DEFAULT; }
-  DELETE       { return DELETE; }
-  DELIMITED    { return DELIMITED; }
-  DELIMITER    { return DELIMITER; }
-  DEPENDING    { return DEPENDING; }
-  DESCENDING   { return DESCENDING; }
-  DETAIL       { return DETAIL; }
-  DISPLAY      { return DISPLAY; }
-  DIVIDE       { return DIVIDE; }
-  DOWN         { return DOWN; }
-  DUPLICATES   { return DUPLICATES; }
-  DYNAMIC      { return DYNAMIC; }
-  EC           { return EC; }
-  ELSE         { return ELSE; }
-  END          { return END; }
-  END-ACCEPT   { return END_ACCEPT; }
-  END-ADD      { return END_ADD; }
-  END-CALL     { return END_CALL; }
-  END-DELETE   { return END_DELETE; }
-  END-DISPLAY  { return END_DISPLAY; }
-  END-DIVIDE   { return END_DIVIDE; }
-  END-EVALUATE { return END_EVALUATE; }
-  END-IF       { return END_IF; }
-  END-MULTIPLY { return END_MULTIPLY; }
-  END-PERFORM  { return END_PERFORM; }
-  END-READ     { return END_READ; }
-  END-RETURN   { return END_RETURN; }
-  END-REWRITE  { return END_REWRITE; }
-  END-SEARCH   { return END_SEARCH; }
-  END-SUBTRACT { return END_SUBTRACT; }
-  END-WRITE    { return END_WRITE; }
-  ENVIRONMENT  { return ENVIRONMENT; }
-  EQUAL                { ydflval.string = yylval.string = xstrdup(yytext);
-                 return EQ; }
-  ERROR                { return ERROR; }
-  EVALUATE     { return EVALUATE; }
-  EXCEPTION    { return EXCEPTION; }
-  EXIT         { return EXIT; }
-  EXTEND       { return EXTEND; }
-  EXTERNAL     { return EXTERNAL; }
-
-  FD           { return FD; }
-  FINAL                { return FINAL; }
-  FINALLY      { return FINALLY; }
-  FIRST                { return FIRST; }
-  FOOTING      { return FOOTING; }
-  FOR          { return FOR; }
-  FREE         { return FREE; }
-  FROM         { return FROM; }
-  FUNCTION     { return FUNCTION; }
-  GENERATE     { return GENERATE; }
-  GIVING       { return GIVING; }
-  GLOBAL       { return GLOBAL; }
-  GO           { return GO; }
-  GOBACK       { return GOBACK; }
-  GROUP                { return GROUP; }
-  HEADING      { return HEADING; }
-  IF           { return IF; }
-  IN           { return IN; }
-  INDEX                { return INDEX; }
-  INDEXED      { return INDEXED; }
-  INDICATE     { return INDICATE; }
-  INITIAL      { return INITIAL; }
-  INITIALIZE   { return INITIALIZE; }
-  INITIATE     { return INITIATE; }
-  INPUT                { return INPUT; }
-  INSPECT      { return INSPECT; }
-  INTERFACE    { return INTERFACE; }
-  INTO         { return INTO; }
-  INVOKE       { return INVOKE; }
-  IS           { return IS; }
-  KEY          { return KEY; }
-  LAST         { return LAST; }
-  LEADING      { return LEADING; }
-  LEFT         { return LEFT; }
-  LENGTH       { return LENGTH; }
-  LIMIT                { return LIMIT; }
-  LIMITS       { return LIMITS; }
-  LINAGE       { return LINAGE; }
-  LINE         { return LINE; }
-  LINE-COUNTER { return LINE_COUNTER; }
-  LINES                { return LINES; }
-  LINKAGE      { return LINKAGE; }
-  LOCAL-STORAGE        { return LOCAL_STORAGE; }
-  LOCALE       { return LOCALE; }
-  LOCATION     { return LOCATION; }
-  LOCK         { return LOCK; }
-  MERGE                { return MERGE; }
-  MODE         { return MODE; }
-  MOVE         { return MOVE; }
-  MULTIPLY     { return MULTIPLY; }
-  NATIONAL     { return NATIONAL; }
-  NATIONAL-EDITED      { return NATIONAL_EDITED; }
-  NATIVE       { return NATIVE; }
-  NEGATIVE     { return NEGATIVE; }
-  NESTED       { return NESTED; }
-  NEXT         { return NEXT; }
-  NO           { return NO; }
-  NOT          { return NOT; }
-  NUMBER       { return NUMBER; }
-  NUMERIC      { return NUMERIC; }
-  NUMERIC-EDITED       { return NUMERIC_EDITED; }
-  OCCURS       { return OCCURS; }
-  OF           { return OF; }
-  OFF          { return OFF; }
-  OMITTED      { return OMITTED; }
-  ON           { return ON; }
-  OPEN         { return OPEN; }
-  OPTIONAL     { return OPTIONAL; }
-  OPTIONS      { return OPTIONS; }
-  OR           { return OR; }
-  ORDER                { return ORDER; }
-  ORGANI[SZ]ATION      { return ORGANIZATION; }
-  OTHER                { return OTHER; }
-  OUTPUT       { return OUTPUT; }
-  OVERFLOW     { return OVERFLOW_kw; }
-  OVERRIDE     { return OVERRIDE; }
-  PACKED-DECIMAL       { return PACKED_DECIMAL; }
-  PAGE         { return PAGE; }
-  PAGE-COUNTER { return PAGE_COUNTER; }
-  PERFORM      { return PERFORM; }
-  PF           { return PF; }
-  PH           { return PH; }
-  PIC          { return PIC; }
-  PICTURE      { return PICTURE; }
-  PLUS         { return PLUS; }
-  POINTER      { return POINTER; }
-  POSITIVE     { return POSITIVE; }
-  PROCEDURE    { return PROCEDURE; }
-  PROGRAM      { return PROGRAM_kw; }
-  PROGRAM-ID   { return PROGRAM_ID; }
-  PROPERTY     { return PROPERTY; }
-  PROTOTYPE    { return PROTOTYPE; }
-  QUOTES       { return QUOTES; }
-  RAISE                { return RAISE; }
-  RAISING      { return RAISING; }
-  RANDOM       { return RANDOM; }
-  RD           { return RD; }
-  READ         { return READ; }
-  RECORD       { return RECORD; }
-  RECORDS      { return RECORDS; }
-  REDEFINES    { return REDEFINES; }
-  REEL         { return REEL; }
-  REFERENCE    { return REFERENCE; }
-  RELATIVE     { return RELATIVE; }
-  RELEASE      { return RELEASE; }
-  REMAINDER    { return REMAINDER; }
-  REMOVAL      { return REMOVAL; }
-  RENAMES      { return RENAMES; }
-  REPLACE      { return REPLACE; }
-  REPLACING    { return REPLACING; }
-  REPORT       { return REPORT; }
-  REPORTING    { return REPORTING; }
-  REPORTS      { return REPORTS; }
-  REPOSITORY   { return REPOSITORY; }
-  RESERVE      { return RESERVE; }
-  RESET                { return RESET; }
-  RESUME       { return RESUME; }
-  RETURN       { return RETURN; }
-  RETURNING    { return RETURNING; }
-  REWIND       { return REWIND; }
-  REWRITE      { return REWRITE; }
-  RF           { return RF; }
-  RH           { return RH; }
-  RIGHT                { return RIGHT; }
-  ROUNDED      { return ROUNDED; }
-  RUN          { return RUN; }
-  SAME         { return SAME; }
-  SCREEN       { return SCREEN; }
-  SD           { return SD; }
-  SEARCH       { return SEARCH; }
-  SECTION      { yylval.string = NULL; return SECTION; }
-  SELECT       { return SELECT; }
-  SENTENCE     { return SENTENCE; }
-  SEPARATE     { return SEPARATE; }
-  SEQUENCE     { return SEQUENCE; }
-  SEQUENTIAL   { return SEQUENTIAL; }
-  SET          { return SET; }
-  SHARING      { return SHARING; }
-  SIGN         { return SIGN; }
-  SIZE         { return SIZE; }
-  SORT         { return SORT; }
-  SORT-MERGE   { return SORT_MERGE; }
-  SOURCE       { return SOURCE; }
-  SPACE                { return SPACE; }
-  SPACES       { return SPACES; }
-  SPECIAL-NAMES        { return SPECIAL_NAMES; }
-  STANDARD     { return STANDARD; }
-  STANDARD-1   { return STANDARD_1; }
-  START                { return START; }
-  STATUS       { return STATUS; }
-  STOP         { return STOP; }
-  SUBTRACT     { return SUBTRACT; }
-  SUM          { return SUM; }
-  SUPPRESS     { return SUPPRESS; }
-  SYMBOLIC     { return SYMBOLIC; }
-  TALLYING     { return TALLYING; }
-  TERMINATE    { return TERMINATE; }
-  TEST         { return TEST; }
-  THAN         { return THAN; }
-  THEN         { return THEN; }
-  THRU         { return THRU; }
-  TIME         { return TIME; }
-  TIMES                { return TIMES; }
-  TO           { return TO; }
-  TOP          { return TOP; }
-  TRAILING     { return TRAILING; }
-
-  TYPE         { return TYPE; }
-  TYPEDEF      { return TYPEDEF; }
-  UNIT         { return UNIT; }
-  UNTIL                { return UNTIL; }
-  UP           { return UP; }
-  UPON         { return UPON; }
-  USAGE                { return USAGE; }
-  USE          { return USE; }
-  USING                { return USING; }
-  VALUE                { return VALUE; }
-  VARYING      { return VARYING; }
-  WHEN         { return WHEN; }
-  WITH         { return WITH; }
-  WORKING-STORAGE      { return WORKING_STORAGE; }
-  WRITE                { return WRITE; }
-
-  ZERO |
-  ZEROES       |
-  ZEROS                { return ZERO; }
-}
-
 <*>{
   %EBCDIC-MODE         { ydflval.number = feature_internal_ebcdic_e;
                          return FEATURE; }

Reply via email to