from pygments.lexer import RegexLexer, bygroups from pygments.token import * class SudsLexer(RegexLexer): name = 'SUDS' aliases = ['suds'] filenames = ['*.sud'] tokens = { 'root': [ (r'===\s*\n', Generic.Heading), # Choices (r'\s*\*\-?\s+[^\@\n]+[\@\n]', Generic.Subheading), (r'\s*#.*\n', Comment), # Speaker lines (r'\s*\S+\:', Name.Class, 'speakerline'), # Open brackets for special functions (r'\[', Operator, 'squarebrackets'), # Variables (r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)), (r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)), (r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant), # Line IDs (r'\@[0-9a-fA-F]+\@', Comment.Special), # Embedded markup (r'\<\w+\>', Name.Decorator), (r'\<\/\>', Name.Decorator), # Goto labels (r'\s*:\S+\n', Name.Label), # Comments (r'\s*\#[\=\+\%]?.*\n', Comment.Special), # Fallback for all other text # Needs an optional \n on the end to finish lines correctly (r'\s+[\n]?', Text), (r'\S+?[\n]?', Text), # non-greedy so we don't consume all non-whitespace ], # While in a speaker line, we ignore everything else except variables & markup 'speakerline' : [ # Variables (r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)), (r'(\|)(plural|gender)(\()(.*?)(\))', bygroups(Operator, Keyword, Operator, Keyword, Operator)), (r'[\@\n]', Text, '#pop'), # Embedded markup (r'\<\w+\>', Name.Decorator), (r'\<\/\>', Name.Decorator), (r'[^\@\n\<\{]+', Text), ], # While in a [] block, highlight operators etc (don't do it elsewhere) 'squarebrackets' : [ # Close bracket finishes (r'\]\s*[\n]?', Operator, '#pop'), # Variables (r'(\{)([\w\.]+)(\})', bygroups(Operator, Name.Variable, Operator)), (r'\+\/\-\*\!\%', Operator), (r'\"[^\"]*\"', String.Double), (r'\`[^\`]*\`', String.Escape), (r'\d+(\.\d+)?', Number), (r'\b([tT]rue|[fF]alse|[mM]asculine|[fF]eminine|[nN]euter)\b', Name.Constant), # Set, event commands so we can highlight variable/event differently (r'\s*(set|event)(\s+)([^\]\s]+)', bygroups(Keyword, Text, Name.Variable)), (r'\s*(if|else|elseif|endif|event|return|goto|gosub|go to|go sub|random|endrandom)\b', Keyword), (r'\b(and|or|&&|\|\||not)\b', Operator), (r'[,]', Punctuation), (r'\s+', Text), # whitespace OK ] }