wsh Syntax 2.0

kind = '.' | '-' | '=' | '@'| '%' | '#'
op = '.' | '-' | '<' | '@' | '^' | '!' | '?'
primary = (('.' | '-') op* kind?)? (sConst | name | block ) $/../ is a blockEnd, not a primary
expR = ( (noDo+ | '$'primary ) comment* )+
expW = primary | (('run' | 'runobj' | 'runstr') sp* primary sp*) exprBlo?) | 'compile' sp* primary
expr = expR | expW
exprS = spCom* expr spCom*
varE = exprS expression of kind =, yielding a variable name
varR = a rexx variable
exprBlo = op* kind? ( block | exprS )
stmt = '$$' exprBlo | '$'?'=' ( varE '=')? exprBlo | '$'?'@'expW | ('$' '@'?)? stmtA | '$'? pipeSt
stmtA = ( 'for' | 'with' | 'forWith' ) (varE '=')? exprS stmt
| 'ct' spCom* stmt
| 'proc' varE? stmt
| 'do' (spCom* varR spCom* '=')? exprB stmt
| 'table' (':'name)? (spCom* nl)? (sp* '<'? sp* name)+
pipeSt = ';' | '!' | ('<' | '>' | '>>') exprBlo
unitR = (spCom* | expR) ( (nl | spCom* stmt spCom) expR?)* (nl spCom*)?
unitW = (spNlCom | expW | stmt)+
unit = unitR | unitW | litText
block = '{' unit '}' | '[' unit '$]' | '/' noSla* '/' unit '$/' noSla* '/'
wsh = nl'$#version'version)? (nl unit)? ( nl'$#' (hook | kind) nl unit | nl'$#*' litText)* (nl( '$#end' | '$#out' ) litText )*

hook: text without nl. wshHook<first word of hook>(hook, run) is called twice, first with run='' to get default kind, then with compiled run, to get final code

variable name operators:

  • & access to varPool, plus field access if binary
  • * access to m., plus field access if binary
  • . inline dot
  • final op (if ends in text) if no ops at all then →& else →*
  • if no & or *, then first . → &, remaining . → *
  • \: escape

news

  • objectAccess String → String+
    • .- → embedded '.'
    • ./x → splitting ., / disappears and x is not interpreted
    • .y with y neither - nor / → splitting .,y carried over
    • paramters get, put, put with default creation
    • . fieldName oder [expr] ==> embedded '.' machen keine Probleme,

new semantics

Classes

  • b: block
  • s: String
  • o: Object
  • f: File
  • r: Run

Operators (all unary)

  • - 2string: s, o2String(o), concatenate f, concatenate 2file(r)
  • . 2object: string2object(s). o, f, r
  • < 2file: s → file with filename s, b+r → out of running it, first successfull cast (f, r, s) | f, output of run r, b: run
  • @ 2run: fail, first cast (r, f), a run doing aread f and write it to output, r
  • ^ run yielding return value which is assumed to be a String or Object depending of preceeding (or default) op
  • & variable Access

kind(laOp, ki, kiVa, defOp, defKi) = if k notNull then ki, kiVa elif laOp notNull then defKind(laOp) else

primary = (('.' | '-') op* kind?)? (sConst | name | block )
A primary yields an object or a string from a source possibly transformed by several operator (from right to left). kind is only allowed before a block. The 3 possible sources yield
A Constant its value,
name a variable access and
a block a Run.

Missing Operators and/or kind are defaulted as follows

without operatorChain/kind: context depending default op (. or -), additionaly a block is prefixed by &-=
otherwise kind is defaulted depending on last op: <→=, ^→@, &→= and all other ops to itself

Defaults: dOp, dKi

  • name → dCl & name
  • string → dCl string
  • block → dCl & = block
  • defOp: . or - if op is omitted

for string/name/noOpBlock$name → $.&name or $-&name

  • $ .& or -& =
  • $. ! .

new Spezialzeichen

symbolstatementopkindvarAccessfileSpec
$escape to wsh    
 output    
