feat(sshd_config): Add antlr parser for match option

This commit is contained in:
Myzel394 2024-09-14 22:22:01 +02:00
parent d3b655dc68
commit 83d7ac144f
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
15 changed files with 1625 additions and 11 deletions

View File

@ -8,17 +8,6 @@ import (
"strings" "strings"
) )
func createListener(
config *SSHConfig,
context *sshListenerContext,
) sshParserListener {
return sshParserListener{
Config: config,
Errors: make([]common.LSPError, 0),
sshContext: context,
}
}
type sshListenerContext struct { type sshListenerContext struct {
line uint32 line uint32
currentOption *SSHOption currentOption *SSHOption
@ -33,6 +22,17 @@ func createSSHListenerContext() *sshListenerContext {
return context return context
} }
func createListener(
config *SSHConfig,
context *sshListenerContext,
) sshParserListener {
return sshParserListener{
Config: config,
Errors: make([]common.LSPError, 0),
sshContext: context,
}
}
type sshParserListener struct { type sshParserListener struct {
*parser.BaseConfigListener *parser.BaseConfigListener
Config *SSHConfig Config *SSHConfig

View File

@ -0,0 +1,67 @@
grammar Match;
root
: matchEntry? (WHITESPACE matchEntry)* EOF
;
matchEntry
: criteria WHITESPACE? values?
;
criteria
: USER
| GROUP
| HOST
| LOCALADDRESS
| LOCALPORT
| RDOMAIN
| ADDRESS
;
values
: value? (COMMA value?)*
;
value
: STRING
;
USER
: ('U'|'u') ('S'|'s') ('E'|'e') ('R'|'r')
;
GROUP
: ('G'|'g') ('R'|'r') ('O'|'o') ('U'|'u') ('P'|'p')
;
HOST
: ('H'|'h') ('O'|'o') ('S'|'s') ('T'|'t')
;
LOCALADDRESS
: ('L'|'l') ('O'|'o') ('C'|'c') ('A'|'a') ('L'|'l') ('A'|'a') ('D'|'d') ('D'|'d') ('R'|'r') ('E'|'e') ('S'|'s') ('S'|'s')
;
LOCALPORT
: ('L'|'l') ('O'|'o') ('C'|'c') ('A'|'a') ('L'|'l') ('P'|'p') ('O'|'o') ('R'|'r') ('T'|'t')
;
RDOMAIN
: ('R'|'r') ('D'|'d') ('O'|'o') ('M'|'m') ('A'|'a') ('I'|'i') ('N'|'n')
;
ADDRESS
: ('A'|'a') ('D'|'d') ('D'|'d') ('R'|'r') ('E'|'e') ('S'|'s') ('S'|'s')
;
COMMA
: ','
;
STRING
: ~(' ' | '\t' | '\r' | '\n' | '#' | ',')+
;
WHITESPACE
: [ \t]+
;

View File

@ -0,0 +1,45 @@
package match_parser
import (
"config-lsp/common"
"github.com/antlr4-go/antlr/v4"
)
type errorListenerContext struct {
line uint32
}
func createErrorListener(
line uint32,
) errorListener {
return errorListener{
Errors: make([]common.LSPError, 0),
context: errorListenerContext{
line: line,
},
}
}
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,
},
})
}

View File

@ -0,0 +1,99 @@
package match_parser
import (
"config-lsp/common"
"config-lsp/handlers/sshd_config/fields/match-parser/parser"
"config-lsp/utils"
"errors"
"fmt"
"strings"
)
func createMatchListenerContext(
line uint32,
) *matchListenerContext {
return &matchListenerContext{
currentEntry: nil,
line: line,
}
}
type matchListenerContext struct {
currentEntry *MatchEntry
line uint32
}
func createListener(
match *Match,
context *matchListenerContext,
) matchParserListener {
return matchParserListener{
match: match,
Errors: make([]common.LSPError, 0),
matchContext: context,
}
}
type matchParserListener struct {
*parser.BaseMatchListener
match *Match
Errors []common.LSPError
matchContext *matchListenerContext
}
func (s *matchParserListener) EnterMatchEntry(ctx *parser.MatchEntryContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.matchContext.line)
entry := &MatchEntry{
LocationRange: location,
Value: ctx.GetText(),
Values: make([]*MatchValue, 0),
}
s.match.Entries = append(s.match.Entries, entry)
s.matchContext.currentEntry = entry
}
func (s *matchParserListener) ExitMatchEntry(ctx *parser.MatchEntryContext) {
s.matchContext.currentEntry = nil
}
var availableCriteria = map[string]MatchCriteriaType{
string(MatchCriteriaTypeUser): MatchCriteriaTypeUser,
string(MatchCriteriaTypeGroup): MatchCriteriaTypeGroup,
string(MatchCriteriaTypeHost): MatchCriteriaTypeHost,
string(MatchCriteriaTypeLocalAddress): MatchCriteriaTypeLocalAddress,
string(MatchCriteriaTypeLocalPort): MatchCriteriaTypeLocalPort,
string(MatchCriteriaTypeRDomain): MatchCriteriaTypeRDomain,
string(MatchCriteriaTypeAddress): MatchCriteriaTypeAddress,
}
func (s *matchParserListener) EnterCriteria(ctx *parser.CriteriaContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.matchContext.line)
criteria, found := availableCriteria[ctx.GetText()]
if !found {
s.Errors = append(s.Errors, common.LSPError{
Range: location,
Err: errors.New(fmt.Sprintf("Unknown criteria: %s; It must be one of: %s", ctx.GetText(), strings.Join(utils.KeysOfMap(availableCriteria), ", "))),
})
return
}
s.matchContext.currentEntry.Criteria = criteria
}
func (s *matchParserListener) EnterValue(ctx *parser.ValueContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.matchContext.line)
value := &MatchValue{
LocationRange: location,
Value: ctx.GetText(),
}
s.matchContext.currentEntry.Values = append(s.matchContext.currentEntry.Values, value)
}

