aboutsummaryrefslogtreecommitdiff
path: root/lua/lexers/systemd.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/lexers/systemd.lua')
-rw-r--r--lua/lexers/systemd.lua540
1 files changed, 115 insertions, 425 deletions
diff --git a/lua/lexers/systemd.lua b/lua/lexers/systemd.lua
index 5f9e618..8557a70 100644
--- a/lua/lexers/systemd.lua
+++ b/lua/lexers/systemd.lua
@@ -1,443 +1,133 @@
--- Copyright 2016 Christian Hesse
+-- Copyright 2016-2022 Christian Hesse. See LICENSE.
-- systemd unit file LPeg lexer.
-local l = require('lexer')
-local token, word_match = l.token, l.word_match
-local P, R, S = lpeg.P, lpeg.R, lpeg.S
+local lexer = require('lexer')
+local token, word_match = lexer.token, lexer.word_match
+local P, S = lpeg.P, lpeg.S
-local M = {_NAME = 'systemd'}
+local lex = lexer.new('systemd', {lex_by_line = true})
-- Whitespace.
-local ws = token(l.WHITESPACE, l.space^1)
-
--- Comments.
-local comment = token(l.COMMENT, l.starts_line(S(';#')) * l.nonnewline^0)
-
--- Strings.
-local sq_str = l.delimited_range("'")
-local dq_str = l.delimited_range('"')
-local section_word = word_match{
- 'Automount',
- 'BusName',
- 'Install',
- 'Mount',
- 'Path',
- 'Service',
- 'Service',
- 'Socket',
- 'Timer',
- 'Unit'
-}
-local string = token(l.STRING, sq_str + dq_str + '[' * section_word * ']')
-
--- Numbers.
-local dec = l.digit^1 * ('_' * l.digit^1)^0
-local oct_num = '0' * S('01234567_')^1
-local integer = S('+-')^-1 * (l.hex_num + oct_num + dec)
-local number = token(l.NUMBER, (l.float + integer))
+lex:add_rule('whitespace', token(lexer.WHITESPACE, lexer.space^1))
-- Keywords.
-local keyword = token(l.KEYWORD, word_match({
- -- boolean values
- 'true',
- 'false',
- 'on',
- 'off',
- 'yes',
- 'no',
-
- -- service types
- 'forking',
- 'simple',
- 'oneshot',
- 'dbus',
- 'notify',
- 'idle',
-
- -- special system units
- 'basic.target',
- 'ctrl-alt-del.target',
- 'cryptsetup.target',
- 'dbus.service',
- 'dbus.socket',
- 'default.target',
- 'display-manager.service',
- 'emergency.target',
- 'exit.target',
- 'final.target',
- 'getty.target',
- 'graphical.target',
- 'hibernate.target',
- 'hybrid-sleep.target',
- 'halt.target',
- 'initrd-fs.target',
- 'kbrequest.target',
- 'kexec.target',
- 'local-fs.target',
- 'multi-user.target',
- 'network-online.target',
- 'paths.target',
- 'poweroff.target',
- 'reboot.target',
- 'remote-fs.target',
- 'rescue.target',
- 'initrd-root-fs.target',
- 'runlevel2.target',
- 'runlevel3.target',
- 'runlevel4.target',
- 'runlevel5.target',
- 'shutdown.target',
- 'sigpwr.target',
- 'sleep.target',
- 'slices.target',
- 'sockets.target',
- 'suspend.target',
- 'swap.target',
- 'sysinit.target',
- 'syslog.socket',
- 'system-update.target',
- 'timers.target',
- 'umount.target',
-
- -- special system units for devices
- 'bluetooth.target',
- 'printer.target',
- 'smartcard.target',
- 'sound.target',
-
- -- special passive system units
- 'cryptsetup-pre.target',
- 'local-fs-pre.target',
- 'network.target',
- 'network-pre.target',
- 'nss-lookup.target',
- 'nss-user-lookup.target',
- 'remote-fs-pre.target',
- 'rpcbind.target',
+lex:add_rule('keyword', token(lexer.KEYWORD, word_match{
+ -- Boolean values.
+ 'true', 'false', 'on', 'off', 'yes', 'no',
+ -- Service types.
+ 'forking', 'simple', 'oneshot', 'dbus', 'notify', 'idle',
+ -- Special system units.
+ 'basic.target', 'ctrl-alt-del.target', 'cryptsetup.target', 'dbus.service', 'dbus.socket',
+ 'default.target', 'display-manager.service', 'emergency.target', 'exit.target', 'final.target',
+ 'getty.target', 'graphical.target', 'hibernate.target', 'hybrid-sleep.target', 'halt.target',
+ 'initrd-fs.target', 'kbrequest.target', 'kexec.target', 'local-fs.target', 'multi-user.target',
+ 'network-online.target', 'paths.target', 'poweroff.target', 'reboot.target', 'remote-fs.target',
+ 'rescue.target', 'initrd-root-fs.target', 'runlevel2.target', 'runlevel3.target',
+ 'runlevel4.target', 'runlevel5.target', 'shutdown.target', 'sigpwr.target', 'sleep.target',
+ 'slices.target', 'sockets.target', 'suspend.target', 'swap.target', 'sysinit.target',
+ 'syslog.socket', 'system-update.target', 'timers.target', 'umount.target',
+ -- Special system units for devices.
+ 'bluetooth.target', 'printer.target', 'smartcard.target', 'sound.target',
+ -- Special passive system units.
+ 'cryptsetup-pre.target', 'local-fs-pre.target', 'network.target', 'network-pre.target',
+ 'nss-lookup.target', 'nss-user-lookup.target', 'remote-fs-pre.target', 'rpcbind.target',
'time-sync.target',
-
- -- specail slice units
- '-.slice',
- 'system.slice',
- 'user.slice',
- 'machine.slice',
-
- -- environment variables
- 'PATH',
- 'LANG',
- 'USER',
- 'LOGNAME',
- 'HOME',
- 'SHELL',
- 'XDG_RUNTIME_DIR',
- 'XDG_SESSION_ID',
- 'XDG_SEAT',
- 'XDG_VTNR',
- 'MAINPID',
- 'MANAGERPID',
- 'LISTEN_FDS',
- 'LISTEN_PID',
- 'LISTEN_FDNAMES',
- 'NOTIFY_SOCKET',
- 'WATCHDOG_PID',
- 'WATCHDOG_USEC',
- 'TERM'
-}, '.-'))
+ -- Specail slice units.
+ '-.slice', 'system.slice', 'user.slice', 'machine.slice',
+ -- Environment variables.
+ 'PATH', 'LANG', 'USER', 'LOGNAME', 'HOME', 'SHELL', 'XDG_RUNTIME_DIR', 'XDG_SESSION_ID',
+ 'XDG_SEAT', 'XDG_VTNR', 'MAINPID', 'MANAGERPID', 'LISTEN_FDS', 'LISTEN_PID', 'LISTEN_FDNAMES',
+ 'NOTIFY_SOCKET', 'WATCHDOG_PID', 'WATCHDOG_USEC', 'TERM'
+}))
-- Options.
-local option_word = word_match{
- -- unit section options
- 'Description',
- 'Documentation',
- 'Requires',
- 'Requisite',
- 'Wants',
- 'BindsTo',
- 'PartOf',
- 'Conflicts',
- 'Before',
- 'After',
- 'OnFailure',
- 'PropagatesReloadTo',
- 'ReloadPropagatedFrom',
- 'JoinsNamespaceOf',
- 'RequiresMountsFor',
- 'OnFailureJobMode',
- 'IgnoreOnIsolate',
- 'StopWhenUnneeded',
- 'RefuseManualStart',
- 'RefuseManualStop',
- 'AllowIsolate',
- 'DefaultDependencies',
- 'JobTimeoutSec',
- 'JobTimeoutAction',
- 'JobTimeoutRebootArgument',
- 'StartLimitInterval',
- 'StartLimitBurst',
- 'StartLimitAction',
- 'RebootArgument',
- 'ConditionArchitecture',
- 'ConditionVirtualization',
- 'ConditionHost',
- 'ConditionKernelCommandLine',
- 'ConditionSecurity',
- 'ConditionCapability',
- 'ConditionACPower',
- 'ConditionNeedsUpdate',
- 'ConditionFirstBoot',
- 'ConditionPathExists',
- 'ConditionPathExistsGlob',
- 'ConditionPathIsDirectory',
- 'ConditionPathIsSymbolicLink',
- 'ConditionPathIsMountPoint',
- 'ConditionPathIsReadWrite',
- 'ConditionDirectoryNotEmpty',
- 'ConditionFileNotEmpty',
- 'ConditionFileIsExecutable',
- 'AssertArchitecture',
- 'AssertVirtualization',
- 'AssertHost',
- 'AssertKernelCommandLine',
- 'AssertSecurity',
- 'AssertCapability',
- 'AssertACPower',
- 'AssertNeedsUpdate',
- 'AssertFirstBoot',
- 'AssertPathExists',
- 'AssertPathExistsGlob',
- 'AssertPathIsDirectory',
- 'AssertPathIsSymbolicLink',
- 'AssertPathIsMountPoint',
- 'AssertPathIsReadWrite',
- 'AssertDirectoryNotEmpty',
- 'AssertFileNotEmpty',
- 'AssertFileIsExecutable',
- 'SourcePath',
-
- -- install section options
- 'Alias',
- 'WantedBy',
- 'RequiredBy',
- 'Also',
- 'DefaultInstance',
-
- -- service section options
- 'Type',
- 'RemainAfterExit',
- 'GuessMainPID',
- 'PIDFile',
- 'BusName',
- 'BusPolicy',
- 'ExecStart',
- 'ExecStartPre',
- 'ExecStartPost',
- 'ExecReload',
- 'ExecStop',
- 'ExecStopPost',
- 'RestartSec',
- 'TimeoutStartSec',
- 'TimeoutStopSec',
- 'TimeoutSec',
- 'RuntimeMaxSec',
- 'WatchdogSec',
- 'Restart',
- 'SuccessExitStatus',
- 'RestartPreventExitStatus',
- 'RestartForceExitStatus',
- 'PermissionsStartOnly',
- 'RootDirectoryStartOnly',
- 'NonBlocking',
- 'NotifyAccess',
- 'Sockets',
- 'FailureAction',
- 'FileDescriptorStoreMax',
- 'USBFunctionDescriptors',
- 'USBFunctionStrings',
-
- -- socket section options
- 'ListenStream',
- 'ListenDatagram',
- 'ListenSequentialPacket',
- 'ListenFIFO',
- 'ListenSpecial',
- 'ListenNetlink',
- 'ListenMessageQueue',
- 'ListenUSBFunction',
- 'SocketProtocol',
- 'BindIPv6Only',
- 'Backlog',
- 'BindToDevice',
- 'SocketUser',
- 'SocketGroup',
- 'SocketMode',
- 'DirectoryMode',
- 'Accept',
- 'Writable',
- 'MaxConnections',
- 'KeepAlive',
- 'KeepAliveTimeSec',
- 'KeepAliveIntervalSec',
- 'KeepAliveProbes',
- 'NoDelay',
- 'Priority',
- 'DeferAcceptSec',
- 'ReceiveBuffer',
- 'SendBuffer',
- 'IPTOS',
- 'IPTTL',
- 'Mark',
- 'ReusePort',
- 'SmackLabel',
- 'SmackLabelIPIn',
- 'SmackLabelIPOut',
- 'SELinuxContextFromNet',
- 'PipeSize',
- 'MessageQueueMaxMessages',
- 'MessageQueueMessageSize',
- 'FreeBind',
- 'Transparent',
- 'Broadcast',
- 'PassCredentials',
- 'PassSecurity',
- 'TCPCongestion',
- 'ExecStartPre',
- 'ExecStartPost',
- 'ExecStopPre',
- 'ExecStopPost',
- 'TimeoutSec',
- 'Service',
- 'RemoveOnStop',
- 'Symlinks',
- 'FileDescriptorName',
+lex:add_rule('option', token(lexer.PREPROCESSOR, word_match{
+ -- Unit section.
+ 'Description', 'Documentation', 'Requires', 'Requisite', 'Wants', 'BindsTo', 'PartOf',
+ 'Conflicts', 'Before', 'After', 'OnFailure', 'PropagatesReloadTo', 'ReloadPropagatedFrom',
+ 'JoinsNamespaceOf', 'RequiresMountsFor', 'OnFailureJobMode', 'IgnoreOnIsolate',
+ 'StopWhenUnneeded', 'RefuseManualStart', 'RefuseManualStop', 'AllowIsolate',
+ 'DefaultDependencies', 'JobTimeoutSec', 'JobTimeoutAction', 'JobTimeoutRebootArgument',
+ 'StartLimitInterval', 'StartLimitBurst', 'StartLimitAction', 'RebootArgument',
+ 'ConditionArchitecture', 'ConditionVirtualization', 'ConditionHost', 'ConditionKernelCommandLine',
+ 'ConditionSecurity', 'ConditionCapability', 'ConditionACPower', 'ConditionNeedsUpdate',
+ 'ConditionFirstBoot', 'ConditionPathExists', 'ConditionPathExistsGlob',
+ 'ConditionPathIsDirectory', 'ConditionPathIsSymbolicLink', 'ConditionPathIsMountPoint',
+ 'ConditionPathIsReadWrite', 'ConditionDirectoryNotEmpty', 'ConditionFileNotEmpty',
+ 'ConditionFileIsExecutable', 'AssertArchitecture', 'AssertVirtualization', 'AssertHost',
+ 'AssertKernelCommandLine', 'AssertSecurity', 'AssertCapability', 'AssertACPower',
+ 'AssertNeedsUpdate', 'AssertFirstBoot', 'AssertPathExists', 'AssertPathExistsGlob',
+ 'AssertPathIsDirectory', 'AssertPathIsSymbolicLink', 'AssertPathIsMountPoint',
+ 'AssertPathIsReadWrite', 'AssertDirectoryNotEmpty', 'AssertFileNotEmpty',
+ 'AssertFileIsExecutable', 'SourcePath',
+ -- Install section.
+ 'Alias', 'WantedBy', 'RequiredBy', 'Also', 'DefaultInstance',
+ -- Service section.
+ 'Type', 'RemainAfterExit', 'GuessMainPID', 'PIDFile', 'BusName', 'BusPolicy', 'ExecStart',
+ 'ExecStartPre', 'ExecStartPost', 'ExecReload', 'ExecStop', 'ExecStopPost', 'RestartSec',
+ 'TimeoutStartSec', 'TimeoutStopSec', 'TimeoutSec', 'RuntimeMaxSec', 'WatchdogSec', 'Restart',
+ 'SuccessExitStatus', 'RestartPreventExitStatus', 'RestartForceExitStatus', 'PermissionsStartOnly',
+ 'RootDirectoryStartOnly', 'NonBlocking', 'NotifyAccess', 'Sockets', 'FailureAction',
+ 'FileDescriptorStoreMax', 'USBFunctionDescriptors', 'USBFunctionStrings',
+ -- Socket section.
+ 'ListenStream', 'ListenDatagram', 'ListenSequentialPacket', 'ListenFIFO', 'ListenSpecial',
+ 'ListenNetlink', 'ListenMessageQueue', 'ListenUSBFunction', 'SocketProtocol', 'BindIPv6Only',
+ 'Backlog', 'BindToDevice', 'SocketUser', 'SocketGroup', 'SocketMode', 'DirectoryMode', 'Accept',
+ 'Writable', 'MaxConnections', 'KeepAlive', 'KeepAliveTimeSec', 'KeepAliveIntervalSec',
+ 'KeepAliveProbes', 'NoDelay', 'Priority', 'DeferAcceptSec', 'ReceiveBuffer', 'SendBuffer',
+ 'IPTOS', 'IPTTL', 'Mark', 'ReusePort', 'SmackLabel', 'SmackLabelIPIn', 'SmackLabelIPOut',
+ 'SELinuxContextFromNet', 'PipeSize', 'MessageQueueMaxMessages', 'MessageQueueMessageSize',
+ 'FreeBind', 'Transparent', 'Broadcast', 'PassCredentials', 'PassSecurity', 'TCPCongestion',
+ 'ExecStartPre', 'ExecStartPost', 'ExecStopPre', 'ExecStopPost', 'TimeoutSec', 'Service',
+ 'RemoveOnStop', 'Symlinks', 'FileDescriptorName',
+ -- Mount section.
+ 'What', 'Where', 'Type', 'Options', 'SloppyOptions', 'DirectoryMode', 'TimeoutSec',
+ -- Path section.
+ 'PathExists', 'PathExistsGlob', 'PathChanged', 'PathModified', 'DirectoryNotEmpty', 'Unit',
+ 'MakeDirectory', 'DirectoryMode',
+ -- Timer section.
+ 'OnActiveSec', 'OnBootSec', 'OnStartupSec', 'OnUnitActiveSec', 'OnUnitInactiveSec', 'OnCalendar',
+ 'AccuracySec', 'RandomizedDelaySec', 'Unit', 'Persistent', 'WakeSystem', 'RemainAfterElapse',
+ -- Exec section.
+ 'WorkingDirectory', 'RootDirectory', 'User', 'Group', 'SupplementaryGroups', 'Nice',
+ 'OOMScoreAdjust', 'IOSchedulingClass', 'IOSchedulingPriority', 'CPUSchedulingPolicy',
+ 'CPUSchedulingPriority', 'CPUSchedulingResetOnFork', 'CPUAffinity', 'UMask', 'Environment',
+ 'EnvironmentFile', 'PassEnvironment', 'StandardInput', 'StandardOutput', 'StandardError',
+ 'TTYPath', 'TTYReset', 'TTYVHangup', 'TTYVTDisallocate', 'SyslogIdentifier', 'SyslogFacility',
+ 'SyslogLevel', 'SyslogLevelPrefix', 'TimerSlackNSec', 'LimitCPU', 'LimitFSIZE', 'LimitDATA',
+ 'LimitSTACK', 'LimitCORE', 'LimitRSS', 'LimitNOFILE', 'LimitAS', 'LimitNPROC', 'LimitMEMLOCK',
+ 'LimitLOCKS', 'LimitSIGPENDING', 'LimitMSGQUEUE', 'LimitNICE', 'LimitRTPRIO', 'LimitRTTIME',
+ 'PAMName', 'CapabilityBoundingSet', 'AmbientCapabilities', 'SecureBits', 'Capabilities',
+ 'ReadWriteDirectories', 'ReadOnlyDirectories', 'InaccessibleDirectories', 'PrivateTmp',
+ 'PrivateDevices', 'PrivateNetwork', 'ProtectSystem', 'ProtectHome', 'MountFlags',
+ 'UtmpIdentifier', 'UtmpMode', 'SELinuxContext', 'AppArmorProfile', 'SmackProcessLabel',
+ 'IgnoreSIGPIPE', 'NoNewPrivileges', 'SystemCallFilter', 'SystemCallErrorNumber',
+ 'SystemCallArchitectures', 'RestrictAddressFamilies', 'Personality', 'RuntimeDirectory',
+ 'RuntimeDirectoryMode'
+}))
- -- mount section options
- 'What',
- 'Where',
- 'Type',
- 'Options',
- 'SloppyOptions',
- 'DirectoryMode',
- 'TimeoutSec',
+-- Identifiers.
+lex:add_rule('identifier', token(lexer.IDENTIFIER, (lexer.alpha + '_') * (lexer.alnum + S('_.'))^0))
- -- path section options
- 'PathExists',
- 'PathExistsGlob',
- 'PathChanged',
- 'PathModified',
- 'DirectoryNotEmpty',
- 'Unit',
- 'MakeDirectory',
- 'DirectoryMode',
+-- Strings.
+local sq_str = lexer.range("'")
+local dq_str = lexer.range('"')
+lex:add_rule('string', token(lexer.STRING, sq_str + dq_str))
- -- timer section options
- 'OnActiveSec',
- 'OnBootSec',
- 'OnStartupSec',
- 'OnUnitActiveSec',
- 'OnUnitInactiveSec',
- 'OnCalendar',
- 'AccuracySec',
- 'RandomizedDelaySec',
- 'Unit',
- 'Persistent',
- 'WakeSystem',
- 'RemainAfterElapse',
+-- Sections.
+lex:add_rule('section', token(lexer.LABEL, '[' *
+ word_match('Automount BusName Install Mount Path Service Service Socket Timer Unit') * ']'))
- -- exec section options
- 'WorkingDirectory',
- 'RootDirectory',
- 'User',
- 'Group',
- 'SupplementaryGroups',
- 'Nice',
- 'OOMScoreAdjust',
- 'IOSchedulingClass',
- 'IOSchedulingPriority',
- 'CPUSchedulingPolicy',
- 'CPUSchedulingPriority',
- 'CPUSchedulingResetOnFork',
- 'CPUAffinity',
- 'UMask',
- 'Environment',
- 'EnvironmentFile',
- 'PassEnvironment',
- 'StandardInput',
- 'StandardOutput',
- 'StandardError',
- 'TTYPath',
- 'TTYReset',
- 'TTYVHangup',
- 'TTYVTDisallocate',
- 'SyslogIdentifier',
- 'SyslogFacility',
- 'SyslogLevel',
- 'SyslogLevelPrefix',
- 'TimerSlackNSec',
- 'LimitCPU',
- 'LimitFSIZE',
- 'LimitDATA',
- 'LimitSTACK',
- 'LimitCORE',
- 'LimitRSS',
- 'LimitNOFILE',
- 'LimitAS',
- 'LimitNPROC',
- 'LimitMEMLOCK',
- 'LimitLOCKS',
- 'LimitSIGPENDING',
- 'LimitMSGQUEUE',
- 'LimitNICE',
- 'LimitRTPRIO',
- 'LimitRTTIME',
- 'PAMName',
- 'CapabilityBoundingSet',
- 'AmbientCapabilities',
- 'SecureBits',
- 'Capabilities',
- 'ReadWriteDirectories',
- 'ReadOnlyDirectories',
- 'InaccessibleDirectories',
- 'PrivateTmp',
- 'PrivateDevices',
- 'PrivateNetwork',
- 'ProtectSystem',
- 'ProtectHome',
- 'MountFlags',
- 'UtmpIdentifier',
- 'UtmpMode',
- 'SELinuxContext',
- 'AppArmorProfile',
- 'SmackProcessLabel',
- 'IgnoreSIGPIPE',
- 'NoNewPrivileges',
- 'SystemCallFilter',
- 'SystemCallErrorNumber',
- 'SystemCallArchitectures',
- 'RestrictAddressFamilies',
- 'Personality',
- 'RuntimeDirectory',
- 'RuntimeDirectoryMode'
-}
-local preproc = token(l.PREPROCESSOR, option_word)
+-- Comments.
+lex:add_rule('comment', token(lexer.COMMENT, lexer.starts_line(lexer.to_eol(S(';#')))))
--- Identifiers.
-local word = (l.alpha + '_') * (l.alnum + S('_.'))^0
-local identifier = token(l.IDENTIFIER, word)
+-- Numbers.
+local dec = lexer.digit^1 * ('_' * lexer.digit^1)^0
+local oct_num = '0' * S('01234567_')^1
+local integer = S('+-')^-1 * (lexer.hex_num + oct_num + dec)
+lex:add_rule('number', token(lexer.NUMBER, lexer.float + integer))
-- Operators.
-local operator = token(l.OPERATOR, '=')
-
-M._rules = {
- {'whitespace', ws},
- {'keyword', keyword},
- {'string', string},
- {'preproc', preproc},
- {'identifier', identifier},
- {'comment', comment},
- {'number', number},
- {'operator', operator},
-}
-
-M._LEXBYLINE = true
+lex:add_rule('operator', token(lexer.OPERATOR, '='))
-return M
+return lex