*comment    
#compilerDirective literal  
!pipesingelton 1assTab 1dereference 
>redirectOutput  read 
<redirectInputa2file 1  
;pipe separator    
=assignment skeleton  
@runrunshell  
@proc  a2run   
- a2valuerexxString  
. a2objrexxObjdereference or subfieldexternal
? singleOrNull isDefined when??? 
& varAccess   
:  assAtt attributes ifNew
%callArgs  subField 
'StringDelimiter    
"StringDelimiter    
{...}braceBlock    
{ , }callArgs    
( )callArgs    
^functionCall    
[...$]bracketBlock    
/name/ .... $/name/namedBlock    
~    user
+     
\     
£     
      
  • 1 if a statement or an expression is expected, < is the redirection statement, for a2file use .<

newer syntax ohne $

  • primary = op* (sConst | name | kind? block )
  • primar1 = primary not starting with something that starts a command
  • exprW = primary ('^' primary)*

new syntax ohne $!

  • prim1 = sConst | var | kind? block
  • kind = ('.' | '-' | '=' | ':' | '#' | '@')? '!' ?
  • prim2 = o1* ('@' | '^') (prim1 | prim2) '%' op* prim1
  • primary = (o1 | '@' | '^')* prim2

abbreviations

  • $name → varAccess
  • ${expr} → varAccess
  • $@name() oder { , , } → call mit varAccess
