1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | package Torello.CSS; import Torello.Java.Additional.ByRef; import java.util.Vector; import java.util.function.Consumer; /** Represents a CSS Comment-Block */ @Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="CSS_TOK") public class Comment extends CSSToken implements CharSequence, java.io.Serializable, Comparable<CharSequence> { /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ protected static final long serialVersionUID = 1; // ******************************************************************************************** // ******************************************************************************************** // Private Constructor, API "is" and "if" Methods // ******************************************************************************************** // ******************************************************************************************** private Comment(final int[] css, final int sPos, final int ePos) { super(css, sPos, ePos); } @Override public final boolean isComment() { return true; } @Override public final Comment ifComment() { return this; } // ******************************************************************************************** // ******************************************************************************************** // User's Constructor: a static "build" method // ******************************************************************************************** // ******************************************************************************************** /** * <EMBED CLASS=defs DATA-TOK=Comment DATA-P=commentStr> * <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_DESC> * @param commentStr <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_PARAM> * @return <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_RET> * @throws TokenizeException <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_TOK_EX> */ @SuppressWarnings("unchecked") public static Comment build(final String commentStr) { return (Comment) CSSToken.build(commentStr, INPUT_CHECKER, Comment::consume); } private static final CSSToken.InputChecker INPUT_CHECKER = (int[] css) -> { if (css.length < 4) throw new TokenizeException(Comment.class); if ((css[0] != '/') || (css[1] != '*')) throw new TokenizeException ("Input-String does not start with \"/*\""); }; // ******************************************************************************************** // ******************************************************************************************** // Tokenizer's "is" Method(s) // ******************************************************************************************** // ******************************************************************************************** /** * Checks whether or not the next token to consume is a Comment * <EMBED CLASS=defs DATA-TOK=Comment DATA-URL=comment-diagram DATA-OP=Check> * <EMBED CLASS=external-html DATA-FILE-ID=COPIED_CSS_WG_RR> * <EMBED CLASS=external-html DATA-FILE-ID=COMMENT_SVG> * @param css CSS-{@code String} as an array of code-points. * @param sPos The array-index where the tokenizer is to consume its next token * @return {@code TRUE} if and only if the next token in the array is a comment */ public static boolean is(final int[] css, final int sPos) { if ((sPos + 1) >= css.length) return false; if ((css[sPos] != '/') || (css[sPos + 1] != '*')) return false; return true; } // ******************************************************************************************** // ******************************************************************************************** // CONSUME // ******************************************************************************************** // ******************************************************************************************** // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Copied from: // https://drafts.csswg.org/css-syntax-3/#consume-comment // April 2024 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // // 4.3.2. Consume comments // // This section describes how to consume comments from a stream of code points. It returns // nothing. // // If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*), // consume them and all following code points up to and including the first U+002A ASTERISK (*) // followed by a U+002F SOLIDUS (/), or up to an EOF code point. Return to the start of this // step. // // If the preceding paragraph ended by consuming an EOF code point, this is a parse error. // // Return nothing. /** * This is a tokenizer method which <B>"consumes"</B> the next Comment-Token from the * input Code-Point Array. * * <EMBED CLASS=defs DATA-TOK=Comment DATA-URL=consume-comment * DATA-OP=Consume> * <EMBED CLASS=external-html DATA-FILE-ID=COPIED_CSS_WG> * <EMBED CLASS=external-html DATA-FILE-ID=COMMENTS> */ protected static void consume( // When invoked from 'CSSTokenizer' final int[] css, // C, int[] css final ByRef<Integer> POS, // P, array-pos loop-variable final Consumer<CSSToken> returnParsedToken, // T, Vector<CSSToken>.add final Consumer<TokenizeError> errorEncountered // E, Vector<TokenizeError>.add ) { int pos = POS.f + 2; for (; (pos + 1) < css.length; pos++) if ((css[pos] == '*') && (css[pos + 1] == '/')) { returnParsedToken.accept(new Comment(css, POS.f, pos += 2)); POS.f = pos; return; } errorEncountered.accept( new TokenizeError( css, POS.f, pos, Comment.class, "An Opening-Comment '/*' Character-Sequence was encountered, but EOF was " + "reached before the Matching, Closing '*/' sequence was identified." )); POS.f = pos; } } |