diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..1b8fa16e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: push + +jobs: + ci: + name: CI + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + with: + node-version: 12 + + - name: npm install + run: npm install + + - name: Compile + run: npm run compile + + - name: Test + run: npm test diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index a9c406e4..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Node.js -# Build a general Node.js project with npm. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript - -trigger: - - master - -pool: - vmImage: 'ubuntu-latest' - -steps: - - task: NodeTool@0 - inputs: - versionSpec: '10.x' - displayName: 'Install Node.js' - - - script: | - npm install - displayName: 'npm install' - - - script: | - npm run compile - displayName: 'compile' - - - script: | - npm test - displayName: 'test' diff --git a/src/ecl/ecl.contribution.ts b/src/ecl/ecl.contribution.ts new file mode 100644 index 00000000..dfa4ed90 --- /dev/null +++ b/src/ecl/ecl.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'ecl', + extensions: ['.ecl'], + aliases: ['ECL', 'Ecl', 'ecl'], + loader: () => import('./ecl') +}); diff --git a/src/ecl/ecl.test.ts b/src/ecl/ecl.test.ts new file mode 100644 index 00000000..d2bbaed1 --- /dev/null +++ b/src/ecl/ecl.test.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('ecl', []); diff --git a/src/ecl/ecl.ts b/src/ecl/ecl.ts new file mode 100644 index 00000000..a1061738 --- /dev/null +++ b/src/ecl/ecl.ts @@ -0,0 +1,481 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.ecl', + ignoreCase: true, + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + pounds: [ + 'append', + 'break', + 'declare', + 'demangle', + 'end', + 'for', + 'getdatatype', + 'if', + 'inmodule', + 'loop', + 'mangle', + 'onwarning', + 'option', + 'set', + 'stored', + 'uniquename' + ].join('|'), + + keywords: [ + '__compressed__', + 'after', + 'all', + 'and', + 'any', + 'as', + 'atmost', + 'before', + 'beginc', + 'best', + 'between', + 'case', + 'cluster', + 'compressed', + 'compression', + 'const', + 'counter', + 'csv', + 'default', + 'descend', + 'embed', + 'encoding', + 'encrypt', + 'end', + 'endc', + 'endembed', + 'endmacro', + 'enum', + 'escape', + 'except', + 'exclusive', + 'expire', + 'export', + 'extend', + 'fail', + 'few', + 'fileposition', + 'first', + 'flat', + 'forward', + 'from', + 'full', + 'function', + 'functionmacro', + 'group', + 'grouped', + 'heading', + 'hole', + 'ifblock', + 'import', + 'in', + 'inner', + 'interface', + 'internal', + 'joined', + 'keep', + 'keyed', + 'last', + 'left', + 'limit', + 'linkcounted', + 'literal', + 'little_endian', + 'load', + 'local', + 'locale', + 'lookup', + 'lzw', + 'macro', + 'many', + 'maxcount', + 'maxlength', + 'min skew', + 'module', + 'mofn', + 'multiple', + 'named', + 'namespace', + 'nocase', + 'noroot', + 'noscan', + 'nosort', + 'not', + 'noxpath', + 'of', + 'onfail', + 'only', + 'opt', + 'or', + 'outer', + 'overwrite', + 'packed', + 'partition', + 'penalty', + 'physicallength', + 'pipe', + 'prefetch', + 'quote', + 'record', + 'repeat', + 'retry', + 'return', + 'right', + 'right1', + 'right2', + 'rows', + 'rowset', + 'scan', + 'scope', + 'self', + 'separator', + 'service', + 'shared', + 'skew', + 'skip', + 'smart', + 'soapaction', + 'sql', + 'stable', + 'store', + 'terminator', + 'thor', + 'threshold', + 'timelimit', + 'timeout', + 'token', + 'transform', + 'trim', + 'type', + 'unicodeorder', + 'unordered', + 'unsorted', + 'unstable', + 'update', + 'use', + 'validate', + 'virtual', + 'whole', + 'width', + 'wild', + 'within', + 'wnotrim', + 'xml', + 'xpath' + ], + + functions: [ + 'abs', + 'acos', + 'aggregate', + 'allnodes', + 'apply', + 'ascii', + 'asin', + 'assert', + 'asstring', + 'atan', + 'atan2', + 'ave', + 'build', + 'buildindex', + 'case', + 'catch', + 'choose', + 'choosen', + 'choosesets', + 'clustersize', + 'combine', + 'correlation', + 'cos', + 'cosh', + 'count', + 'covariance', + 'cron', + 'dataset', + 'dedup', + 'define', + 'denormalize', + 'dictionary', + 'distribute', + 'distributed', + 'distribution', + 'ebcdic', + 'enth', + 'error', + 'evaluate', + 'event', + 'eventextra', + 'eventname', + 'exists', + 'exp', + 'fail', + 'failcode', + 'failmessage', + 'fetch', + 'fromunicode', + 'fromxml', + 'getenv', + 'getisvalid', + 'global', + 'graph', + 'group', + 'hash', + 'hash32', + 'hash64', + 'hashcrc', + 'hashmd5', + 'having', + 'httpcall', + 'httpheader', + 'if', + 'iff', + 'index', + 'intformat', + 'isvalid', + 'iterate', + 'join', + 'keydiff', + 'keypatch', + 'keyunicode', + 'length', + 'library', + 'limit', + 'ln', + 'loadxml', + 'local', + 'log', + 'loop', + 'map', + 'matched', + 'matchlength', + 'matchposition', + 'matchtext', + 'matchunicode', + 'max', + 'merge', + 'mergejoin', + 'min', + 'nofold', + 'nolocal', + 'nonempty', + 'normalize', + 'nothor', + 'notify', + 'output', + 'parallel', + 'parse', + 'pipe', + 'power', + 'preload', + 'process', + 'project', + 'pull', + 'random', + 'range', + 'rank', + 'ranked', + 'realformat', + 'recordof', + 'regexfind', + 'regexreplace', + 'regroup', + 'rejected', + 'rollup', + 'round', + 'roundup', + 'row', + 'rowdiff', + 'sample', + 'sequential', + 'set', + 'sin', + 'sinh', + 'sizeof', + 'soapcall', + 'sort', + 'sorted', + 'sqrt', + 'stepped', + 'stored', + 'sum', + 'table', + 'tan', + 'tanh', + 'thisnode', + 'topn', + 'tounicode', + 'toxml', + 'transfer', + 'transform', + 'trim', + 'truncate', + 'typeof', + 'ungroup', + 'unicodeorder', + 'variance', + 'wait', + 'which', + 'workunit', + 'xmldecode', + 'xmlencode', + 'xmltext', + 'xmlunicode' + ], + + typesint: ['integer', 'unsigned'].join('|'), + + typesnum: ['data', 'qstring', 'string', 'unicode', 'utf8', 'varstring', 'varunicode'], + + typesone: [ + 'ascii', + 'big_endian', + 'boolean', + 'data', + 'decimal', + 'ebcdic', + 'grouped', + 'integer', + 'linkcounted', + 'pattern', + 'qstring', + 'real', + 'record', + 'rule', + 'set of', + 'streamed', + 'string', + 'token', + 'udecimal', + 'unicode', + 'unsigned', + 'utf8', + 'varstring', + 'varunicode' + ].join('|'), + + operators: ['+', '-', '/', ':=', '<', '<>', '=', '>', '\\', 'and', 'in', 'not', 'or'], + + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/[0-9_]*\.[0-9_]+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F_]+/, 'number.hex'], + [/0[bB][01]+/, 'number.hex'], // binary: use same theme style as hex + [/[0-9_]+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\v\f\r\n]+/, ''], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + string: [ + [/[^\\']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, 'string', '@pop'] + ] + } +}; diff --git a/src/hcl/hcl.test.ts b/src/hcl/hcl.test.ts index 9a776e42..3f2f7632 100644 --- a/src/hcl/hcl.test.ts +++ b/src/hcl/hcl.test.ts @@ -992,6 +992,35 @@ testTokenization('hcl', [ } ], /* + foo = <<-EOF + bar + EOF + */ + [ + { + line: ' foo = <<-EOF', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.hcl' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'operator.hcl' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.heredoc.delimiter.hcl' } + ] + }, + { + line: ' bar', + tokens: [{ startIndex: 0, type: 'string.heredoc.hcl' }] + }, + { + line: ' EOF', + tokens: [ + { startIndex: 0, type: 'string.heredoc.hcl' }, + { startIndex: 2, type: 'string.heredoc.delimiter.hcl' } + ] + } + ], + /* foo = <{ ], heredocBody: [ [ - /^([\w\-]+)$/, + /([\w\-]+)$/, { cases: { '$1==$S2': [ diff --git a/src/m3/m3.contribution.ts b/src/m3/m3.contribution.ts new file mode 100644 index 00000000..bbb84fb1 --- /dev/null +++ b/src/m3/m3.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'm3', + extensions: ['.m3', '.i3', '.mg', '.ig'], + aliases: ['Modula-3', 'Modula3', 'modula3', 'm3'], + loader: () => import('./m3') +}); diff --git a/src/m3/m3.test.ts b/src/m3/m3.test.ts new file mode 100644 index 00000000..c089527e --- /dev/null +++ b/src/m3/m3.test.ts @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('m3', [ + [ + { + line: '(**)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: ' (* a comment *)', + tokens: [ + { startIndex: 0, type: 'white.m3' }, + { startIndex: 4, type: 'comment.m3' } + ] + } + ], + + [ + { + line: '(* Lorem ipsum dolor sit amet, consectetur ', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' adipiscing elit, sed do eiusmod tempor', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' incididunt ut labore et dolore magna aliqua. *)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: '(* Lorem ipsum dolor sit amet (*, consectetur ', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' adipiscing elit, sed do eiusmod tempor', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' incididunt*) ut labore et dolore magna aliqua. *)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: 'MODULE Test EXPORTS Main; FROM IO IMPORT Put; BEGIN Put("test\\n") END Test.', + tokens: [ + { startIndex: 0, type: 'keyword.MODULE.m3' }, + { startIndex: 6, type: 'white.m3' }, + { startIndex: 7, type: 'identifier.m3' }, + { startIndex: 11, type: 'white.m3' }, + { startIndex: 12, type: 'keyword.EXPORTS.m3' }, + { startIndex: 19, type: 'white.m3' }, + { startIndex: 20, type: 'identifier.m3' }, + { startIndex: 24, type: 'delimiter.m3' }, + { startIndex: 25, type: 'white.m3' }, + + { startIndex: 26, type: 'keyword.FROM.m3' }, + { startIndex: 30, type: 'white.m3' }, + { startIndex: 31, type: 'identifier.m3' }, + { startIndex: 33, type: 'white.m3' }, + { startIndex: 34, type: 'keyword.IMPORT.m3' }, + { startIndex: 40, type: 'white.m3' }, + { startIndex: 41, type: 'identifier.m3' }, + { startIndex: 44, type: 'delimiter.m3' }, + { startIndex: 45, type: 'white.m3' }, + + { startIndex: 46, type: 'keyword.BEGIN.m3' }, + { startIndex: 51, type: 'white.m3' }, + { startIndex: 52, type: 'identifier.m3' }, + { startIndex: 55, type: 'delimiter.parenthesis.m3' }, + { startIndex: 56, type: 'string.text.m3' }, + { startIndex: 61, type: 'string.escape.m3' }, + { startIndex: 63, type: 'string.text.m3' }, + { startIndex: 64, type: 'delimiter.parenthesis.m3' }, + { startIndex: 65, type: 'white.m3' }, + + { startIndex: 66, type: 'keyword.END.m3' }, + { startIndex: 69, type: 'white.m3' }, + { startIndex: 70, type: 'identifier.m3' }, + { startIndex: 74, type: 'operators.m3' } + ] + } + ], + + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.m3' }] + } + ], + [ + { + line: '-16_B33f', + tokens: [ + { startIndex: 0, type: 'operators.m3' }, + { startIndex: 1, type: 'number.m3' } + ] + } + ], + [ + { + line: '2.0D-5', + tokens: [{ startIndex: 0, type: 'number.float.m3' }] + } + ] +]); diff --git a/src/m3/m3.ts b/src/m3/m3.ts new file mode 100644 index 00000000..243f36bd --- /dev/null +++ b/src/m3/m3.ts @@ -0,0 +1,226 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + blockComment: ['(*', '*)'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '[', close: ']' }, + { open: '{', close: '}' }, + { open: '(', close: ')' }, + { open: '(*', close: '*)' }, + { open: '<*', close: '*>' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.m3', + + brackets: [ + { token: 'delimiter.curly', open: '{', close: '}' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' }, + { token: 'delimiter.square', open: '[', close: ']' } + ], + keywords: [ + 'AND', + 'ANY', + 'ARRAY', + 'AS', + 'BEGIN', + 'BITS', + 'BRANDED', + 'BY', + 'CASE', + 'CONST', + 'DIV', + 'DO', + 'ELSE', + 'ELSIF', + 'END', + 'EVAL', + 'EXCEPT', + 'EXCEPTION', + 'EXIT', + 'EXPORTS', + 'FINALLY', + 'FOR', + 'FROM', + 'GENERIC', + 'IF', + 'IMPORT', + 'IN', + 'INTERFACE', + 'LOCK', + 'LOOP', + 'METHODS', + 'MOD', + 'MODULE', + 'NOT', + 'OBJECT', + 'OF', + 'OR', + 'OVERRIDES', + 'PROCEDURE', + 'RAISE', + 'RAISES', + 'READONLY', + 'RECORD', + 'REF', + 'REPEAT', + 'RETURN', + 'REVEAL', + 'SET', + 'THEN', + 'TO', + 'TRY', + 'TYPE', + 'TYPECASE', + 'UNSAFE', + 'UNTIL', + 'UNTRACED', + 'VALUE', + 'VAR', + 'WHILE', + 'WITH' + ], + reservedConstNames: [ + 'ABS', + 'ADR', + 'ADRSIZE', + 'BITSIZE', + 'BYTESIZE', + 'CEILING', + 'DEC', + 'DISPOSE', + 'FALSE', + 'FIRST', + 'FLOAT', + 'FLOOR', + 'INC', + 'ISTYPE', + 'LAST', + 'LOOPHOLE', + 'MAX', + 'MIN', + 'NARROW', + 'NEW', + 'NIL', + 'NUMBER', + 'ORD', + 'ROUND', + 'SUBARRAY', + 'TRUE', + 'TRUNC', + 'TYPECODE', + 'VAL' + ], + reservedTypeNames: [ + 'ADDRESS', + 'ANY', + 'BOOLEAN', + 'CARDINAL', + 'CHAR', + 'EXTENDED', + 'INTEGER', + 'LONGCARD', + 'LONGINT', + 'LONGREAL', + 'MUTEX', + 'NULL', + 'REAL', + 'REFANY', + 'ROOT', + 'TEXT' + ], + operators: ['+', '-', '*', '/', '&', '^', '.'], + relations: ['=', '#', '<', '<=', '>', '>=', '<:', ':'], + delimiters: ['|', '..', '=>', ',', ';', ':='], + symbols: /[>=<#.,:;+\-*/&^]+/, + escapes: /\\(?:[\\fnrt"']|[0-7]{3})/, + + tokenizer: { + root: [ + // Identifiers and keywords + [/_\w*/, 'invalid'], + [ + /[a-zA-Z][a-zA-Z0-9_]*/, + { + cases: { + '@keywords': { token: 'keyword.$0' }, + '@reservedConstNames': { token: 'constant.reserved.$0' }, + '@reservedTypeNames': { token: 'type.reserved.$0' }, + '@default': 'identifier' + } + } + ], + + // Whitespace + { include: '@whitespace' }, + [/[{}()\[\]]/, '@brackets'], + + // Integer- and real literals + [/[0-9]+\.[0-9]+(?:[DdEeXx][\+\-]?[0-9]+)?/, 'number.float'], + [/[0-9]+(?:\_[0-9a-fA-F]+)?L?/, 'number'], + + // Operators, relations, and delimiters + [ + /@symbols/, + { + cases: { + '@operators': 'operators', + '@relations': 'operators', + '@delimiters': 'delimiter', + '@default': 'invalid' + } + } + ], + + // Character literals + [/'[^\\']'/, 'string.char'], + [/(')(@escapes)(')/, ['string.char', 'string.escape', 'string.char']], + [/'/, 'invalid'], + + // Text literals + [/"([^"\\]|\\.)*$/, 'invalid'], + [/"/, 'string.text', '@text'] + ], + + text: [ + [/[^\\"]+/, 'string.text'], + [/@escapes/, 'string.escape'], + [/\\./, 'invalid'], + [/"/, 'string.text', '@pop'] + ], + + comment: [ + [/\(\*/, 'comment', '@push'], + [/\*\)/, 'comment', '@pop'], + [/./, 'comment'] + ], + + pragma: [ + [/<\*/, 'keyword.pragma', '@push'], + [/\*>/, 'keyword.pragma', '@pop'], + [/./, 'keyword.pragma'] + ], + + whitespace: [ + [/[ \t\r\n]+/, 'white'], + [/\(\*/, 'comment', '@comment'], + [/<\*/, 'keyword.pragma', '@pragma'] + ] + } +}; diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index d67526d5..cf90f679 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -16,6 +16,7 @@ import './csp/csp.contribution'; import './css/css.contribution'; import './dart/dart.contribution'; import './dockerfile/dockerfile.contribution'; +import './ecl/ecl.contribution'; import './fsharp/fsharp.contribution'; import './go/go.contribution'; import './graphql/graphql.contribution'; @@ -30,6 +31,7 @@ import './kotlin/kotlin.contribution'; import './less/less.contribution'; import './lexon/lexon.contribution'; import './lua/lua.contribution'; +import './m3/m3.contribution'; import './markdown/markdown.contribution'; import './mips/mips.contribution'; import './msdax/msdax.contribution';