View File

@ -0,0 +1,40 @@
package match_parser
import (
"config-lsp/common"
)
type Match struct {
Entries []*MatchEntry
}
type MatchCriteriaType string
const (
MatchCriteriaTypeUser MatchCriteriaType = "User"
MatchCriteriaTypeGroup MatchCriteriaType = "Group"
MatchCriteriaTypeHost MatchCriteriaType = "Host"
MatchCriteriaTypeLocalAddress MatchCriteriaType = "LocalAddress"
MatchCriteriaTypeLocalPort MatchCriteriaType = "LocalPort"
MatchCriteriaTypeRDomain MatchCriteriaType = "RDomain"
MatchCriteriaTypeAddress MatchCriteriaType = "Address"
)
type MatchCriteria struct {
common.LocationRange
Type MatchCriteriaType
}
type MatchEntry struct {
common.LocationRange
Value string
Criteria MatchCriteriaType
Values []*MatchValue
}
type MatchValue struct {
common.LocationRange
Value string
}

View File

@ -0,0 +1,52 @@
package match_parser
import (
"config-lsp/common"
"config-lsp/handlers/sshd_config/fields/match-parser/parser"
"github.com/antlr4-go/antlr/v4"
)
func NewMatch() *Match {
match := new(Match)
match.Clear()
return match
}
func (m *Match) Clear() {
m.Entries = make([]*MatchEntry, 0)
}
func (m *Match) Parse(
input string,
line uint32,
) []common.LSPError {
context := createMatchListenerContext(line)
stream := antlr.NewInputStream(input)
lexerErrorListener := createErrorListener(context.line)
lexer := parser.NewMatchLexer(stream)
lexer.RemoveErrorListeners()
lexer.AddErrorListener(&lexerErrorListener)
tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
parserErrorListener := createErrorListener(context.line)
antlrParser := parser.NewMatchParser(tokenStream)
antlrParser.RemoveErrorListeners()
antlrParser.AddErrorListener(&parserErrorListener)
listener := createListener(m, context)
antlr.ParseTreeWalkerDefault.Walk(
&listener,
antlrParser.Root(),
)
errors := lexerErrorListener.Errors
errors = append(errors, parserErrorListener.Errors...)
errors = append(errors, listener.Errors...)
return errors
}

View File

@ -0,0 +1,36 @@
token literal names:
null
null
null
null
null
null
null
null
','
null
null
token symbolic names:
null
USER
GROUP
HOST
LOCALADDRESS
LOCALPORT
RDOMAIN
ADDRESS
COMMA
STRING
WHITESPACE
rule names:
root
matchEntry
criteria
values
value
atn:
[4, 1, 10, 46, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 3, 0, 12, 8, 0, 1, 0, 1, 0, 5, 0, 16, 8, 0, 10, 0, 12, 0, 19, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 3, 1, 25, 8, 1, 1, 1, 3, 1, 28, 8, 1, 1, 2, 1, 2, 1, 3, 3, 3, 33, 8, 3, 1, 3, 1, 3, 3, 3, 37, 8, 3, 5, 3, 39, 8, 3, 10, 3, 12, 3, 42, 9, 3, 1, 4, 1, 4, 1, 4, 0, 0, 5, 0, 2, 4, 6, 8, 0, 1, 1, 0, 1, 7, 47, 0, 11, 1, 0, 0, 0, 2, 22, 1, 0, 0, 0, 4, 29, 1, 0, 0, 0, 6, 32, 1, 0, 0, 0, 8, 43, 1, 0, 0, 0, 10, 12, 3, 2, 1, 0, 11, 10, 1, 0, 0, 0, 11, 12, 1, 0, 0, 0, 12, 17, 1, 0, 0, 0, 13, 14, 5, 10, 0, 0, 14, 16, 3, 2, 1, 0, 15, 13, 1, 0, 0, 0, 16, 19, 1, 0, 0, 0, 17, 15, 1, 0, 0, 0, 17, 18, 1, 0, 0, 0, 18, 20, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 20, 21, 5, 0, 0, 1, 21, 1, 1, 0, 0, 0, 22, 24, 3, 4, 2, 0, 23, 25, 5, 10, 0, 0, 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 3, 6, 3, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 3, 1, 0, 0, 0, 29, 30, 7, 0, 0, 0, 30, 5, 1, 0, 0, 0, 31, 33, 3, 8, 4, 0, 32, 31, 1, 0, 0, 0, 32, 33, 1, 0, 0, 0, 33, 40, 1, 0, 0, 0, 34, 36, 5, 8, 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, 34, 1, 0, 0, 0, 39, 42, 1, 0, 0, 0, 40, 38, 1, 0, 0, 0, 40, 41, 1, 0, 0, 0, 41, 7, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 43, 44, 5, 9, 0, 0, 44, 9, 1, 0, 0, 0, 7, 11, 17, 24, 27, 32, 36, 40]

View File

@ -0,0 +1,11 @@
USER=1
GROUP=2
HOST=3
LOCALADDRESS=4
LOCALPORT=5
RDOMAIN=6
ADDRESS=7
COMMA=8
STRING=9
WHITESPACE=10
','=8

View File