shell = pipe ? (';' pipe? )*
pipe = ioRedir stmts ( '!' stmts )*
ioRedir = (('<' | '>' | '>>') file spNlCom* )+
stmts = ( ( stmt | expr ) spNlCom* )+
data = ( spCom* | expr) (nl (expr | sp* comment spCom* )* (nl spCom* )? (stmt data )*
expr = (( noDo+ | primary ) comment* )+
primary = op* (varCo | '<' file | 'compile' kind | kind? block )
var = ( '?' | '?>' )? ( name | '[' exprB ']' ) ('.' name | '[' exprB ']')*
varCo = sConst | var
file = exprBlo
if exprBlo (default kind =) is a block without preceeding operators, its lines become the content of the file (JBuf), otherwise the value is casted to file e.g. String yields a fileSpec.
exprBlo = (op* kind)? ( block | exprS )
exec = '@' exprBlo
call = '@' name ('(' spCom* ')' | ( '-', '=' | '.' )? '{' exprB '}' )
ass = '=' ( var '=')? exprBlo
embedded assignment (speziell für with, do)
wsh = cUnit ? ( '$#' name '#' kind cUnit )* ( ( '$#end' | '$#out' ) litText )
wsh input consists of a compilation unit possibly followed by named compilation units, that are put into the variable pool. This allows to combine the arguments to the interpreter and several fragments of the source file.
cUnit = unit ? ( '$#' kind unit )*
a compilationUnit consists possibly of an unit of implicit kind, possibly followed by units of explicit kind.
unit = data | shell | assAtt | assTab | litText
A unit with implicit kind, which is determined by the environment
data = ( spCom* | expr) (nl (expr | sp* comment spCom* )* (nl spCom* )? (stmt data )*
Defines line oriented data and consists of expressions and statements.
  • All expressions are of the same kind or constant
  • Partial lines (i.e. at begin, end or beside a stmt) are ignored, if they consist only of spaces and comments.
  • Empty lines with comments are also ignored
shell = pipe ? ('$;' pipe? )*
A pipe is a statement or language code with optional IO redirections. Caution: Semicolons without $ do not terminate a pipe but are part of the underlying language.
expr = (( noDo+ | primary ) comment* )+
expressions consists text (without dollars or newLines) and primaries, comments are ignored (i.e. substitued by 0 or 1 space depending on the context). The kind of the expression determines how text is interpreted.
exprS = spCom* expr spCom*
an expression with leading and trailing spaces stripped
exprB = spCom* (( noBr+ | primary ) comment* )+ spCom*
a type of expressions with texts without {}=, leading and trailing spaces stripped
exprW = (( word | primary ) comment* )+
an type of expressions with texts without (free) spaces or {}=
kind = '.' | '-' | '=' | ':' | '!' | '#' | '@'
there are 7 kinds with the following meaning
three flavours of stringData
- = string: text is (part of) a rexx expression that yields a String
= = skeleton: text is literal data, expression yields a string
# = literal text: text without rexx or wsh interpretation
three flavours of object(s)
. = object: text is (part of) a rexx expression that yields an Object
: = object(s) in assAtt (attribute assignment syntax}
! = object(s) in assTab {tabular assignment syntax)
and finally code yielding an ORun
@ = shell: text is (part of) rexx statements
op = '.' | '-' | '<' | '@' | '!' | '?'
there are 6 object operators:
. = a2object: a string is lifted to an objectString, everything else unchanged
- = a2string: objectString to its value, conacatenates the contents of a File or Run (with one space between lines, files any line is no

string), otherwise fails

< = a2file: String to file with that specification, an ORun to OBuf with the output of running the ORun, otherwise fails
@ = a2run: a file or run as a run, ohterwise fails
! = exact1: singelton operator: if File or Run, extracts the only element of the content, fails if it contains 0 or more than 1 element, identiy on other objects
? = max1: File or Run, extracts the only element of the content, or null if it contains 0 elements. Fails if more than 1 element, identiy on other objects
primary = op* (varCo | '<' file | 'compile' kind | kind? block )
A primary is an object or a string from a
variable expansion,
string constant

or an operator chain to a

file,
variable expansion or string constant
compilation of stdIn as the specified kind to a Run
block which yields an instance of string, object, Run or File, depending on the operator chain and kind,
varCo = sConst | ( '?' | '?>' )? name ('.' name | '[' exprB ']')*
a variable expansion or a string constant. The variable expansion yields a string or an object depending on context. The form with braces allows options, nested variables and variable names that are not a name.
? yields 1 if variable is defined, 0 otherwise
> reads stdIn into variable, yields 1 if not at end
otherwise does a normal expansion
exprB yields an arbitrary variableName, possibly with nested variable expansions
file = exprBlo
if exprBlo (default kind =) is a block without preceeding operators, its lines become the content of the file (JBuf), otherwise the value is casted to file e.g. String yields a fileSpec.
exprBlo = (op* kind)? ( block | exprS )
allows a block or an expression of a possibly specified kind possible transformed by an operator chain
block = '{' unit '}' | '[' unit '$]' | '/' noSla* '/' unit '$/' noSla* '/'
A block combines several expressions or statements in a single syntactical entitiy. The content of a block is evaluated according to a kind. This kind is implîed or explicitley given, immedidiatly before the block. For clarity, {} blocks do not allow nls. The slashes give label a block with the same label at the begin and end
pipe = ioRedir stmts ( '!' stmts )*
this is execution order, syntax order is more flexible
ioRedir = (('<' | '>' | '>>') file spNlCom* )+
$< designates an input file, several input files are concatenated. An Output with $> replaces an existing file, $>> appends to it. Several Outputs are an error.
stmts = ( ( stmt | expr ) spNlCom* )+
expr yields rexx statements with trailing comma handling for rexx line continuations
stmt = '$=' ass
| ( '$@for' | '$@with' | '$@forWith' ) exprB stmt
| '$@ct' spCom* stmt
| '$@proc' exprB stmt
| '$@do' (spCom* name spCom* '=')? exprB stmt
| '$@' name '(' spCom* ')'
| '$@' name ( '-', '=' | '.' )? '{' exprB '}'
| '$@' exprBlo
| '$$' exprBlo
$@for readloop on stdIn, the read object is assigned to the variabe named exprB
$@ct executes the statement at compile time
$@proc declares the variable named exprB as a procedure (an instance of run) at compile time
$@do: rexx do logic, control variable assigned
$@name() run the procedure (oRun of the object in variable pool) of the given name
$@name?{exprB} run the procedure (object in variable pool) of the given name with exprB as arguments, the kind of exprB is given between name and {, default -
$@obj run the object
$$ exprBlo writes the exprBlo to stdOut (default kind =, no cast)
ass = ( exprB '=')? exprBlo
assigns variable named exprB the contents of exprBlo.
  • If exprB is missing, the expr must be a named block, and its name is used as the name of the variable, e.g. $=/lines/ ... $/lines/
  • an assignment can address object in the variable pool, or an attritute at the end of an attribute chain of an object from the variable pool.
  • If the block is of kind attribute or tabular assignment then the addressed variable or attribute defines the environment for that block
assAtt = ( ass | stmt | ( '$'? (':' class | ':.' exprB)? ';' ) | spNlCom )*
the ass (without $) are confined to the latest with, typically from an assignment of the form .... =:... The semicolon (with or without $) create the next element of collection. This only works after =<: (replacment of old collection) or =<<: (append to old collection). Currently it only works for stems. The dollar before the block terminator (] or /../) can be omitted on the beginning of a new line or anywhere, the scanner can recognise it.
assTab = spNlCom? ( name spCom )* nl (spNlCom | stmt | (exprW spCom)+ nl )*
Multiple assignments in the form of a table. The list of names are the headers with the fieldName to be assigned to. Each line of exprWs assigns the fields of one element of a collection. Each expression must overlap with exactly on name from the header. All expression are of kind = and cannot contain free spaces - however $-string constants with spaces are ok (e.g. $" "). The rest is similar to assAtt.

Lexicals

sConst = '$''' ((* noNl not '''' *) | '''''')* '''' | '$"' ((* noNl not '”' *) | '””')* '”'' ''''
a string enclosed in single or double quotes, prefixed by a dollar. Inside, two quotes stand for a single one.
name = (* starting with a letter followed by any number of digits or letters, case sensitive! *)
nl = (* newLine character(s) or record switch *)
noNl = (* one character not nl *)
sp = (* one space character ' ', tab etc., but not nl *)
noDo = (* one character neither '$' nor nl *)
noSla = (* one character neither '/' nor nl *)
noBr = (* one character neither in '{}=' nor nl *)
word = (* one or more characters of noBr but not space *)
textB = ( noBr+ | '{' textB '}' )*
textLns = spCom* (nl noNl* )*
comment = '$**' noNl* | '$*+' noNl* nl | '$*(' (comment | sConst | noNl | nl )* '$*)'
$** starts a comment until the last character before next nl,
$*+ includes also the next nl (joins lines)
* if found by the parser direclty in assAtt or assTab is an abbreviation for $**
spCom = sp | comment
spNlCom = sp | nl | comment
litText = (* any number of any characters, newlines, etc. *)
uninterpreted text, with or without stopper, depending on the context

Uebersicht Spezialzeichen

namesymbolLinuxwshrexx
escape to wsh$ Escape to wsh, variableMarker $var, output $$ 
comment* $**, $*+ or $*(....$*) 
piping
pipe!|stmt1 $| stmt2... call pipe ...
redirectOutput> output redirection $>...call pipeLast '> fileName'
redirectInput< input redirection $<...call pipeBegin '< fileName'
semicolon; Statement separator in $;call pipeBegin ... call pipeEnd
accessPath Ops
Subfeld% ${a%f1}m.a.f1
Referenz! ${a!r1} über die Referenz im a%r1xx = m.a.r1; m.xx
Ref or Sub. ${a.x1} je nach DatenTyp a%x1 oder a!x1 
expressions
value- expression in $(, $-[, $-{, $-comp..., o2string
obj. expression in $(, $-[, $-{, $-comp..., s2o, file, etc.
singleton! ! $@[ $$ a ] 
isDefined? in ${?a}: is variable defined?envHasKey
StringDelimiter" $"..." 
StringDelimiter' $'...' 
statements
assignment= $=var= ...envPut, envPutO
run@ run block, call procedure, run object, $@for etc.call ...
blocks
braceBlock{...} for variables ${a} or short blocks $-{1+1} 
bracketBlock[...$]   
slashBlock/name/ .... $/name/   
fileSpecs
external spec.   
user~ ~.work.~dsn2jcl
attributes if new: