@@ -3,12 +3,22 @@ import {
33 PreprocessorAstNode ,
44 PreprocessorElseIfNode ,
55 PreprocessorIdentifierNode ,
6- PreprocessorIfNode ,
76 PreprocessorLiteralNode ,
87 PreprocessorSegmentNode ,
98} from './preprocessor-node.js' ;
109import generate from './generator.js' ;
1110
11+ import * as parser from './preprocessor-parser.js' ;
12+ import { formatError } from '../error.js' ;
13+
14+ // Register the constant_expression parser so preprocessor.ts can parse #if
15+ // expression strings after macro expansion.
16+ const expressionParser = ( src : string ) : PreprocessorAstNode =>
17+ formatError ( parser ) ( src , {
18+ grammarSource : 'expression' ,
19+ startRule : 'constant_expression' ,
20+ } ) ;
21+
1222export type PreprocessorProgram = {
1323 type : string ;
1424 program : PreprocessorSegmentNode [ ] ;
@@ -479,40 +489,24 @@ export type PreprocessorOptions = {
479489 grammarSource ?: string ;
480490} ;
481491
482- // Parser for constant_expression strings, registered by index.ts at startup.
483- // Must be set before preprocessAst() is called on any program that uses #if.
484- let _exprParser : ( ( src : string ) => PreprocessorAstNode ) | undefined ;
485- export const initExpressionParser = (
486- fn : ( src : string ) => PreprocessorAstNode
487- ) => {
488- _exprParser = fn ;
489- } ;
490-
491492// Evaluate a raw #if / #elif expression string against the current macros.
492493// Handles defined() before macro expansion (spec-correct order), then
493494// parses the result as a constant_expression AST and evaluates it.
494495const evaluateExpressionString = ( expr : string , macros : Macros ) : any => {
495- if ( ! _exprParser ) {
496- throw new Error (
497- 'No expression parser registered. Import from preprocessor/index.js, or call initExpressionParser() first.'
498- ) ;
499- }
500496 // Strip inline comments so "defined/**/A" is treated as "defined A"
501497 const stripped = preprocessComments ( expr ) ;
502498 // Step 1: evaluate defined(X) / defined X before any macro expansion
503499 const withDefined = stripped
504- . replace (
505- / d e f i n e d \s * \( \s * ( [ A - Z a - z _ ] [ A - Z a - z _ 0 - 9 ] * ) \s * \) / g,
506- ( _ , id ) => ( id in macros ? '1' : '0' )
500+ . replace ( / d e f i n e d \s * \( \s * ( [ A - Z a - z _ ] [ A - Z a - z _ 0 - 9 ] * ) \s * \) / g, ( _ , id ) =>
501+ id in macros ? '1' : '0'
507502 )
508- . replace (
509- / d e f i n e d \s + ( [ A - Z a - z _ ] [ A - Z a - z _ 0 - 9 ] * ) / g,
510- ( _ , id ) => ( id in macros ? '1' : '0' )
503+ . replace ( / d e f i n e d \s + ( [ A - Z a - z _ ] [ A - Z a - z _ 0 - 9 ] * ) / g, ( _ , id ) =>
504+ id in macros ? '1' : '0'
511505 ) ;
512506 // Step 2: expand all macros in the resulting string
513507 const expanded = expandMacros ( withDefined , macros ) ;
514508 // Step 3: parse the expanded string as a constant_expression and evaluate
515- return evaluteExpression ( _exprParser ( expanded . trim ( ) ) , macros ) ;
509+ return evaluteExpression ( expressionParser ( expanded . trim ( ) ) , macros ) ;
516510} ;
517511
518512// Remove escaped newlines, rather than try to handle them in the grammar
0 commit comments