@ -0,0 +1,47 @@
token literal names:
null
null
null
null
null
null
null
null
','
null
null
token symbolic names:
null
USER
GROUP
HOST
LOCALADDRESS
LOCALPORT
RDOMAIN
ADDRESS
COMMA
STRING
WHITESPACE
rule names:
USER
GROUP
HOST
LOCALADDRESS
LOCALPORT
RDOMAIN
ADDRESS
COMMA
STRING
WHITESPACE
channel names:
DEFAULT_TOKEN_CHANNEL
HIDDEN
mode names:
DEFAULT_MODE
atn:
[4, 0, 10, 88, 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, 2, 9, 7, 9, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 4, 8, 80, 8, 8, 11, 8, 12, 8, 81, 1, 9, 4, 9, 85, 8, 9, 11, 9, 12, 9, 86, 0, 0, 10, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 1, 0, 18, 2, 0, 85, 85, 117, 117, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101, 2, 0, 82, 82, 114, 114, 2, 0, 71, 71, 103, 103, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 72, 72, 104, 104, 2, 0, 84, 84, 116, 116, 2, 0, 76, 76, 108, 108, 2, 0, 67, 67, 99, 99, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 77, 77, 109, 109, 2, 0, 73, 73, 105, 105, 2, 0, 78, 78, 110, 110, 5, 0, 9, 10, 13, 13, 32, 32, 35, 35, 44, 44, 2, 0, 9, 9, 32, 32, 89, 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, 0, 19, 1, 0, 0, 0, 1, 21, 1, 0, 0, 0, 3, 26, 1, 0, 0, 0, 5, 32, 1, 0, 0, 0, 7, 37, 1, 0, 0, 0, 9, 50, 1, 0, 0, 0, 11, 60, 1, 0, 0, 0, 13, 68, 1, 0, 0, 0, 15, 76, 1, 0, 0, 0, 17, 79, 1, 0, 0, 0, 19, 84, 1, 0, 0, 0, 21, 22, 7, 0, 0, 0, 22, 23, 7, 1, 0, 0, 23, 24, 7, 2, 0, 0, 24, 25, 7, 3, 0, 0, 25, 2, 1, 0, 0, 0, 26, 27, 7, 4, 0, 0, 27, 28, 7, 3, 0, 0, 28, 29, 7, 5, 0, 0, 29, 30, 7, 0, 0, 0, 30, 31, 7, 6, 0, 0, 31, 4, 1, 0, 0, 0, 32, 33, 7, 7, 0, 0, 33, 34, 7, 5, 0, 0, 34, 35, 7, 1, 0, 0, 35, 36, 7, 8, 0, 0, 36, 6, 1, 0, 0, 0, 37, 38, 7, 9, 0, 0, 38, 39, 7, 5, 0, 0, 39, 40, 7, 10, 0, 0, 40, 41, 7, 11, 0, 0, 41, 42, 7, 9, 0, 0, 42, 43, 7, 11, 0, 0, 43, 44, 7, 12, 0, 0, 44, 45, 7, 12, 0, 0, 45, 46, 7, 3, 0, 0, 46, 47, 7, 2, 0, 0, 47, 48, 7, 1, 0, 0, 48, 49, 7, 1, 0, 0, 49, 8, 1, 0, 0, 0, 50, 51, 7, 9, 0, 0, 51, 52, 7, 5, 0, 0, 52, 53, 7, 10, 0, 0, 53, 54, 7, 11, 0, 0, 54, 55, 7, 9, 0, 0, 55, 56, 7, 6, 0, 0, 56, 57, 7, 5, 0, 0, 57, 58, 7, 3, 0, 0, 58, 59, 7, 8, 0, 0, 59, 10, 1, 0, 0, 0, 60, 61, 7, 3, 0, 0, 61, 62, 7, 12, 0, 0, 62, 63, 7, 5, 0, 0, 63, 64, 7, 13, 0, 0, 64, 65, 7, 11, 0, 0, 65, 66, 7, 14, 0, 0, 66, 67, 7, 15, 0, 0, 67, 12, 1, 0, 0, 0, 68, 69, 7, 11, 0, 0, 69, 70, 7, 12, 0, 0, 70, 71, 7, 12, 0, 0, 71, 72, 7, 3, 0, 0, 72, 73, 7, 2, 0, 0, 73, 74, 7, 1, 0, 0, 74, 75, 7, 1, 0, 0, 75, 14, 1, 0, 0, 0, 76, 77, 5, 44, 0, 0, 77, 16, 1, 0, 0, 0, 78, 80, 8, 16, 0, 0, 79, 78, 1, 0, 0, 0, 80, 81, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 18, 1, 0, 0, 0, 83, 85, 7, 17, 0, 0, 84, 83, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 20, 1, 0, 0, 0, 3, 0, 81, 86, 0]

View File

@ -0,0 +1,11 @@
USER=1
GROUP=2
HOST=3
LOCALADDRESS=4
LOCALPORT=5
RDOMAIN=6
ADDRESS=7
COMMA=8
STRING=9
WHITESPACE=10
','=8

View File

@ -0,0 +1,52 @@
// Code generated from Match.g4 by ANTLR 4.13.0. DO NOT EDIT.
package parser // Match
import "github.com/antlr4-go/antlr/v4"
// BaseMatchListener is a complete listener for a parse tree produced by MatchParser.
type BaseMatchListener struct{}
var _ MatchListener = &BaseMatchListener{}
// VisitTerminal is called when a terminal node is visited.
func (s *BaseMatchListener) VisitTerminal(node antlr.TerminalNode) {}
// VisitErrorNode is called when an error node is visited.
func (s *BaseMatchListener) VisitErrorNode(node antlr.ErrorNode) {}
// EnterEveryRule is called when any rule is entered.
func (s *BaseMatchListener) EnterEveryRule(ctx antlr.ParserRuleContext) {}
// ExitEveryRule is called when any rule is exited.
func (s *BaseMatchListener) ExitEveryRule(ctx antlr.ParserRuleContext) {}
// EnterRoot is called when production root is entered.
func (s *BaseMatchListener) EnterRoot(ctx *RootContext) {}
// ExitRoot is called when production root is exited.
func (s *BaseMatchListener) ExitRoot(ctx *RootContext) {}
// EnterMatchEntry is called when production matchEntry is entered.
func (s *BaseMatchListener) EnterMatchEntry(ctx *MatchEntryContext) {}
// ExitMatchEntry is called when production matchEntry is exited.
func (s *BaseMatchListener) ExitMatchEntry(ctx *MatchEntryContext) {}
// EnterCriteria is called when production criteria is entered.
func (s *BaseMatchListener) EnterCriteria(ctx *CriteriaContext) {}
// ExitCriteria is called when production criteria is exited.
func (s *BaseMatchListener) ExitCriteria(ctx *CriteriaContext) {}
// EnterValues is called when production values is entered.
func (s *BaseMatchListener) EnterValues(ctx *ValuesContext) {}
// ExitValues is called when production values is exited.
func (s *BaseMatchListener) ExitValues(ctx *ValuesContext) {}
// EnterValue is called when production value is entered.
func (s *BaseMatchListener) EnterValue(ctx *ValueContext) {}
// ExitValue is called when production value is exited.
func (s *BaseMatchListener) ExitValue(ctx *ValueContext) {}

