1"""
2 pygments.lexers.business
3 ~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Lexers for "business-oriented" languages.
6
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11import re
12
13from pygments.lexer import RegexLexer, include, words, bygroups
14from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
15 Number, Punctuation, Error, Whitespace
16
17from pygments.lexers._openedge_builtins import OPENEDGEKEYWORDS
18
19__all__ = ['CobolLexer', 'CobolFreeformatLexer', 'ABAPLexer', 'OpenEdgeLexer',
20 'GoodDataCLLexer', 'MaqlLexer']
21
22
23class CobolLexer(RegexLexer):
24 """
25 Lexer for OpenCOBOL code.
26 """
27 name = 'COBOL'
28 aliases = ['cobol']
29 filenames = ['*.cob', '*.COB', '*.cpy', '*.CPY']
30 mimetypes = ['text/x-cobol']
31 url = 'https://en.wikipedia.org/wiki/COBOL'
32 version_added = '1.6'
33
34 flags = re.IGNORECASE | re.MULTILINE
35
36 # Data Types: by PICTURE and USAGE
37 # Operators: **, *, +, -, /, <, >, <=, >=, =, <>
38 # Logical (?): NOT, AND, OR
39
40 # Reserved words:
41 # http://opencobol.add1tocobol.com/#reserved-words
42 # Intrinsics:
43 # http://opencobol.add1tocobol.com/#does-opencobol-implement-any-intrinsic-functions
44
45 tokens = {
46 'root': [
47 include('comment'),
48 include('strings'),
49 include('core'),
50 include('nums'),
51 (r'[a-z0-9]([\w\-]*[a-z0-9]+)?', Name.Variable),
52 # (r'[\s]+', Text),
53 (r'[ \t]+', Whitespace),
54 ],
55 'comment': [
56 (r'(^.{6}[*/].*\n|^.{6}|\*>.*\n)', Comment),
57 ],
58 'core': [
59 # Figurative constants
60 (r'(^|(?<=[^\w\-]))(ALL\s+)?'
61 r'((ZEROES)|(HIGH-VALUE|LOW-VALUE|QUOTE|SPACE|ZERO)(S)?)'
62 r'\s*($|(?=[^\w\-]))',
63 Name.Constant),
64
65 # Reserved words STATEMENTS and other bolds
66 (words((
67 'ACCEPT', 'ADD', 'ALLOCATE', 'CALL', 'CANCEL', 'CLOSE', 'COMPUTE',
68 'CONFIGURATION', 'CONTINUE', 'DATA', 'DELETE', 'DISPLAY', 'DIVIDE',
69 'DIVISION', 'ELSE', 'END', 'END-ACCEPT',
70 'END-ADD', 'END-CALL', 'END-COMPUTE', 'END-DELETE', 'END-DISPLAY',
71 'END-DIVIDE', 'END-EVALUATE', 'END-IF', 'END-MULTIPLY', 'END-OF-PAGE',
72 'END-PERFORM', 'END-READ', 'END-RETURN', 'END-REWRITE', 'END-SEARCH',
73 'END-START', 'END-STRING', 'END-SUBTRACT', 'END-UNSTRING', 'END-WRITE',
74 'ENVIRONMENT', 'EVALUATE', 'EXIT', 'FD', 'FILE', 'FILE-CONTROL', 'FOREVER',
75 'FREE', 'GENERATE', 'GO', 'GOBACK', 'IDENTIFICATION', 'IF', 'INITIALIZE',
76 'INITIATE', 'INPUT-OUTPUT', 'INSPECT', 'INVOKE', 'I-O-CONTROL', 'LINKAGE',
77 'LOCAL-STORAGE', 'MERGE', 'MOVE', 'MULTIPLY', 'OPEN', 'PERFORM',
78 'PROCEDURE', 'PROGRAM-ID', 'RAISE', 'READ', 'RELEASE', 'RESUME',
79 'RETURN', 'REWRITE', 'SCREEN', 'SD', 'SEARCH', 'SECTION', 'SET',
80 'SORT', 'START', 'STOP', 'STRING', 'SUBTRACT', 'SUPPRESS',
81 'TERMINATE', 'THEN', 'UNLOCK', 'UNSTRING', 'USE', 'VALIDATE',
82 'WORKING-STORAGE', 'WRITE'), prefix=r'(^|(?<=[^\w\-]))',
83 suffix=r'\s*($|(?=[^\w\-]))'),
84 Keyword.Reserved),
85
86 # Reserved words
87 (words((
88 'ACCESS', 'ADDRESS', 'ADVANCING', 'AFTER', 'ALL',
89 'ALPHABET', 'ALPHABETIC', 'ALPHABETIC-LOWER', 'ALPHABETIC-UPPER',
90 'ALPHANUMERIC', 'ALPHANUMERIC-EDITED', 'ALSO', 'ALTER', 'ALTERNATE'
91 'ANY', 'ARE', 'AREA', 'AREAS', 'ARGUMENT-NUMBER', 'ARGUMENT-VALUE', 'AS',
92 'ASCENDING', 'ASSIGN', 'AT', 'AUTO', 'AUTO-SKIP', 'AUTOMATIC',
93 'AUTOTERMINATE', 'BACKGROUND-COLOR', 'BASED', 'BEEP', 'BEFORE', 'BELL',
94 'BLANK', 'BLINK', 'BLOCK', 'BOTTOM', 'BY', 'BYTE-LENGTH', 'CHAINING',
95 'CHARACTER', 'CHARACTERS', 'CLASS', 'CODE', 'CODE-SET', 'COL',
96 'COLLATING', 'COLS', 'COLUMN', 'COLUMNS', 'COMMA', 'COMMAND-LINE',
97 'COMMIT', 'COMMON', 'CONSTANT', 'CONTAINS', 'CONTENT', 'CONTROL',
98 'CONTROLS', 'CONVERTING', 'COPY', 'CORR', 'CORRESPONDING', 'COUNT', 'CRT',
99 'CURRENCY', 'CURSOR', 'CYCLE', 'DATE', 'DAY', 'DAY-OF-WEEK', 'DE',
100 'DEBUGGING', 'DECIMAL-POINT', 'DECLARATIVES', 'DEFAULT', 'DELIMITED',
101 'DELIMITER', 'DEPENDING', 'DESCENDING', 'DETAIL', 'DISK',
102 'DOWN', 'DUPLICATES', 'DYNAMIC', 'EBCDIC',
103 'ENTRY', 'ENVIRONMENT-NAME', 'ENVIRONMENT-VALUE', 'EOL', 'EOP',
104 'EOS', 'ERASE', 'ERROR', 'ESCAPE', 'EXCEPTION',
105 'EXCLUSIVE', 'EXTEND', 'EXTERNAL', 'FILE-ID', 'FILLER', 'FINAL',
106 'FIRST', 'FIXED', 'FLOAT-LONG', 'FLOAT-SHORT',
107 'FOOTING', 'FOR', 'FOREGROUND-COLOR', 'FORMAT', 'FROM', 'FULL',
108 'FUNCTION', 'FUNCTION-ID', 'GIVING', 'GLOBAL', 'GROUP',
109 'HEADING', 'HIGHLIGHT', 'I-O', 'ID',
110 'IGNORE', 'IGNORING', 'IN', 'INDEX', 'INDEXED', 'INDICATE',
111 'INITIAL', 'INITIALIZED', 'INPUT', 'INTO', 'INTRINSIC', 'INVALID',
112 'IS', 'JUST', 'JUSTIFIED', 'KEY', 'LABEL',
113 'LAST', 'LEADING', 'LEFT', 'LENGTH', 'LIMIT', 'LIMITS', 'LINAGE',
114 'LINAGE-COUNTER', 'LINE', 'LINES', 'LOCALE', 'LOCK',
115 'LOWLIGHT', 'MANUAL', 'MEMORY', 'MINUS', 'MODE', 'MULTIPLE',
116 'NATIONAL', 'NATIONAL-EDITED', 'NATIVE', 'NEGATIVE', 'NEXT', 'NO',
117 'NULL', 'NULLS', 'NUMBER', 'NUMBERS', 'NUMERIC', 'NUMERIC-EDITED',
118 'OBJECT-COMPUTER', 'OCCURS', 'OF', 'OFF', 'OMITTED', 'ON', 'ONLY',
119 'OPTIONAL', 'ORDER', 'ORGANIZATION', 'OTHER', 'OUTPUT', 'OVERFLOW',
120 'OVERLINE', 'PACKED-DECIMAL', 'PADDING', 'PAGE', 'PARAGRAPH',
121 'PLUS', 'POINTER', 'POSITION', 'POSITIVE', 'PRESENT', 'PREVIOUS',
122 'PRINTER', 'PRINTING', 'PROCEDURE-POINTER', 'PROCEDURES',
123 'PROCEED', 'PROGRAM', 'PROGRAM-POINTER', 'PROMPT', 'QUOTE',
124 'QUOTES', 'RANDOM', 'RD', 'RECORD', 'RECORDING', 'RECORDS', 'RECURSIVE',
125 'REDEFINES', 'REEL', 'REFERENCE', 'RELATIVE', 'REMAINDER', 'REMOVAL',
126 'RENAMES', 'REPLACING', 'REPORT', 'REPORTING', 'REPORTS', 'REPOSITORY',
127 'REQUIRED', 'RESERVE', 'RETURNING', 'REVERSE-VIDEO', 'REWIND',
128 'RIGHT', 'ROLLBACK', 'ROUNDED', 'RUN', 'SAME', 'SCROLL',
129 'SECURE', 'SEGMENT-LIMIT', 'SELECT', 'SENTENCE', 'SEPARATE',
130 'SEQUENCE', 'SEQUENTIAL', 'SHARING', 'SIGN', 'SIGNED', 'SIGNED-INT',
131 'SIGNED-LONG', 'SIGNED-SHORT', 'SIZE', 'SORT-MERGE', 'SOURCE',
132 'SOURCE-COMPUTER', 'SPECIAL-NAMES', 'STANDARD',
133 'STANDARD-1', 'STANDARD-2', 'STATUS', 'SUBKEY', 'SUM',
134 'SYMBOLIC', 'SYNC', 'SYNCHRONIZED', 'TALLYING', 'TAPE',
135 'TEST', 'THROUGH', 'THRU', 'TIME', 'TIMES', 'TO', 'TOP', 'TRAILING',
136 'TRANSFORM', 'TYPE', 'UNDERLINE', 'UNIT', 'UNSIGNED',
137 'UNSIGNED-INT', 'UNSIGNED-LONG', 'UNSIGNED-SHORT', 'UNTIL', 'UP',
138 'UPDATE', 'UPON', 'USAGE', 'USING', 'VALUE', 'VALUES', 'VARYING',
139 'WAIT', 'WHEN', 'WITH', 'WORDS', 'YYYYDDD', 'YYYYMMDD'),
140 prefix=r'(^|(?<=[^\w\-]))', suffix=r'\s*($|(?=[^\w\-]))'),
141 Keyword.Pseudo),
142
143 # inactive reserved words
144 (words((
145 'ACTIVE-CLASS', 'ALIGNED', 'ANYCASE', 'ARITHMETIC', 'ATTRIBUTE',
146 'B-AND', 'B-NOT', 'B-OR', 'B-XOR', 'BIT', 'BOOLEAN', 'CD', 'CENTER',
147 'CF', 'CH', 'CHAIN', 'CLASS-ID', 'CLASSIFICATION', 'COMMUNICATION',
148 'CONDITION', 'DATA-POINTER', 'DESTINATION', 'DISABLE', 'EC', 'EGI',
149 'EMI', 'ENABLE', 'END-RECEIVE', 'ENTRY-CONVENTION', 'EO', 'ESI',
150 'EXCEPTION-OBJECT', 'EXPANDS', 'FACTORY', 'FLOAT-BINARY-16',
151 'FLOAT-BINARY-34', 'FLOAT-BINARY-7', 'FLOAT-DECIMAL-16',
152 'FLOAT-DECIMAL-34', 'FLOAT-EXTENDED', 'FORMAT', 'FUNCTION-POINTER',
153 'GET', 'GROUP-USAGE', 'IMPLEMENTS', 'INFINITY', 'INHERITS',
154 'INTERFACE', 'INTERFACE-ID', 'INVOKE', 'LC_ALL', 'LC_COLLATE',
155 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME',
156 'LINE-COUNTER', 'MESSAGE', 'METHOD', 'METHOD-ID', 'NESTED', 'NONE',
157 'NORMAL', 'OBJECT', 'OBJECT-REFERENCE', 'OPTIONS', 'OVERRIDE',
158 'PAGE-COUNTER', 'PF', 'PH', 'PROPERTY', 'PROTOTYPE', 'PURGE',
159 'QUEUE', 'RAISE', 'RAISING', 'RECEIVE', 'RELATION', 'REPLACE',
160 'REPRESENTS-NOT-A-NUMBER', 'RESET', 'RESUME', 'RETRY', 'RF', 'RH',
161 'SECONDS', 'SEGMENT', 'SELF', 'SEND', 'SOURCES', 'STATEMENT',
162 'STEP', 'STRONG', 'SUB-QUEUE-1', 'SUB-QUEUE-2', 'SUB-QUEUE-3',
163 'SUPER', 'SYMBOL', 'SYSTEM-DEFAULT', 'TABLE', 'TERMINAL', 'TEXT',
164 'TYPEDEF', 'UCS-4', 'UNIVERSAL', 'USER-DEFAULT', 'UTF-16', 'UTF-8',
165 'VAL-STATUS', 'VALID', 'VALIDATE', 'VALIDATE-STATUS'),
166 prefix=r'(^|(?<=[^\w\-]))', suffix=r'\s*($|(?=[^\w\-]))'),
167 Error),
168
169 # Data Types
170 (r'(^|(?<=[^\w\-]))'
171 r'(PIC\s+.+?(?=(\s|\.\s))|PICTURE\s+.+?(?=(\s|\.\s))|'
172 r'(COMPUTATIONAL)(-[1-5X])?|(COMP)(-[1-5X])?|'
173 r'BINARY-C-LONG|'
174 r'BINARY-CHAR|BINARY-DOUBLE|BINARY-LONG|BINARY-SHORT|'
175 r'BINARY)\s*($|(?=[^\w\-]))', Keyword.Type),
176
177 # Operators
178 (r'(\*\*|\*|\+|-|/|<=|>=|<|>|==|/=|=)', Operator),
179
180 # (r'(::)', Keyword.Declaration),
181
182 (r'([(),;:&%.])', Punctuation),
183
184 # Intrinsics
185 (r'(^|(?<=[^\w\-]))(ABS|ACOS|ANNUITY|ASIN|ATAN|BYTE-LENGTH|'
186 r'CHAR|COMBINED-DATETIME|CONCATENATE|COS|CURRENT-DATE|'
187 r'DATE-OF-INTEGER|DATE-TO-YYYYMMDD|DAY-OF-INTEGER|DAY-TO-YYYYDDD|'
188 r'EXCEPTION-(?:FILE|LOCATION|STATEMENT|STATUS)|EXP10|EXP|E|'
189 r'FACTORIAL|FRACTION-PART|INTEGER-OF-(?:DATE|DAY|PART)|INTEGER|'
190 r'LENGTH|LOCALE-(?:DATE|TIME(?:-FROM-SECONDS)?)|LOG(?:10)?|'
191 r'LOWER-CASE|MAX|MEAN|MEDIAN|MIDRANGE|MIN|MOD|NUMVAL(?:-C)?|'
192 r'ORD(?:-MAX|-MIN)?|PI|PRESENT-VALUE|RANDOM|RANGE|REM|REVERSE|'
193 r'SECONDS-FROM-FORMATTED-TIME|SECONDS-PAST-MIDNIGHT|SIGN|SIN|SQRT|'
194 r'STANDARD-DEVIATION|STORED-CHAR-LENGTH|SUBSTITUTE(?:-CASE)?|'
195 r'SUM|TAN|TEST-DATE-YYYYMMDD|TEST-DAY-YYYYDDD|TRIM|'
196 r'UPPER-CASE|VARIANCE|WHEN-COMPILED|YEAR-TO-YYYY)\s*'
197 r'($|(?=[^\w\-]))', Name.Function),
198
199 # Booleans
200 (r'(^|(?<=[^\w\-]))(true|false)\s*($|(?=[^\w\-]))', Name.Builtin),
201 # Comparing Operators
202 (r'(^|(?<=[^\w\-]))(equal|equals|ne|lt|le|gt|ge|'
203 r'greater|less|than|not|and|or)\s*($|(?=[^\w\-]))', Operator.Word),
204 ],
205
206 # \"[^\"\n]*\"|\'[^\'\n]*\'
207 'strings': [
208 # apparently strings can be delimited by EOL if they are continued
209 # in the next line
210 (r'"[^"\n]*("|\n)', String.Double),
211 (r"'[^'\n]*('|\n)", String.Single),
212 ],
213
214 'nums': [
215 (r'\d+(\s*|\.$|$)', Number.Integer),
216 (r'[+-]?\d*\.\d+(E[-+]?\d+)?', Number.Float),
217 (r'[+-]?\d+\.\d*(E[-+]?\d+)?', Number.Float),
218 ],
219 }
220
221
222class CobolFreeformatLexer(CobolLexer):
223 """
224 Lexer for Free format OpenCOBOL code.
225 """
226 name = 'COBOLFree'
227 aliases = ['cobolfree']
228 filenames = ['*.cbl', '*.CBL']
229 mimetypes = []
230 url = 'https://opencobol.add1tocobol.com'
231 version_added = '1.6'
232
233 flags = re.IGNORECASE | re.MULTILINE
234
235 tokens = {
236 'comment': [
237 (r'(\*>.*\n|^\w*\*.*$)', Comment),
238 ],
239 }
240
241
242class ABAPLexer(RegexLexer):
243 """
244 Lexer for ABAP, SAP's integrated language.
245 """
246 name = 'ABAP'
247 aliases = ['abap']
248 filenames = ['*.abap', '*.ABAP']
249 mimetypes = ['text/x-abap']
250 url = 'https://community.sap.com/topics/abap'
251 version_added = '1.1'
252
253 flags = re.IGNORECASE | re.MULTILINE
254
255 tokens = {
256 'common': [
257 (r'\s+', Whitespace),
258 (r'^\*.*$', Comment.Single),
259 (r'\".*?\n', Comment.Single),
260 (r'##\w+', Comment.Special),
261 ],
262 'variable-names': [
263 (r'<\S+>', Name.Variable),
264 (r'\w[\w~]*(?:(\[\])|->\*)?', Name.Variable),
265 ],
266 'root': [
267 include('common'),
268 # function calls
269 (r'CALL\s+(?:BADI|CUSTOMER-FUNCTION|FUNCTION)',
270 Keyword),
271 (r'(CALL\s+(?:DIALOG|SCREEN|SUBSCREEN|SELECTION-SCREEN|'
272 r'TRANSACTION|TRANSFORMATION))\b',
273 Keyword),
274 (r'(FORM|PERFORM)(\s+)(\w+)',
275 bygroups(Keyword, Whitespace, Name.Function)),
276 (r'(PERFORM)(\s+)(\()(\w+)(\))',
277 bygroups(Keyword, Whitespace, Punctuation, Name.Variable, Punctuation)),
278 (r'(MODULE)(\s+)(\S+)(\s+)(INPUT|OUTPUT)',
279 bygroups(Keyword, Whitespace, Name.Function, Whitespace, Keyword)),
280
281 # method implementation
282 (r'(METHOD)(\s+)([\w~]+)',
283 bygroups(Keyword, Whitespace, Name.Function)),
284 # method calls
285 (r'(\s+)([\w\-]+)([=\-]>)([\w\-~]+)',
286 bygroups(Whitespace, Name.Variable, Operator, Name.Function)),
287 # call methodnames returning style
288 (r'(?<=(=|-)>)([\w\-~]+)(?=\()', Name.Function),
289
290 # text elements
291 (r'(TEXT)(-)(\d{3})',
292 bygroups(Keyword, Punctuation, Number.Integer)),
293 (r'(TEXT)(-)(\w{3})',
294 bygroups(Keyword, Punctuation, Name.Variable)),
295
296 # keywords with dashes in them.
297 # these need to be first, because for instance the -ID part
298 # of MESSAGE-ID wouldn't get highlighted if MESSAGE was
299 # first in the list of keywords.
300 (r'(ADD-CORRESPONDING|AUTHORITY-CHECK|'
301 r'CLASS-DATA|CLASS-EVENTS|CLASS-METHODS|CLASS-POOL|'
302 r'DELETE-ADJACENT|DIVIDE-CORRESPONDING|'
303 r'EDITOR-CALL|ENHANCEMENT-POINT|ENHANCEMENT-SECTION|EXIT-COMMAND|'
304 r'FIELD-GROUPS|FIELD-SYMBOLS|FIELD-SYMBOL|FUNCTION-POOL|'
305 r'INTERFACE-POOL|INVERTED-DATE|'
306 r'LOAD-OF-PROGRAM|LOG-POINT|'
307 r'MESSAGE-ID|MOVE-CORRESPONDING|MULTIPLY-CORRESPONDING|'
308 r'NEW-LINE|NEW-PAGE|NEW-SECTION|NO-EXTENSION|'
309 r'OUTPUT-LENGTH|PRINT-CONTROL|'
310 r'SELECT-OPTIONS|START-OF-SELECTION|SUBTRACT-CORRESPONDING|'
311 r'SYNTAX-CHECK|SYSTEM-EXCEPTIONS|'
312 r'TYPE-POOL|TYPE-POOLS|NO-DISPLAY'
313 r')\b', Keyword),
314
315 # keyword kombinations
316 (r'(?<![-\>])(CREATE\s+(PUBLIC|PRIVATE|DATA|OBJECT)|'
317 r'(PUBLIC|PRIVATE|PROTECTED)\s+SECTION|'
318 r'(TYPE|LIKE)\s+((LINE\s+OF|REF\s+TO|'
319 r'(SORTED|STANDARD|HASHED)\s+TABLE\s+OF))?|'
320 r'FROM\s+(DATABASE|MEMORY)|CALL\s+METHOD|'
321 r'(GROUP|ORDER) BY|HAVING|SEPARATED BY|'
322 r'GET\s+(BADI|BIT|CURSOR|DATASET|LOCALE|PARAMETER|'
323 r'PF-STATUS|(PROPERTY|REFERENCE)\s+OF|'
324 r'RUN\s+TIME|TIME\s+(STAMP)?)?|'
325 r'SET\s+(BIT|BLANK\s+LINES|COUNTRY|CURSOR|DATASET|EXTENDED\s+CHECK|'
326 r'HANDLER|HOLD\s+DATA|LANGUAGE|LEFT\s+SCROLL-BOUNDARY|'
327 r'LOCALE|MARGIN|PARAMETER|PF-STATUS|PROPERTY\s+OF|'
328 r'RUN\s+TIME\s+(ANALYZER|CLOCK\s+RESOLUTION)|SCREEN|'
329 r'TITLEBAR|UPADTE\s+TASK\s+LOCAL|USER-COMMAND)|'
330 r'CONVERT\s+((INVERTED-)?DATE|TIME|TIME\s+STAMP|TEXT)|'
331 r'(CLOSE|OPEN)\s+(DATASET|CURSOR)|'
332 r'(TO|FROM)\s+(DATA BUFFER|INTERNAL TABLE|MEMORY ID|'
333 r'DATABASE|SHARED\s+(MEMORY|BUFFER))|'
334 r'DESCRIBE\s+(DISTANCE\s+BETWEEN|FIELD|LIST|TABLE)|'
335 r'FREE\s(MEMORY|OBJECT)?|'
336 r'PROCESS\s+(BEFORE\s+OUTPUT|AFTER\s+INPUT|'
337 r'ON\s+(VALUE-REQUEST|HELP-REQUEST))|'
338 r'AT\s+(LINE-SELECTION|USER-COMMAND|END\s+OF|NEW)|'
339 r'AT\s+SELECTION-SCREEN(\s+(ON(\s+(BLOCK|(HELP|VALUE)-REQUEST\s+FOR|'
340 r'END\s+OF|RADIOBUTTON\s+GROUP))?|OUTPUT))?|'
341 r'SELECTION-SCREEN:?\s+((BEGIN|END)\s+OF\s+((TABBED\s+)?BLOCK|LINE|'
342 r'SCREEN)|COMMENT|FUNCTION\s+KEY|'
343 r'INCLUDE\s+BLOCKS|POSITION|PUSHBUTTON|'
344 r'SKIP|ULINE)|'
345 r'LEAVE\s+(LIST-PROCESSING|PROGRAM|SCREEN|'
346 r'TO LIST-PROCESSING|TO TRANSACTION)'
347 r'(ENDING|STARTING)\s+AT|'
348 r'FORMAT\s+(COLOR|INTENSIFIED|INVERSE|HOTSPOT|INPUT|FRAMES|RESET)|'
349 r'AS\s+(CHECKBOX|SUBSCREEN|WINDOW)|'
350 r'WITH\s+(((NON-)?UNIQUE)?\s+KEY|FRAME)|'
351 r'(BEGIN|END)\s+OF|'
352 r'DELETE(\s+ADJACENT\s+DUPLICATES\sFROM)?|'
353 r'COMPARING(\s+ALL\s+FIELDS)?|'
354 r'(INSERT|APPEND)(\s+INITIAL\s+LINE\s+(IN)?TO|\s+LINES\s+OF)?|'
355 r'IN\s+((BYTE|CHARACTER)\s+MODE|PROGRAM)|'
356 r'END-OF-(DEFINITION|PAGE|SELECTION)|'
357 r'WITH\s+FRAME(\s+TITLE)|'
358 r'(REPLACE|FIND)\s+((FIRST|ALL)\s+OCCURRENCES?\s+OF\s+)?(SUBSTRING|REGEX)?|'
359 r'MATCH\s+(LENGTH|COUNT|LINE|OFFSET)|'
360 r'(RESPECTING|IGNORING)\s+CASE|'
361 r'IN\s+UPDATE\s+TASK|'
362 r'(SOURCE|RESULT)\s+(XML)?|'
363 r'REFERENCE\s+INTO|'
364
365 # simple kombinations
366 r'AND\s+(MARK|RETURN)|CLIENT\s+SPECIFIED|CORRESPONDING\s+FIELDS\s+OF|'
367 r'IF\s+FOUND|FOR\s+EVENT|INHERITING\s+FROM|LEAVE\s+TO\s+SCREEN|'
368 r'LOOP\s+AT\s+(SCREEN)?|LOWER\s+CASE|MATCHCODE\s+OBJECT|MODIF\s+ID|'
369 r'MODIFY\s+SCREEN|NESTING\s+LEVEL|NO\s+INTERVALS|OF\s+STRUCTURE|'
370 r'RADIOBUTTON\s+GROUP|RANGE\s+OF|REF\s+TO|SUPPRESS DIALOG|'
371 r'TABLE\s+OF|UPPER\s+CASE|TRANSPORTING\s+NO\s+FIELDS|'
372 r'VALUE\s+CHECK|VISIBLE\s+LENGTH|HEADER\s+LINE|COMMON\s+PART)\b', Keyword),
373
374 # single word keywords.
375 (r'(^|(?<=(\s|\.)))(ABBREVIATED|ABSTRACT|ADD|ALIASES|ALIGN|ALPHA|'
376 r'ASSERT|AS|ASSIGN(ING)?|AT(\s+FIRST)?|'
377 r'BACK|BLOCK|BREAK-POINT|'
378 r'CASE|CAST|CATCH|CHANGING|CHECK|CLASS|CLEAR|COLLECT|COLOR|COMMIT|COND|CONV|'
379 r'CREATE|COMMUNICATION|COMPONENTS?|COMPUTE|CONCATENATE|CONDENSE|'
380 r'CONSTANTS|CONTEXTS|CONTINUE|CONTROLS|COUNTRY|CURRENCY|'
381 r'DATA|DATE|DECIMALS|DEFAULT|DEFINE|DEFINITION|DEFERRED|DEMAND|'
382 r'DETAIL|DIRECTORY|DIVIDE|DO|DUMMY|'
383 r'ELSE(IF)?|ENDAT|ENDCASE|ENDCATCH|ENDCLASS|ENDDO|ENDFORM|ENDFUNCTION|'
384 r'ENDIF|ENDINTERFACE|ENDLOOP|ENDMETHOD|ENDMODULE|ENDSELECT|ENDTRY|ENDWHILE|'
385 r'ENHANCEMENT|EVENTS|EXACT|EXCEPTIONS?|EXIT|EXPONENT|EXPORT|EXPORTING|EXTRACT|'
386 r'FETCH|FIELDS?|FOR|FORM|FORMAT|FREE|FROM|FUNCTION|'
387 r'HIDE|'
388 r'ID|IF|IMPORT|IMPLEMENTATION|IMPORTING|IN|INCLUDE|INCLUDING|'
389 r'INDEX|INFOTYPES|INITIALIZATION|INTERFACE|INTERFACES|INTO|'
390 r'LANGUAGE|LEAVE|LENGTH|LINES|LOAD|LOCAL|'
391 r'JOIN|'
392 r'KEY|'
393 r'NEW|NEXT|'
394 r'MAXIMUM|MESSAGE|METHOD[S]?|MINIMUM|MODULE|MODIFIER|MODIFY|MOVE|MULTIPLY|'
395 r'NODES|NUMBER|'
396 r'OBLIGATORY|OBJECT|OF|OFF|ON|OTHERS|OVERLAY|'
397 r'PACK|PAD|PARAMETERS|PERCENTAGE|POSITION|PROGRAM|PROVIDE|PUBLIC|PUT|PF\d\d|'
398 r'RAISE|RAISING|RANGES?|READ|RECEIVE|REDEFINITION|REFRESH|REJECT|REPORT|RESERVE|'
399 r'REF|RESUME|RETRY|RETURN|RETURNING|RIGHT|ROLLBACK|REPLACE|'
400 r'SCROLL|SEARCH|SELECT|SHIFT|SIGN|SINGLE|SIZE|SKIP|SORT|SPLIT|STATICS|STOP|'
401 r'STYLE|SUBMATCHES|SUBMIT|SUBTRACT|SUM(?!\()|SUMMARY|SUMMING|SUPPLY|SWITCH|'
402 r'TABLE|TABLES|TIMESTAMP|TIMES?|TIMEZONE|TITLE|\??TO|'
403 r'TOP-OF-PAGE|TRANSFER|TRANSLATE|TRY|TYPES|'
404 r'ULINE|UNDER|UNPACK|UPDATE|USING|'
405 r'VALUE|VALUES|VIA|VARYING|VARY|'
406 r'WAIT|WHEN|WHERE|WIDTH|WHILE|WITH|WINDOW|WRITE|XSD|ZERO)\b', Keyword),
407
408 # builtins
409 (r'(abs|acos|asin|atan|'
410 r'boolc|boolx|bit_set|'
411 r'char_off|charlen|ceil|cmax|cmin|condense|contains|'
412 r'contains_any_of|contains_any_not_of|concat_lines_of|cos|cosh|'
413 r'count|count_any_of|count_any_not_of|'
414 r'dbmaxlen|distance|'
415 r'escape|exp|'
416 r'find|find_end|find_any_of|find_any_not_of|floor|frac|from_mixed|'
417 r'insert|'
418 r'lines|log|log10|'
419 r'match|matches|'
420 r'nmax|nmin|numofchar|'
421 r'repeat|replace|rescale|reverse|round|'
422 r'segment|shift_left|shift_right|sign|sin|sinh|sqrt|strlen|'
423 r'substring|substring_after|substring_from|substring_before|substring_to|'
424 r'tan|tanh|to_upper|to_lower|to_mixed|translate|trunc|'
425 r'xstrlen)(\()\b', bygroups(Name.Builtin, Punctuation)),
426
427 (r'&[0-9]', Name),
428 (r'[0-9]+', Number.Integer),
429
430 # operators which look like variable names before
431 # parsing variable names.
432 (r'(?<=(\s|.))(AND|OR|EQ|NE|GT|LT|GE|LE|CO|CN|CA|NA|CS|NOT|NS|CP|NP|'
433 r'BYTE-CO|BYTE-CN|BYTE-CA|BYTE-NA|BYTE-CS|BYTE-NS|'
434 r'IS\s+(NOT\s+)?(INITIAL|ASSIGNED|REQUESTED|BOUND))\b', Operator.Word),
435
436 include('variable-names'),
437
438 # standard operators after variable names,
439 # because < and > are part of field symbols.
440 (r'[?*<>=\-+&]', Operator),
441 (r"'(''|[^'])*'", String.Single),
442 (r"`([^`])*`", String.Single),
443 (r"([|}])([^{}|]*?)([|{])",
444 bygroups(Punctuation, String.Single, Punctuation)),
445 (r'[/;:()\[\],.]', Punctuation),
446 (r'(!)(\w+)', bygroups(Operator, Name)),
447 ],
448 }
449
450
451class OpenEdgeLexer(RegexLexer):
452 """
453 Lexer for OpenEdge ABL (formerly Progress) source code.
454 """
455 name = 'OpenEdge ABL'
456 aliases = ['openedge', 'abl', 'progress']
457 filenames = ['*.p', '*.cls']
458 mimetypes = ['text/x-openedge', 'application/x-openedge']
459 url = 'https://www.progress.com/openedge/features/abl'
460 version_added = '1.5'
461
462 types = (r'(?i)(^|(?<=[^\w\-]))(CHARACTER|CHAR|CHARA|CHARAC|CHARACT|CHARACTE|'
463 r'COM-HANDLE|DATE|DATETIME|DATETIME-TZ|'
464 r'DECIMAL|DEC|DECI|DECIM|DECIMA|HANDLE|'
465 r'INT64|INTEGER|INT|INTE|INTEG|INTEGE|'
466 r'LOGICAL|LONGCHAR|MEMPTR|RAW|RECID|ROWID)\s*($|(?=[^\w\-]))')
467
468 keywords = words(OPENEDGEKEYWORDS,
469 prefix=r'(?i)(^|(?<=[^\w\-]))',
470 suffix=r'\s*($|(?=[^\w\-]))')
471
472 tokens = {
473 'root': [
474 (r'/\*', Comment.Multiline, 'comment'),
475 (r'\{', Comment.Preproc, 'preprocessor'),
476 (r'\s*&.*', Comment.Preproc),
477 (r'0[xX][0-9a-fA-F]+[LlUu]*', Number.Hex),
478 (r'(?i)(DEFINE|DEF|DEFI|DEFIN)\b', Keyword.Declaration),
479 (types, Keyword.Type),
480 (keywords, Name.Builtin),
481 (r'"(\\\\|\\[^\\]|[^"\\])*"', String.Double),
482 (r"'(\\\\|\\[^\\]|[^'\\])*'", String.Single),
483 (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float),
484 (r'[0-9]+', Number.Integer),
485 (r'\s+', Whitespace),
486 (r'[+*/=-]', Operator),
487 (r'[.:()]', Punctuation),
488 (r'.', Name.Variable), # Lazy catch-all
489 ],
490 'comment': [
491 (r'[^*/]', Comment.Multiline),
492 (r'/\*', Comment.Multiline, '#push'),
493 (r'\*/', Comment.Multiline, '#pop'),
494 (r'[*/]', Comment.Multiline)
495 ],
496 'preprocessor': [
497 (r'[^{}]', Comment.Preproc),
498 (r'\{', Comment.Preproc, '#push'),
499 (r'\}', Comment.Preproc, '#pop'),
500 ],
501 }
502
503 def analyse_text(text):
504 """Try to identify OpenEdge ABL based on a few common constructs."""
505 result = 0
506
507 if 'END.' in text:
508 result += 0.05
509
510 if 'END PROCEDURE.' in text:
511 result += 0.05
512
513 if 'ELSE DO:' in text:
514 result += 0.05
515
516 return result
517
518
519class GoodDataCLLexer(RegexLexer):
520 """
521 Lexer for GoodData-CL script files.
522 """
523
524 name = 'GoodData-CL'
525 aliases = ['gooddata-cl']
526 filenames = ['*.gdc']
527 mimetypes = ['text/x-gooddata-cl']
528 url = 'https://github.com/gooddata/GoodData-CL'
529 version_added = '1.4'
530
531 flags = re.IGNORECASE
532
533 # Syntax:
534 # https://github.com/gooddata/GoodData-CL/raw/master/cli/src/main/resources/com/gooddata/processor/COMMANDS.txt
535 tokens = {
536 'root': [
537 # Comments
538 (r'#.*', Comment.Single),
539 # Function call
540 (r'[a-z]\w*', Name.Function),
541 # Argument list
542 (r'\(', Punctuation, 'args-list'),
543 # Punctuation
544 (r';', Punctuation),
545 # Space is not significant
546 (r'\s+', Text)
547 ],
548 'args-list': [
549 (r'\)', Punctuation, '#pop'),
550 (r',', Punctuation),
551 (r'[a-z]\w*', Name.Variable),
552 (r'=', Operator),
553 (r'"', String, 'string-literal'),
554 (r'[0-9]+(?:\.[0-9]+)?(?:e[+-]?[0-9]{1,3})?', Number),
555 # Space is not significant
556 (r'\s', Whitespace)
557 ],
558 'string-literal': [
559 (r'\\[tnrfbae"\\]', String.Escape),
560 (r'"', String, '#pop'),
561 (r'[^\\"]+', String)
562 ]
563 }
564
565
566class MaqlLexer(RegexLexer):
567 """
568 Lexer for GoodData MAQL scripts.
569 """
570
571 name = 'MAQL'
572 aliases = ['maql']
573 filenames = ['*.maql']
574 mimetypes = ['text/x-gooddata-maql', 'application/x-gooddata-maql']
575 url = 'https://help.gooddata.com/doc/enterprise/en/dashboards-and-insights/maql-analytical-query-language'
576 version_added = '1.4'
577
578 flags = re.IGNORECASE
579 tokens = {
580 'root': [
581 # IDENTITY
582 (r'IDENTIFIER\b', Name.Builtin),
583 # IDENTIFIER
584 (r'\{[^}]+\}', Name.Variable),
585 # NUMBER
586 (r'[0-9]+(?:\.[0-9]+)?(?:e[+-]?[0-9]{1,3})?', Number),
587 # STRING
588 (r'"', String, 'string-literal'),
589 # RELATION
590 (r'\<\>|\!\=', Operator),
591 (r'\=|\>\=|\>|\<\=|\<', Operator),
592 # :=
593 (r'\:\=', Operator),
594 # OBJECT
595 (r'\[[^]]+\]', Name.Variable.Class),
596 # keywords
597 (words((
598 'DIMENSION', 'DIMENSIONS', 'BOTTOM', 'METRIC', 'COUNT', 'OTHER',
599 'FACT', 'WITH', 'TOP', 'OR', 'ATTRIBUTE', 'CREATE', 'PARENT',
600 'FALSE', 'ROW', 'ROWS', 'FROM', 'ALL', 'AS', 'PF', 'COLUMN',
601 'COLUMNS', 'DEFINE', 'REPORT', 'LIMIT', 'TABLE', 'LIKE', 'AND',
602 'BY', 'BETWEEN', 'EXCEPT', 'SELECT', 'MATCH', 'WHERE', 'TRUE',
603 'FOR', 'IN', 'WITHOUT', 'FILTER', 'ALIAS', 'WHEN', 'NOT', 'ON',
604 'KEYS', 'KEY', 'FULLSET', 'PRIMARY', 'LABELS', 'LABEL',
605 'VISUAL', 'TITLE', 'DESCRIPTION', 'FOLDER', 'ALTER', 'DROP',
606 'ADD', 'DATASET', 'DATATYPE', 'INT', 'BIGINT', 'DOUBLE', 'DATE',
607 'VARCHAR', 'DECIMAL', 'SYNCHRONIZE', 'TYPE', 'DEFAULT', 'ORDER',
608 'ASC', 'DESC', 'HYPERLINK', 'INCLUDE', 'TEMPLATE', 'MODIFY'),
609 suffix=r'\b'),
610 Keyword),
611 # FUNCNAME
612 (r'[a-z]\w*\b', Name.Function),
613 # Comments
614 (r'#.*', Comment.Single),
615 # Punctuation
616 (r'[,;()]', Punctuation),
617 # Space is not significant
618 (r'\s+', Whitespace)
619 ],
620 'string-literal': [
621 (r'\\[tnrfbae"\\]', String.Escape),
622 (r'"', String, '#pop'),
623 (r'[^\\"]+', String)
624 ],
625 }