From 1dd6be38d8a3be9d74dae87c7ead11053076259d Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:17:53 +0200 Subject: [PATCH] feat(gitconfig): Add first version of gitconfig ast --- server/doc-values/value-enum.go | 6 +- server/handlers/gitconfig/Config.g4 | 51 + .../handlers/gitconfig/ast/error-listener.go | 45 + server/handlers/gitconfig/ast/gitconfig.go | 47 + .../gitconfig/ast/gitconfig_fields.go | 6 + server/handlers/gitconfig/ast/listener.go | 95 ++ server/handlers/gitconfig/ast/parser.go | 148 +++ .../gitconfig/ast/parser/Config.interp | 28 + .../gitconfig/ast/parser/Config.tokens | 7 + .../gitconfig/ast/parser/ConfigLexer.interp | 32 + .../gitconfig/ast/parser/ConfigLexer.tokens | 7 + .../ast/parser/config_base_listener.go | 64 + .../gitconfig/ast/parser/config_lexer.go | 121 ++ .../gitconfig/ast/parser/config_listener.go | 52 + .../gitconfig/ast/parser/config_parser.go | 1086 +++++++++++++++++ server/update_antlr_parser.sh | 5 +- 16 files changed, 1794 insertions(+), 6 deletions(-) create mode 100644 server/handlers/gitconfig/Config.g4 create mode 100644 server/handlers/gitconfig/ast/error-listener.go create mode 100644 server/handlers/gitconfig/ast/gitconfig.go create mode 100644 server/handlers/gitconfig/ast/gitconfig_fields.go create mode 100644 server/handlers/gitconfig/ast/listener.go create mode 100644 server/handlers/gitconfig/ast/parser.go create mode 100644 server/handlers/gitconfig/ast/parser/Config.interp create mode 100644 server/handlers/gitconfig/ast/parser/Config.tokens create mode 100644 server/handlers/gitconfig/ast/parser/ConfigLexer.interp create mode 100644 server/handlers/gitconfig/ast/parser/ConfigLexer.tokens create mode 100644 server/handlers/gitconfig/ast/parser/config_base_listener.go create mode 100644 server/handlers/gitconfig/ast/parser/config_lexer.go create mode 100644 server/handlers/gitconfig/ast/parser/config_listener.go create mode 100644 server/handlers/gitconfig/ast/parser/config_parser.go diff --git a/server/doc-values/value-enum.go b/server/doc-values/value-enum.go index 875f5f5..f7ab1e6 100644 --- a/server/doc-values/value-enum.go +++ b/server/doc-values/value-enum.go @@ -14,11 +14,7 @@ type ValueNotInEnumError struct { } func (e ValueNotInEnumError) Error() string { - if len(e.AvailableValues) <= 6 { - return fmt.Sprintf("This value is not valid. Select one from: %s", strings.Join(e.AvailableValues, ",")) - } else { - return fmt.Sprintf("This value is not valid") - } + return fmt.Sprintf("This value is not an enum value. Select one from: %s", strings.Join(e.AvailableValues, ",")) } type EnumString struct { diff --git a/server/handlers/gitconfig/Config.g4 b/server/handlers/gitconfig/Config.g4 new file mode 100644 index 0000000..b059136 --- /dev/null +++ b/server/handlers/gitconfig/Config.g4 @@ -0,0 +1,51 @@ +grammar Config; + +lineStatement + : entry EOF + ; + +entry + : WHITESPACE? key? separator? value? leadingComment? + ; + +leadingComment + : HASH WHITESPACE? (string WHITESPACE?)+ + ; + +key + : string + ; + +separator + : EQUAL + ; + +value + : string + ; + +string + : (QUOTED_STRING | STRING) + ; + +/////////////////////////////////////////////// + +EQUAL + : '=' + ; + +HASH + : '#' + ; + +WHITESPACE + : [ \t]+ + ; + +STRING + : ~('#' | '\r' | '\n' | '"' | ' ' | '\t')+ + ; + +QUOTED_STRING + : '"' WHITESPACE? (STRING WHITESPACE)* STRING? ('"')? + ; diff --git a/server/handlers/gitconfig/ast/error-listener.go b/server/handlers/gitconfig/ast/error-listener.go new file mode 100644 index 0000000..74d4387 --- /dev/null +++ b/server/handlers/gitconfig/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/gitconfig/ast/gitconfig.go b/server/handlers/gitconfig/ast/gitconfig.go new file mode 100644 index 0000000..a9f8899 --- /dev/null +++ b/server/handlers/gitconfig/ast/gitconfig.go @@ -0,0 +1,47 @@ +package ast + +import ( + "config-lsp/common" + "config-lsp/common/parser" + + "github.com/emirpasic/gods/maps/treemap" +) + +type GitKey struct { + common.LocationRange + Value parser.ParsedString +} + +type GitSeparator struct { + common.LocationRange + Value parser.ParsedString +} + +type GitValue struct { + common.LocationRange + Value parser.ParsedString +} + +type GitEntry struct { + common.LocationRange + Key *GitKey + Separator *GitSeparator + Value *GitValue +} + +type GitSectionHeader struct { + common.LocationRange + Title *parser.ParsedString +} + +type GitSection struct { + common.LocationRange + Entries *treemap.Map + Title *GitSectionHeader +} + +type GitConfig struct { + Sections []*GitSection + CommentLines map[uint32]struct{} +} + diff --git a/server/handlers/gitconfig/ast/gitconfig_fields.go b/server/handlers/gitconfig/ast/gitconfig_fields.go new file mode 100644 index 0000000..b5f59c1 --- /dev/null +++ b/server/handlers/gitconfig/ast/gitconfig_fields.go @@ -0,0 +1,6 @@ +package ast + +func (c *GitConfig) Clear() { + c.Sections = []*GitSection{} +} + diff --git a/server/handlers/gitconfig/ast/listener.go b/server/handlers/gitconfig/ast/listener.go new file mode 100644 index 0000000..75f92f4 --- /dev/null +++ b/server/handlers/gitconfig/ast/listener.go @@ -0,0 +1,95 @@ +package ast + +import ( + "config-lsp/common" + commonparser "config-lsp/common/parser" + "config-lsp/handlers/gitconfig/ast/parser" +) + +type gitconfigListenerContext struct { + line uint32 + currentSection *GitSection + currentEntry *GitEntry +} + +func createListenerContext() *gitconfigListenerContext { + context := new(gitconfigListenerContext) + + return context +} + +type gitconfigParserListener struct { + *parser.BaseConfigListener + Config *GitConfig + Errors []common.LSPError + gitconfigContext *gitconfigListenerContext +} + +func createListener( + config *GitConfig, + context *gitconfigListenerContext, +) gitconfigParserListener { + return gitconfigParserListener{ + Config: config, + Errors: make([]common.LSPError, 0), + gitconfigContext: context, + } +} + +func (s *gitconfigParserListener) EnterEntry(ctx *parser.EntryContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.gitconfigContext.line) + + s.gitconfigContext.currentEntry = &GitEntry{ + LocationRange: location, + } + + s.gitconfigContext.currentSection.Entries.Put( + location.Start.Line, + s.gitconfigContext.currentEntry, + ) +} + +func (s *gitconfigParserListener) ExitEntry(ctx *parser.EntryContext) { + s.gitconfigContext.currentEntry = nil +} + +func (s *gitconfigParserListener) EnterKey(ctx *parser.KeyContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.gitconfigContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.gitconfigContext.currentEntry.Key = &GitKey{ + LocationRange: location, + Value: value, + } +} + +func (s *gitconfigParserListener) EnterSeparator(ctx *parser.SeparatorContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.gitconfigContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.gitconfigContext.currentEntry.Separator = &GitSeparator{ + LocationRange: location, + Value: value, + } +} + +func (s *gitconfigParserListener) EnterValue(ctx *parser.ValueContext) { + location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext) + location.ChangeBothLines(s.gitconfigContext.line) + + text := ctx.GetText() + value := commonparser.ParseRawString(text, commonparser.FullFeatures) + + s.gitconfigContext.currentEntry.Value = &GitValue{ + LocationRange: location, + Value: value, + } +} + diff --git a/server/handlers/gitconfig/ast/parser.go b/server/handlers/gitconfig/ast/parser.go new file mode 100644 index 0000000..65dcd7d --- /dev/null +++ b/server/handlers/gitconfig/ast/parser.go @@ -0,0 +1,148 @@ +package ast + +import ( + "config-lsp/common" + "config-lsp/utils" + "regexp" + "strings" + + "github.com/antlr4-go/antlr/v4" + protocol "github.com/tliron/glsp/protocol_3_16" +) + +func NewGitConfig() *GitConfig { + config := &GitConfig{} + config.Clear() + + return config +} + +var commentPattern = regexp.MustCompile(`^\s*#`) +var emptyLinePattern = regexp.MustCompile(`^\s*$`) +var headerPattern = regexp.MustCompile(`^\s*\[`) + +func (c *GitConfig) Parse(input string) []common.LSPError { + errors := make([]common.LSPError, 0) + lines := utils.SplitIntoLines(input) + context := createListenerContext() + + for rawLineNumber, line := range lines { + lineNumber := uint32(rawLineNumber) + + if emptyLinePattern.MatchString(line) { + continue + } + + if commentPattern.MatchString(line) { + c.CommentLines[lineNumber] = struct{}{} + continue + } + + if headerPattern.MatchString(line) { + c.parseHeader(context, line) + } + + errors = append( + errors, + c.parseStatement(context, line)..., + ) + } + + return errors +} + +func (c *GitConfig) parseHeader( + context *gitconfigListenerContext, + input string, +) []protocol.Diagnostic { + leftBracketIndex := strings.Index(input, "[") + rightBracketIndex := strings.Index(input, "]") + + if rightBracketIndex == -1 { + return []protocol.Diagnostic{ + { + Range: protocol.Range{ + Start: protocol.Position{ + Line: context.line, + Character: 0, + }, + End: protocol.Position{ + Line: context.line, + Character: uint32(len(input)), + }, + }, + Message: `This section title is missing a closing bracket "]"`, + }, + } + } + + if leftBracketIndex != 0 { + return []protocol.Diagnostic{ + { + Range: protocol.Range{ + Start: protocol.Position{ + Line: context.line, + Character: 0, + }, + End: protocol.Position{ + Line: context.line, + Character: uint32(leftBracketIndex), + }, + }, + Message: `A section title should not have any characters before the opening bracket "["`, + }, + } + } + + if rightBracketIndex != len(input)-1 { + return []protocol.Diagnostic{ + { + Range: protocol.Range{ + Start: protocol.Position{ + Line: context.line, + Character: uint32(rightBracketIndex), + }, + End: protocol.Position{ + Line: context.line, + Character: uint32(len(input)), + }, + }, + Message: `A section title should not have any characters after the closing bracket "]"`, + }, + } + } + + return nil +} + +func (c *GitConfig) parseStatement( + context *gitconfigListenerContext, + input string, +) []common.LSPError { + stream := antlr.NewInputStream(input) + + lexerErrorListener := createErrorListener(context.line) + lexer := parser.NewConfigLexer(stream) + lexer.RemoveErrorListeners() + lexer.AddErrorListener(&lexerErrorListener) + + tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) + + parserErrorListener := createErrorListener(context.line) + antlrParser := parser.NewConfigParser(tokenStream) + antlrParser.RemoveErrorListeners() + antlrParser.AddErrorListener(&parserErrorListener) + + listener := createListener(c, context) + antlr.ParseTreeWalkerDefault.Walk( + &listener, + antlrParser.LineStatement(), + ) + + errors := lexerErrorListener.Errors + errors = append(errors, parserErrorListener.Errors...) + errors = append(errors, listener.Errors...) + + return errors +} + diff --git a/server/handlers/gitconfig/ast/parser/Config.interp b/server/handlers/gitconfig/ast/parser/Config.interp new file mode 100644 index 0000000..832bd92 --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/Config.interp @@ -0,0 +1,28 @@ +token literal names: +null +'=' +'#' +null +null +null + +token symbolic names: +null +EQUAL +HASH +WHITESPACE +STRING +QUOTED_STRING + +rule names: +lineStatement +entry +leadingComment +key +separator +value +string + + +atn: +[4, 1, 5, 53, 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, 1, 0, 1, 0, 1, 1, 3, 1, 19, 8, 1, 1, 1, 3, 1, 22, 8, 1, 1, 1, 3, 1, 25, 8, 1, 1, 1, 3, 1, 28, 8, 1, 1, 1, 3, 1, 31, 8, 1, 1, 2, 1, 2, 3, 2, 35, 8, 2, 1, 2, 1, 2, 3, 2, 39, 8, 2, 4, 2, 41, 8, 2, 11, 2, 12, 2, 42, 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, 1, 1, 0, 4, 5, 53, 0, 14, 1, 0, 0, 0, 2, 18, 1, 0, 0, 0, 4, 32, 1, 0, 0, 0, 6, 44, 1, 0, 0, 0, 8, 46, 1, 0, 0, 0, 10, 48, 1, 0, 0, 0, 12, 50, 1, 0, 0, 0, 14, 15, 3, 2, 1, 0, 15, 16, 5, 0, 0, 1, 16, 1, 1, 0, 0, 0, 17, 19, 5, 3, 0, 0, 18, 17, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 21, 1, 0, 0, 0, 20, 22, 3, 6, 3, 0, 21, 20, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 24, 1, 0, 0, 0, 23, 25, 3, 8, 4, 0, 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 3, 10, 5, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, 31, 3, 4, 2, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 3, 1, 0, 0, 0, 32, 34, 5, 2, 0, 0, 33, 35, 5, 3, 0, 0, 34, 33, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 40, 1, 0, 0, 0, 36, 38, 3, 12, 6, 0, 37, 39, 5, 3, 0, 0, 38, 37, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 41, 1, 0, 0, 0, 40, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 5, 1, 0, 0, 0, 44, 45, 3, 12, 6, 0, 45, 7, 1, 0, 0, 0, 46, 47, 5, 1, 0, 0, 47, 9, 1, 0, 0, 0, 48, 49, 3, 12, 6, 0, 49, 11, 1, 0, 0, 0, 50, 51, 7, 0, 0, 0, 51, 13, 1, 0, 0, 0, 8, 18, 21, 24, 27, 30, 34, 38, 42] \ No newline at end of file diff --git a/server/handlers/gitconfig/ast/parser/Config.tokens b/server/handlers/gitconfig/ast/parser/Config.tokens new file mode 100644 index 0000000..0ee5167 --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/Config.tokens @@ -0,0 +1,7 @@ +EQUAL=1 +HASH=2 +WHITESPACE=3 +STRING=4 +QUOTED_STRING=5 +'='=1 +'#'=2 diff --git a/server/handlers/gitconfig/ast/parser/ConfigLexer.interp b/server/handlers/gitconfig/ast/parser/ConfigLexer.interp new file mode 100644 index 0000000..0daf76c --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/ConfigLexer.interp @@ -0,0 +1,32 @@ +token literal names: +null +'=' +'#' +null +null +null + +token symbolic names: +null +EQUAL +HASH +WHITESPACE +STRING +QUOTED_STRING + +rule names: +EQUAL +HASH +WHITESPACE +STRING +QUOTED_STRING + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 5, 43, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 4, 2, 17, 8, 2, 11, 2, 12, 2, 18, 1, 3, 4, 3, 22, 8, 3, 11, 3, 12, 3, 23, 1, 4, 1, 4, 3, 4, 28, 8, 4, 1, 4, 1, 4, 1, 4, 5, 4, 33, 8, 4, 10, 4, 12, 4, 36, 9, 4, 1, 4, 3, 4, 39, 8, 4, 1, 4, 3, 4, 42, 8, 4, 0, 0, 5, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 0, 2, 2, 0, 9, 9, 32, 32, 4, 0, 9, 10, 13, 13, 32, 32, 34, 35, 48, 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, 1, 11, 1, 0, 0, 0, 3, 13, 1, 0, 0, 0, 5, 16, 1, 0, 0, 0, 7, 21, 1, 0, 0, 0, 9, 25, 1, 0, 0, 0, 11, 12, 5, 61, 0, 0, 12, 2, 1, 0, 0, 0, 13, 14, 5, 35, 0, 0, 14, 4, 1, 0, 0, 0, 15, 17, 7, 0, 0, 0, 16, 15, 1, 0, 0, 0, 17, 18, 1, 0, 0, 0, 18, 16, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 6, 1, 0, 0, 0, 20, 22, 8, 1, 0, 0, 21, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 21, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 8, 1, 0, 0, 0, 25, 27, 5, 34, 0, 0, 26, 28, 3, 5, 2, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 34, 1, 0, 0, 0, 29, 30, 3, 7, 3, 0, 30, 31, 3, 5, 2, 0, 31, 33, 1, 0, 0, 0, 32, 29, 1, 0, 0, 0, 33, 36, 1, 0, 0, 0, 34, 32, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 38, 1, 0, 0, 0, 36, 34, 1, 0, 0, 0, 37, 39, 3, 7, 3, 0, 38, 37, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 41, 1, 0, 0, 0, 40, 42, 5, 34, 0, 0, 41, 40, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 10, 1, 0, 0, 0, 7, 0, 18, 23, 27, 34, 38, 41, 0] \ No newline at end of file diff --git a/server/handlers/gitconfig/ast/parser/ConfigLexer.tokens b/server/handlers/gitconfig/ast/parser/ConfigLexer.tokens new file mode 100644 index 0000000..0ee5167 --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/ConfigLexer.tokens @@ -0,0 +1,7 @@ +EQUAL=1 +HASH=2 +WHITESPACE=3 +STRING=4 +QUOTED_STRING=5 +'='=1 +'#'=2 diff --git a/server/handlers/gitconfig/ast/parser/config_base_listener.go b/server/handlers/gitconfig/ast/parser/config_base_listener.go new file mode 100644 index 0000000..fc6b18a --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/config_base_listener.go @@ -0,0 +1,64 @@ +// Code generated from Config.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Config + +import "github.com/antlr4-go/antlr/v4" + +// BaseConfigListener is a complete listener for a parse tree produced by ConfigParser. +type BaseConfigListener struct{} + +var _ ConfigListener = &BaseConfigListener{} + +// VisitTerminal is called when a terminal node is visited. +func (s *BaseConfigListener) VisitTerminal(node antlr.TerminalNode) {} + +// VisitErrorNode is called when an error node is visited. +func (s *BaseConfigListener) VisitErrorNode(node antlr.ErrorNode) {} + +// EnterEveryRule is called when any rule is entered. +func (s *BaseConfigListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} + +// ExitEveryRule is called when any rule is exited. +func (s *BaseConfigListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} + +// EnterLineStatement is called when production lineStatement is entered. +func (s *BaseConfigListener) EnterLineStatement(ctx *LineStatementContext) {} + +// ExitLineStatement is called when production lineStatement is exited. +func (s *BaseConfigListener) ExitLineStatement(ctx *LineStatementContext) {} + +// EnterEntry is called when production entry is entered. +func (s *BaseConfigListener) EnterEntry(ctx *EntryContext) {} + +// ExitEntry is called when production entry is exited. +func (s *BaseConfigListener) ExitEntry(ctx *EntryContext) {} + +// EnterLeadingComment is called when production leadingComment is entered. +func (s *BaseConfigListener) EnterLeadingComment(ctx *LeadingCommentContext) {} + +// ExitLeadingComment is called when production leadingComment is exited. +func (s *BaseConfigListener) ExitLeadingComment(ctx *LeadingCommentContext) {} + +// EnterKey is called when production key is entered. +func (s *BaseConfigListener) EnterKey(ctx *KeyContext) {} + +// ExitKey is called when production key is exited. +func (s *BaseConfigListener) ExitKey(ctx *KeyContext) {} + +// EnterSeparator is called when production separator is entered. +func (s *BaseConfigListener) EnterSeparator(ctx *SeparatorContext) {} + +// ExitSeparator is called when production separator is exited. +func (s *BaseConfigListener) ExitSeparator(ctx *SeparatorContext) {} + +// EnterValue is called when production value is entered. +func (s *BaseConfigListener) EnterValue(ctx *ValueContext) {} + +// ExitValue is called when production value is exited. +func (s *BaseConfigListener) ExitValue(ctx *ValueContext) {} + +// EnterString is called when production string is entered. +func (s *BaseConfigListener) EnterString(ctx *StringContext) {} + +// ExitString is called when production string is exited. +func (s *BaseConfigListener) ExitString(ctx *StringContext) {} diff --git a/server/handlers/gitconfig/ast/parser/config_lexer.go b/server/handlers/gitconfig/ast/parser/config_lexer.go new file mode 100644 index 0000000..6ac413d --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/config_lexer.go @@ -0,0 +1,121 @@ +// Code generated from Config.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 ConfigLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +var ConfigLexerLexerStaticData 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 configlexerLexerInit() { + staticData := &ConfigLexerLexerStaticData + staticData.ChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + } + staticData.ModeNames = []string{ + "DEFAULT_MODE", + } + staticData.LiteralNames = []string{ + "", "'='", "'#'", + } + staticData.SymbolicNames = []string{ + "", "EQUAL", "HASH", "WHITESPACE", "STRING", "QUOTED_STRING", + } + staticData.RuleNames = []string{ + "EQUAL", "HASH", "WHITESPACE", "STRING", "QUOTED_STRING", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 0, 5, 43, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 7, 4, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 4, 2, 17, 8, 2, 11, 2, 12, 2, 18, + 1, 3, 4, 3, 22, 8, 3, 11, 3, 12, 3, 23, 1, 4, 1, 4, 3, 4, 28, 8, 4, 1, + 4, 1, 4, 1, 4, 5, 4, 33, 8, 4, 10, 4, 12, 4, 36, 9, 4, 1, 4, 3, 4, 39, + 8, 4, 1, 4, 3, 4, 42, 8, 4, 0, 0, 5, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 0, + 2, 2, 0, 9, 9, 32, 32, 4, 0, 9, 10, 13, 13, 32, 32, 34, 35, 48, 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, 1, 11, 1, 0, 0, 0, 3, 13, 1, 0, 0, 0, 5, 16, 1, 0, 0, 0, 7, 21, + 1, 0, 0, 0, 9, 25, 1, 0, 0, 0, 11, 12, 5, 61, 0, 0, 12, 2, 1, 0, 0, 0, + 13, 14, 5, 35, 0, 0, 14, 4, 1, 0, 0, 0, 15, 17, 7, 0, 0, 0, 16, 15, 1, + 0, 0, 0, 17, 18, 1, 0, 0, 0, 18, 16, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, + 6, 1, 0, 0, 0, 20, 22, 8, 1, 0, 0, 21, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, + 0, 23, 21, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 8, 1, 0, 0, 0, 25, 27, 5, + 34, 0, 0, 26, 28, 3, 5, 2, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, + 34, 1, 0, 0, 0, 29, 30, 3, 7, 3, 0, 30, 31, 3, 5, 2, 0, 31, 33, 1, 0, 0, + 0, 32, 29, 1, 0, 0, 0, 33, 36, 1, 0, 0, 0, 34, 32, 1, 0, 0, 0, 34, 35, + 1, 0, 0, 0, 35, 38, 1, 0, 0, 0, 36, 34, 1, 0, 0, 0, 37, 39, 3, 7, 3, 0, + 38, 37, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 41, 1, 0, 0, 0, 40, 42, 5, + 34, 0, 0, 41, 40, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 10, 1, 0, 0, 0, 7, + 0, 18, 23, 27, 34, 38, 41, 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) + } +} + +// ConfigLexerInit initializes any static state used to implement ConfigLexer. By default the +// static state used to implement the lexer is lazily initialized during the first call to +// NewConfigLexer(). You can call this function if you wish to initialize the static state ahead +// of time. +func ConfigLexerInit() { + staticData := &ConfigLexerLexerStaticData + staticData.once.Do(configlexerLexerInit) +} + +// NewConfigLexer produces a new lexer instance for the optional input antlr.CharStream. +func NewConfigLexer(input antlr.CharStream) *ConfigLexer { + ConfigLexerInit() + l := new(ConfigLexer) + l.BaseLexer = antlr.NewBaseLexer(input) + staticData := &ConfigLexerLexerStaticData + 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 = "Config.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// ConfigLexer tokens. +const ( + ConfigLexerEQUAL = 1 + ConfigLexerHASH = 2 + ConfigLexerWHITESPACE = 3 + ConfigLexerSTRING = 4 + ConfigLexerQUOTED_STRING = 5 +) diff --git a/server/handlers/gitconfig/ast/parser/config_listener.go b/server/handlers/gitconfig/ast/parser/config_listener.go new file mode 100644 index 0000000..83428cd --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/config_listener.go @@ -0,0 +1,52 @@ +// Code generated from Config.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Config + +import "github.com/antlr4-go/antlr/v4" + +// ConfigListener is a complete listener for a parse tree produced by ConfigParser. +type ConfigListener interface { + antlr.ParseTreeListener + + // EnterLineStatement is called when entering the lineStatement production. + EnterLineStatement(c *LineStatementContext) + + // EnterEntry is called when entering the entry production. + EnterEntry(c *EntryContext) + + // EnterLeadingComment is called when entering the leadingComment production. + EnterLeadingComment(c *LeadingCommentContext) + + // EnterKey is called when entering the key production. + EnterKey(c *KeyContext) + + // EnterSeparator is called when entering the separator production. + EnterSeparator(c *SeparatorContext) + + // EnterValue is called when entering the value production. + EnterValue(c *ValueContext) + + // EnterString is called when entering the string production. + EnterString(c *StringContext) + + // ExitLineStatement is called when exiting the lineStatement production. + ExitLineStatement(c *LineStatementContext) + + // ExitEntry is called when exiting the entry production. + ExitEntry(c *EntryContext) + + // ExitLeadingComment is called when exiting the leadingComment production. + ExitLeadingComment(c *LeadingCommentContext) + + // ExitKey is called when exiting the key production. + ExitKey(c *KeyContext) + + // ExitSeparator is called when exiting the separator production. + ExitSeparator(c *SeparatorContext) + + // ExitValue is called when exiting the value production. + ExitValue(c *ValueContext) + + // ExitString is called when exiting the string production. + ExitString(c *StringContext) +} diff --git a/server/handlers/gitconfig/ast/parser/config_parser.go b/server/handlers/gitconfig/ast/parser/config_parser.go new file mode 100644 index 0000000..79a75b9 --- /dev/null +++ b/server/handlers/gitconfig/ast/parser/config_parser.go @@ -0,0 +1,1086 @@ +// Code generated from Config.g4 by ANTLR 4.13.0. DO NOT EDIT. + +package parser // Config + +import ( + "fmt" + "strconv" + "sync" + + "github.com/antlr4-go/antlr/v4" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = strconv.Itoa +var _ = sync.Once{} + +type ConfigParser struct { + *antlr.BaseParser +} + +var ConfigParserStaticData struct { + once sync.Once + serializedATN []int32 + LiteralNames []string + SymbolicNames []string + RuleNames []string + PredictionContextCache *antlr.PredictionContextCache + atn *antlr.ATN + decisionToDFA []*antlr.DFA +} + +func configParserInit() { + staticData := &ConfigParserStaticData + staticData.LiteralNames = []string{ + "", "'='", "'#'", + } + staticData.SymbolicNames = []string{ + "", "EQUAL", "HASH", "WHITESPACE", "STRING", "QUOTED_STRING", + } + staticData.RuleNames = []string{ + "lineStatement", "entry", "leadingComment", "key", "separator", "value", + "string", + } + staticData.PredictionContextCache = antlr.NewPredictionContextCache() + staticData.serializedATN = []int32{ + 4, 1, 5, 53, 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, 1, 0, 1, 0, 1, 1, 3, 1, 19, 8, 1, 1, 1, 3, + 1, 22, 8, 1, 1, 1, 3, 1, 25, 8, 1, 1, 1, 3, 1, 28, 8, 1, 1, 1, 3, 1, 31, + 8, 1, 1, 2, 1, 2, 3, 2, 35, 8, 2, 1, 2, 1, 2, 3, 2, 39, 8, 2, 4, 2, 41, + 8, 2, 11, 2, 12, 2, 42, 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, 1, 1, 0, 4, 5, 53, 0, 14, 1, 0, + 0, 0, 2, 18, 1, 0, 0, 0, 4, 32, 1, 0, 0, 0, 6, 44, 1, 0, 0, 0, 8, 46, 1, + 0, 0, 0, 10, 48, 1, 0, 0, 0, 12, 50, 1, 0, 0, 0, 14, 15, 3, 2, 1, 0, 15, + 16, 5, 0, 0, 1, 16, 1, 1, 0, 0, 0, 17, 19, 5, 3, 0, 0, 18, 17, 1, 0, 0, + 0, 18, 19, 1, 0, 0, 0, 19, 21, 1, 0, 0, 0, 20, 22, 3, 6, 3, 0, 21, 20, + 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 24, 1, 0, 0, 0, 23, 25, 3, 8, 4, 0, + 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 3, + 10, 5, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, + 31, 3, 4, 2, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 3, 1, 0, 0, + 0, 32, 34, 5, 2, 0, 0, 33, 35, 5, 3, 0, 0, 34, 33, 1, 0, 0, 0, 34, 35, + 1, 0, 0, 0, 35, 40, 1, 0, 0, 0, 36, 38, 3, 12, 6, 0, 37, 39, 5, 3, 0, 0, + 38, 37, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 41, 1, 0, 0, 0, 40, 36, 1, + 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, + 5, 1, 0, 0, 0, 44, 45, 3, 12, 6, 0, 45, 7, 1, 0, 0, 0, 46, 47, 5, 1, 0, + 0, 47, 9, 1, 0, 0, 0, 48, 49, 3, 12, 6, 0, 49, 11, 1, 0, 0, 0, 50, 51, + 7, 0, 0, 0, 51, 13, 1, 0, 0, 0, 8, 18, 21, 24, 27, 30, 34, 38, 42, + } + 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) + } +} + +// ConfigParserInit initializes any static state used to implement ConfigParser. By default the +// static state used to implement the parser is lazily initialized during the first call to +// NewConfigParser(). You can call this function if you wish to initialize the static state ahead +// of time. +func ConfigParserInit() { + staticData := &ConfigParserStaticData + staticData.once.Do(configParserInit) +} + +// NewConfigParser produces a new parser instance for the optional input antlr.TokenStream. +func NewConfigParser(input antlr.TokenStream) *ConfigParser { + ConfigParserInit() + this := new(ConfigParser) + this.BaseParser = antlr.NewBaseParser(input) + staticData := &ConfigParserStaticData + 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 = "Config.g4" + + return this +} + +// ConfigParser tokens. +const ( + ConfigParserEOF = antlr.TokenEOF + ConfigParserEQUAL = 1 + ConfigParserHASH = 2 + ConfigParserWHITESPACE = 3 + ConfigParserSTRING = 4 + ConfigParserQUOTED_STRING = 5 +) + +// ConfigParser rules. +const ( + ConfigParserRULE_lineStatement = 0 + ConfigParserRULE_entry = 1 + ConfigParserRULE_leadingComment = 2 + ConfigParserRULE_key = 3 + ConfigParserRULE_separator = 4 + ConfigParserRULE_value = 5 + ConfigParserRULE_string = 6 +) + +// ILineStatementContext is an interface to support dynamic dispatch. +type ILineStatementContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + Entry() IEntryContext + EOF() antlr.TerminalNode + + // IsLineStatementContext differentiates from other interfaces. + IsLineStatementContext() +} + +type LineStatementContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyLineStatementContext() *LineStatementContext { + var p = new(LineStatementContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_lineStatement + return p +} + +func InitEmptyLineStatementContext(p *LineStatementContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_lineStatement +} + +func (*LineStatementContext) IsLineStatementContext() {} + +func NewLineStatementContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *LineStatementContext { + var p = new(LineStatementContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_lineStatement + + return p +} + +func (s *LineStatementContext) GetParser() antlr.Parser { return s.parser } + +func (s *LineStatementContext) Entry() IEntryContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IEntryContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IEntryContext) +} + +func (s *LineStatementContext) EOF() antlr.TerminalNode { + return s.GetToken(ConfigParserEOF, 0) +} + +func (s *LineStatementContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *LineStatementContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *LineStatementContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterLineStatement(s) + } +} + +func (s *LineStatementContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitLineStatement(s) + } +} + +func (p *ConfigParser) LineStatement() (localctx ILineStatementContext) { + localctx = NewLineStatementContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, ConfigParserRULE_lineStatement) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(14) + p.Entry() + } + { + p.SetState(15) + p.Match(ConfigParserEOF) + 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 +} + +// IEntryContext is an interface to support dynamic dispatch. +type IEntryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + WHITESPACE() antlr.TerminalNode + Key() IKeyContext + Separator() ISeparatorContext + Value() IValueContext + LeadingComment() ILeadingCommentContext + + // 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 = ConfigParserRULE_entry + return p +} + +func InitEmptyEntryContext(p *EntryContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_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 = ConfigParserRULE_entry + + return p +} + +func (s *EntryContext) GetParser() antlr.Parser { return s.parser } + +func (s *EntryContext) WHITESPACE() antlr.TerminalNode { + return s.GetToken(ConfigParserWHITESPACE, 0) +} + +func (s *EntryContext) Key() IKeyContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IKeyContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IKeyContext) +} + +func (s *EntryContext) Separator() ISeparatorContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ISeparatorContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ISeparatorContext) +} + +func (s *EntryContext) Value() IValueContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IValueContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IValueContext) +} + +func (s *EntryContext) LeadingComment() ILeadingCommentContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(ILeadingCommentContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(ILeadingCommentContext) +} + +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.(ConfigListener); ok { + listenerT.EnterEntry(s) + } +} + +func (s *EntryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitEntry(s) + } +} + +func (p *ConfigParser) Entry() (localctx IEntryContext) { + localctx = NewEntryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, ConfigParserRULE_entry) + var _la int + + p.EnterOuterAlt(localctx, 1) + p.SetState(18) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserWHITESPACE { + { + p.SetState(17) + p.Match(ConfigParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + p.SetState(21) + p.GetErrorHandler().Sync(p) + + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 1, p.GetParserRuleContext()) == 1 { + { + p.SetState(20) + p.Key() + } + + } else if p.HasError() { // JIM + goto errorExit + } + p.SetState(24) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserEQUAL { + { + p.SetState(23) + p.Separator() + } + + } + p.SetState(27) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserSTRING || _la == ConfigParserQUOTED_STRING { + { + p.SetState(26) + p.Value() + } + + } + p.SetState(30) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserHASH { + { + p.SetState(29) + p.LeadingComment() + } + + } + +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 +} + +// ILeadingCommentContext is an interface to support dynamic dispatch. +type ILeadingCommentContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + HASH() antlr.TerminalNode + AllWHITESPACE() []antlr.TerminalNode + WHITESPACE(i int) antlr.TerminalNode + AllString_() []IStringContext + String_(i int) IStringContext + + // IsLeadingCommentContext differentiates from other interfaces. + IsLeadingCommentContext() +} + +type LeadingCommentContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyLeadingCommentContext() *LeadingCommentContext { + var p = new(LeadingCommentContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_leadingComment + return p +} + +func InitEmptyLeadingCommentContext(p *LeadingCommentContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_leadingComment +} + +func (*LeadingCommentContext) IsLeadingCommentContext() {} + +func NewLeadingCommentContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *LeadingCommentContext { + var p = new(LeadingCommentContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_leadingComment + + return p +} + +func (s *LeadingCommentContext) GetParser() antlr.Parser { return s.parser } + +func (s *LeadingCommentContext) HASH() antlr.TerminalNode { + return s.GetToken(ConfigParserHASH, 0) +} + +func (s *LeadingCommentContext) AllWHITESPACE() []antlr.TerminalNode { + return s.GetTokens(ConfigParserWHITESPACE) +} + +func (s *LeadingCommentContext) WHITESPACE(i int) antlr.TerminalNode { + return s.GetToken(ConfigParserWHITESPACE, i) +} + +func (s *LeadingCommentContext) AllString_() []IStringContext { + children := s.GetChildren() + len := 0 + for _, ctx := range children { + if _, ok := ctx.(IStringContext); ok { + len++ + } + } + + tst := make([]IStringContext, len) + i := 0 + for _, ctx := range children { + if t, ok := ctx.(IStringContext); ok { + tst[i] = t.(IStringContext) + i++ + } + } + + return tst +} + +func (s *LeadingCommentContext) String_(i int) IStringContext { + var t antlr.RuleContext + j := 0 + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IStringContext); ok { + if j == i { + t = ctx.(antlr.RuleContext) + break + } + j++ + } + } + + if t == nil { + return nil + } + + return t.(IStringContext) +} + +func (s *LeadingCommentContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *LeadingCommentContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *LeadingCommentContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterLeadingComment(s) + } +} + +func (s *LeadingCommentContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitLeadingComment(s) + } +} + +func (p *ConfigParser) LeadingComment() (localctx ILeadingCommentContext) { + localctx = NewLeadingCommentContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 4, ConfigParserRULE_leadingComment) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(32) + p.Match(ConfigParserHASH) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + p.SetState(34) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserWHITESPACE { + { + p.SetState(33) + p.Match(ConfigParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + p.SetState(40) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for ok := true; ok; ok = _la == ConfigParserSTRING || _la == ConfigParserQUOTED_STRING { + { + p.SetState(36) + p.String_() + } + p.SetState(38) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + if _la == ConfigParserWHITESPACE { + { + p.SetState(37) + p.Match(ConfigParserWHITESPACE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + + p.SetState(42) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + } + +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 +} + +// IKeyContext is an interface to support dynamic dispatch. +type IKeyContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + String_() IStringContext + + // IsKeyContext differentiates from other interfaces. + IsKeyContext() +} + +type KeyContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyKeyContext() *KeyContext { + var p = new(KeyContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_key + return p +} + +func InitEmptyKeyContext(p *KeyContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_key +} + +func (*KeyContext) IsKeyContext() {} + +func NewKeyContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *KeyContext { + var p = new(KeyContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_key + + return p +} + +func (s *KeyContext) GetParser() antlr.Parser { return s.parser } + +func (s *KeyContext) String_() IStringContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IStringContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IStringContext) +} + +func (s *KeyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *KeyContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *KeyContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterKey(s) + } +} + +func (s *KeyContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitKey(s) + } +} + +func (p *ConfigParser) Key() (localctx IKeyContext) { + localctx = NewKeyContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, ConfigParserRULE_key) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(44) + p.String_() + } + +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 +} + +// ISeparatorContext is an interface to support dynamic dispatch. +type ISeparatorContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + EQUAL() antlr.TerminalNode + + // IsSeparatorContext differentiates from other interfaces. + IsSeparatorContext() +} + +type SeparatorContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptySeparatorContext() *SeparatorContext { + var p = new(SeparatorContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_separator + return p +} + +func InitEmptySeparatorContext(p *SeparatorContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_separator +} + +func (*SeparatorContext) IsSeparatorContext() {} + +func NewSeparatorContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SeparatorContext { + var p = new(SeparatorContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_separator + + return p +} + +func (s *SeparatorContext) GetParser() antlr.Parser { return s.parser } + +func (s *SeparatorContext) EQUAL() antlr.TerminalNode { + return s.GetToken(ConfigParserEQUAL, 0) +} + +func (s *SeparatorContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *SeparatorContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *SeparatorContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterSeparator(s) + } +} + +func (s *SeparatorContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitSeparator(s) + } +} + +func (p *ConfigParser) Separator() (localctx ISeparatorContext) { + localctx = NewSeparatorContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, ConfigParserRULE_separator) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(46) + p.Match(ConfigParserEQUAL) + 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 +} + +// IValueContext is an interface to support dynamic dispatch. +type IValueContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + String_() IStringContext + + // IsValueContext differentiates from other interfaces. + IsValueContext() +} + +type ValueContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyValueContext() *ValueContext { + var p = new(ValueContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_value + return p +} + +func InitEmptyValueContext(p *ValueContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_value +} + +func (*ValueContext) IsValueContext() {} + +func NewValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ValueContext { + var p = new(ValueContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_value + + return p +} + +func (s *ValueContext) GetParser() antlr.Parser { return s.parser } + +func (s *ValueContext) String_() IStringContext { + var t antlr.RuleContext + for _, ctx := range s.GetChildren() { + if _, ok := ctx.(IStringContext); ok { + t = ctx.(antlr.RuleContext) + break + } + } + + if t == nil { + return nil + } + + return t.(IStringContext) +} + +func (s *ValueContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ValueContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *ValueContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterValue(s) + } +} + +func (s *ValueContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitValue(s) + } +} + +func (p *ConfigParser) Value() (localctx IValueContext) { + localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, ConfigParserRULE_value) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(48) + p.String_() + } + +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 +} + +// IStringContext is an interface to support dynamic dispatch. +type IStringContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // Getter signatures + QUOTED_STRING() antlr.TerminalNode + STRING() antlr.TerminalNode + + // IsStringContext differentiates from other interfaces. + IsStringContext() +} + +type StringContext struct { + antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyStringContext() *StringContext { + var p = new(StringContext) + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_string + return p +} + +func InitEmptyStringContext(p *StringContext) { + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) + p.RuleIndex = ConfigParserRULE_string +} + +func (*StringContext) IsStringContext() {} + +func NewStringContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *StringContext { + var p = new(StringContext) + + antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) + + p.parser = parser + p.RuleIndex = ConfigParserRULE_string + + return p +} + +func (s *StringContext) GetParser() antlr.Parser { return s.parser } + +func (s *StringContext) QUOTED_STRING() antlr.TerminalNode { + return s.GetToken(ConfigParserQUOTED_STRING, 0) +} + +func (s *StringContext) STRING() antlr.TerminalNode { + return s.GetToken(ConfigParserSTRING, 0) +} + +func (s *StringContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *StringContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *StringContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.EnterString(s) + } +} + +func (s *StringContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(ConfigListener); ok { + listenerT.ExitString(s) + } +} + +func (p *ConfigParser) String_() (localctx IStringContext) { + localctx = NewStringContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 12, ConfigParserRULE_string) + var _la int + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(50) + _la = p.GetTokenStream().LA(1) + + if !(_la == ConfigParserSTRING || _la == ConfigParserQUOTED_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 +} diff --git a/server/update_antlr_parser.sh b/server/update_antlr_parser.sh index 9534937..cab7e92 100755 --- a/server/update_antlr_parser.sh +++ b/server/update_antlr_parser.sh @@ -6,7 +6,10 @@ ROOT=$(git rev-parse --show-toplevel)/server 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 +cd $ROOT/handlers/fstab && antlr4 -Dlanguage=Go -o ast/parser Fstab.g4 + +# gitconfig +cd $ROOT/handlers/gitconfig && antlr4 -Dlanguage=Go -o ast/parser Config.g4 # sshd_config cd $ROOT/handlers/sshd_config && antlr4 -Dlanguage=Go -o ast/parser Config.g4