vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

makefile.lua

(5080B)


      1 -- Copyright 2006-2025 Mitchell. See LICENSE.
      2 -- Makefile LPeg lexer.
      3 
      4 local lexer = lexer
      5 local P, S, B = lpeg.P, lpeg.S, lpeg.B
      6 
      7 local lex = lexer.new(..., {lex_by_line = true})
      8 
      9 -- Function definition.
     10 local word = (lexer.any - lexer.space - S('$:,#=(){}'))^1
     11 local func_name = lex:tag(lexer.FUNCTION, word)
     12 local ws = lex:get_rule('whitespace')
     13 local eq = lex:tag(lexer.OPERATOR, '=')
     14 lex:add_rule('function_def', lex:tag(lexer.KEYWORD, lexer.word_match('define')) * ws * func_name *
     15 	ws^-1 * (eq + -1))
     16 
     17 -- Keywords.
     18 lex:add_rule('keyword', lex:tag(lexer.KEYWORD, P('!')^-1 * lex:word_match(lexer.KEYWORD, true)))
     19 
     20 -- Targets.
     21 local special_target = lex:tag(lexer.CONSTANT_BUILTIN, '.' * lex:word_match('special_targets'))
     22 -- local normal_target = lex:tag('target', (lexer.any - lexer.space - S(':+?!=#'))^1)
     23 local target = special_target -- + normal_target * (ws * normal_target)^0
     24 lex:add_rule('target', lexer.starts_line(target * ws^-1 * #(':' * lexer.space)))
     25 
     26 -- Variable and function assignments.
     27 local func_assign = func_name * ws^-1 * eq *
     28 	#P(function(input, index) return input:find('%$%(%d%)', index) end)
     29 local builtin_var = lex:tag(lexer.VARIABLE_BUILTIN, lex:word_match(lexer.VARIABLE_BUILTIN))
     30 local var_name = lex:tag(lexer.VARIABLE, word)
     31 local var_assign = (builtin_var + var_name) * ws^-1 *
     32 	lex:tag(lexer.OPERATOR, S(':+?!')^-1 * '=' + '::=')
     33 lex:add_rule('assign', lexer.starts_line(func_assign + var_assign, true) + B(': ') * var_assign)
     34 
     35 -- Operators.
     36 lex:add_rule('operator', lex:tag(lexer.OPERATOR, S(':(){}|')))
     37 
     38 -- Strings.
     39 lex:add_rule('string', lexer.range("'", true) + lexer.range('"', true))
     40 
     41 -- Identifiers.
     42 lex:add_rule('identifier', lex:tag(lexer.IDENTIFIER, word))
     43 
     44 -- Functions.
     45 local builtin_func = lex:tag(lexer.FUNCTION_BUILTIN, lex:word_match(lexer.FUNCTION_BUILTIN))
     46 local call_func = lex:tag(lexer.FUNCTION_BUILTIN, 'call') * ws * func_name
     47 local func = lex:tag(lexer.OPERATOR, '$' * S('({')) * (call_func + builtin_func)
     48 lex:add_rule('function', func)
     49 
     50 -- Variables.
     51 local auto_var = lex:tag(lexer.OPERATOR, '$') * lex:tag(lexer.VARIABLE_BUILTIN, S('@%<?^+|*')) +
     52 	lex:tag(lexer.OPERATOR, '$(') * lex:tag(lexer.VARIABLE_BUILTIN, S('@%<?^+*') * S('DF'))
     53 local var_ref = lex:tag(lexer.OPERATOR, P('$(') + '${') * (builtin_var + var_name)
     54 local var = auto_var + var_ref
     55 lex:add_rule('variable', var)
     56 
     57 -- Comments.
     58 lex:add_rule('comment', lex:tag(lexer.COMMENT, lexer.to_eol('#')))
     59 
     60 -- Embedded Bash in target rules.
     61 local bash = lexer.load('bash')
     62 bash:modify_rule('variable',
     63 	lex:tag(lexer.VARIABLE, '$$' * word) + func + var + bash:get_rule('variable'))
     64 local bash_start_rule = lex:tag(lexer.WHITESPACE, '\t') + lex:tag(lexer.OPERATOR, ';')
     65 local bash_end_rule = lex:tag(lexer.WHITESPACE, '\n')
     66 lex:embed(bash, bash_start_rule, bash_end_rule)
     67 -- Embedded Bash in $(shell ...) calls.
     68 local shell = lexer.load('bash', 'bash.shell')
     69 bash_start_rule = #P('$(shell') * func
     70 bash_end_rule = -B('\\') * lex:tag(lexer.OPERATOR, ')')
     71 lex:embed(shell, bash_start_rule, bash_end_rule)
     72 
     73 -- Word lists.
     74 lex:set_word_list(lexer.KEYWORD, {
     75 	'define', 'endef', -- multi-line
     76 	'else', 'endif', 'ifdef', 'ifeq', 'ifndef', 'ifneq', -- conditionals
     77 	'export', 'include', 'load', 'override', 'undefine', 'unexport', 'vpath', -- directives
     78 	'private', --
     79 	'if', 'elseif', 'elseifdef', 'elseifndef' -- non-Make conditionals
     80 })
     81 
     82 lex:set_word_list('special_targets', {
     83 	'DEFAULT', 'DELETE_ON_ERROR', 'EXPORT_ALL_VARIABLES', 'IGNORE', 'INTERMEDIATE',
     84 	'LOW_RESOLUTION_TIME', 'NOTPARALLEL', 'ONESHELL', 'PHONY', 'POSIX', 'PRECIOUS', 'SECONDARY',
     85 	'SECONDEXPANSION', 'SILENT', 'SUFFIXES'
     86 })
     87 
     88 lex:set_word_list(lexer.VARIABLE_BUILTIN, {
     89 	-- Special.
     90 	'.DEFAULT_GOAL', '.FEATURES', '.INCLUDE_DIRS', '.LIBPATTERNS', '.LOADED', '.RECIPEPREFIX',
     91 	'.SHELLFLAGS', '.SHELLSTATUS', '.VARIABLES', --
     92 	'COMSPEC', 'MAKESHELL', 'SHELL', -- choosing the shell
     93 	'GPATH', 'VPATH', -- search
     94 	-- Make.
     95 	'MAKE', 'MAKECMDGOALS', 'MAKEFILES', 'MAKEFILE_LIST', 'MAKEFLAGS', 'MAKELEVEL', 'MAKEOVERRIDES',
     96 	'MAKE_RESTARTS', 'MAKE_TERMERR', 'MAKE_TERMOUT', 'MFLAGS',
     97 	-- Other.
     98 	'CURDIR', 'OUTPUT_OPTION', 'SUFFIXES',
     99 	-- Implicit.
    100 	'AR', 'ARFLAGS', 'AS', 'ASFLAGS', 'CC', 'CFLAGS', 'CO', 'COFLAGS', 'CPP', 'CPPFLAGS', 'CTANGLE',
    101 	'CWEAVE', 'CXX', 'CXXFLAGS', 'FC', 'FFLAGS', 'GET', 'GFLAGS', 'LDFLAGS', 'LDLIBS', 'LEX',
    102 	'LFLAGS', 'LINT', 'LINTFLAGS', 'M2C', 'MAKEINFO', 'PC', 'PFLAGS', 'RFLAGS', 'RM', 'TANGLE', 'TEX',
    103 	'TEXI2DVI', 'WEAVE', 'YACC', 'YFLAGS', --
    104 	'bindir', 'DESTDIR', 'exec_prefix', 'libexecdir', 'prefix', 'sbindir' -- directory
    105 })
    106 
    107 lex:set_word_list(lexer.FUNCTION_BUILTIN, {
    108 	-- Filename.
    109 	'abspath', 'addprefix', 'addsuffix', 'basename', 'dir', 'join', 'notdir', 'realpath', 'suffix',
    110 	'wildcard', --
    111 	'and', 'if', 'or', -- conditional
    112 	'error', 'info', 'warning', -- control
    113 	'filter', 'filter-out', 'findstring', 'firstword', 'lastword', 'patsubst', 'sort', 'strip',
    114 	-- Text.
    115 	'subst', 'word', 'wordlist', 'words', --
    116 	'call', 'eval', 'file', 'flavor', 'foreach', 'origin', 'shell', 'value' -- other
    117 })
    118 
    119 lexer.property['scintillua.comment'] = '#'
    120 
    121 return lex