91 lines
3.4 KiB
Lua
Executable File
91 lines
3.4 KiB
Lua
Executable File
-- Copyright 2006-2019 Mitchell mitchell.att.foicica.com. See License.txt.
|
|
-- Makefile LPeg lexer.
|
|
|
|
local lexer = require('lexer')
|
|
local token, word_match = lexer.token, lexer.word_match
|
|
local P, R, S = lpeg.P, lpeg.R, lpeg.S
|
|
|
|
local lex = lexer.new('makefile', {lex_by_line = true})
|
|
|
|
-- Whitespace.
|
|
local ws = token(lexer.WHITESPACE, lexer.space^1)
|
|
lex:add_rule('whitespace', ws)
|
|
|
|
-- Keywords.
|
|
lex:add_rule('keyword', token(lexer.KEYWORD, P('!')^-1 * word_match([[
|
|
-- GNU Make conditionals.
|
|
ifeq ifneq ifdef ifndef else endif
|
|
-- Other conditionals.
|
|
if elseif elseifdef elseifndef
|
|
-- Directives and other keywords.
|
|
define endef export include override private undefine unexport vpath
|
|
]], true)))
|
|
|
|
-- Targets.
|
|
local special_target = token(lexer.CONSTANT, word_match[[
|
|
.PHONY .SUFFIXES .DEFAULT .PRECIOUS .INTERMEDIATE .SECONDARY .SECONDEXPANSION
|
|
.DELETE_ON_ERROR .IGNORE .LOW_RESOLUTION_TIME .SILENT .EXPORT_ALL_VARIABLES
|
|
.NOTPARALLEL .ONESHELL .POSIX
|
|
]])
|
|
local normal_target = token('target', (lexer.any - lexer.space - S(':#='))^1)
|
|
lex:add_rule('target', lexer.starts_line((special_target + normal_target) *
|
|
ws^0 * #(':' * -P('='))))
|
|
lex:add_style('target', lexer.STYLE_LABEL)
|
|
|
|
-- Variables.
|
|
local word_char = lexer.any - lexer.space - S(':#=(){}')
|
|
local assign = S(':+?')^-1 * '='
|
|
local expanded_var = '$' * ('(' * word_char^1 * ')' + '{' * word_char^1 * '}')
|
|
local auto_var = '$' * S('@%<?^+|*')
|
|
local special_var = word_match[[
|
|
MAKEFILE_LIST .DEFAULT_GOAL MAKE_RESTARTS .RECIPEPREFIX .VARIABLES .FEATURES
|
|
.INCLUDE_DIRS GPATH MAKECMDGOALS MAKESHELL SHELL VPATH
|
|
]] * #(ws^0 * assign)
|
|
local implicit_var = word_match[[
|
|
-- Some common variables.
|
|
AR AS CC CXX CPP FC M2C PC CO GET LEX YACC LINT MAKEINFO TEX TEXI2DVI WEAVE
|
|
CWEAVE TANGLE CTANGLE RM
|
|
-- Some common flag variables.
|
|
ARFLAGS ASFLAGS CFLAGS CXXFLAGS COFLAGS CPPFLAGS FFLAGS GFLAGS LDFLAGS LFLAGS
|
|
YFLAGS PFLAGS RFLAGS LINTFLAGS
|
|
-- Other.
|
|
DESTDIR MAKE MAKEFLAGS MAKEOVERRIDES MFLAGS
|
|
]] * #(ws^0 * assign)
|
|
local computed_var = token(lexer.OPERATOR, '$' * S('({')) *
|
|
token(lexer.FUNCTION, word_match[[
|
|
-- Functions for String Substitution and Analysis.
|
|
subst patsubst strip findstring filter filter-out sort word wordlist words
|
|
firstword lastword
|
|
-- Functions for File Names.
|
|
dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath
|
|
-- Functions for Conditionals.
|
|
if or and
|
|
-- Miscellaneous Functions.
|
|
foreach call value eval origin flavor shell
|
|
-- Functions That Control Make.
|
|
error warning info
|
|
]])
|
|
local variable = token(lexer.VARIABLE, expanded_var + auto_var + special_var +
|
|
implicit_var) + computed_var
|
|
lex:add_rule('variable', variable)
|
|
|
|
-- Operators.
|
|
lex:add_rule('operator', token(lexer.OPERATOR, assign + S(':$(){}')))
|
|
|
|
-- Identifiers.
|
|
lex:add_rule('identifier', token(lexer.IDENTIFIER, word_char^1))
|
|
|
|
-- Comments.
|
|
lex:add_rule('comment', token(lexer.COMMENT, '#' * lexer.nonnewline^0))
|
|
|
|
-- Embedded Bash.
|
|
local bash = lexer.load('bash')
|
|
bash:modify_rule('variable', token(lexer.VARIABLE, '$$' * word_char^1) +
|
|
bash:get_rule('variable') + variable)
|
|
local bash_start_rule = token(lexer.WHITESPACE, P('\t')) +
|
|
token(lexer.OPERATOR, P(';'))
|
|
local bash_end_rule = token(lexer.WHITESPACE, P('\n'))
|
|
lex:embed(bash, bash_start_rule, bash_end_rule)
|
|
|
|
return lex
|