182 lines
6.6 KiB
Go
182 lines
6.6 KiB
Go
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// Symbol.go
|
|
package expr
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
var symbolMap map[Symbol]symbolSpec
|
|
|
|
type symbolClass int16
|
|
|
|
const (
|
|
symClassOperator symbolClass = iota
|
|
symClassPostOp
|
|
symClassIdentifier
|
|
symClassDelimiter
|
|
symClassParenthesis
|
|
symClassDeclaration
|
|
symClassValue
|
|
symClassOther
|
|
)
|
|
|
|
type symbolSpec struct {
|
|
repr string
|
|
kind symbolClass
|
|
}
|
|
|
|
func init() {
|
|
|
|
symbolMap = map[Symbol]symbolSpec{
|
|
SymUnknown: {"<unknown>", symClassOther}, // -1: Unknown symbol
|
|
SymNone: {"<null>", symClassOther}, // 0: Null value for variable of type symbol
|
|
SymError: {"<error>", symClassOther}, // 1: Error reading from stream
|
|
SymEos: {"<eos>", symClassOther}, // 2: End of stream
|
|
SymMinus: {"-", symClassOperator}, // 3: '-'
|
|
SymMinusEqual: {"-=", symClassOperator}, // 4: '-='
|
|
SymDoubleMinus: {"--", symClassOperator}, // 5: '--'
|
|
SymPlus: {"+", symClassOperator}, // 6: '+'
|
|
SymPlusEqual: {"+=", symClassOperator}, // 7: '+='
|
|
SymDoublePlus: {"++", symClassOperator}, // 8: '++'
|
|
SymStar: {"*", symClassOperator}, // 9: '*'
|
|
SymDoubleStar: {"**", symClassOperator}, // 10: '**'
|
|
SymSlash: {"/", symClassOperator}, // 11: '/'
|
|
SymBackSlash: {"\\", symClassOperator}, // 12: '\'
|
|
SymVertBar: {"|", symClassOperator}, // 13: '|'
|
|
SymDoubleVertBar: {"||", symClassOperator}, // 14: '||'
|
|
SymComma: {",", symClassOperator}, // 15: ','
|
|
SymColon: {":", symClassOperator}, // 16: ':'
|
|
SymSemiColon: {";", symClassOperator}, // 17: ';'
|
|
SymDot: {".", symClassOperator}, // 18: '.'
|
|
SymDotSlash: {"./", symClassOperator}, // 19: './'
|
|
SymQuote: {"'", symClassDelimiter}, // 20: '\''
|
|
SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"'
|
|
SymBackTick: {"`", symClassOperator}, // 22: '`'
|
|
SymExclamation: {"!", symClassPostOp}, // 23: '!'
|
|
SymQuestion: {"?", symClassOperator}, // 24: '?'
|
|
SymAmpersand: {"&", symClassOperator}, // 25: '&'
|
|
SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&'
|
|
SymPercent: {"%", symClassOperator}, // 27: '%'
|
|
SymAt: {"@", symClassOperator}, // 28: '@'
|
|
SymUndescore: {"_", symClassOperator}, // 29: '_'
|
|
SymEqual: {"=", symClassOperator}, // 30: '='
|
|
SymDoubleEqual: {"==", symClassOperator}, // 31: '=='
|
|
SymLess: {"<", symClassOperator}, // 32: '<'
|
|
SymLessOrEqual: {"<=", symClassOperator}, // 33: '<='
|
|
SymGreater: {">", symClassOperator}, // 34: '>'
|
|
SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>='
|
|
SymLessGreater: {"<>", symClassOperator}, // 36: '<>'
|
|
SymNotEqual: {"!=", symClassOperator}, // 37: '!='
|
|
SymDollar: {"$", symClassOperator}, // 38: '$'
|
|
SymHash: {"#", symClassOperator}, // 39: '#'
|
|
SymOpenRound: {"(", symClassParenthesis}, // 40: '('
|
|
SymClosedRound: {")", symClassParenthesis}, // 41: ')'
|
|
SymOpenSquare: {"[", symClassParenthesis}, // 42: '['
|
|
SymClosedSquare: {"]", symClassParenthesis}, // 43: ']'
|
|
SymOpenBrace: {"{", symClassParenthesis}, // 44: '{'
|
|
SymClosedBrace: {"}", symClassParenthesis}, // 45: '}'
|
|
SymTilde: {"~", symClassOperator}, // 46: '~'
|
|
SymDoubleQuestion: {"??", symClassOperator}, // 47: '??'
|
|
SymQuestionEqual: {"?=", symClassOperator}, // 48: '?='
|
|
SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!'
|
|
SymDoubleAt: {"@@", symClassOperator}, // 50: '@@'
|
|
SymDoubleColon: {"::", symClassOperator}, // 51: '::'
|
|
SymInsert: {">>", symClassOperator}, // 52: '>>'
|
|
SymAppend: {"<<", symClassOperator}, // 53: '<<'
|
|
SymCaret: {"^", symClassOperator}, // 54: '^'
|
|
SymDollarRound: {"$(", symClassOperator}, // 55: '$('
|
|
SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()'
|
|
SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$'
|
|
SymDoubleDot: {"..", symClassOperator}, // 58: '..'
|
|
SymTripleDot: {"...", symClassOperator}, // 59: '...'
|
|
SymStarEqual: {"*=", symClassOperator}, // 60: '*='
|
|
SymSlashEqual: {"/=", symClassOperator}, // 61: '/='
|
|
SymPercEqual: {"%=", symClassOperator}, // 62: '%='
|
|
// SymChangeSign
|
|
// SymUnchangeSign
|
|
// SymIdentifier
|
|
// SymBool
|
|
// SymInteger
|
|
// SymVariable
|
|
// SymFloat
|
|
// SymFraction
|
|
// SymString
|
|
// SymIterator
|
|
// SymOr: "or",
|
|
// SymAnd: "and",
|
|
// SymNot: "not",
|
|
// SymComment
|
|
// SymFuncCall
|
|
// SymFuncDef
|
|
// SymList
|
|
// SymDict
|
|
// SymIndex
|
|
// SymExpression
|
|
// SymSelector // <selector> ::= <expr> "?" <selector-case> {":" <selector-case>} ["::" <default-selector-case>]
|
|
// SymSelectorCase // <selector-case> ::= [<list>] "{" <multi-expr> "}"
|
|
// // SymOpenComment // 0: '/*'
|
|
// // SymClosedComment // 0: '*/'
|
|
// // SymOneLineComment // 0: '//'
|
|
// keywordBase
|
|
SymKwAnd: {"and", symClassOperator},
|
|
SymKwNot: {"not", symClassOperator},
|
|
SymKwOr: {"or", symClassOperator},
|
|
SymKwBut: {"but", symClassOperator},
|
|
SymKwFunc: {"func(", symClassDeclaration},
|
|
SymKwBuiltin: {"builtin", symClassOperator},
|
|
SymKwPlugin: {"plugin", symClassOperator},
|
|
SymKwIn: {"in", symClassOperator},
|
|
SymKwInclude: {"include", symClassOperator},
|
|
SymKwNil: {"nil", symClassValue},
|
|
SymKwUnset: {"unset", symClassOperator},
|
|
}
|
|
}
|
|
|
|
func SymToString(sym Symbol) string {
|
|
if s, ok := symbolMap[sym]; ok {
|
|
return s.repr
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func SymListToString(symList []Symbol, quote bool) string {
|
|
var sb strings.Builder
|
|
if len(symList) == 0 {
|
|
sb.WriteString("<nothing>")
|
|
} else {
|
|
for _, sym := range symList {
|
|
if sb.Len() > 0 {
|
|
sb.WriteByte(',')
|
|
sb.WriteByte(' ')
|
|
}
|
|
if quote {
|
|
sb.WriteByte('`')
|
|
}
|
|
sb.WriteString(SymToString(sym))
|
|
if quote {
|
|
sb.WriteByte('`')
|
|
}
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
func StringEndsWithOperator(s string) bool {
|
|
return endingOperator(s) != SymNone
|
|
}
|
|
|
|
func endingOperator(s string) (sym Symbol) {
|
|
sym = SymNone
|
|
lower := strings.ToLower(s)
|
|
for symbol, spec := range symbolMap {
|
|
if spec.kind == symClassOperator && strings.HasSuffix(lower, spec.repr) {
|
|
sym = symbol
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|