// 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 symClassCommand symClassIdentifier symClassDelimiter symClassParenthesis symClassDeclaration symClassValue symClassOther ) type symbolSpec struct { repr string kind symbolClass opType termPosition } func init() { symbolMap = map[Symbol]symbolSpec{ SymUnknown: {"", symClassOther, posLeaf}, // -1: Unknown symbol SymNone: {"", symClassOther, posLeaf}, // 0: Null value for variable of type symbol SymError: {"", symClassOther, posLeaf}, // 1: Error reading from stream SymEos: {"", symClassOther, posLeaf}, // 2: End of stream SymMinus: {"-", symClassOperator, posInfix}, // 3: '-' SymMinusEqual: {"-=", symClassOperator, posInfix}, // 4: '-=' SymDoubleMinus: {"--", symClassOperator, posPostfix}, // 5: '--' SymPlus: {"+", symClassOperator, posInfix}, // 6: '+' SymPlusEqual: {"+=", symClassOperator, posInfix}, // 7: '+=' SymDoublePlus: {"++", symClassOperator, posPostfix}, // 8: '++' SymStar: {"*", symClassOperator, posInfix}, // 9: '*' SymDoubleStar: {"**", symClassOperator, posInfix}, // 10: '**' SymSlash: {"/", symClassOperator, posInfix}, // 11: '/' SymBackSlash: {"\\", symClassOperator, posLeaf}, // 12: '\' SymVertBar: {"|", symClassOperator, posInfix}, // 13: '|' SymDoubleVertBar: {"||", symClassOperator, posInfix}, // 14: '||' SymComma: {",", symClassOperator, posInfix}, // 15: ',' SymColon: {":", symClassOperator, posInfix}, // 16: ':' SymSemiColon: {";", symClassOperator, posInfix}, // 17: ';' SymDot: {".", symClassOperator, posInfix}, // 18: '.' SymDotSlash: {"./", symClassOperator, posInfix}, // 19: './' SymQuote: {"'", symClassDelimiter, posLeaf}, // 20: '\'' SymDoubleQuote: {"\"", symClassDelimiter, posLeaf}, // 21: '"' SymBackTick: {"`", symClassDelimiter, posLeaf}, // 22: '`' SymExclamation: {"!", symClassOperator, posPostfix}, // 23: '!' SymQuestion: {"?", symClassOperator, posInfix}, // 24: '?' SymAmpersand: {"&", symClassOperator, posInfix}, // 25: '&' SymDoubleAmpersand: {"&&", symClassOperator, posInfix}, // 26: '&&' SymPercent: {"%", symClassOperator, posInfix}, // 27: '%' SymAt: {"@", symClassOperator, posPrefix}, // 28: '@' SymUndescore: {"_", symClassIdentifier, posLeaf}, // 29: '_' SymEqual: {"=", symClassOperator, posInfix}, // 30: '=' SymDoubleEqual: {"==", symClassOperator, posInfix}, // 31: '==' SymLess: {"<", symClassOperator, posInfix}, // 32: '<' SymLessOrEqual: {"<=", symClassOperator, posInfix}, // 33: '<=' SymGreater: {">", symClassOperator, posInfix}, // 34: '>' SymGreaterOrEqual: {">=", symClassOperator, posInfix}, // 35: '>=' SymLessGreater: {"<>", symClassOperator, posInfix}, // 36: '<>' SymNotEqual: {"!=", symClassOperator, posInfix}, // 37: '!=' SymDollar: {"$", symClassOperator, posPrefix}, // 38: '$' SymHash: {"#", symClassOperator, posPrefix}, // 39: '#' SymOpenRound: {"(", symClassParenthesis, posPrefix}, // 40: '(' SymClosedRound: {")", symClassParenthesis, posPostfix}, // 41: ')' SymOpenSquare: {"[", symClassParenthesis, posPrefix}, // 42: '[' SymClosedSquare: {"]", symClassParenthesis, posPostfix}, // 43: ']' SymOpenBrace: {"{", symClassParenthesis, posPrefix}, // 44: '{' SymClosedBrace: {"}", symClassParenthesis, posPostfix}, // 45: '}' SymTilde: {"~", symClassOperator, posPrefix}, // 46: '~' SymDoubleQuestion: {"??", symClassOperator, posInfix}, // 47: '??' SymQuestionEqual: {"?=", symClassOperator, posInfix}, // 48: '?=' SymQuestionExclam: {"?!", symClassOperator, posInfix}, // 49: '?!' SymDoubleAt: {"@@", symClassCommand, posLeaf}, // 50: '@@' SymDoubleColon: {"::", symClassOperator, posInfix}, // 51: '::' SymDoubleGreater: {">>", symClassOperator, posInfix}, // 52: '>>' SymDoubleLess: {"<<", symClassOperator, posInfix}, // 53: '<<' SymCaret: {"^", symClassOperator, posInfix}, // 54: '^' SymDollarRound: {"$(", symClassOperator, posPrefix}, // 55: '$(' SymOpenClosedRound: {"()", symClassOperator, posPostfix}, // 56: '()' SymDoubleDollar: {"$$", symClassCommand, posLeaf}, // 57: '$$' SymDoubleDot: {"..", symClassOperator, posInfix}, // 58: '..' SymTripleDot: {"...", symClassOperator, posPostfix}, // 59: '...' SymStarEqual: {"*=", symClassOperator, posInfix}, // 60: '*=' SymSlashEqual: {"/=", symClassOperator, posInfix}, // 61: '/=' SymPercEqual: {"%=", symClassOperator, posInfix}, // 62: '%=' SymDoubleLessEqual: {"<<=", symClassOperator, posInfix}, // 63: '<<=' SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>=' SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&=' SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|=' SymCaretEqual: {"^=", symClassOperator, posInfix}, // 66: '^=' SymPlusGreater: {"+>", symClassOperator, posInfix}, // 67: '+>' SymLessPlus: {"<+", symClassOperator, posInfix}, // 68: '<+' SymPreInc: {"++", symClassOperator, posPrefix}, // : '++' SymPreDec: {"--", symClassOperator, posPrefix}, // : '--' // SymChangeSign // SymUnchangeSign // SymIdentifier // SymBool // SymInteger // SymVariable // SymFloat // SymFraction // SymString // SymIterator // SymOr: "or", // SymAnd: "and", // SymNot: "not", // SymComment // SymFuncCall // SymFuncDef // SymList // SymDict // SymIndex // SymExpression // SymSelector // ::= "?" {":" } ["::" ] // SymSelectorCase // ::= [] "{" "}" // // SymOpenComment // 0: '/*' // // SymClosedComment // 0: '*/' // // SymOneLineComment // 0: '//' // keywordBase SymKwAnd: {"and", symClassOperator, posInfix}, SymKwNot: {"not", symClassOperator, posInfix}, SymKwOr: {"or", symClassOperator, posInfix}, SymKwBut: {"but", symClassOperator, posInfix}, SymKwFunc: {"func(", symClassDeclaration, posPrefix}, SymKwBuiltin: {"builtin", symClassOperator, posPrefix}, SymKwPlugin: {"plugin", symClassOperator, posPrefix}, SymKwIn: {"in", symClassOperator, posInfix}, SymKwInclude: {"include", symClassOperator, posPrefix}, SymKwNil: {"nil", symClassValue, posLeaf}, SymKwUnset: {"unset", symClassOperator, posPrefix}, } } 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("") } 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) { var matchLength = 0 sym = SymNone lower := strings.TrimRight(strings.ToLower(s), " \t") for symbol, spec := range symbolMap { if strings.HasSuffix(lower, spec.repr) { if len(spec.repr) > matchLength { matchLength = len(spec.repr) if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) { sym = symbol } else { sym = SymNone } } } } return }