|
|
|
package parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"asciigoat.org/core/lexer"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
RuneComment = ';' // RuneComment is the standard dosini comment character
|
|
|
|
RuneCommentExtra = '#' // RuneCommentExtra is UNIX shell's comment character
|
|
|
|
RuneSectionStart = '[' // RuneSectionStart indicates the start of a section declaration
|
|
|
|
RuneSectionEnd = ']' // RuneSectionEnd indiciates the end of a section declaration
|
|
|
|
RuneFieldEqual = '=' // RuneFieldEqual separates field keys from their values
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// RunesComment is a string containing all runes acceptable to start comments
|
|
|
|
RunesComment = string([]rune{
|
|
|
|
RuneComment,
|
|
|
|
RuneCommentExtra,
|
|
|
|
})
|
|
|
|
// RunesSpecial is a string containing all the runes with special meaning
|
|
|
|
RunesSpecial = string([]rune{
|
|
|
|
RuneComment,
|
|
|
|
RuneCommentExtra,
|
|
|
|
RuneSectionStart,
|
|
|
|
RuneSectionEnd,
|
|
|
|
RuneFieldEqual,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// IsNewLine tells if the rune indicates a line break or the start of one
|
|
|
|
IsNewLine = lexer.NewIsIn("\r\n")
|
|
|
|
// IsNotNewLine tells if the rune is not a line break nor the start of one
|
|
|
|
IsNotNewLine = lexer.NewIsNot(IsNewLine)
|
|
|
|
// IsSpace tells if the rune is considered whitespace by Unicode
|
|
|
|
IsSpace = lexer.IsSpace
|
|
|
|
// IsNotSpace tells if the rune is not considered whitespace by Unicode
|
|
|
|
IsNotSpace = lexer.NewIsNot(IsSpace)
|
|
|
|
// IsCommentStart ...
|
|
|
|
IsCommentStart = lexer.NewIsIn(RunesComment)
|
|
|
|
)
|
|
|
|
|
|
|
|
// IsAny accepts any rune
|
|
|
|
func IsAny(_ rune) bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsSpaceNotNewLine indicates a rune is whitespace but not a new line
|
|
|
|
func IsSpaceNotNewLine(r rune) bool {
|
|
|
|
return IsSpace(r) && !IsNewLine(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsSectionStart indicates the rune starts the section declaration
|
|
|
|
func IsSectionStart(r rune) bool { return r == RuneSectionStart }
|
|
|
|
|
|
|
|
// IsSectionEnd indicates the rune ends the section declaration
|
|
|
|
func IsSectionEnd(r rune) bool { return r == RuneSectionEnd }
|
|
|
|
|
|
|
|
// IsName indicates a rune is acceptable for section or field names
|
|
|
|
func IsName(r rune) bool {
|
|
|
|
switch {
|
|
|
|
case IsSpace(r):
|
|
|
|
return false
|
|
|
|
case strings.ContainsRune(RunesSpecial, r):
|
|
|
|
return false
|
|
|
|
default:
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|