packages/bicep-syntax/lexer.py (116 lines of code) (raw):
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# NOTES:
# This module implements a pygments lexer for Bicep.
# Local testing:
# To test the lexer, you can use the following code snippet:
# pygmentize -l bicep docs/examples/resources/keyvault.bicep
import logging
from pygments.lexer import RegexLexer, bygroups, words, include
from pygments.token import Comment, Operator, Keyword, Name, String, Number, Punctuation, Whitespace
log = logging.getLogger(f"mkdocs")
__all__ = ['BicepLexer',]
BICEP_KEYWORDS = [
'metadata', 'targetScope', 'for', 'in', 'if', 'existing', 'as', 'with', 'extends', 'assert', 'extension',
]
BICEP_DECLARATIONS = [
'var', 'func', 'type'
]
BICEP_DECORATORS = [
'secure', 'metadata', 'description', 'export', 'maxLength', 'minLength', 'allowed'
]
class BicepLexer(RegexLexer):
'''A lexer for Bicep.'''
name = 'Bicep'
aliases = ['bicep']
filenames = ['*.bicep']
log.warning(f"Loading Bicep lexer")
tokens = {
'root': [
(words(['import', 'using'], suffix=' '), Keyword.Namespace),
(r'^(param)(\s)(\w+)(\s)(\w+)', bygroups(Keyword.Declaration, Whitespace, Name.Symbol, Whitespace, Name.Type), 'param'),
(r'^(output)(\s)(\w+)(\s)(\w+)', bygroups(Keyword.Declaration, Whitespace, Name.Symbol, Whitespace, Name.Type), 'output'),
(r'^(resource)(\s)(\w+)', bygroups(Keyword.Declaration, Whitespace, Name.Symbol), 'resource'),
(r'^(module)(\s)(\w+)', bygroups(Keyword.Declaration, Whitespace, Name.Symbol), 'module'),
(words(BICEP_DECLARATIONS, suffix=' ', prefix='\n'), Keyword.Declaration),
(r'^(\@)(secure|metadata|description|export|maxLength|minLength|allowed)(\()', bygroups(Keyword.Decorator, Keyword.Decorator, Punctuation), 'decorator'),
(words(BICEP_KEYWORDS, suffix=r'\b'), Keyword),
include('core'),
],
'core': [
(r'(\[)(for)', bygroups(Punctuation, Keyword), 'loop'),
include('comments'),
include('complex'),
include('literal'),
(r'\n', Whitespace),
(r'\s+', Whitespace),
(r'\=|\+|\-', Operator),
],
'numbers': [
(r"\d+[.]\d*|[.]\d+", Number.Float),
(r"\d+", Number.Integer),
],
'literal': [
include('numbers'),
(r"'", String, 'single_string'),
(r'(true|false|null)\b', Keyword.Constant),
],
'complex': [
(r'\{', Punctuation, 'object'),
(r'\[', Punctuation, 'array'),
],
'comments': [
(r'//.*?$', Comment.Single),
(r'/\*', Comment.Multiline, 'multiline-comments'),
],
'multiline-comments': [
(r'.*?\*/', Comment.Multiline, '#pop'),
(r'.+', Comment.Multiline),
],
'decorator': [
(r'\)', Punctuation, '#pop'),
(r'\n', Whitespace, '#pop'),
(r'\s+', Whitespace),
include('literal'),
include('complex'),
include('comments'),
],
'single_string': [
(r"'", String, "#pop"),
(r"\\.", String.Escape),
(r"[^'\\]+", String),
],
'array': [
(r',', Punctuation),
(r'\]', Punctuation, '#pop'),
include('core'),
],
'object': [
(r'(\s+)(\w+)(\:)', bygroups(Whitespace, Name.Property, Punctuation)),
(r'\s+', Whitespace),
(r'\}', Punctuation, '#pop'),
include('core'),
],
'param': [
(r'\n', Whitespace, '#pop'),
(r'\=', Operator, '#pop'),
],
'output': [
(r'\n', Whitespace, '#pop'),
(r'\=', Operator, '#pop'),
],
'resource': [
(r"'", String, 'single_string'),
(words(['existing']), Keyword),
(r'\n', Whitespace, '#pop'),
(r'\=', Operator, '#pop'),
],
'module': [
(r"'", String, 'single_string'),
(r'\n', Whitespace, '#pop'),
(r'\=', Operator, '#pop'),
],
'loop': [
(words(['in', 'range', 'items']), Keyword),
(r'\(|\)|\,', Punctuation),
(r'\:', Punctuation, '#pop'),
include('core'),
],
'condition': [
(r'\)', Punctuation, '#pop'),
include('literal'),
]
}