Elident
Elident ("ELement IDENTity") is a self-consistency utility. It checks that a program is identical to the concatenation of the values of all its parsed elements.
Usage
[rexx] elident [options] file
Options
-xtr,
--executor |
Enable Executor support |
-?, --help |
Display this information |
Program source
#!/usr/bin/env rexx
/******************************************************************************/
/* */
/* elident.rex - Check that a program is equal to its Element API parsing */
/* ====================================================================== */
/* */
/* This program 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 */
/* 20241208 0.1a c/CLASSIC_COMMENT/STANDARD_COMMENT/ */
/* 20250328 0.2 Main dir is now rexx-parser instead of rexx[.]parser */
/* 20251110 0.3a Change the name to elident.rex */
/* 20252111 Add Executor support, move to /bin */
/* */
/******************************************************************************/
Signal On Syntax
Parse Arg args
args = Strip( args )
If args == "" Then Signal Help
executor = 0
Loop While args[1] == "-"
Parse Var args option args
Select Case Lower(option)
When "--help", "-?" Then Signal Help
When "--executor", "-xtr" Then executor = 1
End
End
Call RetrieveFilename
-- Read the whole file into an array
chunk = CharIn(file,1,Chars(file))
Call Stream file,"c","close"
source = chunk~makeArray
-- Makearray has a funny definition that ignores a possible
-- last empty line.
If Right(chunk,1) = "0a"X Then source~append("")
options = .Array~new
If executor Then options~append(("EXECUTOR", 1))
parser = .Rexx.Parser~new( file, source, options )
currentLineNo = 1
currentLine = ""
element = parser~firstElement -- Same as parser~package~prolog~body~begin
Do Counter elements Until element == .Nil
If element~from \== element~to Then Do
category = element~category
elementLine = element~from~word(1)
If elementLine > currentLineNo Then Call ChangeLine
If category == .EL.STANDARD_COMMENT Then Call StandardComment
Else If category == .EL.DOC_COMMENT Then Call StandardComment
Else If category == .EL.DOC_COMMENT_MARKDOWN Then Call StandardComment
Else If category == .EL.RESOURCE_DATA Then Call ResourceData
Else currentLine ||= element~source
End
element = element~next
End
Exit 0
Help:
Say .Resources["HELP"]
Exit 1
StandardComment:
lastLine = element~to~word(1)
start = element~from~word(2)
end = element~ to~word(2)
If elementLine == lastLine Then Do
currentLine ||= source[currentLineNo][ start, end-start ]
Return
End
elementLine += 1
currentLine ||= SubStr( source[currentLineNo], start )
Call ChangeLine
currentLineNo = lastLine
currentLine = source[currentLineNo][1, end - 1]
Return
ResourceData:
lastLine = element~to~word(1)
currentLineNo = lastLine + 1
currentLine = ""
Return
ChangeLine:
Do While elementLine > currentLineNo
If source[currentLineNo] \== currentLine Then Do
Say "Difference found in line number" currentLineNo":"
Say "Source line is '"source[currentLineNo]"',"
Say "Parsed line is '"currentLine"'."
Exit 1
End
currentLineNo += 1
currentLine = ""
End
Return
RetrieveFilename:
c = args[1]
-- Quoted filenames
If ( '"' || "'" )~contains( c ) Then Do
Parse Var args +1 fileName (c) extra
extra = Strip( extra )
If extra \== "" Then Do
Say "Unrecognized parameter '"extra"'."
Exit 1
End
End
Else fileName = args
-- Try the file name as-is first, then add ".rex" at the end
file = Stream(fileName,"c","query exists")
If file = "" Then Do
If \ fileName~caselessEndsWith(".rex") Then
file = Stream(fileName".rex","c","query exists")
If file = "" Then Do
Say "File '"fileName"' not found."
Exit 1
End
End
Return
-- This is the standard condition handler for the Rexx parser
Syntax:
co = condition("O")
If co~code \== 98.900 Then Do
Say "Error" co~code "in" co~program", line" co~position":"
Raise Propagate
End
br = (.Parser.options~hasIndex( html ) == "1")~?("<br>",.endOfLine)
additional = Condition("A")
Say additional[1]":"
line = Additional~lastItem~position
Say Right(line,6) "*-*" source[line]
Say Copies("-",80)
Say co~stackFrames~makeArray~makeString("L",br)
additional = additional~lastItem
Raise Syntax (additional~code) Additional (additional~additional)
Exit
::Resource HELP
Usage: elident [OPTION]... [FILE]
Check that the Rexx Parser returns a stream of elements identical to a FILE.
If the only option is --help or -?, or if no arguments are present,
then display this help and exit.
Options:
--executor, -xtr Activate support for Executor language extensions
::END
::Requires "Rexx.Parser.cls"
