Elements


Elements


Usage

[rexx] elements [options] file

Transform file into a list of elements, according to options, and print the list.

If file does not include an extension, .rex is automatically appended.

When called without arguments, display help information and exit.

Options

-h, --help Display help and exit
-e, --experimental   Enable Experimental features (also -exp, --exp)
-xtr, --executor Enable Executor support
--from [LINE] Show elements starting at line LINE
-it, --itrace Print internal traceback on error
--no-show-spaces Leave spaces untouched
--show-spaces Show spaces as the "␣" character (default)
--to [LINE] Stop showing elements after line LINE
-u, --unicode, --tutor Enable TUTOR-flavored Unicode

Program source

#!/usr/bin/env rexx
/******************************************************************************/
/*                                                                            */
/* elements.rex - Transform a file into a list of elements                    */
/* =======================================================                    */
/*                                                                            */
/* This file is part of the Rexx Parser package                               */
/* [See https://rexx.epbcn.com/rexx-parser/]                                  */
/*                                                                            */
/* Copyright (c) 2024-2026 Josep Maria Blasco <josep.maria.blasco@epbcn.com>  */
/*                                                                            */
/* License: Apache License 2.0 (https://www.apache.org/licenses/LICENSE-2.0)  */
/*                                                                            */
/* Version history:                                                           */
/*                                                                            */
/* Date     Version Details                                                   */
/* -------- ------- --------------------------------------------------------- */
/* 20241206    0.1  First public release                                      */
/* 20250103    0.1f Add TUTOR-flavored Unicode support                        */
/* 20250215    0.1g Rename to elements.rex                                    */
/* 20250328    0.2  Main dir is now rexx-parser instead of rexx[.]parser      */
/*                  Binary directory is now "bin" instead of "cls"            */
/*                  Move "modules" directory inside "bin"                     */
/* 20250426    0.2b Fix compound count, simplify REQUIRES                     */
/* 20250606    0.2c Add --from and --to options                               */
/* 20250928    0.2e Fix crash when no args, add .rex to file when needed      */
/* 20251114    0.3a Add support for Experimental features                     */
/* 20251125         Add support for Executor                                  */
/* 20251221    0.4a Add --itrace option, improve error messages               */
/* 20251226         Send error messages to .error, not .output                */
/* 20251227         Use .SysCArgs when available                              */
/* 20260102         Standardize help options to -h and --help                 */
/* 20260228         Add --[no-]show-spaces options (suggestion by RGF)        */
/* 20260313    0.5  Move error handling to ErrorHandler.cls                   */
/*                                                                            */
/******************************************************************************/

  -- Errors returned by the parser require special handling
  Signal On Syntax

  CLIhelper = InitCLI()
  myName = CLIhelper~name
  myHelp = CLIhelper~help
  args   = CLIhelper~args

--------------------------------------------------------------------------------
-- Main program                                                               --
--------------------------------------------------------------------------------

  unicode        = 0
  experimental   = 0
  executor       = 0
  opFrom         = 1
  itrace         = 0
  opTo           = "*"
  showSpaces = 1

ProcessOptions:
  If args~items == 0 Then Signal Help

  option = args[1]
  args~delete(1)

  If option[1] == "-" Then Do
    Select Case Lower(option)
      When "-h", "--help"        Then Signal Help
      When "-u", "--tutor", -
        "--unicode"              Then unicode = 1
      When "-e", "-exp", -
        "--experimental"         Then experimental = 1
      When "-xtr", "--executor"  Then executor = 1
      When "-it", "--itrace"     Then itrace = 1
      When "--from"              Then opFrom = Integer()
      When "--to"                Then opTo   = Integer()
      When "--show-spaces"       Then showSpaces = 1
      When "--no-show-spaces"    Then showSpaces = 0
      Otherwise Call Error "Invalid option '"option"'."
    End
    Signal ProcessOptions
  End

  If args~items > 0 Then Call Error "Invalid argument '"args[1]"'."

  file = option

  fullPath = .context~package~findProgram(file)

  If fullPath == .Nil Then Call Error "File '"file"' does not exist."

  -- We need to compute the source separately to properly handle syntax errors
  source = File2Array(fullPath)

  -- Adjust "opTo" if necessary

  If opTo = "*"          Then opTo = source~items
  If opTo > source~items Then opTo = source~items

  -- Print a nice prolog
  Say myName".rex run on" Date() "at" Time()
  Say
  Say "Examining" fullPath"..."
  Say
  Say "Elements marked '>' are inserted by the parser."
  Say "Elements marked 'X' are ignorable."
  Say "Elements marked 'A' have isAssigned=1."
  Say "Compound symbol components are distinguished with a '->' mark."
  Say
  Say "[   from  :    to   ] >XA 'value' (class)"
  Say " --------- ---------  --- ---------------------------"

  -- Parse our program, and get the first element
  Options = .Array~new
  If Unicode      Then Options~append(("UNICODE", 1))
  If experimental Then Options~append(("EXPERIMENTAL", 1))
  If executor     Then Options~append(("EXECUTOR", 1))
  parser = .Rexx.Parser~new(file, source, Options)

  element  = parser~firstElement

  -- Iterate over all elements and print them
  elements = 0
  compound = 0
  Do Counter elements Until element == .Nil
    Parse Value element~from With line .
    If line >  opTo   Then Leave
    If line >= opFrom Then Call Print element
    element = element~next
  End
  Say "Total:" elements "elements and" compound "compound symbol elements examined."

  -- We are done
  Exit 0

--------------------------------------------------------------------------------

Error:
 .Error~Say(Arg(1))
  Exit 1

--------------------------------------------------------------------------------

Help:
  Say .Resources[Help]~makeString        -
    ~caselessChangeStr("myName", myName) -
    ~caselessChangeStr("myHelp", myHelp)
  Exit 1

--------------------------------------------------------------------------------

Integer:
  n = ""
  If args~items > 0 Then Do
    n = args[1]
    args~delete(1)
  End
  If DataType(n,"W"), n > 0 Then Return n
  Call Error "Positive whole number expected, found '"n"'."

--------------------------------------------------------------------------------

BadArgument:
  Call Error "Incorrect file specification:" file

--------------------------------------------------------------------------------

Print:
  class = element~category
  from = element~from
  to   = element~to
  Parse Var from fromLine fromCol
  Parse Var   to   toLine   toCol
  Call Chunk "["Extent(element)"]"
  Call Chunk (element~isInserted)~?(" >","  ")
  Call Chunk (element~ignorable)~?("X"," ")
  Call Chunk (element~isAssigned)~?("A"," ")
  If class \== .EL.RESOURCE_DATA Then Do
    value = element~value
    If showSpaces Then
      value = ChangeStr(" ",value,"")
  End
  Else value = "[... resource data ...]"
  Call Chunk " '"value"'"
  If class == .EL.TAKEN_CONSTANT Then Do
    Say " ("AorAN(ConstantName(element~subCategory))" taken_constant)"
  End
  Else Do
    Say " ("AorAn(CategoryName(element~category))")"
    If element < .ALL.COMPOUND_VARIABLES Then Call Compound
  End
  If value == .Nil Then
    Call Error "Unexpected .Nil value for element condition."
Return

--------------------------------------------------------------------------------

Extent: Procedure
  Use Arg element
  from = element~from
  to   = element~to
  Parse Var from fromLine fromCol
  Parse Var   to   toLine   toCol
Return Right(fromLine,5) Right(fromCol,3)":"Right(toLine,5) Right(toCol,3)

--------------------------------------------------------------------------------

Compound:
  compound += 1
  Do part Over element~parts
    Say " "Extent(part)"     -> '"part~value"' ("||,
      AorAN(.Parser.CategoryName[part~category])")"
  End
Return

--------------------------------------------------------------------------------

AorAN:
  If "AEIOU"~contains(Arg(1)[1]) Then Return "An" Arg(1)
  Return "A" Arg(1)

--------------------------------------------------------------------------------

Chunk:
  Call CharOut , Arg(1)
Return

--------------------------------------------------------------------------------
-- Delegate parsing errors to the standard ErrorHandler                       --
--------------------------------------------------------------------------------

Syntax:
  co = condition("O")
  -- Not a 98.900? This is an application error
  If co~code \== 98.900 Then Do
   .Error~Say( "Error" co~code "in" co~program", line" co~position":" )
    Raise Propagate
  End
  Exit ErrorHandler( fullPath, source, co, itrace)

--------------------------------------------------------------------------------
-- Help text                                                                  --
--------------------------------------------------------------------------------

::Requires "Rexx.Parser.cls"
::Requires "Globals.cls"
::Requires "ErrorHandler.cls"
::Requires "CLISupport.cls"
::Requires "BaseClassesAndRoutines.cls"
::Requires "modules/print/print.cls"

::Resource Help end "::End"
myname - Transform a file into its constituent elements and list them

Usage: myName [options] FILE

Options:
-xtr,--executor     Enable support for Executor
-e,  --experimental Enable Experimental features (also -exp)
     --from [LINE]  Show elements starting at line LINE
     --help         Display this information
-it, --itrace       Print internal traceback on error
     --to   [LINE]  Stop showing elements after line LINE
     --tutor        Enable TUTOR-flavored Unicode
-u,  --unicode      Enable TUTOR-flavored Unicode
--show-spaces       Display spaces as "␣" (requires UTF8)
--no-show-spaces    Display spaces as spaces

The 'myname' program is part of the Rexx Parser package,
see https://rexx.epbcn.com/rexx-parser/. It is distributed under
the Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0).

Copyright (c) 2024-2026 Josep Maria Blasco <josep.maria.blasco@epbcn.com>.

See myhelp for details.
::End