Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JCL syntax hiliter update #289

Merged
merged 4 commits into from
Sep 6, 2022
Merged
Changes from 1 commit
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
168 changes: 94 additions & 74 deletions webClient/src/app/editor/code-editor/monaco/hiliters/jcl.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import { environment } from '../../../../../environments/environment';
const jclDebug = !environment.production;

const JCL_KEYWORDS = '(CNTL|DD|EXEC|EXPORT|JOB|INCLUDE|JCLLIB|OUTPUT|PROC|SCHEDULE|SET|XMIT|COMMAND|JOBGROUP|\
GJOB|JOBSET|SJOB|ENDSET|AFTER|BEFORE|CONCURRENT|ENDGROUP)';
const JCL_KEYWORDS_SPECIAL = '(ENDCNTL|EXPORT|ELSE|ENDIF|PEND|THEN)';

export const JCL_HILITE = {
// Set defaultToken to invalid to see what you do not tokenize yet
defaultToken: 'default',
Expand All @@ -8,100 +15,113 @@ export const JCL_HILITE = {


// Expand tokenizer via: https://microsoft.github.io/monaco-editor/monarch.html
// Logging for debugging:
// o [$S0] - displays the state
// o <nnn> - which hilite style is used
// o -> nnn - which state is next or '---' for none (= use the current state again)
// o '$0' - shows the regex match
tokenizer: {
root: [
[/^\/\/\*.*$/, { token: 'jcl-comment' }], //Comment begins with //*, lasts until end of line
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2'}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default' }], //Checks for linenumber + linebreak (new JCL statement)
[/( +)/, { token: 'whitespace' }], //Removes any previous line spaces
[/^\/\*/, { token: 'jcl-statement', next: '@nameFirstChar' }], //Statements begin with /* ...
[/^\/\//, { token: 'jcl-statement', next: '@nameFirstChar' }], // or //
[/.*/, { token: 'jcl-none' }], //When a token doesn't match, the line is blue
[/^\/\/\*.*$/, {token: 'jcl-comment', ...jclDebug && {log: '[$S0] <comment> -> --- \'$0\''}} ], //Comment begins with //*, lasts until end of line
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', ...jclDebug && {log: '[$S0] <default> -> --- \'$0\'' }}], //Checks for linenumber + linebreak (new JCL statement)
[/( +)/, { token: 'whitespace', ...jclDebug && {log: '[$S0] <whitespace> -> --- \'$0\'' }}], //Removes any previous line spaces
[/^\/\*[ ]*$/, { token: 'jcl-statement', ...jclDebug && {log: '[$S0] <statement> -> ---' }}], //Starts with /* followed by end or spaces and end
[/^\/\*[ ]/, { token: 'jcl-statement', next: '@comments', ...jclDebug && {log: '[$S0] <statement> -> comments \'$0\'' }}], //Statements begin with /*space ...
[/^\/\*/, { token: 'jcl-statement', next: '@nameFirstChar', ...jclDebug && {log: '[$S0] <statement> -> nameFirstChar \'$0\'' }}], //Statements begin with /* ...
[/^\/\//, { token: 'jcl-statement', next: '@nameFirstChar', ...jclDebug && {log: '[$S0] <statement> -> nameFirstChar \'$0\'' }}], // or //
[/.*/, { token: 'jcl-none', ...jclDebug && {log: '[$S0] <none> -> --- \'$0\'' }}], //When a token doesn't match, the line is blue
],
nameFirstChar: [
[/[ ]/, { token: 'jcl-default', next: '@operator' }], //Name must start with capital or national symbols
[/[A-Z|@|#|$| ]/, { token: 'jcl-default', next: '@name' }], //Name must start with capital or national symbols
[/./, { token: 'jcl-invalid', next: '@name' }], //For everything else
[/[ ]/, { token: 'jcl-default', next: '@operator', ...jclDebug && {log: '[$S0] <default> -> operator \'$0\'' }}], //Name must start with capital or national symbols
[/[A-Z|@|#|$| ]/, { token: 'jcl-default', next: '@name', ...jclDebug && {log: '[$S0] <default> -> name \'$0\'' }}], //Name must start with capital or national symbols (space is for 1 letter label)
[/./, { token: 'jcl-invalid', next: '@name', ...jclDebug && {log: '[$S0] <invalid> -> name \'$0\'' }}], //For everything else
],
name: [
[/[A-Z|@|#|$|0-9]{0,7}/, { token: 'jcl-default', next: '@invalidName' }], //Name must be between {0, 8} characters
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2'}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall' }], //Checks for linenumber + linebreak (new JCL statement)
[/( +)/, { token: 'whitespace', next: '@operator' }], //Spaces(s) designate when to check for operator keywords after name
[/'.*'/, { token: 'jcl-string', next: '@strings' }],
[/[^A-Z|@|#|$|0-9]/, { token: 'jcl-invalid' }], // Checks for invalid JCL characters in names
[/./, { token: 'jcl-default' }]
name: [
[/[A-Z|@|#|$|\.|0-9]{0,16}/, { token: 'jcl-default', next: '@invalidName', ...jclDebug && {log: '[$S0] <default> -> invalidName \'$0\'' }}], //Name must be between {0, 16} characters
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for linenumber + linebreak (new JCL statement)
[/( +)/, { token: 'whitespace', next: '@operator', ...jclDebug && {log: '[$S0] <whitespace> -> operator \'$0\'' }}], //Spaces(s) designate when to check for operator keywords after name
[/'.*'/, { token: 'jcl-string', next: '@strings', ...jclDebug && {log: '[$S0] <string> -> string \'$0\'' }}],
[/[^A-Z|@|#|$|0-9]/, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> ---\'$0\'' }}], // Checks for invalid JCL characters in names
[/./, { token: 'jcl-default', ...jclDebug && {log: '[$S0] <default> -> --- \'$0\'' }}]
],

invalidName: [
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/( +)/, { token: 'jcl-invalid', next: '@operator' }], //Name must be between {0, 8} characters
[/./, { token: 'jcl-invalid', }], //Name must be between {0, 8} characters
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/( +)/, { token: 'jcl-invalid', next: '@operator', ...jclDebug && {log: '[$S0] <invalid> -> operator \'$0\'' }}], //Name must be between {0, 8} characters
[/./, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> --- \'$0\'' }}], //Name must be between {0, 8} characters
],
operator: [
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/!/, { token: 'jcl-invalid', next: '@operands' }], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid', next: '@operands' }], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter', next: '@operands'}],
[/'/, { token: 'jcl-string', next: '@strings' }],
[/[()]/, '@brackets'],
[/(IF)/, { token: 'jcl-operator', next: '@if' }], //If is special, gets its own logic
[/(DD|CNTL|EXEC|JOB|INCLUDE|JCLLIB|OUTPUT|PROC|SCHEDULE|SET|XMIT|COMMAND) *$/, { token: 'jcl-operator', next: '@popall' }],
[/(DD|CNTL|EXEC|JOB|INCLUDE|JCLLIB|OUTPUT|PROC|SCHEDULE|SET|XMIT|COMMAND) +/, { token: 'jcl-operator', next: '@operands' }],
[/(ENDCNTL|EXPORT|ELSE|ENDIF|PEND|THEN) *$/, { token: 'jcl-operator', next: '@popall' }],
[/(ENDCNTL|EXPORT|ELSE|ENDIF|PEND|THEN) +/, { token: 'jcl-operator', next: '@comments' }],
[/[^\s\\a-z(,|&|=|\^)]+/, { token: 'jcl-default', next: '@operands'}], //Matches the rest
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/!/, { token: 'jcl-invalid', next: '@operands', ...jclDebug && {log: '[$S0] <invalid> -> operands \'$0\'' }}], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid', next: '@operands', ...jclDebug && {log: '[$S0] <invalid> -> operands \'$0\'' }}], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter', next: '@operands', ...jclDebug && {log: '[$S0] <delimiter> -> operands \'$0\'' }}],
[/'/, { token: 'jcl-string', next: '@strings', ...jclDebug && {log: '[$S0] <string> -> string \'$0\'' }}],
[/[()]/, '@brackets' ],
[/(IF)/, { token: 'jcl-operator', next: '@if', ...jclDebug && {log: '[$S0] <operator> -> if \'$0\'' }}], //If is special, gets its own logic
[new RegExp(JCL_KEYWORDS + " *$"), { token: 'jcl-operator', next: '@popall', ...jclDebug && {log: '[$S0] <operator> -> popall \'$0\'' }}],
[new RegExp(JCL_KEYWORDS + " +"), { token: 'jcl-operator', next: '@operands', ...jclDebug && {log: '[$S0] <operator> -> operands \'$0\'' }}],
[new RegExp(JCL_KEYWORDS_SPECIAL + " *$"), { token: 'jcl-operator', next: '@popall', ...jclDebug && {log: '[$S0] <operator> -> popall \'$0\'' }}],
[new RegExp(JCL_KEYWORDS_SPECIAL + " +"), { token: 'jcl-operator', next: '@comments', ...jclDebug && {log: '[$S0] <operator> -> comments \'$0\'' }}],
[/[^\s\\a-z(,|&|=|\^)]+/, { token: 'jcl-default', next: '@operands', ...jclDebug && {log: '[$S0] <default> -> operands \'$0\'' }}], //Matches the rest
],
if: [
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/(THEN )/, { token: 'jcl-operator', next: '@comments' }],
[/./, { token: 'jcl-variable' }],
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/(THEN )/, { token: 'jcl-operator', next: '@comments', ...jclDebug && {log: '[$S0] <operator> -> comments \'$0\'' }}],
[/./, { token: 'jcl-variable', ...jclDebug && {log: '[$S0] <variable> -> --- \'$0\'' }}],
],
operands: [
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2'}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall' }], //Checks for linenumber + linebreak (new JCL statement)
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/, /, { token: 'jcl-delimiter', next: '@comments' }], //Checks for , + space (leads to comment)
[/'/, { token: 'jcl-string', next: '@strings' }],
[/!/, { token: 'jcl-invalid' }], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid' }], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter' }],
[/[()]/, '@brackets'],
[/ /, { token: 'jcl-variable', next: '@comments' }],//Space leads to comments
[/./, { token: 'jcl-variable' }],//For everything else
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for linenumber + linebreak (new JCL statement)
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/, /, { token: 'jcl-delimiter', next: '@comments', ...jclDebug && {log: '[$S0] <delimiter> -> comments \'$0\'' }}], //Checks for , + space (leads to comment)
[/'/, { token: 'jcl-string', next: '@strings', ...jclDebug && {log: '[$S0] <string> -> string \'$0\'' }}],
[/!/, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> --- \'$0\'' }}], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> --- \'$0\'' }}], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter', ...jclDebug && {log: '[$S0] <delimiter> -> --- \'$0\'' }}],
[/[)]$/, {token: 'jcl-delimiter', next:'@popall', ...jclDebug && {log: '[$S0] <delimiter> -> popall' }}],
[/[()]/, '@brackets' ],
[/ /, { token: 'jcl-variable', next: '@comments', ...jclDebug && {log: '[$S0] <variable> -> comments \'$0\'' }}],//Space leads to comments
[/\*$/, { token: 'jcl-variable', next: '@popall', ...jclDebug && {log: '[$S0] <variable> -> popall \'$0\'' }}], //(*) as last char
[/.$/, { token: 'jcl-variable', next: '@popall', ...jclDebug && {log: '[$S0] <variable> -> popall \'$0\'' }}], //For end
[/./, { token: 'jcl-variable', ...jclDebug && {log: '[$S0] <variable> -> --- \'$0\'' }}], //For everything else

],
operands2: [ //JCL has a behavior where it will accept two sets of operands before detecting comments
//for certain conditions, usually when statements are continued via a ','
[/, *$/, { token: 'jcl-delimiter', next: '@operands2' }], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2'}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall' }], //Checks for linenumber + linebreak (new JCL statement)
[/, /, { token: 'jcl-delimiter', next: '@comments' }], //Checks for , + space (leads to comment)
[/'/, { token: 'jcl-string', next: '@strings' }],
[/!/, { token: 'jcl-invalid' }], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid' }], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter' }],
[/[()]/, '@brackets'],
[/ +/, { token: 'jcl-variable', next: '@operands' }],//Space leads to next operand
[/\//, { token: 'jcl-variable' }],
[/^.*/, { token: 'jcl-none' }], //When a token doesn't match, the line is blue
[/./, { token: 'jcl-variable' }],//For everything else
//for certain conditions, usually when statements are continued via a ','
[/, *$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for end of line with a ','
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for end of line without a ','
[/,( +)[0-9]+$/, { token: 'jcl-delimiter', next: '@operands2', ...jclDebug && {log: '[$S0] <delimiter> -> operands2 \'$0\'' }}], //Checks for ',' + linenumber + linebreak (continuation of statement)
[/( *)[0-9]+$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> popall \'$0\'' }}], //Checks for linenumber + linebreak (new JCL statement)
[/, /, { token: 'jcl-delimiter', next: '@comments', ...jclDebug && {log: '[$S0] <delimiter> -> comments \'$0\'' }}], //Checks for , + space (leads to comment)
[/'/, { token: 'jcl-string', next: '@strings', ...jclDebug && {log: '[$S0] <string> -> string \'$0\'' }}],
[/!/, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> --- \'$0\'' }}], // Checks for invalid JCL characters
[/[a-z]+/, { token: 'jcl-invalid', ...jclDebug && {log: '[$S0] <invalid> -> --- \'$0\'' }}], // Checks for invalid lowercase JCL
[/(,|&|=|\^)/, { token: 'jcl-delimiter', ...jclDebug && {log: '[$S0] <delimiter> -> --- \'$0\'' }}],
[/[()]/, '@brackets' ],
[/ +/, { token: 'jcl-variable', next: '@operands', ...jclDebug && {log: '10. [$S0] <variable> -> operands \'$0\'' }}],//Space leads to next operand
[/\//, { token: 'jcl-variable', ...jclDebug && {log: '[$S0] <variable> -> --- \'$0\'' }}],
[/^.*/, { token: 'jcl-none', ...jclDebug && {log: '[$S0] <none> -> --- \'$0\'' }}], //When a token doesn't match, the line is blue
[/./, { token: 'jcl-variable', ...jclDebug && {log: '[$S0] <variable> -> --- \'$0\'' }}],//For everything else
],
comments: [
[/.*/, { token: 'jcl-comment', next: '@popall' }],
[/ *\n| *$/, { token: 'jcl-default', next: '@popall' }],
[/.*/, { token: 'jcl-comment', next: '@popall', ...jclDebug && {log: '[$S0] <comment> -> popall \'$0\'' }}],
[/ *\n| *$/, { token: 'jcl-default', next: '@popall', ...jclDebug && {log: '[$S0] <default> -> --- \'$0\'' }}],
],
strings: [ //Strings get their own category because Monaco doesn't seem to deal with pattern matching
//over line breaks, even with multiline flags. This way, we just put strings into their own loop.
[/.*' /, { token: 'jcl-string', next: '@comments' }], // Space after the ending (') character is a comment
[/.*' */, { token: 'jcl-string', next: '@operands' }], // Covers all characters in string until ending (') character
[/.*/, { token: 'jcl-string' }],
[/.*' *$/, { token: 'jcl-string', next: '@popall', ...jclDebug && {log: '[$S0] <string> -> popall \'$0\'' }}], // (') character ending line -> we are done here
[/.*' /, { token: 'jcl-string', next: '@comments', ...jclDebug && {log: '[$S0] <string> -> comments \'$0\'' }}], // Space after the ending (') character is a comment
[/.*' */, { token: 'jcl-string', next: '@operands', ...jclDebug && {log: '[$S0] <string> -> operands \'$0\'' }}], // Covers all characters in string until ending (') character
[/.*/, { token: 'jcl-string', ...jclDebug && {log: '[$S0] <string> -> --- \'$0\'' }}],
]
}
};