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;
    }
}