001package Torello.CSS; 002 003import Torello.Java.Additional.ByRef; 004 005import java.util.Vector; 006import java.util.function.Consumer; 007 008/** 009 * CSS-Tokenizer Class for <B>At-Rule</B> Identifiers. 010 */ 011@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="CSS_TOK") 012public class AtKeyword extends Identifier 013 implements CharSequence, java.io.Serializable, Comparable<CharSequence> 014{ 015 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 016 protected static final long serialVersionUID = 1; 017 018 019 // ******************************************************************************************** 020 // ******************************************************************************************** 021 // Private Constructor, API "is" and "if" Methods 022 // ******************************************************************************************** 023 // ******************************************************************************************** 024 025 026 private AtKeyword( 027 final int[] css, 028 final int sPos, 029 final int ePos, 030 final String identifier 031 ) 032 { super(css, sPos, ePos, identifier); } 033 034 @Override 035 public final boolean isAtKeyword() { return true; } 036 037 @Override 038 public final AtKeyword ifAtKeyword() { return this; } 039 040 041 // ******************************************************************************************** 042 // ******************************************************************************************** 043 // User's Constructor: a static "build" method 044 // ******************************************************************************************** 045 // ******************************************************************************************** 046 047 048 /** 049 * <EMBED CLASS=defs DATA-TOK=AtKeyword DATA-P=atKeyword> 050 * <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_DESC> 051 * @param atKeyword <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_PARAM> 052 * @return <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_RET> 053 * @throws TokenizeException <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_TOK_EX> 054 */ 055 @SuppressWarnings("unchecked") 056 public static AtKeyword build(final String atKeyword) 057 { return (AtKeyword) CSSToken.build(atKeyword, INPUT_CHECKER, AtKeyword::consume); } 058 059 private static final CSSToken.InputChecker INPUT_CHECKER = (int[] css) -> 060 { 061 if (css.length < 2) throw new TokenizeException(AtKeyword.class); 062 063 if (css[0] != '@') throw new TokenizeException 064 ("Input String does not start with the @-Symbol"); 065 066 if (! Identifier.startsIdentSequence(css, 1)) throw new TokenizeException 067 ("String-text after the opening @-Symbol does not constitute a valid CSS Identifier"); 068 }; 069 070 071 // ******************************************************************************************** 072 // ******************************************************************************************** 073 // CONSUME 074 // ******************************************************************************************** 075 // ******************************************************************************************** 076 077 078 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 079 // Copied from: 080 // https://drafts.csswg.org/css-syntax-3/ - NO '#' Sub-Page Link 081 // March 2024 082 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 083 // This is an extremely simple one: 084 // 085 // U+0040 COMMERCIAL AT (@) 086 // 087 // If the next 3 input code points would start an ident sequence, consume an ident sequence, 088 // create an <at-keyword-token> with its value set to the returned value, and return it. 089 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 090 091 /** 092 * This is a tokenizer method which <B>"consumes"</B> the next At-Rule Token from the 093 * input Code-Point Array. 094 * 095 * <EMBED CLASS=defs DATA-TOK=At-Rule-Identifier DATA-URL=at-keyword-token-diagram 096 * DATA-OP=Consume> 097 * <EMBED CLASS=external-html DATA-FILE-ID=COPIED_CSS_WG_RR> 098 * <EMBED CLASS=external-html DATA-FILE-ID=AT_KEYWORD_TOK_SVG> 099 */ 100 protected static void consume( // When invoked from 'CSSTokenizer' 101 final int[] css, // C, int[] css 102 final ByRef<Integer> POS, // P, array-pos loop-variable 103 final Consumer<CSSToken> returnParsedToken // T, Vector<CSSToken>.add 104 ) 105 { 106 // NOTE: This method is, indeed, package-private and would never be invoked unless the 107 // code-point at css[0] actually were an `@` Symbol. The `build` method which allows 108 // a user to build an AtKeyword token also check this. 109 // 110 // It also guarantees that an actual identifer follows the `@` symbol 111 112 final ByRef<String> identifier = new ByRef<>(); 113 114 final int sPos = POS.f; // When I finally get to "consumeIdentSequence", fix this!! 115 final int ePos = Identifier.consumeIdentSequence(css, POS.f + 1, identifier); 116 117 returnParsedToken.accept(new AtKeyword(css, sPos, ePos, identifier.f)); 118 119 POS.f = ePos; 120 } 121}