View File

@ -0,0 +1,148 @@
// Code generated from Match.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 MatchLexer struct {
*antlr.BaseLexer
channelNames []string
modeNames []string
// TODO: EOF string
}
var MatchLexerLexerStaticData 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 matchlexerLexerInit() {
staticData := &MatchLexerLexerStaticData
staticData.ChannelNames = []string{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
}
staticData.ModeNames = []string{
"DEFAULT_MODE",
}
staticData.LiteralNames = []string{
"", "", "", "", "", "", "", "", "','",
}
staticData.SymbolicNames = []string{
"", "USER", "GROUP", "HOST", "LOCALADDRESS", "LOCALPORT", "RDOMAIN",
"ADDRESS", "COMMA", "STRING", "WHITESPACE",
}
staticData.RuleNames = []string{
"USER", "GROUP", "HOST", "LOCALADDRESS", "LOCALPORT", "RDOMAIN", "ADDRESS",
"COMMA", "STRING", "WHITESPACE",
}
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
4, 0, 10, 88, 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, 2, 9, 7, 9, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1,
4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1,
6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 4, 8, 80, 8, 8,
11, 8, 12, 8, 81, 1, 9, 4, 9, 85, 8, 9, 11, 9, 12, 9, 86, 0, 0, 10, 1,
1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 1, 0, 18,
2, 0, 85, 85, 117, 117, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101,
2, 0, 82, 82, 114, 114, 2, 0, 71, 71, 103, 103, 2, 0, 79, 79, 111, 111,
2, 0, 80, 80, 112, 112, 2, 0, 72, 72, 104, 104, 2, 0, 84, 84, 116, 116,
2, 0, 76, 76, 108, 108, 2, 0, 67, 67, 99, 99, 2, 0, 65, 65, 97, 97, 2,
0, 68, 68, 100, 100, 2, 0, 77, 77, 109, 109, 2, 0, 73, 73, 105, 105, 2,
0, 78, 78, 110, 110, 5, 0, 9, 10, 13, 13, 32, 32, 35, 35, 44, 44, 2, 0,
9, 9, 32, 32, 89, 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, 0, 19, 1, 0, 0, 0, 1, 21, 1, 0,
0, 0, 3, 26, 1, 0, 0, 0, 5, 32, 1, 0, 0, 0, 7, 37, 1, 0, 0, 0, 9, 50, 1,
0, 0, 0, 11, 60, 1, 0, 0, 0, 13, 68, 1, 0, 0, 0, 15, 76, 1, 0, 0, 0, 17,
79, 1, 0, 0, 0, 19, 84, 1, 0, 0, 0, 21, 22, 7, 0, 0, 0, 22, 23, 7, 1, 0,
0, 23, 24, 7, 2, 0, 0, 24, 25, 7, 3, 0, 0, 25, 2, 1, 0, 0, 0, 26, 27, 7,
4, 0, 0, 27, 28, 7, 3, 0, 0, 28, 29, 7, 5, 0, 0, 29, 30, 7, 0, 0, 0, 30,
31, 7, 6, 0, 0, 31, 4, 1, 0, 0, 0, 32, 33, 7, 7, 0, 0, 33, 34, 7, 5, 0,
0, 34, 35, 7, 1, 0, 0, 35, 36, 7, 8, 0, 0, 36, 6, 1, 0, 0, 0, 37, 38, 7,
9, 0, 0, 38, 39, 7, 5, 0, 0, 39, 40, 7, 10, 0, 0, 40, 41, 7, 11, 0, 0,
41, 42, 7, 9, 0, 0, 42, 43, 7, 11, 0, 0, 43, 44, 7, 12, 0, 0, 44, 45, 7,
12, 0, 0, 45, 46, 7, 3, 0, 0, 46, 47, 7, 2, 0, 0, 47, 48, 7, 1, 0, 0, 48,
49, 7, 1, 0, 0, 49, 8, 1, 0, 0, 0, 50, 51, 7, 9, 0, 0, 51, 52, 7, 5, 0,
0, 52, 53, 7, 10, 0, 0, 53, 54, 7, 11, 0, 0, 54, 55, 7, 9, 0, 0, 55, 56,
7, 6, 0, 0, 56, 57, 7, 5, 0, 0, 57, 58, 7, 3, 0, 0, 58, 59, 7, 8, 0, 0,
59, 10, 1, 0, 0, 0, 60, 61, 7, 3, 0, 0, 61, 62, 7, 12, 0, 0, 62, 63, 7,
5, 0, 0, 63, 64, 7, 13, 0, 0, 64, 65, 7, 11, 0, 0, 65, 66, 7, 14, 0, 0,
66, 67, 7, 15, 0, 0, 67, 12, 1, 0, 0, 0, 68, 69, 7, 11, 0, 0, 69, 70, 7,
12, 0, 0, 70, 71, 7, 12, 0, 0, 71, 72, 7, 3, 0, 0, 72, 73, 7, 2, 0, 0,
73, 74, 7, 1, 0, 0, 74, 75, 7, 1, 0, 0, 75, 14, 1, 0, 0, 0, 76, 77, 5,
44, 0, 0, 77, 16, 1, 0, 0, 0, 78, 80, 8, 16, 0, 0, 79, 78, 1, 0, 0, 0,
80, 81, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 18, 1,
0, 0, 0, 83, 85, 7, 17, 0, 0, 84, 83, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86,
84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 20, 1, 0, 0, 0, 3, 0, 81, 86, 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)
}
}
// MatchLexerInit initializes any static state used to implement MatchLexer. By default the
// static state used to implement the lexer is lazily initialized during the first call to
// NewMatchLexer(). You can call this function if you wish to initialize the static state ahead
// of time.
func MatchLexerInit() {
staticData := &MatchLexerLexerStaticData
staticData.once.Do(matchlexerLexerInit)
}
// NewMatchLexer produces a new lexer instance for the optional input antlr.CharStream.
func NewMatchLexer(input antlr.CharStream) *MatchLexer {
MatchLexerInit()
l := new(MatchLexer)
l.BaseLexer = antlr.NewBaseLexer(input)
staticData := &MatchLexerLexerStaticData
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 = "Match.g4"
// TODO: l.EOF = antlr.TokenEOF
return l
}
// MatchLexer tokens.
const (
MatchLexerUSER = 1
MatchLexerGROUP = 2
MatchLexerHOST = 3
MatchLexerLOCALADDRESS = 4
MatchLexerLOCALPORT = 5
MatchLexerRDOMAIN = 6
MatchLexerADDRESS = 7
MatchLexerCOMMA = 8
MatchLexerSTRING = 9
MatchLexerWHITESPACE = 10
)

