001package gudusoft.gsqlparser.parser.powerquery;
002
003/**
004 * Power Query M-Language token codes.
005 *
006 * <p>Isolated from {@link gudusoft.gsqlparser.TBaseType} to avoid
007 * reshuffling existing vendor token values when Power Query support is
008 * added.  Codes here start at 2000 (well above all existing base codes
009 * and well below any vendor-reserved range).
010 *
011 * <p>The sentinel {@code PQ_TOKEN_BASE = 2000} gives 96 slots for
012 * M-specific tokens which is generous even for a full Tier 3 grammar.
013 */
014public final class PowerQueryTokenCodes {
015
016    private PowerQueryTokenCodes() {}
017
018    public static final int PQ_TOKEN_BASE = 2000;
019
020    // Keywords
021    public static final int RW_LET       = PQ_TOKEN_BASE + 1;
022    public static final int RW_IN        = PQ_TOKEN_BASE + 2;
023    public static final int RW_EACH      = PQ_TOKEN_BASE + 3;
024    public static final int RW_IF        = PQ_TOKEN_BASE + 4;
025    public static final int RW_THEN      = PQ_TOKEN_BASE + 5;
026    public static final int RW_ELSE      = PQ_TOKEN_BASE + 6;
027    public static final int RW_TRUE      = PQ_TOKEN_BASE + 7;
028    public static final int RW_FALSE     = PQ_TOKEN_BASE + 8;
029    public static final int RW_NULL      = PQ_TOKEN_BASE + 9;
030    public static final int RW_AND       = PQ_TOKEN_BASE + 10;
031    public static final int RW_OR        = PQ_TOKEN_BASE + 11;
032    public static final int RW_NOT       = PQ_TOKEN_BASE + 12;
033    public static final int RW_TRY       = PQ_TOKEN_BASE + 13;
034    public static final int RW_OTHERWISE = PQ_TOKEN_BASE + 14;
035    public static final int RW_ERROR     = PQ_TOKEN_BASE + 15;
036    public static final int RW_IS        = PQ_TOKEN_BASE + 16;
037    public static final int RW_AS        = PQ_TOKEN_BASE + 17;
038    public static final int RW_TYPE      = PQ_TOKEN_BASE + 18;
039    public static final int RW_META      = PQ_TOKEN_BASE + 19;
040    public static final int RW_SECTION   = PQ_TOKEN_BASE + 20;
041    public static final int RW_SHARED    = PQ_TOKEN_BASE + 21;
042
043    // Multi-char operators specific to M
044    public static final int FAT_ARROW    = PQ_TOKEN_BASE + 40; // =>
045    public static final int DOUBLE_DOT   = PQ_TOKEN_BASE + 41; // ..
046    public static final int ELLIPSIS     = PQ_TOKEN_BASE + 42; // ...
047    public static final int QIDENT       = PQ_TOKEN_BASE + 43; // #"quoted ident"
048
049    /**
050     * Reverse lookup: given a token code, return its M-language keyword
051     * text (uppercase) or {@code null}.  Useful for diagnostics.
052     */
053    public static String keywordText(int tokencode) {
054        switch (tokencode) {
055            case RW_LET:       return "LET";
056            case RW_IN:        return "IN";
057            case RW_EACH:      return "EACH";
058            case RW_IF:        return "IF";
059            case RW_THEN:      return "THEN";
060            case RW_ELSE:      return "ELSE";
061            case RW_TRUE:      return "TRUE";
062            case RW_FALSE:     return "FALSE";
063            case RW_NULL:      return "NULL";
064            case RW_AND:       return "AND";
065            case RW_OR:        return "OR";
066            case RW_NOT:       return "NOT";
067            case RW_TRY:       return "TRY";
068            case RW_OTHERWISE: return "OTHERWISE";
069            case RW_ERROR:     return "ERROR";
070            case RW_IS:        return "IS";
071            case RW_AS:        return "AS";
072            case RW_TYPE:      return "TYPE";
073            case RW_META:      return "META";
074            case RW_SECTION:   return "SECTION";
075            case RW_SHARED:    return "SHARED";
076            default:           return null;
077        }
078    }
079
080    /**
081     * Map an uppercase identifier text to its keyword token code, or
082     * {@code -1} if the text is not a reserved M keyword.
083     */
084    public static int keywordCode(String upperText) {
085        if (upperText == null) return -1;
086        switch (upperText) {
087            case "LET":       return RW_LET;
088            case "IN":        return RW_IN;
089            case "EACH":      return RW_EACH;
090            case "IF":        return RW_IF;
091            case "THEN":      return RW_THEN;
092            case "ELSE":      return RW_ELSE;
093            case "TRUE":      return RW_TRUE;
094            case "FALSE":     return RW_FALSE;
095            case "NULL":      return RW_NULL;
096            case "AND":       return RW_AND;
097            case "OR":        return RW_OR;
098            case "NOT":       return RW_NOT;
099            case "TRY":       return RW_TRY;
100            case "OTHERWISE": return RW_OTHERWISE;
101            case "ERROR":     return RW_ERROR;
102            case "IS":        return RW_IS;
103            case "AS":        return RW_AS;
104            case "TYPE":      return RW_TYPE;
105            case "META":      return RW_META;
106            case "SECTION":   return RW_SECTION;
107            case "SHARED":    return RW_SHARED;
108            default:          return -1;
109        }
110    }
111}