stride3d/stride · warning · LexerException
{msg}
Error message
{msg} What it means
JoinReader.warning reports lexer warnings (e.g. trigraph conversion/ignoring) by forwarding them to the current LexerSource; if no source is attached (source == null), it throws LexerException with the warning text instead. In other words, a merely warning-grade condition becomes a fatal error when the reader has no source to report through.
Solutions
- Call init(preprocessor, lexerSource) on the JoinReader before reading so warnings route to the source's warning handler.
- Remove or escape the trigraph sequence (e.g. '??(' -> '( ') from the input text.
- Disable trigraph warnings via the preprocessor feature/warning flags (Feature.TRIGRAPHS / Warning.TRIGRAPHS) if trigraphs are intentional.
- Install a PreprocessorListener so LexerSource.warning logs instead of propagating.
Example fix
// before: reader created without a source; a trigraph warning throws var reader = new JoinReader(stream); // after: attach source so warnings are reported, not thrown var reader = new JoinReader(stream); reader.init(preprocessor, new LexerSource(reader, "shader.sdsl"));
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the reader is wired to a source before reading
if (!readerIsInitialized)
throw new InvalidOperationException("JoinReader must be init(pp, source)-ed before read()"); Try / catch
try
{
int c = reader.read();
}
catch (LexerException ex)
{
logger.Warn($"Trigraph/diagnostic while lexing: {ex.Message}");
} Prevention
- Always call init(preprocessor, lexerSource) before the first read().
- Enable Feature.TRIGRAPHS/WARNING flags deliberately; avoid raw '??x' sequences in shader sources.
- Install a PreprocessorListener so warnings never escalate to exceptions.
When it happens
Trigger: Reading input through a JoinReader that was never init()-ed with a Preprocessor/LexerSource (or whose source was detached) while a trigraph sequence '??x' is encountered and trigraph warnings are enabled (Warning.TRIGRAPHS).
Common situations: Constructing a JoinReader manually without calling init(pp, source); preprocessing shader code containing legacy '??(' style trigraph sequences on a reader without a source; ported C preprocessor code paths where the source is set later than first read.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/3155dd6767060cb3.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/CppNet/JoinReader.cs:88
if(uptr > 0)
return unget[--uptr];
return _in.Read();
}
private void _unread(int c)
{
if(c != -1)
unget[uptr++] = c;
System.Diagnostics.Debug.Assert(uptr <= unget.Length,
"JoinReader ungets too many characters");
}
protected void warning(String msg)
{
if(source != null)
source.warning(msg);
else
throw new LexerException(msg);
}
private char trigraph(char raw, char repl)
{
if(trigraphs) {
if(warnings)
warning("trigraph ??" + raw + " converted to " + repl);
return repl;
} else {
if(warnings)
warning("trigraph ??" + raw + " ignored");
_unread(raw);
_unread('?');
return '?';
}
}
private int _read()View on GitHub (pinned to 96fad776d2)