View File

@ -0,0 +1,40 @@
// Code generated from Match.g4 by ANTLR 4.13.0. DO NOT EDIT.
package parser // Match
import "github.com/antlr4-go/antlr/v4"
// MatchListener is a complete listener for a parse tree produced by MatchParser.
type MatchListener interface {
antlr.ParseTreeListener
// EnterRoot is called when entering the root production.
EnterRoot(c *RootContext)
// EnterMatchEntry is called when entering the matchEntry production.
EnterMatchEntry(c *MatchEntryContext)
// EnterCriteria is called when entering the criteria production.
EnterCriteria(c *CriteriaContext)
// EnterValues is called when entering the values production.
EnterValues(c *ValuesContext)
// EnterValue is called when entering the value production.
EnterValue(c *ValueContext)
// ExitRoot is called when exiting the root production.
ExitRoot(c *RootContext)
// ExitMatchEntry is called when exiting the matchEntry production.
ExitMatchEntry(c *MatchEntryContext)
// ExitCriteria is called when exiting the criteria production.
ExitCriteria(c *CriteriaContext)
// ExitValues is called when exiting the values production.
ExitValues(c *ValuesContext)
// ExitValue is called when exiting the value production.
ExitValue(c *ValueContext)
}

View File

@ -0,0 +1,887 @@
// Code generated from Match.g4 by ANTLR 4.13.0. DO NOT EDIT.
package parser // Match
import (
"fmt"
"strconv"
"sync"
"github.com/antlr4-go/antlr/v4"
)
// Suppress unused import errors
var _ = fmt.Printf
var _ = strconv.Itoa
var _ = sync.Once{}
type MatchParser struct {
*antlr.BaseParser
}
var MatchParserStaticData struct {
once sync.Once
serializedATN []int32
LiteralNames []string
SymbolicNames []string
RuleNames []string
PredictionContextCache *antlr.PredictionContextCache
atn *antlr.ATN
decisionToDFA []*antlr.DFA
}
func matchParserInit() {
staticData := &MatchParserStaticData
staticData.LiteralNames = []string{
"", "", "", "", "", "", "", "", "','",
}
staticData.SymbolicNames = []string{
"", "USER", "GROUP", "HOST", "LOCALADDRESS", "LOCALPORT", "RDOMAIN",
"ADDRESS", "COMMA", "STRING", "WHITESPACE",
}
staticData.RuleNames = []string{
"root", "matchEntry", "criteria", "values", "value",
}
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
4, 1, 10, 46, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7,
4, 1, 0, 3, 0, 12, 8, 0, 1, 0, 1, 0, 5, 0, 16, 8, 0, 10, 0, 12, 0, 19,
9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 3, 1, 25, 8, 1, 1, 1, 3, 1, 28, 8, 1, 1,
2, 1, 2, 1, 3, 3, 3, 33, 8, 3, 1, 3, 1, 3, 3, 3, 37, 8, 3, 5, 3, 39, 8,
3, 10, 3, 12, 3, 42, 9, 3, 1, 4, 1, 4, 1, 4, 0, 0, 5, 0, 2, 4, 6, 8, 0,
1, 1, 0, 1, 7, 47, 0, 11, 1, 0, 0, 0, 2, 22, 1, 0, 0, 0, 4, 29, 1, 0, 0,
0, 6, 32, 1, 0, 0, 0, 8, 43, 1, 0, 0, 0, 10, 12, 3, 2, 1, 0, 11, 10, 1,
0, 0, 0, 11, 12, 1, 0, 0, 0, 12, 17, 1, 0, 0, 0, 13, 14, 5, 10, 0, 0, 14,
16, 3, 2, 1, 0, 15, 13, 1, 0, 0, 0, 16, 19, 1, 0, 0, 0, 17, 15, 1, 0, 0,
0, 17, 18, 1, 0, 0, 0, 18, 20, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 20, 21,
5, 0, 0, 1, 21, 1, 1, 0, 0, 0, 22, 24, 3, 4, 2, 0, 23, 25, 5, 10, 0, 0,
24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 3,
6, 3, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 3, 1, 0, 0, 0, 29,
30, 7, 0, 0, 0, 30, 5, 1, 0, 0, 0, 31, 33, 3, 8, 4, 0, 32, 31, 1, 0, 0,
0, 32, 33, 1, 0, 0, 0, 33, 40, 1, 0, 0, 0, 34, 36, 5, 8, 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, 34, 1, 0, 0, 0, 39, 42, 1, 0, 0, 0, 40, 38, 1, 0, 0, 0, 40, 41, 1,
0, 0, 0, 41, 7, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 43, 44, 5, 9, 0, 0, 44,
9, 1, 0, 0, 0, 7, 11, 17, 24, 27, 32, 36, 40,
}
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)
}
}
// MatchParserInit initializes any static state used to implement MatchParser. By default the
// static state used to implement the parser is lazily initialized during the first call to
// NewMatchParser(). You can call this function if you wish to initialize the static state ahead
// of time.
func MatchParserInit() {
staticData := &MatchParserStaticData
staticData.once.Do(matchParserInit)
}
// NewMatchParser produces a new parser instance for the optional input antlr.TokenStream.
func NewMatchParser(input antlr.TokenStream) *MatchParser {
MatchParserInit()
this := new(MatchParser)
this.BaseParser = antlr.NewBaseParser(input)
staticData := &MatchParserStaticData
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 = "Match.g4"
return this
}
// MatchParser tokens.
const (
MatchParserEOF = antlr.TokenEOF
MatchParserUSER = 1
MatchParserGROUP = 2
MatchParserHOST = 3
MatchParserLOCALADDRESS = 4
MatchParserLOCALPORT = 5
MatchParserRDOMAIN = 6
MatchParserADDRESS = 7
MatchParserCOMMA = 8
MatchParserSTRING = 9
MatchParserWHITESPACE = 10
)
// MatchParser rules.
const (
MatchParserRULE_root = 0
MatchParserRULE_matchEntry = 1
MatchParserRULE_criteria = 2
MatchParserRULE_values = 3
MatchParserRULE_value = 4
)
// IRootContext is an interface to support dynamic dispatch.
type IRootContext interface {
antlr.ParserRuleContext
// GetParser returns the parser.
GetParser() antlr.Parser
// Getter signatures
EOF() antlr.TerminalNode
AllMatchEntry() []IMatchEntryContext
MatchEntry(i int) IMatchEntryContext
AllWHITESPACE() []antlr.TerminalNode
WHITESPACE(i int) antlr.TerminalNode
// IsRootContext differentiates from other interfaces.
IsRootContext()
}
type RootContext struct {
antlr.BaseParserRuleContext
parser antlr.Parser
}
func NewEmptyRootContext() *RootContext {
var p = new(RootContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_root
return p
}
func InitEmptyRootContext(p *RootContext) {
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_root
}
func (*RootContext) IsRootContext() {}
func NewRootContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *RootContext {
var p = new(RootContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState)
p.parser = parser
p.RuleIndex = MatchParserRULE_root
return p
}
func (s *RootContext) GetParser() antlr.Parser { return s.parser }
func (s *RootContext) EOF() antlr.TerminalNode {
return s.GetToken(MatchParserEOF, 0)
}
func (s *RootContext) AllMatchEntry() []IMatchEntryContext {
children := s.GetChildren()
len := 0
for _, ctx := range children {
if _, ok := ctx.(IMatchEntryContext); ok {
len++
}
}
tst := make([]IMatchEntryContext, len)
i := 0
for _, ctx := range children {
if t, ok := ctx.(IMatchEntryContext); ok {
tst[i] = t.(IMatchEntryContext)
i++
}
}
return tst
}
func (s *RootContext) MatchEntry(i int) IMatchEntryContext {
var t antlr.RuleContext
j := 0
for _, ctx := range s.GetChildren() {
if _, ok := ctx.(IMatchEntryContext); ok {
if j == i {
t = ctx.(antlr.RuleContext)
break
}
j++
}
}
if t == nil {
return nil
}
return t.(IMatchEntryContext)
}
func (s *RootContext) AllWHITESPACE() []antlr.TerminalNode {
return s.GetTokens(MatchParserWHITESPACE)
}
func (s *RootContext) WHITESPACE(i int) antlr.TerminalNode {
return s.GetToken(MatchParserWHITESPACE, i)
}
func (s *RootContext) GetRuleContext() antlr.RuleContext {
return s
}
func (s *RootContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string {
return antlr.TreesStringTree(s, ruleNames, recog)
}
func (s *RootContext) EnterRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.EnterRoot(s)
}
}
func (s *RootContext) ExitRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.ExitRoot(s)
}
}
func (p *MatchParser) Root() (localctx IRootContext) {
localctx = NewRootContext(p, p.GetParserRuleContext(), p.GetState())
p.EnterRule(localctx, 0, MatchParserRULE_root)
var _la int
p.EnterOuterAlt(localctx, 1)
p.SetState(11)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
if (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&254) != 0 {
{
p.SetState(10)
p.MatchEntry()
}
}
p.SetState(17)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
for _la == MatchParserWHITESPACE {
{
p.SetState(13)
p.Match(MatchParserWHITESPACE)
if p.HasError() {
// Recognition error - abort rule
goto errorExit
}
}
{
p.SetState(14)
p.MatchEntry()
}
p.SetState(19)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
}
{
p.SetState(20)
p.Match(MatchParserEOF)
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
}
// IMatchEntryContext is an interface to support dynamic dispatch.
type IMatchEntryContext interface {
antlr.ParserRuleContext
// GetParser returns the parser.
GetParser() antlr.Parser
// Getter signatures
Criteria() ICriteriaContext
WHITESPACE() antlr.TerminalNode
Values() IValuesContext
// IsMatchEntryContext differentiates from other interfaces.
IsMatchEntryContext()
}
type MatchEntryContext struct {
antlr.BaseParserRuleContext
parser antlr.Parser
}
func NewEmptyMatchEntryContext() *MatchEntryContext {
var p = new(MatchEntryContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_matchEntry
return p
}
func InitEmptyMatchEntryContext(p *MatchEntryContext) {
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_matchEntry
}
func (*MatchEntryContext) IsMatchEntryContext() {}
func NewMatchEntryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MatchEntryContext {
var p = new(MatchEntryContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState)
p.parser = parser
p.RuleIndex = MatchParserRULE_matchEntry
return p
}
func (s *MatchEntryContext) GetParser() antlr.Parser { return s.parser }
func (s *MatchEntryContext) Criteria() ICriteriaContext {
var t antlr.RuleContext
for _, ctx := range s.GetChildren() {
if _, ok := ctx.(ICriteriaContext); ok {
t = ctx.(antlr.RuleContext)
break
}
}
if t == nil {
return nil
}
return t.(ICriteriaContext)
}
func (s *MatchEntryContext) WHITESPACE() antlr.TerminalNode {
return s.GetToken(MatchParserWHITESPACE, 0)
}
func (s *MatchEntryContext) Values() IValuesContext {
var t antlr.RuleContext
for _, ctx := range s.GetChildren() {
if _, ok := ctx.(IValuesContext); ok {
t = ctx.(antlr.RuleContext)
break
}
}
if t == nil {
return nil
}
return t.(IValuesContext)
}
func (s *MatchEntryContext) GetRuleContext() antlr.RuleContext {
return s
}
func (s *MatchEntryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string {
return antlr.TreesStringTree(s, ruleNames, recog)
}
func (s *MatchEntryContext) EnterRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.EnterMatchEntry(s)
}
}
func (s *MatchEntryContext) ExitRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.ExitMatchEntry(s)
}
}
func (p *MatchParser) MatchEntry() (localctx IMatchEntryContext) {
localctx = NewMatchEntryContext(p, p.GetParserRuleContext(), p.GetState())
p.EnterRule(localctx, 2, MatchParserRULE_matchEntry)
p.EnterOuterAlt(localctx, 1)
{
p.SetState(22)
p.Criteria()
}
p.SetState(24)
p.GetErrorHandler().Sync(p)
if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 2, p.GetParserRuleContext()) == 1 {
{
p.SetState(23)
p.Match(MatchParserWHITESPACE)
if p.HasError() {
// Recognition error - abort rule
goto errorExit
}
}
} else if p.HasError() { // JIM
goto errorExit
}
p.SetState(27)
p.GetErrorHandler().Sync(p)
if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 3, p.GetParserRuleContext()) == 1 {
{
p.SetState(26)
p.Values()
}
} else if p.HasError() { // JIM
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
}
// ICriteriaContext is an interface to support dynamic dispatch.
type ICriteriaContext interface {
antlr.ParserRuleContext
// GetParser returns the parser.
GetParser() antlr.Parser
// Getter signatures
USER() antlr.TerminalNode
GROUP() antlr.TerminalNode
HOST() antlr.TerminalNode
LOCALADDRESS() antlr.TerminalNode
LOCALPORT() antlr.TerminalNode
RDOMAIN() antlr.TerminalNode
ADDRESS() antlr.TerminalNode
// IsCriteriaContext differentiates from other interfaces.
IsCriteriaContext()
}
type CriteriaContext struct {
antlr.BaseParserRuleContext
parser antlr.Parser
}
func NewEmptyCriteriaContext() *CriteriaContext {
var p = new(CriteriaContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_criteria
return p
}
func InitEmptyCriteriaContext(p *CriteriaContext) {
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_criteria
}
func (*CriteriaContext) IsCriteriaContext() {}
func NewCriteriaContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *CriteriaContext {
var p = new(CriteriaContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState)
p.parser = parser
p.RuleIndex = MatchParserRULE_criteria
return p
}
func (s *CriteriaContext) GetParser() antlr.Parser { return s.parser }
func (s *CriteriaContext) USER() antlr.TerminalNode {
return s.GetToken(MatchParserUSER, 0)
}
func (s *CriteriaContext) GROUP() antlr.TerminalNode {
return s.GetToken(MatchParserGROUP, 0)
}
func (s *CriteriaContext) HOST() antlr.TerminalNode {
return s.GetToken(MatchParserHOST, 0)
}
func (s *CriteriaContext) LOCALADDRESS() antlr.TerminalNode {
return s.GetToken(MatchParserLOCALADDRESS, 0)
}
func (s *CriteriaContext) LOCALPORT() antlr.TerminalNode {
return s.GetToken(MatchParserLOCALPORT, 0)
}
func (s *CriteriaContext) RDOMAIN() antlr.TerminalNode {
return s.GetToken(MatchParserRDOMAIN, 0)
}
func (s *CriteriaContext) ADDRESS() antlr.TerminalNode {
return s.GetToken(MatchParserADDRESS, 0)
}
func (s *CriteriaContext) GetRuleContext() antlr.RuleContext {
return s
}
func (s *CriteriaContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string {
return antlr.TreesStringTree(s, ruleNames, recog)
}
func (s *CriteriaContext) EnterRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.EnterCriteria(s)
}
}
func (s *CriteriaContext) ExitRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.ExitCriteria(s)
}
}
func (p *MatchParser) Criteria() (localctx ICriteriaContext) {
localctx = NewCriteriaContext(p, p.GetParserRuleContext(), p.GetState())
p.EnterRule(localctx, 4, MatchParserRULE_criteria)
var _la int
p.EnterOuterAlt(localctx, 1)
{
p.SetState(29)
_la = p.GetTokenStream().LA(1)
if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&254) != 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
}
// IValuesContext is an interface to support dynamic dispatch.
type IValuesContext interface {
antlr.ParserRuleContext
// GetParser returns the parser.
GetParser() antlr.Parser
// Getter signatures
AllValue() []IValueContext
Value(i int) IValueContext
AllCOMMA() []antlr.TerminalNode
COMMA(i int) antlr.TerminalNode
// IsValuesContext differentiates from other interfaces.
IsValuesContext()
}
type ValuesContext struct {
antlr.BaseParserRuleContext
parser antlr.Parser
}
func NewEmptyValuesContext() *ValuesContext {
var p = new(ValuesContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_values
return p
}
func InitEmptyValuesContext(p *ValuesContext) {
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_values
}
func (*ValuesContext) IsValuesContext() {}
func NewValuesContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ValuesContext {
var p = new(ValuesContext)
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState)
p.parser = parser
p.RuleIndex = MatchParserRULE_values
return p
}
func (s *ValuesContext) GetParser() antlr.Parser { return s.parser }
func (s *ValuesContext) AllValue() []IValueContext {
children := s.GetChildren()
len := 0
for _, ctx := range children {
if _, ok := ctx.(IValueContext); ok {
len++
}
}
tst := make([]IValueContext, len)
i := 0
for _, ctx := range children {
if t, ok := ctx.(IValueContext); ok {
tst[i] = t.(IValueContext)
i++
}
}
return tst
}
func (s *ValuesContext) Value(i int) IValueContext {
var t antlr.RuleContext
j := 0
for _, ctx := range s.GetChildren() {
if _, ok := ctx.(IValueContext); ok {
if j == i {
t = ctx.(antlr.RuleContext)
break
}
j++
}
}
if t == nil {
return nil
}
return t.(IValueContext)
}
func (s *ValuesContext) AllCOMMA() []antlr.TerminalNode {
return s.GetTokens(MatchParserCOMMA)
}
func (s *ValuesContext) COMMA(i int) antlr.TerminalNode {
return s.GetToken(MatchParserCOMMA, i)
}
func (s *ValuesContext) GetRuleContext() antlr.RuleContext {
return s
}
func (s *ValuesContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string {
return antlr.TreesStringTree(s, ruleNames, recog)
}
func (s *ValuesContext) EnterRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.EnterValues(s)
}
}
func (s *ValuesContext) ExitRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.ExitValues(s)
}
}
func (p *MatchParser) Values() (localctx IValuesContext) {
localctx = NewValuesContext(p, p.GetParserRuleContext(), p.GetState())
p.EnterRule(localctx, 6, MatchParserRULE_values)
var _la int
p.EnterOuterAlt(localctx, 1)
p.SetState(32)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
if _la == MatchParserSTRING {
{
p.SetState(31)
p.Value()
}
}
p.SetState(40)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
for _la == MatchParserCOMMA {
{
p.SetState(34)
p.Match(MatchParserCOMMA)
if p.HasError() {
// Recognition error - abort rule
goto errorExit
}
}
p.SetState(36)
p.GetErrorHandler().Sync(p)
if p.HasError() {
goto errorExit
}
_la = p.GetTokenStream().LA(1)
if _la == MatchParserSTRING {
{
p.SetState(35)
p.Value()
}
}
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
}
// IValueContext is an interface to support dynamic dispatch.
type IValueContext interface {
antlr.ParserRuleContext
// GetParser returns the parser.
GetParser() antlr.Parser
// Getter signatures
STRING() antlr.TerminalNode
// 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 = MatchParserRULE_value
return p
}
func InitEmptyValueContext(p *ValueContext) {
antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1)
p.RuleIndex = MatchParserRULE_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 = MatchParserRULE_value
return p
}
func (s *ValueContext) GetParser() antlr.Parser { return s.parser }
func (s *ValueContext) STRING() antlr.TerminalNode {
return s.GetToken(MatchParserSTRING, 0)
}
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.(MatchListener); ok {
listenerT.EnterValue(s)
}
}
func (s *ValueContext) ExitRule(listener antlr.ParseTreeListener) {
if listenerT, ok := listener.(MatchListener); ok {
listenerT.ExitValue(s)
}
}
func (p *MatchParser) Value() (localctx IValueContext) {
localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState())
p.EnterRule(localctx, 8, MatchParserRULE_value)
p.EnterOuterAlt(localctx, 1)
{
p.SetState(43)
p.Match(MatchParserSTRING)
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
}

