From 3ca0ea8c352e2169fe08292421557721d770ed3d Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:44:32 +0200 Subject: [PATCH] fix(fstab): Improvements; Use antlr parser now --- server/handlers/fstab/Fstab.g4 | 76 ++ server/handlers/fstab/ast/error-listener.go | 45 + server/handlers/fstab/ast/fstab.go | 2 +- server/handlers/fstab/ast/fstab_fields.go | 98 +- server/handlers/fstab/ast/listener.go | 135 ++ server/handlers/fstab/ast/parser.go | 169 ++- server/handlers/fstab/ast/parser/Fstab.interp | 36 + server/handlers/fstab/ast/parser/Fstab.tokens | 10 + .../fstab/ast/parser/FstabLexer.interp | 44 + .../fstab/ast/parser/FstabLexer.tokens | 10 + .../fstab/ast/parser/fstab_base_listener.go | 64 + .../handlers/fstab/ast/parser/fstab_lexer.go | 143 ++ .../fstab/ast/parser/fstab_listener.go | 52 + .../handlers/fstab/ast/parser/fstab_parser.go | 1171 +++++++++++++++++ server/handlers/fstab/ast/parser_test.go | 11 +- server/handlers/fstab/fields/spec.go | 2 +- server/handlers/fstab/fstab_test.go | 30 + server/handlers/fstab/handlers/completions.go | 5 +- server/handlers/ssh_config/ast/listener.go | 14 +- server/update_antlr_parser.sh | 3 + 20 files changed, 2036 insertions(+), 84 deletions(-) create mode 100644 server/handlers/fstab/Fstab.g4 create mode 100644 server/handlers/fstab/ast/error-listener.go create mode 100644 server/handlers/fstab/ast/listener.go create mode 100644 server/handlers/fstab/ast/parser/Fstab.interp create mode 100644 server/handlers/fstab/ast/parser/Fstab.tokens create mode 100644 server/handlers/fstab/ast/parser/FstabLexer.interp create mode 100644 server/handlers/fstab/ast/parser/FstabLexer.tokens create mode 100644 server/handlers/fstab/ast/parser/fstab_base_listener.go create mode 100644 server/handlers/fstab/ast/parser/fstab_lexer.go create mode 100644 server/handlers/fstab/ast/parser/fstab_listener.go create mode 100644 server/handlers/fstab/ast/parser/fstab_parser.go diff --git a/server/handlers/fstab/Fstab.g4 b/server/handlers/fstab/Fstab.g4 new file mode 100644 index 0000000..e5c6b1e --- /dev/null +++ b/server/handlers/fstab/Fstab.g4 @@ -0,0 +1,76 @@ +grammar Fstab; + +entry + : + WHITESPACE? spec? + WHITESPACE? mountPoint? + WHITESPACE? fileSystem? + WHITESPACE? mountOptions? + WHITESPACE? freq? + WHITESPACE? pass? WHITESPACE? + EOF + ; + +spec + : QUOTED_STRING | STRING + ; + +mountPoint + : QUOTED_STRING | STRING + ; + +fileSystem + : ADFS | AFFS | BTRFS | EXFAT + // Still match unknown file systems + | STRING | QUOTED_STRING + ; + +mountOptions + : QUOTED_STRING | STRING + ; + +freq + : DIGITS + ; + +pass + : DIGITS + ; + +DIGITS + : [0-9]+ + ; + +WHITESPACE + : [ \t]+ + ; + +HASH + : '#' + ; + +STRING + : ~(' ' | '\t' | '#')+ + ; + +QUOTED_STRING + : '"' WHITESPACE? (STRING WHITESPACE)* STRING? ('"')? + ; + +// ///// Supported file systems ///// + +ADFS + : ('A' | 'a') ('D' | 'd') ('F' | 'f') ('S' | 's') + ; + +AFFS + : ('A' | 'a') ('F' | 'f') ('F' | 'f') ('S' | 's') + ; + +BTRFS + : ('B' | 'b') ('T' | 't') ('R' | 'r') ('F' | 'f') ('S' | 's') + ; + +EXFAT + : ('E' | 'e') ('X' | 'x') ('F' | 'f') ('A' | 'a') ('T' | 't') + ; diff --git a/server/handlers/fstab/ast/error-listener.go b/server/handlers/fstab/ast/error-listener.go new file mode 100644 index 0000000..74d4387 --- /dev/null +++ b/server/handlers/fstab/ast/error-listener.go @@ -0,0 +1,45 @@ +package ast + +import ( + "config-lsp/common" + + "github.com/antlr4-go/antlr/v4" +) + +type errorListenerContext struct { + line uint32 +} + +type errorListener struct { + *antlr.DefaultErrorListener + Errors []common.LSPError + context errorListenerContext +} + +func (d *errorListener) SyntaxError( + recognizer antlr.Recognizer, + offendingSymbol interface{}, + _ int, + character int, + message string, + error antlr.RecognitionException, +) { + line := d.context.line + d.Errors = append(d.Errors, common.LSPError{ + Range: common.CreateSingleCharRange(uint32(line), uint32(character)), + Err: common.SyntaxError{ + Message: message, + }, + }) +} + +func createErrorListener( + line uint32, +) errorListener { + return errorListener{ + Errors: make([]common.LSPError, 0), + context: errorListenerContext{ + line: line, + }, + } +} diff --git a/server/handlers/fstab/ast/fstab.go b/server/handlers/fstab/ast/fstab.go index 125e624..8286ba0 100644 --- a/server/handlers/fstab/ast/fstab.go +++ b/server/handlers/fstab/ast/fstab.go @@ -33,7 +33,7 @@ type FstabFields struct { } type FstabEntry struct { - Fields FstabFields + Fields *FstabFields } type FstabConfig struct { diff --git a/server/handlers/fstab/ast/fstab_fields.go b/server/handlers/fstab/ast/fstab_fields.go index 468f625..77679b5 100644 --- a/server/handlers/fstab/ast/fstab_fields.go +++ b/server/handlers/fstab/ast/fstab_fields.go @@ -17,30 +17,118 @@ import ( // return entry.(*FstabEntry) // } +// LABEL=test ext4 defaults 0 0 func (e FstabEntry) GetFieldAtPosition(position common.Position) FstabFieldName { - if e.Fields.Spec == nil || (e.Fields.Spec.ContainsPosition(position)) { + // No fields defined, empty line + if e.Fields.Spec == nil && e.Fields.MountPoint == nil && e.Fields.FilesystemType == nil && e.Fields.Options == nil && e.Fields.Freq == nil && e.Fields.Pass == nil { return FstabFieldSpec } - if e.Fields.MountPoint == nil || (e.Fields.MountPoint.ContainsPosition(position)) { + // First, try if out of the existing fields the user wants to edit one of them + + if e.Fields.Spec != nil && e.Fields.Spec.ContainsPosition(position) { + return FstabFieldSpec + } + if e.Fields.MountPoint != nil && e.Fields.MountPoint.ContainsPosition(position) { + return FstabFieldMountPoint + } + if e.Fields.FilesystemType != nil && e.Fields.FilesystemType.ContainsPosition(position) { + return FstabFieldFileSystemType + } + if e.Fields.Options != nil && e.Fields.Options.ContainsPosition(position) { + return FstabFieldOptions + } + if e.Fields.Freq != nil && e.Fields.Freq.ContainsPosition(position) { + return FstabFieldFreq + } + if e.Fields.Pass != nil && e.Fields.Pass.ContainsPosition(position) { + return FstabFieldPass + } + + // Okay let's try to fetch the field by assuming the user is typing from left to right normally + + if e.Fields.Spec != nil && e.Fields.Spec.IsPositionAfterEnd(position) && (e.Fields.MountPoint == nil || e.Fields.MountPoint.IsPositionBeforeEnd(position)) { return FstabFieldMountPoint } - if e.Fields.FilesystemType == nil || (e.Fields.FilesystemType.ContainsPosition(position)) { + if e.Fields.MountPoint != nil && e.Fields.MountPoint.IsPositionAfterEnd(position) && (e.Fields.FilesystemType == nil || e.Fields.FilesystemType.IsPositionBeforeEnd(position)) { return FstabFieldFileSystemType } - if e.Fields.Options == nil || (e.Fields.Options.ContainsPosition(position)) { + if e.Fields.FilesystemType != nil && e.Fields.FilesystemType.IsPositionAfterEnd(position) && (e.Fields.Options == nil || e.Fields.Options.IsPositionBeforeEnd(position)) { return FstabFieldOptions } - if e.Fields.Freq == nil || (e.Fields.Freq.ContainsPosition(position)) { + if e.Fields.Options != nil && e.Fields.Options.IsPositionAfterEnd(position) && (e.Fields.Freq == nil || e.Fields.Freq.IsPositionBeforeEnd(position)) { + return FstabFieldFreq + } + + if e.Fields.Freq != nil && e.Fields.Freq.IsPositionAfterEnd(position) && (e.Fields.Pass == nil || e.Fields.Pass.IsPositionBeforeEnd(position)) { + return FstabFieldPass + } + + // Okay shit no idea, let's just give whatever is missing + + if e.Fields.Spec == nil { + return FstabFieldSpec + } + + if e.Fields.MountPoint == nil { + return FstabFieldMountPoint + } + + if e.Fields.FilesystemType == nil { + return FstabFieldFileSystemType + } + + if e.Fields.Options == nil { + return FstabFieldOptions + } + + if e.Fields.Freq == nil { return FstabFieldFreq } return FstabFieldPass } +// LABEL=test /mnt/test btrfs subvol=backup,fat=32 [0] [0] +func (e FstabEntry) getCursorIndex() uint8 { + definedAmount := e.getDefinedFieldsAmount() + + switch definedAmount { + case 5: + + } + + return 0 +} + +func (e FstabEntry) getDefinedFieldsAmount() uint8 { + var definedAmount uint8 = 0 + + if e.Fields.Spec != nil { + definedAmount++ + } + if e.Fields.MountPoint != nil { + definedAmount++ + } + if e.Fields.FilesystemType != nil { + definedAmount++ + } + if e.Fields.Options != nil { + definedAmount++ + } + if e.Fields.Freq != nil { + definedAmount++ + } + if e.Fields.Pass != nil { + definedAmount++ + } + + return definedAmount +} + // Create a mount options field for the entry func (e FstabEntry) FetchMountOptionsField(includeDefaults bool) docvalues.DeprecatedValue { if e.Fields.FilesystemType == nil { diff --git a/server/handlers/fstab/ast/listener.go b/server/handlers/fstab/ast/listener.go new file mode 100644 index 0000000..a9f16b4 --- /dev/null +++ b/server/handlers/fstab/ast/listener.go @@ -0,0 +1,135 @@ +package ast + +import ( + "config-lsp/common" + "config-lsp/handlers/fstab/ast/parser" + + commonparser "config-lsp/common/parser" +) + +type fstabListenerContext struct { + line uint32 + currentEntry *FstabEntry +} + +func createListenerContext() *fstabListenerContext { + context := new(fstabListenerContext) + + return context +} + +type fstabParserListener struct { + *parser.BaseFstabListener + Config *FstabConfig + Errors []common.LSPError + fstabContext *fstabListenerContext +} + +func createListener( + config *FstabConfig, + context *fstabListenerContext, +) fstabParserListener { + return fstabParserListener{ + Config: config, + Errors: make([]common.LSPError, 0), + fstabContext: context, + } +} + +func (s *fstabParserListener) EnterEntry(ctx *parser.EntryContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + s.fstabContext.currentEntry = &FstabEntry{ + Fields: &FstabFields{ + LocationRange: location, + }, + } + + s.Config.Entries.Put( + s.fstabContext.line, + s.fstabContext.currentEntry, + ) +} + +func (s *fstabParserListener) ExitEntry(ctx *parser.EntryContext) { + s.fstabContext.currentEntry = nil +} + +func (s *fstabParserListener) EnterSpec(ctx *parser.SpecContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.Spec = &FstabField{ + Value: value, + LocationRange: location, + } +} + +func (s *fstabParserListener) EnterMountPoint(ctx *parser.MountPointContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.MountPoint = &FstabField{ + LocationRange: location, + Value: value, + } +} + +func (s *fstabParserListener) EnterFileSystem(ctx *parser.FileSystemContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.FilesystemType = &FstabField{ + LocationRange: location, + Value: value, + } +} + +func (s *fstabParserListener) EnterMountOptions(ctx *parser.MountOptionsContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.Options = &FstabField{ + LocationRange: location, + Value: value, + } +} + +func (s *fstabParserListener) EnterFreq(ctx *parser.FreqContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.Freq = &FstabField{ + LocationRange: location, + Value: value, + } +} + +func (s *fstabParserListener) EnterPass(ctx *parser.PassContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.fstabContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.fstabContext.currentEntry.Fields.Pass = &FstabField{ + LocationRange: location, + Value: value, + } +} diff --git a/server/handlers/fstab/ast/parser.go b/server/handlers/fstab/ast/parser.go index 03dd0bf..ac63d6f 100644 --- a/server/handlers/fstab/ast/parser.go +++ b/server/handlers/fstab/ast/parser.go @@ -3,9 +3,11 @@ package ast import ( "config-lsp/common" commonparser "config-lsp/common/parser" + "config-lsp/handlers/fstab/ast/parser" "config-lsp/utils" "regexp" + "github.com/antlr4-go/antlr/v4" "github.com/emirpasic/gods/maps/treemap" gods "github.com/emirpasic/gods/utils" @@ -25,14 +27,15 @@ func (c *FstabConfig) Clear() { var commentPattern = regexp.MustCompile(`^\s*#`) var emptyPattern = regexp.MustCompile(`^\s*$`) -var whitespacePattern = regexp.MustCompile(`\S+`) func (c *FstabConfig) Parse(input string) []common.LSPError { errors := make([]common.LSPError, 0) lines := utils.SplitIntoLines(input) + context := createListenerContext() for rawLineNumber, line := range lines { lineNumber := uint32(rawLineNumber) + context.line = lineNumber if emptyPattern.MatchString(line) { continue @@ -45,89 +48,121 @@ func (c *FstabConfig) Parse(input string) []common.LSPError { errors = append( errors, - c.parseStatement(lineNumber, line)..., + c.parseStatement(context, line)..., ) } return errors } +// TODO: Handle leading comments func (c *FstabConfig) parseStatement( - line uint32, + context *fstabListenerContext, input string, ) []common.LSPError { - fields := whitespacePattern.FindAllStringIndex(input, -1) + stream := antlr.NewInputStream(input) - if len(fields) == 0 { - return []common.LSPError{ - { - Range: common.LocationRange{ - Start: common.Location{ - Line: line, - Character: 0, - }, - End: common.Location{ - Line: line, - Character: 0, - }, - }, - }, - } - } + lexerErrorListener := createErrorListener(context.line) + lexer := parser.NewFstabLexer(stream) + lexer.RemoveErrorListeners() + lexer.AddErrorListener(&lexerErrorListener) - var spec *FstabField - var mountPoint *FstabField - var filesystemType *FstabField - var options *FstabField - var freq *FstabField - var pass *FstabField + tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) - switch len(fields) { - case 6: - pass = parseField(line, input, fields[5]) - fallthrough - case 5: - freq = parseField(line, input, fields[4]) - fallthrough - case 4: - options = parseField(line, input, fields[3]) - fallthrough - case 3: - filesystemType = parseField(line, input, fields[2]) - fallthrough - case 2: - mountPoint = parseField(line, input, fields[1]) - fallthrough - case 1: - spec = parseField(line, input, fields[0]) - } + parserErrorListener := createErrorListener(context.line) + antlrParser := parser.NewFstabParser(tokenStream) + antlrParser.RemoveErrorListeners() + antlrParser.AddErrorListener(&parserErrorListener) - fstabLine := &FstabEntry{ - Fields: FstabFields{ - LocationRange: common.LocationRange{ - Start: common.Location{ - Line: line, - Character: 0, - }, - End: common.Location{ - Line: line, - Character: uint32(len(input)), - }, - }, - Spec: spec, - MountPoint: mountPoint, - FilesystemType: filesystemType, - Options: options, - Freq: freq, - Pass: pass, - }, - } + listener := createListener(c, context) + antlr.ParseTreeWalkerDefault.Walk( + &listener, + antlrParser.Entry(), + ) - c.Entries.Put(line, fstabLine) + errors := lexerErrorListener.Errors + errors = append(errors, parserErrorListener.Errors...) + errors = append(errors, listener.Errors...) - return nil + return errors } +// func (c *FstabConfig) parseStatement( +// line uint32, +// input string, +// ) []common.LSPError { +// fields := whitespacePattern.FindAllStringIndex(input, -1) +// +// if len(fields) == 0 { +// return []common.LSPError{ +// { +// Range: common.LocationRange{ +// Start: common.Location{ +// Line: line, +// Character: 0, +// }, +// End: common.Location{ +// Line: line, +// Character: 0, +// }, +// }, +// }, +// } +// } +// +// var spec *FstabField +// var mountPoint *FstabField +// var filesystemType *FstabField +// var options *FstabField +// var freq *FstabField +// var pass *FstabField +// +// switch len(fields) { +// case 6: +// pass = parseField(line, input, fields[5]) +// fallthrough +// case 5: +// freq = parseField(line, input, fields[4]) +// fallthrough +// case 4: +// options = parseField(line, input, fields[3]) +// fallthrough +// case 3: +// filesystemType = parseField(line, input, fields[2]) +// fallthrough +// case 2: +// mountPoint = parseField(line, input, fields[1]) +// fallthrough +// case 1: +// spec = parseField(line, input, fields[0]) +// } +// +// fstabLine := &FstabEntry{ +// Fields: FstabFields{ +// LocationRange: common.LocationRange{ +// Start: common.Location{ +// Line: line, +// Character: 0, +// }, +// End: common.Location{ +// Line: line, +// Character: uint32(len(input)), +// }, +// }, +// Spec: spec, +// MountPoint: mountPoint, +// FilesystemType: filesystemType, +// Options: options, +// Freq: freq, +// Pass: pass, +// }, +// } +// +// c.Entries.Put(line, fstabLine) +// +// return nil +// } + func parseField( line uint32, input string, diff --git a/server/handlers/fstab/ast/parser/Fstab.interp b/server/handlers/fstab/ast/parser/Fstab.interp new file mode 100644 index 0000000..eae0ba8 --- /dev/null +++ b/server/handlers/fstab/ast/parser/Fstab.interp @@ -0,0 +1,36 @@ +token literal names: +null +null +null +'#' +null +null +null +null +null +null + +token symbolic names: +null +DIGITS +WHITESPACE +HASH +STRING +QUOTED_STRING +ADFS +AFFS +BTRFS +EXFAT + +rule names: +entry +spec +mountPoint +fileSystem +mountOptions +freq +pass + + +atn: +[4, 1, 9, 68, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 3, 0, 16, 8, 0, 1, 0, 3, 0, 19, 8, 0, 1, 0, 3, 0, 22, 8, 0, 1, 0, 3, 0, 25, 8, 0, 1, 0, 3, 0, 28, 8, 0, 1, 0, 3, 0, 31, 8, 0, 1, 0, 3, 0, 34, 8, 0, 1, 0, 3, 0, 37, 8, 0, 1, 0, 3, 0, 40, 8, 0, 1, 0, 3, 0, 43, 8, 0, 1, 0, 3, 0, 46, 8, 0, 1, 0, 3, 0, 49, 8, 0, 1, 0, 3, 0, 52, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 0, 0, 7, 0, 2, 4, 6, 8, 10, 12, 0, 2, 1, 0, 4, 5, 1, 0, 4, 9, 73, 0, 15, 1, 0, 0, 0, 2, 55, 1, 0, 0, 0, 4, 57, 1, 0, 0, 0, 6, 59, 1, 0, 0, 0, 8, 61, 1, 0, 0, 0, 10, 63, 1, 0, 0, 0, 12, 65, 1, 0, 0, 0, 14, 16, 5, 2, 0, 0, 15, 14, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 18, 1, 0, 0, 0, 17, 19, 3, 2, 1, 0, 18, 17, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 21, 1, 0, 0, 0, 20, 22, 5, 2, 0, 0, 21, 20, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 24, 1, 0, 0, 0, 23, 25, 3, 4, 2, 0, 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 5, 2, 0, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, 31, 3, 6, 3, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, 32, 34, 5, 2, 0, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 8, 4, 0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 39, 1, 0, 0, 0, 38, 40, 5, 2, 0, 0, 39, 38, 1, 0, 0, 0, 39, 40, 1, 0, 0, 0, 40, 42, 1, 0, 0, 0, 41, 43, 3, 10, 5, 0, 42, 41, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 45, 1, 0, 0, 0, 44, 46, 5, 2, 0, 0, 45, 44, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 48, 1, 0, 0, 0, 47, 49, 3, 12, 6, 0, 48, 47, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 51, 1, 0, 0, 0, 50, 52, 5, 2, 0, 0, 51, 50, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 54, 5, 0, 0, 1, 54, 1, 1, 0, 0, 0, 55, 56, 7, 0, 0, 0, 56, 3, 1, 0, 0, 0, 57, 58, 7, 0, 0, 0, 58, 5, 1, 0, 0, 0, 59, 60, 7, 1, 0, 0, 60, 7, 1, 0, 0, 0, 61, 62, 7, 0, 0, 0, 62, 9, 1, 0, 0, 0, 63, 64, 5, 1, 0, 0, 64, 11, 1, 0, 0, 0, 65, 66, 5, 1, 0, 0, 66, 13, 1, 0, 0, 0, 13, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51] \ No newline at end of file diff --git a/server/handlers/fstab/ast/parser/Fstab.tokens b/server/handlers/fstab/ast/parser/Fstab.tokens new file mode 100644 index 0000000..9584238 --- /dev/null +++ b/server/handlers/fstab/ast/parser/Fstab.tokens @@ -0,0 +1,10 @@ +DIGITS=1 +WHITESPACE=2 +HASH=3 +STRING=4 +QUOTED_STRING=5 +ADFS=6 +AFFS=7 +BTRFS=8 +EXFAT=9 +'#'=3 diff --git a/server/handlers/fstab/ast/parser/FstabLexer.interp b/server/handlers/fstab/ast/parser/FstabLexer.interp new file mode 100644 index 0000000..51b46ca --- /dev/null +++ b/server/handlers/fstab/ast/parser/FstabLexer.interp @@ -0,0 +1,44 @@ +token literal names: +null +null +null +'#' +null +null +null +null +null +null + +token symbolic names: +null +DIGITS +WHITESPACE +HASH +STRING +QUOTED_STRING +ADFS +AFFS +BTRFS +EXFAT + +rule names: +DIGITS +WHITESPACE +HASH +STRING +QUOTED_STRING +ADFS +AFFS +BTRFS +EXFAT + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 9, 76, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 1, 0, 4, 0, 21, 8, 0, 11, 0, 12, 0, 22, 1, 1, 4, 1, 26, 8, 1, 11, 1, 12, 1, 27, 1, 2, 1, 2, 1, 3, 4, 3, 33, 8, 3, 11, 3, 12, 3, 34, 1, 4, 1, 4, 3, 4, 39, 8, 4, 1, 4, 1, 4, 1, 4, 5, 4, 44, 8, 4, 10, 4, 12, 4, 47, 9, 4, 1, 4, 3, 4, 50, 8, 4, 1, 4, 3, 4, 53, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 0, 0, 9, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 1, 0, 12, 1, 0, 48, 57, 2, 0, 9, 9, 32, 32, 3, 0, 9, 9, 32, 32, 35, 35, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, 102, 2, 0, 83, 83, 115, 115, 2, 0, 66, 66, 98, 98, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 69, 69, 101, 101, 2, 0, 88, 88, 120, 120, 82, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 1, 20, 1, 0, 0, 0, 3, 25, 1, 0, 0, 0, 5, 29, 1, 0, 0, 0, 7, 32, 1, 0, 0, 0, 9, 36, 1, 0, 0, 0, 11, 54, 1, 0, 0, 0, 13, 59, 1, 0, 0, 0, 15, 64, 1, 0, 0, 0, 17, 70, 1, 0, 0, 0, 19, 21, 7, 0, 0, 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 2, 1, 0, 0, 0, 24, 26, 7, 1, 0, 0, 25, 24, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 4, 1, 0, 0, 0, 29, 30, 5, 35, 0, 0, 30, 6, 1, 0, 0, 0, 31, 33, 8, 2, 0, 0, 32, 31, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 32, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 8, 1, 0, 0, 0, 36, 38, 5, 34, 0, 0, 37, 39, 3, 3, 1, 0, 38, 37, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 45, 1, 0, 0, 0, 40, 41, 3, 7, 3, 0, 41, 42, 3, 3, 1, 0, 42, 44, 1, 0, 0, 0, 43, 40, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 49, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 48, 50, 3, 7, 3, 0, 49, 48, 1, 0, 0, 0, 49, 50, 1, 0, 0, 0, 50, 52, 1, 0, 0, 0, 51, 53, 5, 34, 0, 0, 52, 51, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 10, 1, 0, 0, 0, 54, 55, 7, 3, 0, 0, 55, 56, 7, 4, 0, 0, 56, 57, 7, 5, 0, 0, 57, 58, 7, 6, 0, 0, 58, 12, 1, 0, 0, 0, 59, 60, 7, 3, 0, 0, 60, 61, 7, 5, 0, 0, 61, 62, 7, 5, 0, 0, 62, 63, 7, 6, 0, 0, 63, 14, 1, 0, 0, 0, 64, 65, 7, 7, 0, 0, 65, 66, 7, 8, 0, 0, 66, 67, 7, 9, 0, 0, 67, 68, 7, 5, 0, 0, 68, 69, 7, 6, 0, 0, 69, 16, 1, 0, 0, 0, 70, 71, 7, 10, 0, 0, 71, 72, 7, 11, 0, 0, 72, 73, 7, 5, 0, 0, 73, 74, 7, 3, 0, 0, 74, 75, 7, 8, 0, 0, 75, 18, 1, 0, 0, 0, 8, 0, 22, 27, 34, 38, 45, 49, 52, 0] \ No newline at end of file diff --git a/server/handlers/fstab/ast/parser/FstabLexer.tokens b/server/handlers/fstab/ast/parser/FstabLexer.tokens new file mode 100644 index 0000000..9584238 --- /dev/null +++ b/server/handlers/fstab/ast/parser/FstabLexer.tokens @@ -0,0 +1,10 @@ +DIGITS=1 +WHITESPACE=2 +HASH=3 +STRING=4 +QUOTED_STRING=5 +ADFS=6 +AFFS=7 +BTRFS=8 +EXFAT=9 +'#'=3 diff --git a/server/handlers/fstab/ast/parser/fstab_base_listener.go b/server/handlers/fstab/ast/parser/fstab_base_listener.go new file mode 100644 index 0000000..0578f75 --- /dev/null +++ b/server/handlers/fstab/ast/parser/fstab_base_listener.go @@ -0,0 +1,64 @@ +// Code generated from Fstab.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Fstab + +import "github.com/antlr4-go/antlr/v4" + +// BaseFstabListener is a complete listener for a parse tree produced by FstabParser. +type BaseFstabListener struct{} + +var _ FstabListener = &BaseFstabListener{} + +// VisitTerminal is called when a terminal node is visited. +func (s *BaseFstabListener) VisitTerminal(node antlr.TerminalNode) {} + +// VisitErrorNode is called when an error node is visited. +func (s *BaseFstabListener) VisitErrorNode(node antlr.ErrorNode) {} + +// EnterEveryRule is called when any rule is entered. +func (s *BaseFstabListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} + +// ExitEveryRule is called when any rule is exited. +func (s *BaseFstabListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} + +// EnterEntry is called when production entry is entered. +func (s *BaseFstabListener) EnterEntry(ctx *EntryContext) {} + +// ExitEntry is called when production entry is exited. +func (s *BaseFstabListener) ExitEntry(ctx *EntryContext) {} + +// EnterSpec is called when production spec is entered. +func (s *BaseFstabListener) EnterSpec(ctx *SpecContext) {} + +// ExitSpec is called when production spec is exited. +func (s *BaseFstabListener) ExitSpec(ctx *SpecContext) {} + +// EnterMountPoint is called when production mountPoint is entered. +func (s *BaseFstabListener) EnterMountPoint(ctx *MountPointContext) {} + +// ExitMountPoint is called when production mountPoint is exited. +func (s *BaseFstabListener) ExitMountPoint(ctx *MountPointContext) {} + +// EnterFileSystem is called when production fileSystem is entered. +func (s *BaseFstabListener) EnterFileSystem(ctx *FileSystemContext) {} + +// ExitFileSystem is called when production fileSystem is exited. +func (s *BaseFstabListener) ExitFileSystem(ctx *FileSystemContext) {} + +// EnterMountOptions is called when production mountOptions is entered. +func (s *BaseFstabListener) EnterMountOptions(ctx *MountOptionsContext) {} + +// ExitMountOptions is called when production mountOptions is exited. +func (s *BaseFstabListener) ExitMountOptions(ctx *MountOptionsContext) {} + +// EnterFreq is called when production freq is entered. +func (s *BaseFstabListener) EnterFreq(ctx *FreqContext) {} + +// ExitFreq is called when production freq is exited. +func (s *BaseFstabListener) ExitFreq(ctx *FreqContext) {} + +// EnterPass is called when production pass is entered. +func (s *BaseFstabListener) EnterPass(ctx *PassContext) {} + +// ExitPass is called when production pass is exited. +func (s *BaseFstabListener) ExitPass(ctx *PassContext) {} diff --git a/server/handlers/fstab/ast/parser/fstab_lexer.go b/server/handlers/fstab/ast/parser/fstab_lexer.go new file mode 100644 index 0000000..abac890 --- /dev/null +++ b/server/handlers/fstab/ast/parser/fstab_lexer.go @@ -0,0 +1,143 @@ +// Code generated from Fstab.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/antlr4-go/antlr/v4" + "sync" + "unicode" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = sync.Once{} +var _ = unicode.IsLetter + +type FstabLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +var FstabLexerLexerStaticData struct { + once sync.Once + serializedATN []int32 + ChannelNames []string + ModeNames []string + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func fstablexerLexerInit() { + staticData := &FstabLexerLexerStaticData + staticData.ChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + } + staticData.ModeNames = []string{ + "DEFAULT_MODE", + } + staticData.LiteralNames = []string{ + "", "", "", "'#'", + } + staticData.SymbolicNames = []string{ + "", "DIGITS", "WHITESPACE", "HASH", "STRING", "QUOTED_STRING", "ADFS", + "AFFS", "BTRFS", "EXFAT", + } + staticData.RuleNames = []string{ + "DIGITS", "WHITESPACE", "HASH", "STRING", "QUOTED_STRING", "ADFS", "AFFS", + "BTRFS", "EXFAT", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 0, 9, 76, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 1, 0, 4, 0, 21, + 8, 0, 11, 0, 12, 0, 22, 1, 1, 4, 1, 26, 8, 1, 11, 1, 12, 1, 27, 1, 2, 1, + 2, 1, 3, 4, 3, 33, 8, 3, 11, 3, 12, 3, 34, 1, 4, 1, 4, 3, 4, 39, 8, 4, + 1, 4, 1, 4, 1, 4, 5, 4, 44, 8, 4, 10, 4, 12, 4, 47, 9, 4, 1, 4, 3, 4, 50, + 8, 4, 1, 4, 3, 4, 53, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, + 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, + 8, 1, 8, 1, 8, 0, 0, 9, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, + 8, 17, 9, 1, 0, 12, 1, 0, 48, 57, 2, 0, 9, 9, 32, 32, 3, 0, 9, 9, 32, 32, + 35, 35, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 70, 70, 102, + 102, 2, 0, 83, 83, 115, 115, 2, 0, 66, 66, 98, 98, 2, 0, 84, 84, 116, 116, + 2, 0, 82, 82, 114, 114, 2, 0, 69, 69, 101, 101, 2, 0, 88, 88, 120, 120, + 82, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, + 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, + 0, 0, 0, 17, 1, 0, 0, 0, 1, 20, 1, 0, 0, 0, 3, 25, 1, 0, 0, 0, 5, 29, 1, + 0, 0, 0, 7, 32, 1, 0, 0, 0, 9, 36, 1, 0, 0, 0, 11, 54, 1, 0, 0, 0, 13, + 59, 1, 0, 0, 0, 15, 64, 1, 0, 0, 0, 17, 70, 1, 0, 0, 0, 19, 21, 7, 0, 0, + 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, + 1, 0, 0, 0, 23, 2, 1, 0, 0, 0, 24, 26, 7, 1, 0, 0, 25, 24, 1, 0, 0, 0, + 26, 27, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 4, 1, 0, + 0, 0, 29, 30, 5, 35, 0, 0, 30, 6, 1, 0, 0, 0, 31, 33, 8, 2, 0, 0, 32, 31, + 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 32, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, + 35, 8, 1, 0, 0, 0, 36, 38, 5, 34, 0, 0, 37, 39, 3, 3, 1, 0, 38, 37, 1, + 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 45, 1, 0, 0, 0, 40, 41, 3, 7, 3, 0, 41, + 42, 3, 3, 1, 0, 42, 44, 1, 0, 0, 0, 43, 40, 1, 0, 0, 0, 44, 47, 1, 0, 0, + 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 49, 1, 0, 0, 0, 47, 45, + 1, 0, 0, 0, 48, 50, 3, 7, 3, 0, 49, 48, 1, 0, 0, 0, 49, 50, 1, 0, 0, 0, + 50, 52, 1, 0, 0, 0, 51, 53, 5, 34, 0, 0, 52, 51, 1, 0, 0, 0, 52, 53, 1, + 0, 0, 0, 53, 10, 1, 0, 0, 0, 54, 55, 7, 3, 0, 0, 55, 56, 7, 4, 0, 0, 56, + 57, 7, 5, 0, 0, 57, 58, 7, 6, 0, 0, 58, 12, 1, 0, 0, 0, 59, 60, 7, 3, 0, + 0, 60, 61, 7, 5, 0, 0, 61, 62, 7, 5, 0, 0, 62, 63, 7, 6, 0, 0, 63, 14, + 1, 0, 0, 0, 64, 65, 7, 7, 0, 0, 65, 66, 7, 8, 0, 0, 66, 67, 7, 9, 0, 0, + 67, 68, 7, 5, 0, 0, 68, 69, 7, 6, 0, 0, 69, 16, 1, 0, 0, 0, 70, 71, 7, + 10, 0, 0, 71, 72, 7, 11, 0, 0, 72, 73, 7, 5, 0, 0, 73, 74, 7, 3, 0, 0, + 74, 75, 7, 8, 0, 0, 75, 18, 1, 0, 0, 0, 8, 0, 22, 27, 34, 38, 45, 49, 52, + 0, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// FstabLexerInit initializes any static state used to implement FstabLexer. By default the +// static state used to implement the lexer is lazily initialized during the first call to +// NewFstabLexer(). You can call this function if you wish to initialize the static state ahead +// of time. +func FstabLexerInit() { + staticData := &FstabLexerLexerStaticData + staticData.once.Do(fstablexerLexerInit) +} + +// NewFstabLexer produces a new lexer instance for the optional input antlr.CharStream. +func NewFstabLexer(input antlr.CharStream) *FstabLexer { + FstabLexerInit() + l := new(FstabLexer) + l.BaseLexer = antlr.NewBaseLexer(input) + staticData := &FstabLexerLexerStaticData + l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + l.channelNames = staticData.ChannelNames + l.modeNames = staticData.ModeNames + l.RuleNames = staticData.RuleNames + l.LiteralNames = staticData.LiteralNames + l.SymbolicNames = staticData.SymbolicNames + l.GrammarFileName = "Fstab.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// FstabLexer tokens. +const ( + FstabLexerDIGITS = 1 + FstabLexerWHITESPACE = 2 + FstabLexerHASH = 3 + FstabLexerSTRING = 4 + FstabLexerQUOTED_STRING = 5 + FstabLexerADFS = 6 + FstabLexerAFFS = 7 + FstabLexerBTRFS = 8 + FstabLexerEXFAT = 9 +) diff --git a/server/handlers/fstab/ast/parser/fstab_listener.go b/server/handlers/fstab/ast/parser/fstab_listener.go new file mode 100644 index 0000000..730daae --- /dev/null +++ b/server/handlers/fstab/ast/parser/fstab_listener.go @@ -0,0 +1,52 @@ +// Code generated from Fstab.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Fstab + +import "github.com/antlr4-go/antlr/v4" + +// FstabListener is a complete listener for a parse tree produced by FstabParser. +type FstabListener interface { + antlr.ParseTreeListener + + // EnterEntry is called when entering the entry production. + EnterEntry(c *EntryContext) + + // EnterSpec is called when entering the spec production. + EnterSpec(c *SpecContext) + + // EnterMountPoint is called when entering the mountPoint production. + EnterMountPoint(c *MountPointContext) + + // EnterFileSystem is called when entering the fileSystem production. + EnterFileSystem(c *FileSystemContext) + + // EnterMountOptions is called when entering the mountOptions production. + EnterMountOptions(c *MountOptionsContext) + + // EnterFreq is called when entering the freq production. + EnterFreq(c *FreqContext) + + // EnterPass is called when entering the pass production. + EnterPass(c *PassContext) + + // ExitEntry is called when exiting the entry production. + ExitEntry(c *EntryContext) + + // ExitSpec is called when exiting the spec production. + ExitSpec(c *SpecContext) + + // ExitMountPoint is called when exiting the mountPoint production. + ExitMountPoint(c *MountPointContext) + + // ExitFileSystem is called when exiting the fileSystem production. + ExitFileSystem(c *FileSystemContext) + + // ExitMountOptions is called when exiting the mountOptions production. + ExitMountOptions(c *MountOptionsContext) + + // ExitFreq is called when exiting the freq production. + ExitFreq(c *FreqContext) + + // ExitPass is called when exiting the pass production. + ExitPass(c *PassContext) +} diff --git a/server/handlers/fstab/ast/parser/fstab_parser.go b/server/handlers/fstab/ast/parser/fstab_parser.go new file mode 100644 index 0000000..7cc9582 --- /dev/null +++ b/server/handlers/fstab/ast/parser/fstab_parser.go @@ -0,0 +1,1171 @@ +// Code generated from Fstab.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Fstab + +import ( + "fmt" + "strconv" + "sync" + + "github.com/antlr4-go/antlr/v4" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = strconv.Itoa +var _ = sync.Once{} + +type FstabParser struct { + *antlr.BaseParser +} + +var FstabParserStaticData struct { + once sync.Once + serializedATN []int32 + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func fstabParserInit() { + staticData := &FstabParserStaticData + staticData.LiteralNames = []string{ + "", "", "", "'#'", + } + staticData.SymbolicNames = []string{ + "", "DIGITS", "WHITESPACE", "HASH", "STRING", "QUOTED_STRING", "ADFS", + "AFFS", "BTRFS", "EXFAT", + } + staticData.RuleNames = []string{ + "entry", "spec", "mountPoint", "fileSystem", "mountOptions", "freq", + "pass", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 1, 9, 68, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, + 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 3, 0, 16, 8, 0, 1, 0, 3, 0, 19, 8, 0, 1, + 0, 3, 0, 22, 8, 0, 1, 0, 3, 0, 25, 8, 0, 1, 0, 3, 0, 28, 8, 0, 1, 0, 3, + 0, 31, 8, 0, 1, 0, 3, 0, 34, 8, 0, 1, 0, 3, 0, 37, 8, 0, 1, 0, 3, 0, 40, + 8, 0, 1, 0, 3, 0, 43, 8, 0, 1, 0, 3, 0, 46, 8, 0, 1, 0, 3, 0, 49, 8, 0, + 1, 0, 3, 0, 52, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, + 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 0, 0, 7, 0, 2, 4, 6, 8, 10, 12, + 0, 2, 1, 0, 4, 5, 1, 0, 4, 9, 73, 0, 15, 1, 0, 0, 0, 2, 55, 1, 0, 0, 0, + 4, 57, 1, 0, 0, 0, 6, 59, 1, 0, 0, 0, 8, 61, 1, 0, 0, 0, 10, 63, 1, 0, + 0, 0, 12, 65, 1, 0, 0, 0, 14, 16, 5, 2, 0, 0, 15, 14, 1, 0, 0, 0, 15, 16, + 1, 0, 0, 0, 16, 18, 1, 0, 0, 0, 17, 19, 3, 2, 1, 0, 18, 17, 1, 0, 0, 0, + 18, 19, 1, 0, 0, 0, 19, 21, 1, 0, 0, 0, 20, 22, 5, 2, 0, 0, 21, 20, 1, + 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 24, 1, 0, 0, 0, 23, 25, 3, 4, 2, 0, 24, + 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 5, 2, 0, + 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, 31, + 3, 6, 3, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, + 32, 34, 5, 2, 0, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, + 0, 0, 0, 35, 37, 3, 8, 4, 0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, + 39, 1, 0, 0, 0, 38, 40, 5, 2, 0, 0, 39, 38, 1, 0, 0, 0, 39, 40, 1, 0, 0, + 0, 40, 42, 1, 0, 0, 0, 41, 43, 3, 10, 5, 0, 42, 41, 1, 0, 0, 0, 42, 43, + 1, 0, 0, 0, 43, 45, 1, 0, 0, 0, 44, 46, 5, 2, 0, 0, 45, 44, 1, 0, 0, 0, + 45, 46, 1, 0, 0, 0, 46, 48, 1, 0, 0, 0, 47, 49, 3, 12, 6, 0, 48, 47, 1, + 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 51, 1, 0, 0, 0, 50, 52, 5, 2, 0, 0, 51, + 50, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 54, 5, 0, 0, + 1, 54, 1, 1, 0, 0, 0, 55, 56, 7, 0, 0, 0, 56, 3, 1, 0, 0, 0, 57, 58, 7, + 0, 0, 0, 58, 5, 1, 0, 0, 0, 59, 60, 7, 1, 0, 0, 60, 7, 1, 0, 0, 0, 61, + 62, 7, 0, 0, 0, 62, 9, 1, 0, 0, 0, 63, 64, 5, 1, 0, 0, 64, 11, 1, 0, 0, + 0, 65, 66, 5, 1, 0, 0, 66, 13, 1, 0, 0, 0, 13, 15, 18, 21, 24, 27, 30, + 33, 36, 39, 42, 45, 48, 51, + } + deserializer := antlr.NewATNDeserializer(nil) + staticData.atn = deserializer.Deserialize(staticData.serializedATN) + atn := staticData.atn + staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) + decisionToDFA := staticData.decisionToDFA + for index, state := range atn.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(state, index) + } +} + +// FstabParserInit initializes any static state used to implement FstabParser. By default the +// static state used to implement the parser is lazily initialized during the first call to +// NewFstabParser(). You can call this function if you wish to initialize the static state ahead +// of time. +func FstabParserInit() { + staticData := &FstabParserStaticData + staticData.once.Do(fstabParserInit) +} + +// NewFstabParser produces a new parser instance for the optional input antlr.TokenStream. +func NewFstabParser(input antlr.TokenStream) *FstabParser { + FstabParserInit() + this := new(FstabParser) + this.BaseParser = antlr.NewBaseParser(input) + staticData := &FstabParserStaticData + this.Interpreter = antlr.NewParserATNSimulator(this, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) + this.RuleNames = staticData.RuleNames + this.LiteralNames = staticData.LiteralNames + this.SymbolicNames = staticData.SymbolicNames + this.GrammarFileName = "Fstab.g4" + + return this +} + +// FstabParser tokens. +const ( + FstabParserEOF = antlr.TokenEOF + FstabParserDIGITS = 1 + FstabParserWHITESPACE = 2 + FstabParserHASH = 3 + FstabParserSTRING = 4 + FstabParserQUOTED_STRING = 5 + FstabParserADFS = 6 + FstabParserAFFS = 7 + FstabParserBTRFS = 8 + FstabParserEXFAT = 9 +) + +// FstabParser rules. +const ( + FstabParserRULE_entry = 0 + FstabParserRULE_spec = 1 + FstabParserRULE_mountPoint = 2 + FstabParserRULE_fileSystem = 3 + FstabParserRULE_mountOptions = 4 + FstabParserRULE_freq = 5 + FstabParserRULE_pass = 6 +) + +// IEntryContext is an interface to support dynamic dispatch. +type IEntryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + EOF() antlr.TerminalNode + AllWHITESPACE() []antlr.TerminalNode + WHITESPACE(i int) antlr.TerminalNode + Spec() ISpecContext + MountPoint() IMountPointContext + FileSystem() IFileSystemContext + MountOptions() IMountOptionsContext + Freq() IFreqContext + Pass() IPassContext + + // IsEntryContext differentiates from other interfaces. + IsEntryContext() +} + +type EntryContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyEntryContext() *EntryContext { + var p = new(EntryContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_entry + return p +} + +func InitEmptyEntryContext(p *EntryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_entry +} + +func (*EntryContext) IsEntryContext() {} + +func NewEntryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *EntryContext { + var p = new(EntryContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_entry + + return p +} + +func (s *EntryContext) GetParser() antlr.Parser { return s.parser } + +func (s *EntryContext) EOF() antlr.TerminalNode { + return s.GetToken(FstabParserEOF, 0) +} + +func (s *EntryContext) AllWHITESPACE() []antlr.TerminalNode { + return s.GetTokens(FstabParserWHITESPACE) +} + +func (s *EntryContext) WHITESPACE(i int) antlr.TerminalNode { + return s.GetToken(FstabParserWHITESPACE, i) +} + +func (s *EntryContext) Spec() ISpecContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISpecContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ISpecContext) +} + +func (s *EntryContext) MountPoint() IMountPointContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMountPointContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IMountPointContext) +} + +func (s *EntryContext) FileSystem() IFileSystemContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFileSystemContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IFileSystemContext) +} + +func (s *EntryContext) MountOptions() IMountOptionsContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IMountOptionsContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IMountOptionsContext) +} + +func (s *EntryContext) Freq() IFreqContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IFreqContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IFreqContext) +} + +func (s *EntryContext) Pass() IPassContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IPassContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IPassContext) +} + +func (s *EntryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *EntryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *EntryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterEntry(s) + } +} + +func (s *EntryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitEntry(s) + } +} + +func (p *FstabParser) Entry() (localctx IEntryContext) { + localctx = NewEntryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, FstabParserRULE_entry) + var _la int + + p.EnterOuterAlt(localctx, 1) + p.SetState(15) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 0, p.GetParserRuleContext()) == 1 { + { + p.SetState(14) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(18) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 1, p.GetParserRuleContext()) == 1 { + { + p.SetState(17) + p.Spec() + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(21) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 2, p.GetParserRuleContext()) == 1 { + { + p.SetState(20) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(24) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 3, p.GetParserRuleContext()) == 1 { + { + p.SetState(23) + p.MountPoint() + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(27) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 4, p.GetParserRuleContext()) == 1 { + { + p.SetState(26) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(30) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 5, p.GetParserRuleContext()) == 1 { + { + p.SetState(29) + p.FileSystem() + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(33) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 6, p.GetParserRuleContext()) == 1 { + { + p.SetState(32) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(36) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == FstabParserSTRING || _la == FstabParserQUOTED_STRING { + { + p.SetState(35) + p.MountOptions() + } + + } + p.SetState(39) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 8, p.GetParserRuleContext()) == 1 { + { + p.SetState(38) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(42) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 9, p.GetParserRuleContext()) == 1 { + { + p.SetState(41) + p.Freq() + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(45) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 10, p.GetParserRuleContext()) == 1 { + { + p.SetState(44) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(48) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == FstabParserDIGITS { + { + p.SetState(47) + p.Pass() + } + + } + p.SetState(51) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == FstabParserWHITESPACE { + { + p.SetState(50) + p.Match(FstabParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + { + p.SetState(53) + p.Match(FstabParserEOF) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// ISpecContext is an interface to support dynamic dispatch. +type ISpecContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + QUOTED_STRING() antlr.TerminalNode + STRING() antlr.TerminalNode + + // IsSpecContext differentiates from other interfaces. + IsSpecContext() +} + +type SpecContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySpecContext() *SpecContext { + var p = new(SpecContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_spec + return p +} + +func InitEmptySpecContext(p *SpecContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_spec +} + +func (*SpecContext) IsSpecContext() {} + +func NewSpecContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SpecContext { + var p = new(SpecContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_spec + + return p +} + +func (s *SpecContext) GetParser() antlr.Parser { return s.parser } + +func (s *SpecContext) QUOTED_STRING() antlr.TerminalNode { + return s.GetToken(FstabParserQUOTED_STRING, 0) +} + +func (s *SpecContext) STRING() antlr.TerminalNode { + return s.GetToken(FstabParserSTRING, 0) +} + +func (s *SpecContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *SpecContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *SpecContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterSpec(s) + } +} + +func (s *SpecContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitSpec(s) + } +} + +func (p *FstabParser) Spec() (localctx ISpecContext) { + localctx = NewSpecContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, FstabParserRULE_spec) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(55) + _la = p.GetTokenStream().LA(1) + + if !(_la == FstabParserSTRING || _la == FstabParserQUOTED_STRING) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMountPointContext is an interface to support dynamic dispatch. +type IMountPointContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + QUOTED_STRING() antlr.TerminalNode + STRING() antlr.TerminalNode + + // IsMountPointContext differentiates from other interfaces. + IsMountPointContext() +} + +type MountPointContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMountPointContext() *MountPointContext { + var p = new(MountPointContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_mountPoint + return p +} + +func InitEmptyMountPointContext(p *MountPointContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_mountPoint +} + +func (*MountPointContext) IsMountPointContext() {} + +func NewMountPointContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MountPointContext { + var p = new(MountPointContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_mountPoint + + return p +} + +func (s *MountPointContext) GetParser() antlr.Parser { return s.parser } + +func (s *MountPointContext) QUOTED_STRING() antlr.TerminalNode { + return s.GetToken(FstabParserQUOTED_STRING, 0) +} + +func (s *MountPointContext) STRING() antlr.TerminalNode { + return s.GetToken(FstabParserSTRING, 0) +} + +func (s *MountPointContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *MountPointContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *MountPointContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterMountPoint(s) + } +} + +func (s *MountPointContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitMountPoint(s) + } +} + +func (p *FstabParser) MountPoint() (localctx IMountPointContext) { + localctx = NewMountPointContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 4, FstabParserRULE_mountPoint) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(57) + _la = p.GetTokenStream().LA(1) + + if !(_la == FstabParserSTRING || _la == FstabParserQUOTED_STRING) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFileSystemContext is an interface to support dynamic dispatch. +type IFileSystemContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + ADFS() antlr.TerminalNode + AFFS() antlr.TerminalNode + BTRFS() antlr.TerminalNode + EXFAT() antlr.TerminalNode + STRING() antlr.TerminalNode + QUOTED_STRING() antlr.TerminalNode + + // IsFileSystemContext differentiates from other interfaces. + IsFileSystemContext() +} + +type FileSystemContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyFileSystemContext() *FileSystemContext { + var p = new(FileSystemContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_fileSystem + return p +} + +func InitEmptyFileSystemContext(p *FileSystemContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_fileSystem +} + +func (*FileSystemContext) IsFileSystemContext() {} + +func NewFileSystemContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FileSystemContext { + var p = new(FileSystemContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_fileSystem + + return p +} + +func (s *FileSystemContext) GetParser() antlr.Parser { return s.parser } + +func (s *FileSystemContext) ADFS() antlr.TerminalNode { + return s.GetToken(FstabParserADFS, 0) +} + +func (s *FileSystemContext) AFFS() antlr.TerminalNode { + return s.GetToken(FstabParserAFFS, 0) +} + +func (s *FileSystemContext) BTRFS() antlr.TerminalNode { + return s.GetToken(FstabParserBTRFS, 0) +} + +func (s *FileSystemContext) EXFAT() antlr.TerminalNode { + return s.GetToken(FstabParserEXFAT, 0) +} + +func (s *FileSystemContext) STRING() antlr.TerminalNode { + return s.GetToken(FstabParserSTRING, 0) +} + +func (s *FileSystemContext) QUOTED_STRING() antlr.TerminalNode { + return s.GetToken(FstabParserQUOTED_STRING, 0) +} + +func (s *FileSystemContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FileSystemContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FileSystemContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterFileSystem(s) + } +} + +func (s *FileSystemContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitFileSystem(s) + } +} + +func (p *FstabParser) FileSystem() (localctx IFileSystemContext) { + localctx = NewFileSystemContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, FstabParserRULE_fileSystem) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(59) + _la = p.GetTokenStream().LA(1) + + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&1008) != 0) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IMountOptionsContext is an interface to support dynamic dispatch. +type IMountOptionsContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + QUOTED_STRING() antlr.TerminalNode + STRING() antlr.TerminalNode + + // IsMountOptionsContext differentiates from other interfaces. + IsMountOptionsContext() +} + +type MountOptionsContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyMountOptionsContext() *MountOptionsContext { + var p = new(MountOptionsContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_mountOptions + return p +} + +func InitEmptyMountOptionsContext(p *MountOptionsContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_mountOptions +} + +func (*MountOptionsContext) IsMountOptionsContext() {} + +func NewMountOptionsContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MountOptionsContext { + var p = new(MountOptionsContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_mountOptions + + return p +} + +func (s *MountOptionsContext) GetParser() antlr.Parser { return s.parser } + +func (s *MountOptionsContext) QUOTED_STRING() antlr.TerminalNode { + return s.GetToken(FstabParserQUOTED_STRING, 0) +} + +func (s *MountOptionsContext) STRING() antlr.TerminalNode { + return s.GetToken(FstabParserSTRING, 0) +} + +func (s *MountOptionsContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *MountOptionsContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *MountOptionsContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterMountOptions(s) + } +} + +func (s *MountOptionsContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitMountOptions(s) + } +} + +func (p *FstabParser) MountOptions() (localctx IMountOptionsContext) { + localctx = NewMountOptionsContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, FstabParserRULE_mountOptions) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(61) + _la = p.GetTokenStream().LA(1) + + if !(_la == FstabParserSTRING || _la == FstabParserQUOTED_STRING) { + p.GetErrorHandler().RecoverInline(p) + } else { + p.GetErrorHandler().ReportMatch(p) + p.Consume() + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IFreqContext is an interface to support dynamic dispatch. +type IFreqContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + DIGITS() antlr.TerminalNode + + // IsFreqContext differentiates from other interfaces. + IsFreqContext() +} + +type FreqContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyFreqContext() *FreqContext { + var p = new(FreqContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_freq + return p +} + +func InitEmptyFreqContext(p *FreqContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_freq +} + +func (*FreqContext) IsFreqContext() {} + +func NewFreqContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FreqContext { + var p = new(FreqContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_freq + + return p +} + +func (s *FreqContext) GetParser() antlr.Parser { return s.parser } + +func (s *FreqContext) DIGITS() antlr.TerminalNode { + return s.GetToken(FstabParserDIGITS, 0) +} + +func (s *FreqContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *FreqContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *FreqContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterFreq(s) + } +} + +func (s *FreqContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitFreq(s) + } +} + +func (p *FstabParser) Freq() (localctx IFreqContext) { + localctx = NewFreqContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, FstabParserRULE_freq) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(63) + p.Match(FstabParserDIGITS) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} + +// IPassContext is an interface to support dynamic dispatch. +type IPassContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + DIGITS() antlr.TerminalNode + + // IsPassContext differentiates from other interfaces. + IsPassContext() +} + +type PassContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyPassContext() *PassContext { + var p = new(PassContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_pass + return p +} + +func InitEmptyPassContext(p *PassContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = FstabParserRULE_pass +} + +func (*PassContext) IsPassContext() {} + +func NewPassContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PassContext { + var p = new(PassContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = FstabParserRULE_pass + + return p +} + +func (s *PassContext) GetParser() antlr.Parser { return s.parser } + +func (s *PassContext) DIGITS() antlr.TerminalNode { + return s.GetToken(FstabParserDIGITS, 0) +} + +func (s *PassContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PassContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *PassContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.EnterPass(s) + } +} + +func (s *PassContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(FstabListener); ok { + listenerT.ExitPass(s) + } +} + +func (p *FstabParser) Pass() (localctx IPassContext) { + localctx = NewPassContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 12, FstabParserRULE_pass) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(65) + p.Match(FstabParserDIGITS) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + p.ExitRule() + return localctx + goto errorExit // Trick to prevent compiler error if the label is not used +} diff --git a/server/handlers/fstab/ast/parser_test.go b/server/handlers/fstab/ast/parser_test.go index 6e3a2c7..ac37136 100644 --- a/server/handlers/fstab/ast/parser_test.go +++ b/server/handlers/fstab/ast/parser_test.go @@ -11,6 +11,7 @@ func TestExample1( ) { input := utils.Dedent(` LABEL=test /mnt/test ext4 defaults 0 0 +LABEL=example /mnt/example fat32 defaults 0 2 `) c := NewFstabConfig() @@ -20,8 +21,8 @@ LABEL=test /mnt/test ext4 defaults 0 0 t.Fatalf("Expected no errors, got %v", errors) } - if c.Entries.Size() != 1 { - t.Fatalf("Expected 1 entry, got %d", c.Entries.Size()) + if c.Entries.Size() != 2 { + t.Fatalf("Expected 2 entry, got %d", c.Entries.Size()) } rawFirstEntry, _ := c.Entries.Get(uint32(0)) @@ -93,6 +94,12 @@ LABEL=test /mnt/test ext4 defaults 0 0 if !(field == FstabFieldFreq) { t.Errorf("Expected field to be freq, got %v", field) } + + rawSecondEntry, _ := c.Entries.Get(uint32(1)) + secondEntry := rawSecondEntry.(*FstabEntry) + if !(secondEntry.Fields.Start.Line == 1) { + t.Errorf("Expected start line to be 1, got %d", secondEntry.Fields.Start.Line) + } } func TestIncompleteExample( diff --git a/server/handlers/fstab/fields/spec.go b/server/handlers/fstab/fields/spec.go index ae465ee..df43f6d 100644 --- a/server/handlers/fstab/fields/spec.go +++ b/server/handlers/fstab/fields/spec.go @@ -15,7 +15,7 @@ var LabelField = docvalues.RegexValue{ var SpecField = docvalues.OrValue{ Values: []docvalues.DeprecatedValue{ docvalues.PathValue{ - RequiredType: docvalues.PathTypeFile, + RequiredType: docvalues.PathTypeExistenceOptional, }, docvalues.KeyEnumAssignmentValue{ Separator: "=", diff --git a/server/handlers/fstab/fstab_test.go b/server/handlers/fstab/fstab_test.go index f6b21c1..e36c5f3 100644 --- a/server/handlers/fstab/fstab_test.go +++ b/server/handlers/fstab/fstab_test.go @@ -101,6 +101,36 @@ LABEL=test /mnt/test btrfs subvol=backup,fat=32 0 0 } } +func TestIncompleteExample(t *testing.T) { + input := utils.Dedent(` +LABEL=test /mnt/test defaults 0 0 +`) + p := ast.NewFstabConfig() + + errors := p.Parse(input) + + if len(errors) > 0 { + t.Fatal("ParseFromContent returned error", errors) + } + + rawFirstEntry, _ := p.Entries.Get(uint32(0)) + firstEntry := rawFirstEntry.(*ast.FstabEntry) + name := firstEntry.GetFieldAtPosition(common.CursorPosition(0)) + if !(name == ast.FstabFieldSpec) { + t.Errorf("GetFieldAtPosition failed to return correct field name. Got: %v but expected: %v", name, ast.FstabFieldSpec) + } + + name = firstEntry.GetFieldAtPosition(common.CursorPosition(9)) + if !(name == ast.FstabFieldSpec) { + t.Errorf("GetFieldAtPosition failed to return correct field name. Got: %v but expected: %v", name, ast.FstabFieldSpec) + } + + name = firstEntry.GetFieldAtPosition(common.CursorPosition(21)) + if !(name == ast.FstabFieldFileSystemType) { + t.Errorf("GetFieldAtPosition failed to return correct field name. Got: %v but expected: %v", name, ast.FstabFieldFileSystemType) + } +} + // func TestExample1(t *testing.T) { // input := utils.Dedent(` // /dev/disk/by-uuid/19ae4e13-1d6d-4833-965b-a20197aebf27 /mnt/RetroGames auto nosuid,nodev,nofail,x-gvfs-show 0 0 diff --git a/server/handlers/fstab/handlers/completions.go b/server/handlers/fstab/handlers/completions.go index 9d10d90..c2d00f5 100644 --- a/server/handlers/fstab/handlers/completions.go +++ b/server/handlers/fstab/handlers/completions.go @@ -42,7 +42,6 @@ func GetCompletion( fileSystemType := entry.Fields.FilesystemType.Value.Value completions := make([]protocol.CompletionItem, 0, 50) - println("fetching field options now", line, cursor) for _, completion := range fields.DefaultMountOptionsField.DeprecatedFetchCompletions(line, cursor) { var documentation string @@ -108,5 +107,9 @@ func getFieldSafely(field *ast.FstabField, cursor common.CursorPosition) (string return "", 0 } + if uint32(cursor) < field.Start.Character { + return "", 0 + } + return field.Value.Raw, common.CursorToCharacterIndex(uint32(cursor) - field.Start.Character) } diff --git a/server/handlers/ssh_config/ast/listener.go b/server/handlers/ssh_config/ast/listener.go index ae56143..1522513 100644 --- a/server/handlers/ssh_config/ast/listener.go +++ b/server/handlers/ssh_config/ast/listener.go @@ -26,6 +26,13 @@ func createListenerContext() *sshListenerContext { return context } +type sshParserListener struct { + *parser.BaseConfigListener + Config *SSHConfig + Errors []common.LSPError + sshContext *sshListenerContext +} + func createListener( config *SSHConfig, context *sshListenerContext, @@ -37,13 +44,6 @@ func createListener( } } -type sshParserListener struct { - *parser.BaseConfigListener - Config *SSHConfig - Errors []common.LSPError - sshContext *sshListenerContext -} - func (s *sshParserListener) EnterEntry(ctx *parser.EntryContext) { location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) location.ChangeBothLines(s.sshContext.line) diff --git a/server/update_antlr_parser.sh b/server/update_antlr_parser.sh index e2e6005..9534937 100755 --- a/server/update_antlr_parser.sh +++ b/server/update_antlr_parser.sh @@ -5,6 +5,9 @@ ROOT=$(git rev-parse --show-toplevel)/server # aliases cd $ROOT/handlers/aliases && antlr4 -Dlanguage=Go -o ast/parser Aliases.g4 +# fstab +cd $ROOT/hanlders/fstab && antlr4 -Dlanguage=Go -o ast/parser Fstab.g4 + # sshd_config cd $ROOT/handlers/sshd_config && antlr4 -Dlanguage=Go -o ast/parser Config.g4 cd $ROOT/handlers/sshd_config/match-parser && antlr4 -Dlanguage=Go -o parser Match.g4