From 99d979a04610ecd023e0f8ce84ae0c97e085e438 Mon Sep 17 00:00:00 2001 From: cedporter Date: Tue, 7 Jan 2020 09:10:22 -0500 Subject: [PATCH] SAS: Added CASL support (#2112) This adds CASL support, a scripting language used within PROC CAS in SAS. https://go.documentation.sas.com/?cdcId=pgmsascdc&cdcVersion=9.4_3.4&docsetId=pgmdiff&docsetTarget=p06ibhzb2bklaon1a86ili3wpil9.htm&locale=en --- components/prism-sas.js | 136 +++++++++++++++++----- components/prism-sas.min.js | 2 +- tests/languages/sas/keyword_feature.test | 4 +- tests/languages/sas/proccas_feature.test | 141 +++++++++++++++++++++++ 4 files changed, 249 insertions(+), 34 deletions(-) create mode 100644 tests/languages/sas/proccas_feature.test diff --git a/components/prism-sas.js b/components/prism-sas.js index a3a48442ba..80ae9ed66a 100644 --- a/components/prism-sas.js +++ b/components/prism-sas.js @@ -29,12 +29,22 @@ var punctuation = /[$%@.(){}\[\];,\\]/; + var func = { + pattern: /%?\w+(?=\()/, + alias: 'keyword' + }; + var args = { + 'function' : func, 'arg-value': { - pattern: /(=)[A-Z]+/i, + pattern: /(\s*=\s*)[A-Z\.]+/i, lookbehind: true }, 'operator': /=/, + 'macro-variable': { + pattern: /&[^\.]*\./i, + alias: 'string' + }, 'arg': { pattern: /[A-Z]+/i, alias: 'keyword' @@ -45,6 +55,29 @@ 'string': string }; + var format = { + pattern: /\b(?:format|put)\b=?[\w'$.]+/im, + inside: { + 'keyword': /^(?:format|put)(?=\=)/i, + 'equals': /=/, + 'format': { + pattern: /(?:\w|\$\d)+\.\d?/i, + alias: 'number' + } + } + }; + + var altformat = { + pattern: /\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i, + inside: { + 'keyword': /^(?:format|put)/i, + 'format': { + pattern: /[\w$]+\.\d?/, + alias: 'number' + } + } + }; + var globalStatements = { pattern: /((?:^|[\s])=?)(?:catname|checkpoint execute_always|dm|endsas|filename|footnote|%include|libname|%list|lock|missing|options|page|resetline|%run|sasfile|skip|sysecho|title\d?)\b/i, lookbehind: true, @@ -57,6 +90,34 @@ alias: 'keyword' }; + var actionSets = 'accessControl|cdm|aggregation|aStore|ruleMining|audio|autotune|bayesianNetClassifier|bioMedImage|boolRule|builtins|cardinality|sccasl|clustering|copula|countreg|dataDiscovery|dataPreprocess|dataSciencePilot|dataStep|decisionTree|deepLearn|deepNeural|varReduce|simSystem|ds2|deduplication|ecm|entityRes|espCluster|explainModel|factmac|fastKnn|fcmpact|fedSql|freqTab|gam|gleam|graphSemiSupLearn|gVarCluster|hiddenMarkovModel|hyperGroup|image|iml|ica|kernalPca|langModel|ldaTopic|sparseML|mlTools|mixed|modelPublishing|mbc|network|optNetwork|neuralNet|nonlinear|nmf|nonParametricBayes|optimization|panel|pls|percentile|pca|phreg|qkb|qlim|quantreg|recommend|tsReconcile|deepRnn|regression|reinforcementLearn|robustPca|sampling|sparkEmbeddedProcess|search(?:Analytics)?|sentimentAnalysis|sequence|configuration|session(?:Prop)?|severity|simple|smartData|sandwich|spatialreg|stabilityMonitoring|spc|loadStreams|svDataDescription|svm|table|conditionalRandomFields|text(?:Rule(?:Develop|Score)|Mining|Parse|Topic|Util|Filters|Frequency)|tsInfo|timeData|transpose|uniTimeSeries'; + + var casActions = { + pattern: RegExp('(^|\\s)(?:action\\s+)?(?:)\\.[a-z]+\\b[^;]+'.replace(//g, actionSets), 'i'), + lookbehind: true, + inside: { + 'keyword': RegExp('(?:)\\.[a-z]+\\b'.replace(//g, actionSets), 'i'), + 'action': { + pattern: /(?:action)/i, + alias: 'keyword' + }, + 'function': func, + 'arg-value': args['arg-value'], + 'operator': args.operator, + 'comment': comment, + 'argument': args.arg, + 'number': number, + 'numeric-constant': numericConstant, + 'punctuation': punctuation, + 'string': string + } + }; + + var keywords = { + pattern: /((?:^|\s)=?)(?:after|analysis|and|array|barchart|barwidth|begingraph|by|call|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|continue|data(?=\=)|define|delete|describe|document|do\s+over|do|dol|drop|dul|end(?:source|comp)?|entryTitle|else|eval(?:uate)?|exec(?:ute)?|exit|fill(?:attrs)?|file(?:name)?|flist|fnc|function(?:list)?|goto|global|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|leave|legendlabel|length|libname|loadactionset|merge|midpoints|name|noobs|nowd|_?null_|ods|options|or|otherwise|out(?:put)?|over(?:lay)?|plot|put|print|raise|ranexp|rannor|rbreak|retain|return|select|set|session|sessref|source|statgraph|sum|summarize|table|temp|terminate|then\s+do|then|title\d?|to|var|when|where|xaxisopts|yaxisopts|y2axisopts)\b/i, + lookbehind: true, + }; + Prism.languages.sas = { 'datalines': { pattern: /^(\s*)(?:(?:data)?lines|cards);[\s\S]+?^\s*;/im, @@ -130,6 +191,43 @@ } }, + 'proc-cas': { + pattern: /(^proc\s+cas(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|data);|(?![\s\S]))/im, + lookbehind: true, + inside: { + 'statement-var': { + pattern: /((?:^|\s)=?)saveresult\s+[^;]+/im, + lookbehind: true, + inside: { + 'statement': { + pattern: /^saveresult\s+\S+/i, + inside: { + keyword: /^(?:saveresult)/i + } + }, + rest: args + } + }, + 'cas-actions': casActions, + 'statement': { + pattern: /((?:^|\s)=?)(?:default|(?:un)?set|on|output|upload)[^;]+/im, + lookbehind: true, + inside: args + }, + 'step': step, + 'keyword': keywords, + 'function': func, + 'comment': comment, + 'format': format, + 'altformat': altformat, + 'global-statements': globalStatements, + 'number': number, + 'numeric-constant': numericConstant, + 'punctuation': punctuation, + 'string': string + } + }, + 'proc-args': { pattern: RegExp(/(^proc\s+\w+\s+)(?!\s)(?:[^;"']|)+;/.source.replace(//g, stringPattern), 'im'), lookbehind: true, @@ -176,33 +274,12 @@ lookbehind: true, inside: args }, - 'function': { - pattern: /%?\w+(?=\()/, - alias: 'keyword' - }, - 'format': { - pattern: /\b(?:format|put)\b=?[\w'$.]+/im, - inside: { - 'keyword': /^(?:format|put)(?=\=)/i, - 'equals': /=/, - 'format': { - pattern: /(?:\w|\$\d)+\.\d?/i, - alias: 'number' - } - } - }, - 'altformat': { - pattern: /\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i, - inside: { - 'keyword': /^(?:format|put)/i, - 'format': { - pattern: /[\w$]+\.\d?/, - alias: 'number' - } - } - }, - 'numeric-constant': numericConstant, + 'cas-actions': casActions, 'comment': comment, + 'function': func, + 'format': format, + 'altformat': altformat, + 'numeric-constant': numericConstant, 'datetime': { // '1jan2013'd, '9:25:19pm't, '18jan2003:9:27:05am'dt pattern: RegExp(stringPattern + '(?:dt?|t)'), @@ -210,10 +287,7 @@ }, 'string': string, 'step': step, - 'keyword': { - pattern: /((?:^|\s)=?)(?:action|after|analysis|and|array|barchart|barwidth|begingraph|by|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|data(?=\=)|define|document|do\s+over|do|dol|drop|dul|end|entryTitle|else|endcomp|eval(?:uate)?|exec(?:ute)?|fill(?:attrs)?|filename|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|legendlabel|length|libname|merge|midpoints|name|noobs|nowd|ods|options|or|out(?:put)?|overlay|plot|ranexp|rannor|rbreak|retain|set|session|sessref|statgraph|sum|summarize|table|temp|then\s+do|then|title\d?|to|var|where|xaxisopts|yaxisopts|y2axisopts)\b/i, - lookbehind: true, - }, + 'keyword': keywords, // In SAS Studio syntax highlighting, these operators are styled like keywords 'operator-keyword': { pattern: /\b(?:eq|ne|gt|lt|ge|le|in|not)\b/i, diff --git a/components/prism-sas.min.js b/components/prism-sas.min.js index 91ee6c00ce..bab73d6e50 100644 --- a/components/prism-sas.min.js +++ b/components/prism-sas.min.js @@ -1 +1 @@ -!function(e){var t="(?:\"(?:\"\"|[^\"])*\"(?!\")|'(?:''|[^'])*'(?!'))",a=/\b(?:\d[\da-f]*x|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,n={pattern:RegExp(t+"[bx]"),alias:"number"},s=[/\/\*[\s\S]*?\*\//,{pattern:/(^\s*|;\s*)\*[^;]*;/m,lookbehind:!0}],i={pattern:RegExp(t),greedy:!0},r=/[$%@.(){}\[\];,\\]/,o={"arg-value":{pattern:/(=)[A-Z]+/i,lookbehind:!0},operator:/=/,arg:{pattern:/[A-Z]+/i,alias:"keyword"},number:a,"numeric-constant":n,punctuation:r,string:i},l={pattern:/((?:^|[\s])=?)(?:catname|checkpoint execute_always|dm|endsas|filename|footnote|%include|libname|%list|lock|missing|options|page|resetline|%run|sasfile|skip|sysecho|title\d?)\b/i,lookbehind:!0,alias:"keyword"},d={pattern:/(^|\s)(?:submit(?:\s+(?:load|parseonly|norun))?|endsubmit)\b/i,lookbehind:!0,alias:"keyword"};e.languages.sas={datalines:{pattern:/^(\s*)(?:(?:data)?lines|cards);[\s\S]+?^\s*;/im,lookbehind:!0,alias:"string",inside:{keyword:{pattern:/^(?:(?:data)?lines|cards)/i},punctuation:/;/}},"proc-sql":{pattern:/(^proc\s+(?:fed)?sql(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{sql:{pattern:RegExp("^[ \t]*(?:select|alter\\s+table|(?:create|describe|drop)\\s+(?:index|table(?:\\s+constraints)?|view)|create\\s+unique\\s+index|insert\\s+into|update)(?:|[^;\"'])+;".replace(//g,t),"im"),alias:"language-sql",inside:e.languages.sql},"global-statements":l,"sql-statements":{pattern:/(^|\s)(?:disconnect\s+from|exec(?:ute)?|begin|commit|rollback|reset|validate)\b/i,lookbehind:!0,alias:"keyword"},number:a,"numeric-constant":n,punctuation:r,string:i}},"proc-groovy":{pattern:/(^proc\s+groovy(?:\s+[\w|=]+)?;)(?:\s*submit)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{groovy:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,t),"im"),lookbehind:!0,alias:"language-groovy",inside:e.languages.groovy},"submit-statement":d,"global-statements":l,number:a,"numeric-constant":n,punctuation:r,string:i}},"proc-lua":{pattern:/(^proc\s+lua(?:\s+[\w|=]+)?;)(?:\s*submit)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{lua:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,t),"im"),lookbehind:!0,alias:"language-lua",inside:e.languages.lua},"submit-statement":d,"global-statements":l,number:a,"numeric-constant":n,punctuation:r,string:i}},"proc-args":{pattern:RegExp("(^proc\\s+\\w+\\s+)(?!\\s)(?:[^;\"']|)+;".replace(//g,t),"im"),lookbehind:!0,inside:o},"macro-keyword":{pattern:/((?:^|\s)=?)%(?:ABORT|BQUOTE|BY|CMS|COPY|DISPLAY|DO|ELSE|END|EVAL|GLOBAL|GO|GOTO|IF|INC|INCLUDE|INDEX|INPUT|KTRIM|LENGTH|LET|LIST|LOCAL|NRBQUOTE|NRQUOTE|NRSTR|PUT|QKTRIM|QSCAN|QSUBSTR|QSYSFUNC|QUOTE|QUPCASE|RETURN|RUN|SCAN|STR|SUBSTR|SUPERQ|SYMDEL|SYMGLOBL|SYMLOCAL|SYMEXIST|SYSCALL|SYSEVALF|SYSEXEC|SYSFUNC|SYSGET|SYSRPUT|THEN|TO|TSO|UNQUOTE|UNTIL|UPCASE|WHILE|WINDOW)\b/i,lookbehind:!0,alias:"keyword"},"macro-declaration":{pattern:/^%macro[^;]+(?=;)/im,inside:{keyword:/%macro/i}},"macro-end":{pattern:/^%mend[^;]+(?=;)/im,inside:{keyword:/%mend/i}},macro:{pattern:/%_\w+(?=\()/,alias:"keyword"},input:{pattern:/\binput\s+[-\w\s/*.$&]+;/i,inside:{input:{alias:"keyword",pattern:/^input/i},comment:s,number:a,"numeric-constant":n}},"options-args":{pattern:/(^options)[-'"|/\\<>*+=:()\w\s]*(?=;)/im,lookbehind:!0,inside:o},function:{pattern:/%?\w+(?=\()/,alias:"keyword"},format:{pattern:/\b(?:format|put)\b=?[\w'$.]+/im,inside:{keyword:/^(?:format|put)(?=\=)/i,equals:/=/,format:{pattern:/(?:\w|\$\d)+\.\d?/i,alias:"number"}}},altformat:{pattern:/\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i,inside:{keyword:/^(?:format|put)/i,format:{pattern:/[\w$]+\.\d?/,alias:"number"}}},"numeric-constant":n,comment:s,datetime:{pattern:RegExp(t+"(?:dt?|t)"),alias:"number"},string:i,step:{pattern:/(^|\s+)(?:proc\s+\w+|quit|run|data(?!\=))\b/i,alias:"keyword",lookbehind:!0},keyword:{pattern:/((?:^|\s)=?)(?:action|after|analysis|and|array|barchart|barwidth|begingraph|by|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|data(?=\=)|define|document|do\s+over|do|dol|drop|dul|end|entryTitle|else|endcomp|eval(?:uate)?|exec(?:ute)?|fill(?:attrs)?|filename|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|legendlabel|length|libname|merge|midpoints|name|noobs|nowd|ods|options|or|out(?:put)?|overlay|plot|ranexp|rannor|rbreak|retain|set|session|sessref|statgraph|sum|summarize|table|temp|then\s+do|then|title\d?|to|var|where|xaxisopts|yaxisopts|y2axisopts)\b/i,lookbehind:!0},"operator-keyword":{pattern:/\b(?:eq|ne|gt|lt|ge|le|in|not)\b/i,alias:"operator"},number:a,operator:/\*\*?|\|\|?|!!?|¦¦?|<[>=]?|>[<=]?|[-+\/=&]|[~¬^]=?/i,punctuation:r}}(Prism); \ No newline at end of file +!function(e){var t="(?:\"(?:\"\"|[^\"])*\"(?!\")|'(?:''|[^'])*'(?!'))",a=/\b(?:\d[\da-f]*x|\d+(?:\.\d+)?(?:e[+-]?\d+)?)\b/i,n={pattern:RegExp(t+"[bx]"),alias:"number"},i={pattern:/(^|\s+)(?:proc\s+\w+|quit|run|data(?!\=))\b/i,alias:"keyword",lookbehind:!0},s=[/\/\*[\s\S]*?\*\//,{pattern:/(^\s*|;\s*)\*[^;]*;/m,lookbehind:!0}],r={pattern:RegExp(t),greedy:!0},o=/[$%@.(){}\[\];,\\]/,l={pattern:/%?\w+(?=\()/,alias:"keyword"},d={function:l,"arg-value":{pattern:/(\s*=\s*)[A-Z\.]+/i,lookbehind:!0},operator:/=/,"macro-variable":{pattern:/&[^\.]*\./i,alias:"string"},arg:{pattern:/[A-Z]+/i,alias:"keyword"},number:a,"numeric-constant":n,punctuation:o,string:r},c={pattern:/\b(?:format|put)\b=?[\w'$.]+/im,inside:{keyword:/^(?:format|put)(?=\=)/i,equals:/=/,format:{pattern:/(?:\w|\$\d)+\.\d?/i,alias:"number"}}},p={pattern:/\b(?:format|put)\s+[\w']+(?:\s+[$.\w]+)+(?=;)/i,inside:{keyword:/^(?:format|put)/i,format:{pattern:/[\w$]+\.\d?/,alias:"number"}}},u={pattern:/((?:^|[\s])=?)(?:catname|checkpoint execute_always|dm|endsas|filename|footnote|%include|libname|%list|lock|missing|options|page|resetline|%run|sasfile|skip|sysecho|title\d?)\b/i,lookbehind:!0,alias:"keyword"},m={pattern:/(^|\s)(?:submit(?:\s+(?:load|parseonly|norun))?|endsubmit)\b/i,lookbehind:!0,alias:"keyword"},b="accessControl|cdm|aggregation|aStore|ruleMining|audio|autotune|bayesianNetClassifier|bioMedImage|boolRule|builtins|cardinality|sccasl|clustering|copula|countreg|dataDiscovery|dataPreprocess|dataSciencePilot|dataStep|decisionTree|deepLearn|deepNeural|varReduce|simSystem|ds2|deduplication|ecm|entityRes|espCluster|explainModel|factmac|fastKnn|fcmpact|fedSql|freqTab|gam|gleam|graphSemiSupLearn|gVarCluster|hiddenMarkovModel|hyperGroup|image|iml|ica|kernalPca|langModel|ldaTopic|sparseML|mlTools|mixed|modelPublishing|mbc|network|optNetwork|neuralNet|nonlinear|nmf|nonParametricBayes|optimization|panel|pls|percentile|pca|phreg|qkb|qlim|quantreg|recommend|tsReconcile|deepRnn|regression|reinforcementLearn|robustPca|sampling|sparkEmbeddedProcess|search(?:Analytics)?|sentimentAnalysis|sequence|configuration|session(?:Prop)?|severity|simple|smartData|sandwich|spatialreg|stabilityMonitoring|spc|loadStreams|svDataDescription|svm|table|conditionalRandomFields|text(?:Rule(?:Develop|Score)|Mining|Parse|Topic|Util|Filters|Frequency)|tsInfo|timeData|transpose|uniTimeSeries",g={pattern:RegExp("(^|\\s)(?:action\\s+)?(?:)\\.[a-z]+\\b[^;]+".replace(//g,b),"i"),lookbehind:!0,inside:{keyword:RegExp("(?:)\\.[a-z]+\\b".replace(//g,b),"i"),action:{pattern:/(?:action)/i,alias:"keyword"},function:l,"arg-value":d["arg-value"],operator:d.operator,comment:s,argument:d.arg,number:a,"numeric-constant":n,punctuation:o,string:r}},k={pattern:/((?:^|\s)=?)(?:after|analysis|and|array|barchart|barwidth|begingraph|by|call|cas|cbarline|cfill|class(?:lev)?|close|column|computed?|contains|continue|data(?=\=)|define|delete|describe|document|do\s+over|do|dol|drop|dul|end(?:source|comp)?|entryTitle|else|eval(?:uate)?|exec(?:ute)?|exit|fill(?:attrs)?|file(?:name)?|flist|fnc|function(?:list)?|goto|global|group(?:by)?|headline|headskip|histogram|if|infile|keep|keylabel|keyword|label|layout|leave|legendlabel|length|libname|loadactionset|merge|midpoints|name|noobs|nowd|_?null_|ods|options|or|otherwise|out(?:put)?|over(?:lay)?|plot|put|print|raise|ranexp|rannor|rbreak|retain|return|select|set|session|sessref|source|statgraph|sum|summarize|table|temp|terminate|then\s+do|then|title\d?|to|var|when|where|xaxisopts|yaxisopts|y2axisopts)\b/i,lookbehind:!0};e.languages.sas={datalines:{pattern:/^(\s*)(?:(?:data)?lines|cards);[\s\S]+?^\s*;/im,lookbehind:!0,alias:"string",inside:{keyword:{pattern:/^(?:(?:data)?lines|cards)/i},punctuation:/;/}},"proc-sql":{pattern:/(^proc\s+(?:fed)?sql(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{sql:{pattern:RegExp("^[ \t]*(?:select|alter\\s+table|(?:create|describe|drop)\\s+(?:index|table(?:\\s+constraints)?|view)|create\\s+unique\\s+index|insert\\s+into|update)(?:|[^;\"'])+;".replace(//g,t),"im"),alias:"language-sql",inside:e.languages.sql},"global-statements":u,"sql-statements":{pattern:/(^|\s)(?:disconnect\s+from|exec(?:ute)?|begin|commit|rollback|reset|validate)\b/i,lookbehind:!0,alias:"keyword"},number:a,"numeric-constant":n,punctuation:o,string:r}},"proc-groovy":{pattern:/(^proc\s+groovy(?:\s+[\w|=]+)?;)(?:\s*submit)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{groovy:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,t),"im"),lookbehind:!0,alias:"language-groovy",inside:e.languages.groovy},"submit-statement":m,"global-statements":u,number:a,"numeric-constant":n,punctuation:o,string:r}},"proc-lua":{pattern:/(^proc\s+lua(?:\s+[\w|=]+)?;)(?:\s*submit)[\s\S]+?(?=^(?:proc\s+\w+|quit|run|data);|(?![\s\S]))/im,lookbehind:!0,inside:{lua:{pattern:RegExp("(^[ \t]*submit(?:\\s+(?:load|parseonly|norun))?)(?:|[^\"'])+?(?=endsubmit;)".replace(//g,t),"im"),lookbehind:!0,alias:"language-lua",inside:e.languages.lua},"submit-statement":m,"global-statements":u,number:a,"numeric-constant":n,punctuation:o,string:r}},"proc-cas":{pattern:/(^proc\s+cas(?:\s+[\w|=]+)?;)[\s\S]+?(?=^(?:proc\s+\w+|quit|data);|(?![\s\S]))/im,lookbehind:!0,inside:{"statement-var":{pattern:/((?:^|\s)=?)saveresult\s+[^;]+/im,lookbehind:!0,inside:{statement:{pattern:/^saveresult\s+\S+/i,inside:{keyword:/^(?:saveresult)/i}},rest:d}},"cas-actions":g,statement:{pattern:/((?:^|\s)=?)(?:default|(?:un)?set|on|output|upload)[^;]+/im,lookbehind:!0,inside:d},step:i,keyword:k,function:l,comment:s,format:c,altformat:p,"global-statements":u,number:a,"numeric-constant":n,punctuation:o,string:r}},"proc-args":{pattern:RegExp("(^proc\\s+\\w+\\s+)(?!\\s)(?:[^;\"']|)+;".replace(//g,t),"im"),lookbehind:!0,inside:d},"macro-keyword":{pattern:/((?:^|\s)=?)%(?:ABORT|BQUOTE|BY|CMS|COPY|DISPLAY|DO|ELSE|END|EVAL|GLOBAL|GO|GOTO|IF|INC|INCLUDE|INDEX|INPUT|KTRIM|LENGTH|LET|LIST|LOCAL|NRBQUOTE|NRQUOTE|NRSTR|PUT|QKTRIM|QSCAN|QSUBSTR|QSYSFUNC|QUOTE|QUPCASE|RETURN|RUN|SCAN|STR|SUBSTR|SUPERQ|SYMDEL|SYMGLOBL|SYMLOCAL|SYMEXIST|SYSCALL|SYSEVALF|SYSEXEC|SYSFUNC|SYSGET|SYSRPUT|THEN|TO|TSO|UNQUOTE|UNTIL|UPCASE|WHILE|WINDOW)\b/i,lookbehind:!0,alias:"keyword"},"macro-declaration":{pattern:/^%macro[^;]+(?=;)/im,inside:{keyword:/%macro/i}},"macro-end":{pattern:/^%mend[^;]+(?=;)/im,inside:{keyword:/%mend/i}},macro:{pattern:/%_\w+(?=\()/,alias:"keyword"},input:{pattern:/\binput\s+[-\w\s/*.$&]+;/i,inside:{input:{alias:"keyword",pattern:/^input/i},comment:s,number:a,"numeric-constant":n}},"options-args":{pattern:/(^options)[-'"|/\\<>*+=:()\w\s]*(?=;)/im,lookbehind:!0,inside:d},"cas-actions":g,comment:s,function:l,format:c,altformat:p,"numeric-constant":n,datetime:{pattern:RegExp(t+"(?:dt?|t)"),alias:"number"},string:r,step:i,keyword:k,"operator-keyword":{pattern:/\b(?:eq|ne|gt|lt|ge|le|in|not)\b/i,alias:"operator"},number:a,operator:/\*\*?|\|\|?|!!?|¦¦?|<[>=]?|>[<=]?|[-+\/=&]|[~¬^]=?/i,punctuation:o}}(Prism); \ No newline at end of file diff --git a/tests/languages/sas/keyword_feature.test b/tests/languages/sas/keyword_feature.test index 2b19e9ede4..b0fca4ceae 100644 --- a/tests/languages/sas/keyword_feature.test +++ b/tests/languages/sas/keyword_feature.test @@ -1,4 +1,4 @@ -action after analysis and array barchart barwidth begingraph by +after analysis and array barchart barwidth begingraph by cas cbarline cfill class classlev close column compute computed contains data= define document do do over dol drop dul end entryTitle else endcomp eval evaluate exec execute fill fillattrs filename group groupby headline headskip @@ -10,7 +10,7 @@ then do title to var where xaxisopts yaxisopts y2axisopts ---------------------------------------------------- [ - ["keyword", "action"], ["keyword", "after"], ["keyword", "analysis"], + ["keyword", "after"], ["keyword", "analysis"], ["keyword", "and"], ["keyword", "array"], ["keyword", "barchart"], ["keyword", "barwidth"], ["keyword", "begingraph"], ["keyword", "by"], ["keyword", "cas"], ["keyword", "cbarline"], ["keyword", "cfill"], diff --git a/tests/languages/sas/proccas_feature.test b/tests/languages/sas/proccas_feature.test new file mode 100644 index 0000000000..5bc03d3ad6 --- /dev/null +++ b/tests/languages/sas/proccas_feature.test @@ -0,0 +1,141 @@ +proc cas; + session casauto; + builtins.actionSetInfo result=results; + print results.setinfo[,{'actionset', 'label'}]; +run; +quit; + +proc cas; + session casauto; + output log; + table.loadTable / path="iris.sashdat"; + simple.summary result=iris / table={name="iris"}; + tableIris=findtable(iris); + saveresult tableIris csv="sum.csv"; +run; +quit; + +proc cas; + action table.fileinfo / path="%.csv"; +run; +quit; + +---------------------------------------------------- + +[ + ["step", "proc cas"], + ["punctuation", ";"], + ["proc-cas", + [ + ["keyword", "session"], + " casauto", + ["punctuation", ";"], + ["cas-actions", [ + ["keyword", "builtins.actionSetInfo"], + ["argument", "result"], + ["operator", "="], + ["arg-value", "results"] + ] + ], + ["punctuation", ";"], + ["keyword", "print"], + " results", + ["punctuation", "."], + "setinfo", + ["punctuation", "["], + ["punctuation", ","], + ["punctuation", "{"], + ["string", "'actionset'"], + ["punctuation", ","], + ["string", "'label'"], + ["punctuation", "}"], + ["punctuation", "]"], + ["punctuation", ";"], + ["step", "run"], + ["punctuation", ";"] + ] + ], + ["step", "quit"], + ["punctuation", ";"], + ["step", "proc cas"], + ["punctuation", ";"], + ["proc-cas", + [ + ["keyword", "session"], + " casauto", + ["punctuation", ";"], + ["statement", [ + ["arg", "output"], + ["arg", "log"] + ]], + ["punctuation", ";"], + ["cas-actions", [ + ["keyword", "table.loadTable"], + " / ", + ["argument", "path"], + ["operator", "="], + ["string", "\"iris.sashdat\""] + ] + ], + ["punctuation", ";"], + ["cas-actions", [ + ["keyword", "simple.summary"], + ["argument", "result"], + ["operator", "="], + ["arg-value", "iris"], + " / ", + ["argument", "table"], + ["operator", "="], + ["punctuation", "{"], + ["argument", "name"], + ["operator", "="], + ["string", "\"iris\""], + ["punctuation", "}"] + ] + ], + ["punctuation", ";"], + "\r\n tableIris=", + ["function", "findtable"], + ["punctuation", "("], + "iris", + ["punctuation", ")"], + ["punctuation", ";"], + ["statement-var", [ + [ "statement", [ + ["keyword", "saveresult"], + " tableIris" + ] + ], + ["arg", "csv"], + ["operator", "="], + ["string", "\"sum.csv\""] + ]], + ["punctuation", ";"], + ["step", "run"], + ["punctuation", ";"] + ] + ], + ["step", "quit"], + ["punctuation", ";"], + ["step", "proc cas"], + ["punctuation", ";"], + ["proc-cas", + [ + ["cas-actions", + [ + ["action", "action"], + ["keyword", "table.fileinfo"], + " / ", + ["argument", "path"], + ["operator", "="], + ["string", "\"%.csv\""] + ] + ], + ["punctuation", ";"], + ["step", "run"], + ["punctuation", ";"] + ] + ], + ["step", "quit"], + ["punctuation", ";"] +]