View File

@ -0,0 +1,79 @@
package match_parser
import (
"testing"
)
func TestComplexExample(
t *testing.T,
) {
input := "User root,admin,alice Address *,!192.168.0.1"
match := NewMatch()
errors := match.Parse(input, 32)
if len(errors) > 0 {
t.Fatalf("Expected no errors, but got %v", errors)
}
if !(len(match.Entries) == 2) {
t.Fatalf("Expected 2 entries, but got %v", len(match.Entries))
}
if !(match.Entries[0].Criteria == MatchCriteriaTypeUser) {
t.Fatalf("Expected User, but got %v", match.Entries[0])
}
if !(match.Entries[0].Values[0].Value == "root") {
t.Fatalf("Expected root, but got %v", match.Entries[0].Values[0])
}
if !(match.Entries[0].Values[1].Value == "admin") {
t.Fatalf("Expected admin, but got %v", match.Entries[0].Values[1])
}
if !(match.Entries[0].Values[2].Value == "alice") {
t.Fatalf("Expected alice, but got %v", match.Entries[0].Values[2])
}
if !(match.Entries[1].Criteria == MatchCriteriaTypeAddress) {
t.Fatalf("Expected Address, but got %v", match.Entries[1])
}
if !(match.Entries[1].Values[0].Value == "*") {
t.Fatalf("Expected *, but got %v", match.Entries[1].Values[0])
}
if !(match.Entries[1].Values[1].Value == "!192.168.0.1") {
t.Fatalf("Expected !192.168.0.1, but got %v", match.Entries[1].Values[1])
}
}
func TestSecondComplexExample(
t *testing.T,
) {
input := "Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1"
match := NewMatch()
errors := match.Parse(input, 0)
if len(errors) > 0 {
t.Fatalf("Expected no errors, but got %v", errors)
}
if !(len(match.Entries) == 1) {
t.Fatalf("Expected 1 entries, but got %v", len(match.Entries))
}
if !(match.Entries[0].Criteria == MatchCriteriaTypeAddress) {
t.Fatalf("Expected Address, but got %v", match.Entries[0])
}
if !(len(match.Entries[0].Values) == 3) {
t.Fatalf("Expected 3 values, but got %v", len(match.Entries[0].Values))
}
if !(match.Entries[0].Values[0].Value == "172.22.100.0/24") {
t.Fatalf("Expected 172.22.100.0/24, but got %v", match.Entries[0].Values[0])
}
}