@@ -27,6 +27,92 @@ describe('ANTLR VBA Preprocessor Parser', () => {
2727 return implicitTokens ;
2828 }
2929
30+ /**
31+ * Helper function to create a hierarchical tree view of the parse tree
32+ */
33+ function logParseTree ( parseTree : any , indent : string = ' ' , isLast : boolean = true ) : void {
34+ if ( ! parseTree ) return ;
35+
36+ const nodeType = parseTree . constructor . name || 'UnknownNode' ;
37+ const prefix = isLast ? '└── ' : '├── ' ;
38+
39+ // If it's a terminal node (token), show the token value
40+ if ( parseTree . symbol ) {
41+ const token = parseTree . symbol ;
42+ const displayText = ( token . text || '' ) . replace ( / \n / g, '\\n' ) . replace ( / \r / g, '\\r' ) ;
43+ console . log ( `${ indent } ${ prefix } ${ nodeType } [${ token . type } ] = "${ displayText } "` ) ;
44+ } else {
45+ console . log ( `${ indent } ${ prefix } ${ nodeType } ` ) ;
46+ }
47+
48+ // Recursively display children
49+ if ( parseTree . children && parseTree . children . length > 0 ) {
50+ const childIndent = indent + ( isLast ? ' ' : '│ ' ) ;
51+ parseTree . children . forEach ( ( child : any , index : number ) => {
52+ const isLastChild = index === parseTree . children . length - 1 ;
53+ logParseTree ( child , childIndent , isLastChild ) ;
54+ } ) ;
55+ }
56+ }
57+
58+ /**
59+ * Helper function to create a hierarchical token view based on line structure
60+ */
61+ function logTokenHierarchy ( input : string , tokenInfo : Array < { type : number , text : string , typeName : string } > ) : void {
62+ console . log ( ' 🔗 Token Hierarchy:' ) ;
63+
64+ const lines = input . split ( / \r ? \n / ) ;
65+ const nonEmptyLines = lines . map ( ( line , index ) => ( { line, index } ) ) . filter ( item => item . line . trim ( ) ) ;
66+ let tokenIndex = 0 ;
67+
68+ nonEmptyLines . forEach ( ( lineItem , displayIndex ) => {
69+ const { line, index : lineNum } = lineItem ;
70+ const isLastLine = displayIndex === nonEmptyLines . length - 1 ;
71+ const linePrefix = isLastLine ? '└── ' : '├── ' ;
72+
73+ console . log ( ` ${ linePrefix } Line ${ lineNum + 1 } : "${ line } "` ) ;
74+
75+ // Find tokens that belong to this line
76+ const lineTokens : typeof tokenInfo = [ ] ;
77+ const currentPos = 0 ;
78+
79+ // Simple heuristic to group tokens by line
80+ while ( tokenIndex < tokenInfo . length ) {
81+ const token = tokenInfo [ tokenIndex ] ;
82+
83+ // If it's a newline token, we've reached the end of this line
84+ if ( token . typeName === 'NEWLINE' ) {
85+ tokenIndex ++ ;
86+ break ;
87+ }
88+
89+ lineTokens . push ( token ) ;
90+ tokenIndex ++ ;
91+
92+ // If we've processed all tokens, break
93+ if ( tokenIndex >= tokenInfo . length ) break ;
94+ }
95+
96+ // Display tokens for this line in a hierarchical manner
97+ lineTokens . forEach ( ( token , idx ) => {
98+ const isLastToken = idx === lineTokens . length - 1 ;
99+ const tokenPrefix = isLastToken ? '└── ' : '├── ' ;
100+ const lineConnector = isLastLine ? ' ' : '│ ' ;
101+ const displayText = token . text . replace ( / \n / g, '\\n' ) . replace ( / \r / g, '\\r' ) ;
102+ console . log ( ` ${ lineConnector } ${ tokenPrefix } ${ token . typeName . padEnd ( 12 ) } = "${ displayText } "` ) ;
103+ } ) ;
104+ } ) ;
105+
106+ // Handle any remaining tokens that weren't processed
107+ while ( tokenIndex < tokenInfo . length ) {
108+ const token = tokenInfo [ tokenIndex ] ;
109+ if ( token . typeName === 'NEWLINE' ) {
110+ console . log ( ` └── [End] NEWLINE = "${ token . text . replace ( / \n / g, '\\n' ) . replace ( / \r / g, '\\r' ) } "` ) ;
111+ }
112+ tokenIndex ++ ;
113+ }
114+ }
115+
30116 /**
31117 * Helper function to log parsing results consistently
32118 */
@@ -39,11 +125,23 @@ describe('ANTLR VBA Preprocessor Parser', () => {
39125 console . log ( ` ${ ( index + 1 ) . toString ( ) . padStart ( 2 ) } : ${ line } ` ) ;
40126 }
41127 } ) ;
42- console . log ( ' 🔤 Tokens:' ) ;
128+
129+ // Original flat token view
130+ console . log ( ' 🔤 Tokens (Flat):' ) ;
43131 result . tokenInfo . forEach ( ( t , i ) => {
44132 const displayText = t . text . replace ( / \n / g, '\\n' ) . replace ( / \r / g, '\\r' ) ;
45133 console . log ( ` ${ i . toString ( ) . padStart ( 2 ) } : ${ t . typeName . padEnd ( 12 ) } = "${ displayText } "` ) ;
46134 } ) ;
135+
136+ // New hierarchical token view
137+ logTokenHierarchy ( input , result . tokenInfo ) ;
138+
139+ // Parse tree hierarchy (if available)
140+ if ( result . parseTree ) {
141+ console . log ( ' 🌳 Parse Tree:' ) ;
142+ logParseTree ( result . parseTree ) ;
143+ }
144+
47145 if ( result . lexerErrors . length > 0 ) {
48146 console . log ( ' ❌ Lexer errors:' , result . lexerErrors ) ;
49147 }
0 commit comments