@@ -10,7 +10,7 @@ import type { AbstractElement, Action, Assignment, ParserRule } from '../languag
1010import  type  {  Linker  }  from  '../references/linker.js' ; 
1111import  type  {  LangiumCoreServices  }  from  '../services.js' ; 
1212import  type  {  AstNode ,  AstReflection ,  CompositeCstNode ,  CstNode  }  from  '../syntax-tree.js' ; 
13- import  type  {  Lexer  }  from  './lexer.js' ; 
13+ import  type  {  Lexer ,   LexerResult  }  from  './lexer.js' ; 
1414import  type  {  IParserConfig  }  from  './parser-config.js' ; 
1515import  type  {  ValueConverter  }  from  './value-converter.js' ; 
1616import  {  defaultParserErrorProvider ,  EmbeddedActionsParser ,  LLkLookaheadStrategy  }  from  'chevrotain' ; 
@@ -21,6 +21,7 @@ import { assignMandatoryProperties, getContainerOfType, linkContentToContainer }
2121import  {  CstNodeBuilder  }  from  './cst-node-builder.js' ; 
2222import  type  {  LexingReport  }  from  './token-builder.js' ; 
2323import  {  toDocumentSegment  }  from  '../utils/cst-utils.js' ; 
24+ import  type  {  CommentProvider  }  from  '../documentation/comment-provider.js' ; 
2425
2526export  type  ParseResult < T  =  AstNode >  =  { 
2627    value : T , 
@@ -123,6 +124,7 @@ const withRuleSuffix = (name: string): string => name.endsWith(ruleSuffix) ? nam
123124export  abstract  class  AbstractLangiumParser  implements  BaseParser  { 
124125
125126    protected  readonly  lexer : Lexer ; 
127+     protected  readonly  commentProvider : CommentProvider ; 
126128    protected  readonly  wrapper : ChevrotainWrapper ; 
127129    protected  _unorderedGroups : Map < string ,  boolean [ ] >  =  new  Map < string ,  boolean [ ] > ( ) ; 
128130
@@ -138,6 +140,7 @@ export abstract class AbstractLangiumParser implements BaseParser {
138140            skipValidations : production , 
139141            errorMessageProvider : services . parser . ParserErrorMessageProvider 
140142        } ) ; 
143+         this . commentProvider  =  services . documentation . CommentProvider ; 
141144    } 
142145
143146    alternatives ( idx : number ,  choices : Array < IOrAlt < any > > ) : void { 
@@ -197,6 +200,7 @@ export class LangiumParser extends AbstractLangiumParser {
197200    private  readonly  converter : ValueConverter ; 
198201    private  readonly  astReflection : AstReflection ; 
199202    private  readonly  nodeBuilder  =  new  CstNodeBuilder ( ) ; 
203+     private  lexerResult ?: LexerResult ; 
200204    private  stack : any [ ]  =  [ ] ; 
201205    private  assignmentMap  =  new  Map < AbstractElement ,  AssignmentElement  |  undefined > ( ) ; 
202206    private  currentMode : CstParserMode  =  CstParserMode . Retain ; 
@@ -236,17 +240,15 @@ export class LangiumParser extends AbstractLangiumParser {
236240    parse < T  extends  AstNode  =  AstNode > ( input : string ,  options : ParserOptions  =  { } ) : ParseResult < T >  { 
237241        this . currentMode  =  options . cst  ??  CstParserMode . Retain ; 
238242        this . nodeBuilder . buildRootNode ( input ) ; 
239-         const  lexerResult  =  this . lexer . tokenize ( input ) ; 
243+         const  lexerResult  =  this . lexerResult   =   this . lexer . tokenize ( input ) ; 
240244        this . wrapper . input  =  lexerResult . tokens ; 
241245        const  ruleMethod  =  options . rule  ? this . allRules . get ( options . rule )  : this . mainRule ; 
242246        if  ( ! ruleMethod )  { 
243247            throw  new  Error ( options . rule  ? `No rule found with name '${ options . rule }   : 'No main rule available.' ) ; 
244248        } 
245249        const  result  =  ruleMethod . call ( this . wrapper ,  { } ) ; 
246-         if  ( this . currentMode  ===  CstParserMode . Retain )  { 
247-             this . nodeBuilder . addHiddenTokens ( lexerResult . hidden ) ; 
248-         } 
249250        this . unorderedGroups . clear ( ) ; 
251+         this . lexerResult  =  undefined ; 
250252        return  { 
251253            value : result , 
252254            lexerErrors : lexerResult . errors , 
@@ -277,9 +279,32 @@ export class LangiumParser extends AbstractLangiumParser {
277279        } ; 
278280    } 
279281
282+     private  appendHiddenTokens ( tokens : IToken [ ] ) : void { 
283+         for  ( const  token  of  tokens )  { 
284+             this . nodeBuilder . buildLeafNode ( token ) ; 
285+         } 
286+     } 
287+ 
288+     private  getHiddenTokens ( token : IToken ) : IToken [ ]  { 
289+         const  hiddenTokens  =  this . lexerResult ! . hidden ; 
290+         if  ( ! hiddenTokens . length )  { 
291+             return  [ ] ; 
292+         } 
293+         const  offset  =  token . startOffset ; 
294+         for  ( let  i  =  0 ;  i  <  hiddenTokens . length ;  i ++ )  { 
295+             const  token  =  hiddenTokens [ i ] ; 
296+             if  ( token . startOffset  >  offset )  { 
297+                 return  hiddenTokens . splice ( 0 ,  i ) ; 
298+             } 
299+         } 
300+         return  hiddenTokens . splice ( 0 ,  hiddenTokens . length ) ; 
301+     } 
302+ 
280303    consume ( idx : number ,  tokenType : TokenType ,  feature : AbstractElement ) : void { 
281304        const  token  =  this . wrapper . wrapConsume ( idx ,  tokenType ) ; 
282305        if  ( ! this . isRecording ( )  &&  this . isValidToken ( token ) )  { 
306+             const  hiddenTokens  =  this . getHiddenTokens ( token ) ; 
307+             this . appendHiddenTokens ( hiddenTokens ) ; 
283308            const  leafNode  =  this . nodeBuilder . buildLeafNode ( token ,  feature ) ; 
284309            const  {  assignment,  isCrossRef }  =  this . getAssignment ( feature ) ; 
285310            const  current  =  this . current ; 
@@ -374,9 +399,12 @@ export class LangiumParser extends AbstractLangiumParser {
374399        }  else  { 
375400            assignMandatoryProperties ( this . astReflection ,  obj ) ; 
376401        } 
402+         obj . $cstNode  =  cstNode ; 
403+         delete  obj . $segments . comment ; 
404+         obj . $segments . comment  =  this . commentProvider . getComment ( obj ) ; 
377405        obj . $segments . full  =  toDocumentSegment ( cstNode ) ; 
378-         if  ( this . currentMode  ===  CstParserMode . Retain )  { 
379-             obj . $cstNode  =  cstNode ; 
406+         if  ( this . currentMode  ===  CstParserMode . Discard )  { 
407+             obj . $cstNode  =  undefined ; 
380408        } 
381409        return  [ obj ,  cstNode ] ; 
382410    } 
0 commit comments