sclass Tok { // either one can be null (bot not both) S s; // joined LS tok; // tokenized ITokenizer tokenizer; // optional *() {} *(S *s, ITokenizer *tokenizer) {} *(LS *tok) {} S text() { if (s == null) s = join(tok); ret s; } LS tok() { if (tok == null) tok = tokenizer.tokenize(s); ret tok; } // Note: toString can trigger tokenization toString { ret appendSquareBracketed(text(), nTokens(countTokens(tok()))); } }