-- Copyright 2016 Christian Hesse
-- fstab 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 M = {_NAME = 'fstab'}

-- Whitespace.
local ws = token(l.WHITESPACE, l.space^1)

-- Comments.
local comment = token(l.COMMENT, l.starts_line('#') * l.nonnewline^0)

-- 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))

-- Keywords.
local keyword = token(l.KEYWORD, word_match({
  -- basic filesystem-independent mount options
  'async',
  'atime',
  'auto',
  'comment',
  'context',
  'defaults',
  'defcontext',
  'dev',
  'dirsync',
  'exec',
  'fscontext',
  'group',
  'iversion',
  'lazytime',
  'loud',
  'mand',
  '_netdev',
  'noatime',
  'noauto',
  'nodev',
  'nodiratime',
  'noexec',
  'nofail',
  'noiversion',
  'nolazytime',
  'nomand',
  'norelatime',
  'nostrictatime',
  'nosuid',
  'nouser',
  'owner',
  'relatime',
  'remount',
  'ro',
  'rootcontext',
  'rw',
  'silent',
  'strictatime',
  'suid',
  'sync',
  'user',
  'users',

  -- mount options for systemd, see systemd.mount(5)
  'x-systemd.automount',
  'x-systemd.device-timeout',
  'x-systemd.idle-timeout',
  'x-systemd.mount-timeout',
  'x-systemd.requires',
  'x-systemd.requires-mounts-for',
  'x-initrd.mount',

  -- mount options for adfs
  'uid',
  'gid',
  'ownmask',
  'othmask',

  -- mount options for affs
  'uid',
  'gid',
  'setuid',
  'setgid',
  'mode',
  'protect',
  'usemp',
  'verbose',
  'prefix',
  'volume',
  'reserved',
  'root',
  'bs',
  'grpquota',
  'noquota',
  'quota',
  'usrquota',

  -- mount options for btrfs
  'alloc_start',
  'autodefrag',
  'check_int',
  'check_int_data',
  'check_int_print_mask',
  'commit',
  'compress',
    'zlib',
    'lzo',
    'no',
  'compress-force',
  'degraded',
  'device',
  'discard',
  'enospc_debug',
  'fatal_errors',
    'bug',
    'panic',
  'flushoncommit',
  'inode_cache',
  'max_inline',
  'metadata_ratio',
  'noacl',
  'nobarrier',
  'nodatacow',
  'nodatasum',
  'notreelog',
  'recovery',
  'rescan_uuid_tree',
  'skip_balance',
  'nospace_cache',
  'clear_cache',
  'ssd',
  'nossd',
  'ssd_spread',
  'subvol',
  'subvolid',
  'subvolrootid',
  'thread_pool',
  'user_subvol_rm_allowed',

  -- mount options for devpts
  'uid',
  'gid',
  'mode',
  'newinstance',
  'ptmxmode',

  -- mount options for ext2
  'acl',
  'noacl',
  'bsddf',
  'minixdf',
  'check',
  'nocheck',
  'debug',
  'errors',
    'continue',
    'remount-ro',
    'panic',
  'grpid',
  'bsdgroups',
  'nogrpid',
  'sysvgroups',
  'grpquota',
  'noquota',
  'quota',
  'usrquota',
  'nouid32',
  'oldalloc',
  'orlov',
  'resgid',
  'resuid',
  'sb',
  'user_xattr',
  'nouser_xattr',

  -- mount options for ext3
  'journal',
    'update',
  'journal_dev',
  'journal_path',
  'norecoverynoload',
  'data',
    'journal',
    'ordered',
    'writeback',
  'data_err',
    'ignore',
    'abort',
  'barrier',
  'commit',
  'user_xattr',
  'acl',
  'usrjquota',
  'grpjquota',
  'jqfmt',

  -- mount options for ext4
  'journal_checksum',
  'journal_async_commit',
  'barrier',
  'nobarrier',
  'inode_readahead_blks',
  'stripe',
  'delalloc',
  'nodelalloc',
  'max_batch_time',
  'min_batch_time',
  'journal_ioprio',
  'abort',
  'auto_da_alloc',
  'noauto_da_alloc',
  'noinit_itable',
  'init_itable',
  'discard',
  'nodiscard',
  'nouid32',
  'block_validity',
  'noblock_validity',
  'dioread_lock',
  'dioread_nolock',
  'max_dir_size_kb',
  'i_version',

  -- mount options for fat (common part of msdos, umsdos and vfat)
  'blocksize',
  'uid',
  'gid',
  'umask',
  'dmask',
  'fmask',
  'allow_utime',
  'check',
    'relaxed',
    'normal',
    'strict',
  'codepage',
  'conv',
    'binary',
    'text',
    'auto',
  'cvf_format',
  'cvf_option',
  'debug',
  'discard',
  'dos1xfloppy',
  'errors',
    'panic',
    'continue',
    'remount-ro',
  'fat',
  'iocharset',
  'nfs',
    'stale_rw',
    'nostale_ro',
  'tz',
  'time_offset',
  'quiet',
  'rodir',
  'showexec',
  'sys_immutable',
  'flush',
  'usefree',
  'dots',
  'nodots',
  'dotsOK',

  -- mount options for hfs
  'creator',
  'type',
  'uid',
  'gid',
  'dir_umask',
  'file_umask',
  'umask',
  'session',
  'part',
  'quiet',

  -- mount options for hpfs
  'uid',
  'gid',
  'umask',
  'case',
    'lower',
    'asis',
  'conv',
    'binary',
    'text',
    'auto',
  'nocheck',

  -- mount options for iso9660
  'norock',
  'nojoliet',
  'check',
    'relaxed',
    'strict',
  'uid',
  'gid',
  'map',
    'normal',
    'offacorn',
  'mode',
  'unhide',
  'block',
  'conv',
    'auto',
    'binary',
    'mtext',
    'text',
  'cruft',
  'session',
  'sbsector',
  'iocharset',
  'utf8',

  -- mount options for jfs
  'iocharset',
  'resize',
  'nointegrity',
  'integrity',
  'errors',
    'continue',
    'remount-ro',
    'panic',
  'noquota',
  'quota',
  'usrquota',
  'grpquota',

  -- mount options for ntfs
  'iocharset',
  'nls',
  'utf8',
  'uni_xlate',
  'posix',
  'uid',
  'gid',
  'umask',

  -- mount options for overlay
  'lowerdir',
  'upperdir',
  'workdir',

  -- mount options for reiserfs
  'conv',
  'hash',
    'rupasov',
    'tea',
    'r5',
    'detect',
  'hashed_relocation',
  'no_unhashed_relocation',
  'noborder',
  'nolog',
  'notail',
  'replayonly',
  'resize',
  'user_xattr',
  'acl',
  'barrier',
    'none',
    'flush',

  -- mount options for tmpfs
  'size',
  'nr_blocks',
  'nr_inodes',
  'mode',
  'uid',
  'gid',
  'mpol',
    'default',
    'prefer',
    'bind',
    'interleave',

  -- mount options for ubifs
  'bulk_read',
  'no_bulk_read',
  'chk_data_crc',
  'no_chk_data_crc.',
  'compr',
    'none',
    'lzo',
    'zlib',

  -- mount options for udf
  'gid',
  'umask',
  'uid',
  'unhide',
  'undelete',
  'nostrict',
  'iocharset',
  'bs',
  'novrs',
  'session',
  'anchor',
  'volume',
  'partition',
  'lastblock',
  'fileset',
  'rootdir',

  -- mount options for ufs
  'ufstype',
     'old',
     '44bsd',
     'ufs2',
     '5xbsd',
     'sun',
     'sunx86',
     'hp',
     'nextstep',
     'nextstep-cd',
     'openstep',
  'onerror',
    'lock',
    'umount',
    'repair',

  -- mount options for vfat
  'uni_xlate',
  'posix',
  'nonumtail',
  'utf8',
  'shortname',
    'lower',
    'win95',
    'winnt',
    'mixed',

  -- mount options for usbfs
  'devuid',
  'devgid',
  'devmode',
  'busuid',
  'busgid',
  'busmode',
  'listuid',
  'listgid',
  'listmode',

  -- filesystems
  'adfs',
  'ados',
  'affs',
  'anon_inodefs',
  'atfs',
  'audiofs',
  'auto',
  'autofs',
  'bdev',
  'befs',
  'bfs',
  'btrfs',
  'binfmt_misc',
  'cd9660',
  'cfs',
  'cgroup',
  'cifs',
  'coda',
  'configfs',
  'cpuset',
  'cramfs',
  'devfs',
  'devpts',
  'devtmpfs',
  'e2compr',
  'efs',
  'ext2',
  'ext2fs',
  'ext3',
  'ext4',
  'fdesc',
  'ffs',
  'filecore',
  'fuse',
  'fuseblk',
  'fusectl',
  'hfs',
  'hpfs',
  'hugetlbfs',
  'iso9660',
  'jffs',
  'jffs2',
  'jfs',
  'kernfs',
  'lfs',
  'linprocfs',
  'mfs',
  'minix',
  'mqueue',
  'msdos',
  'ncpfs',
  'nfs',
  'nfsd',
  'nilfs2',
  'none',
  'ntfs',
  'null',
  'nwfs',
  'overlay',
  'ovlfs',
  'pipefs',
  'portal',
  'proc',
  'procfs',
  'pstore',
  'ptyfs',
  'qnx4',
  'reiserfs',
  'ramfs',
  'romfs',
  'securityfs',
  'shm',
  'smbfs',
  'squashfs',
  'sockfs',
  'sshfs',
  'std',
  'subfs',
  'swap',
  'sysfs',
  'sysv',
  'tcfs',
  'tmpfs',
  'udf',
  'ufs',
  'umap',
  'umsdos',
  'union',
  'usbfs',
  'userfs',
  'vfat',
  'vs3fs',
  'vxfs',
  'wrapfs',
  'wvfs',
  'xenfs',
  'xfs',
  'zisofs',
}, '.-'))

-- Identifiers.
local word = (l.alpha + '_') * (l.alnum + S('_.'))^0
local identifier = token(l.IDENTIFIER, word)

-- Operators.
local operator = token(l.OPERATOR, S('=,'))

M._rules = {
  {'whitespace', ws},
  {'keyword', keyword},
  {'identifier', identifier},
  {'comment', comment},
  {'number', number},
  {'operator', operator},
}

M._LEXBYLINE = true

return M
