// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // symbol-map.go package scan import ( "strings" "git.portale-stac.it/go-pkg/expr/sym" ) var symbolMap map[sym.Symbol]symbolSpec type SymbolClass int16 const ( SymClassOperator SymbolClass = iota SymClassCommand SymClassIdentifier SymClassDelimiter SymClassParenthesis SymClassDeclaration SymClassValue SymClassOther ) type symbolSpec struct { repr string kind SymbolClass opType TermPosition } func init() { symbolMap = map[sym.Symbol]symbolSpec{ sym.SymUnknown: {"", SymClassOther, PosLeaf}, // -1: Unknown symbol sym.SymNone: {"", SymClassOther, PosLeaf}, // 0: Null value for variable of type symbol sym.SymError: {"", SymClassOther, PosLeaf}, // 1: Error reading from stream sym.SymEos: {"", SymClassOther, PosLeaf}, // 2: End of stream sym.SymMinus: {"-", SymClassOperator, PosInfix}, // 3: '-' sym.SymMinusEqual: {"-=", SymClassOperator, PosInfix}, // 4: '-=' sym.SymDoubleMinus: {"--", SymClassOperator, PosPostfix}, // 5: '--' sym.SymPlus: {"+", SymClassOperator, PosInfix}, // 6: '+' sym.SymPlusEqual: {"+=", SymClassOperator, PosInfix}, // 7: '+=' sym.SymDoublePlus: {"++", SymClassOperator, PosPostfix}, // 8: '++' sym.SymStar: {"*", SymClassOperator, PosInfix}, // 9: '*' sym.SymDoubleStar: {"**", SymClassOperator, PosInfix}, // 10: '**' sym.SymSlash: {"/", SymClassOperator, PosInfix}, // 11: '/' sym.SymBackSlash: {"\\", SymClassOperator, PosLeaf}, // 12: '\' sym.SymVertBar: {"|", SymClassOperator, PosInfix}, // 13: '|' sym.SymDoubleVertBar: {"||", SymClassOperator, PosInfix}, // 14: '||' sym.SymComma: {",", SymClassOperator, PosInfix}, // 15: ',' sym.SymColon: {":", SymClassOperator, PosInfix}, // 16: ':' sym.SymSemiColon: {";", SymClassOperator, PosInfix}, // 17: ';' sym.SymDot: {".", SymClassOperator, PosInfix}, // 18: '.' sym.SymDotSlash: {"./", SymClassOperator, PosInfix}, // 19: './' sym.SymQuote: {"'", SymClassDelimiter, PosLeaf}, // 20: '\'' sym.SymDoubleQuote: {"\"", SymClassDelimiter, PosLeaf}, // 21: '"' sym.SymBackTick: {"`", SymClassDelimiter, PosLeaf}, // 22: '`' sym.SymExclamation: {"!", SymClassOperator, PosPostfix}, // 23: '!' sym.SymQuestion: {"?", SymClassOperator, PosInfix}, // 24: '?' sym.SymAmpersand: {"&", SymClassOperator, PosInfix}, // 25: '&' sym.SymDoubleAmpersand: {"&&", SymClassOperator, PosInfix}, // 26: '&&' sym.SymPercent: {"%", SymClassOperator, PosInfix}, // 27: '%' sym.SymAt: {"@", SymClassOperator, PosPrefix}, // 28: '@' sym.SymUndescore: {"_", SymClassIdentifier, PosLeaf}, // 29: '_' sym.SymEqual: {"=", SymClassOperator, PosInfix}, // 30: '=' sym.SymColonEqual: {":=", SymClassOperator, PosInfix}, // 31: ':=' sym.SymDoubleEqual: {"==", SymClassOperator, PosInfix}, // 32: '==' sym.SymLess: {"<", SymClassOperator, PosInfix}, // 33: '<' sym.SymLessOrEqual: {"<=", SymClassOperator, PosInfix}, // 34: '<=' sym.SymGreater: {">", SymClassOperator, PosInfix}, // 35: '>' sym.SymGreaterOrEqual: {">=", SymClassOperator, PosInfix}, // 36: '>=' sym.SymLessGreater: {"<>", SymClassOperator, PosInfix}, // 37: '<>' sym.SymNotEqual: {"!=", SymClassOperator, PosInfix}, // 38: '!=' sym.SymDollar: {"$", SymClassOperator, PosPrefix}, // 39: '$' sym.SymHash: {"#", SymClassOperator, PosPrefix}, // 40: '#' sym.SymOpenRound: {"(", SymClassParenthesis, PosPrefix}, // 41: '(' sym.SymClosedRound: {")", SymClassParenthesis, PosPostfix}, // 42: ')' sym.SymOpenSquare: {"[", SymClassParenthesis, PosPrefix}, // 43: '[' sym.SymClosedSquare: {"]", SymClassParenthesis, PosPostfix}, // 44: ']' sym.SymOpenBrace: {"{", SymClassParenthesis, PosPrefix}, // 45: '{' sym.SymClosedBrace: {"}", SymClassParenthesis, PosPostfix}, // 46: '}' sym.SymTilde: {"~", SymClassOperator, PosPrefix}, // 47: '~' sym.SymDoubleQuestion: {"??", SymClassOperator, PosInfix}, // 48: '??' sym.SymQuestionEqual: {"?=", SymClassOperator, PosInfix}, // 49: '?=' sym.SymQuestionExclam: {"?!", SymClassOperator, PosInfix}, // 50: '?!' sym.SymDoubleAt: {"@@", SymClassCommand, PosLeaf}, // 51: '@@' sym.SymDoubleColon: {"::", SymClassOperator, PosInfix}, // 52: '::' sym.SymDoubleGreater: {">>", SymClassOperator, PosInfix}, // 53: '>>' sym.SymDoubleLess: {"<<", SymClassOperator, PosInfix}, // 54: '<<' sym.SymCaret: {"^", SymClassOperator, PosInfix}, // 55: '^' sym.SymDollarRound: {"$(", SymClassOperator, PosPrefix}, // 56: '$(' sym.SymOpenClosedRound: {"()", SymClassOperator, PosPostfix}, // 57: '()' sym.SymDoubleDollar: {"$$", SymClassCommand, PosLeaf}, // 58: '$$' sym.SymDoubleDot: {"..", SymClassOperator, PosInfix}, // 59: '..' sym.SymTripleDot: {"...", SymClassOperator, PosPostfix}, // 60: '...' sym.SymStarEqual: {"*=", SymClassOperator, PosInfix}, // 61: '*=' sym.SymSlashEqual: {"/=", SymClassOperator, PosInfix}, // 62: '/=' sym.SymPercEqual: {"%=", SymClassOperator, PosInfix}, // 63: '%=' sym.SymDoubleLessEqual: {"<<=", SymClassOperator, PosInfix}, // 64: '<<=' sym.SymDoubleGreaterEqual: {">>=", SymClassOperator, PosInfix}, // 65: '>>=' sym.SymAmpersandEqual: {"&=", SymClassOperator, PosInfix}, // 66: '&=' sym.SymVertBarEqual: {"|=", SymClassOperator, PosInfix}, // 67: '|=' sym.SymCaretEqual: {"^=", SymClassOperator, PosInfix}, // 68: '^=' sym.SymPlusGreater: {"+>", SymClassOperator, PosInfix}, // 69: '+>' sym.SymLessPlus: {"<+", SymClassOperator, PosInfix}, // 70: '<+' sym.SymPreInc: {"++", SymClassOperator, PosPrefix}, // 71: '++' sym.SymPreDec: {"--", SymClassOperator, PosPrefix}, // 72: '--' sym.SymOpenSquareLess: {"[<", SymClassOperator, PosPrefix}, // 97: '[<' sym.SymGreaterClosedSquare: {">]", SymClassOperator, PosPostfix}, // 98: '>]' // sym.SymChangeSign // sym.SymUnchangeSign // sym.SymIdentifier // sym.SymBool // sym.SymInteger // sym.SymVariable // sym.SymFloat // sym.SymFraction // sym.SymString // sym.SymIterator // sym.SymOr: "or", // sym.SymAnd: "and", // sym.SymNot: "not", // sym.SymComment // sym.SymFuncCall // sym.SymFuncDef // sym.SymList // sym.SymLinkedList // sym.SymDict // sym.SymIndex // sym.SymExpression // sym.SymSelector // ::= "?" {":" } ["::" ] // sym.SymSelectorCase // ::= [] "{" "}" // // sym.SymOpenComment // 0: '/*' // // sym.SymClosedComment // 0: '*/' // // sym.SymOneLineComment // 0: '//' // keywordBase sym.SymKwAnd: {"and", SymClassOperator, PosInfix}, sym.SymKwNot: {"not", SymClassOperator, PosInfix}, sym.SymKwOr: {"or", SymClassOperator, PosInfix}, sym.SymKwBut: {"but", SymClassOperator, PosInfix}, sym.SymKwMap: {"map", SymClassOperator, PosInfix}, sym.SymKwFilter: {"filter", SymClassOperator, PosInfix}, sym.SymKwDigest: {"digest", SymClassOperator, PosInfix}, sym.SymKwCat: {"cat", SymClassOperator, PosInfix}, sym.SymKwJoin: {"join", SymClassOperator, PosInfix}, sym.SymKwGroupBy: {"groupby", SymClassOperator, PosInfix}, sym.SymKwFunc: {"func(", SymClassDeclaration, PosPrefix}, sym.SymKwBuiltin: {"builtin", SymClassOperator, PosPrefix}, sym.SymKwPlugin: {"plugin", SymClassOperator, PosPrefix}, sym.SymKwIn: {"in", SymClassOperator, PosInfix}, sym.SymKwAt: {"at", SymClassOperator, PosInfix}, sym.SymKwInclude: {"include", SymClassOperator, PosPrefix}, sym.SymKwNil: {"nil", SymClassValue, PosLeaf}, sym.SymKwUnset: {"unset", SymClassOperator, PosPrefix}, } } func SymToString(sym sym.Symbol) string { if s, ok := symbolMap[sym]; ok { return s.repr } return "" } func SymListToString(symList []sym.Symbol, quote bool) string { var sb strings.Builder if len(symList) == 0 { sb.WriteString("") } 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) != sym.SymNone } func endingOperator(s string) (resultSym sym.Symbol) { var matchLength = 0 var repr string resultSym = sym.SymNone lower := strings.TrimRight(strings.ToLower(s), " \t") for symbol, spec := range symbolMap { if len(spec.repr) > matchLength || repr == spec.repr { if strings.HasSuffix(lower, spec.repr) { if isNotEndingSymbol(spec) && repr != spec.repr { repr = spec.repr matchLength = len(spec.repr) resultSym = symbol } else { resultSym = sym.SymNone break // matchLength = 0 } } } } return } func isNotEndingSymbol(spec symbolSpec) bool { return (spec.kind == SymClassOperator && (spec.opType == PosInfix || spec.opType == PosPrefix)) || (spec.kind == SymClassParenthesis && spec.opType == PosPrefix) }