@@ -106,6 +106,8 @@ def initialize(content, options)
106
106
@rests = [ ]
107
107
@seek = 0
108
108
109
+ @heredoc_queue = [ ]
110
+
109
111
@indent = 0
110
112
@indent_stack = [ ]
111
113
@lex_state = :EXPR_BEG
@@ -462,21 +464,43 @@ def lex_init()
462
464
463
465
@OP . def_rule ( "\n " ) do |op , io |
464
466
print "\\ n\n " if RDoc ::RubyLex . debug?
465
- case @lex_state
466
- when :EXPR_BEG , :EXPR_FNAME , :EXPR_DOT
467
- @continue = true
468
- else
469
- @continue = false
470
- @lex_state = :EXPR_BEG
471
- until ( @indent_stack . empty? ||
472
- [ TkLPAREN , TkLBRACK , TkLBRACE ,
473
- TkfLPAREN , TkfLBRACK , TkfLBRACE ] . include? ( @indent_stack . last ) )
474
- @indent_stack . pop
467
+ unless @heredoc_queue . empty?
468
+ info = @heredoc_queue [ 0 ]
469
+ if !info [ :started ] # "\n"
470
+ info [ :started ] = true
471
+ ungetc "\n "
472
+ elsif info [ :heredoc_end ] . nil? # heredoc body
473
+ tk , heredoc_end = identify_here_document_body ( info [ :quoted ] , info [ :lt ] , info [ :indent ] )
474
+ info [ :heredoc_end ] = heredoc_end
475
+ ungetc "\n "
476
+ else # heredoc end
477
+ @heredoc_queue . shift
478
+ @lex_state = :EXPR_BEG
479
+ tk = Token ( TkHEREDOCEND , info [ :heredoc_end ] )
480
+ if !@heredoc_queue . empty?
481
+ @heredoc_queue [ 0 ] [ :started ] = true
482
+ ungetc "\n "
483
+ end
475
484
end
476
485
end
477
- @current_readed = @readed
478
- @here_readed . clear
479
- Token ( TkNL )
486
+ unless tk
487
+ case @lex_state
488
+ when :EXPR_BEG , :EXPR_FNAME , :EXPR_DOT
489
+ @continue = true
490
+ else
491
+ @continue = false
492
+ @lex_state = :EXPR_BEG
493
+ until ( @indent_stack . empty? ||
494
+ [ TkLPAREN , TkLBRACK , TkLBRACE ,
495
+ TkfLPAREN , TkfLBRACK , TkfLBRACE ] . include? ( @indent_stack . last ) )
496
+ @indent_stack . pop
497
+ end
498
+ end
499
+ @current_readed = @readed
500
+ @here_readed . clear
501
+ tk = Token ( TkNL )
502
+ end
503
+ tk
480
504
end
481
505
482
506
@OP . def_rules ( "*" , "**" ,
@@ -506,8 +530,8 @@ def lex_init()
506
530
if @lex_state != :EXPR_END && @lex_state != :EXPR_CLASS &&
507
531
( @lex_state != :EXPR_ARG || @space_seen )
508
532
c = peek ( 0 )
509
- if /\S / =~ c && ( /["'`]/ =~ c || /\w / =~ c || c == "-" )
510
- tk = identify_here_document
533
+ if /\S / =~ c && ( /["'`]/ =~ c || /\w / =~ c || c == "-" || c == "~" )
534
+ tk = identify_here_document ( op )
511
535
end
512
536
end
513
537
unless tk
@@ -985,77 +1009,63 @@ def identify_identifier
985
1009
end
986
1010
end
987
1011
988
- def identify_here_document
1012
+ def identify_here_document ( op )
989
1013
ch = getc
1014
+ start_token = op
990
1015
# if lt = PERCENT_LTYPE[ch]
991
- if ch == "-"
1016
+ if ch == "-" or ch == "~"
1017
+ start_token . concat ch
992
1018
ch = getc
993
1019
indent = true
994
1020
end
995
1021
if /['"`]/ =~ ch
1022
+ start_token . concat ch
996
1023
user_quote = lt = ch
997
1024
quoted = ""
998
1025
while ( c = getc ) && c != lt
999
1026
quoted . concat c
1000
1027
end
1028
+ start_token . concat quoted
1029
+ start_token . concat lt
1001
1030
else
1002
1031
user_quote = nil
1003
1032
lt = '"'
1004
1033
quoted = ch . dup
1005
1034
while ( c = getc ) && c =~ /\w /
1006
1035
quoted . concat c
1007
1036
end
1037
+ start_token . concat quoted
1008
1038
ungetc
1009
1039
end
1010
1040
1011
- ltback , @ltype = @ltype , lt
1012
- reserve = [ ]
1013
- while ch = getc
1014
- reserve . push ch
1015
- if ch == "\\ "
1016
- reserve . push ch = getc
1017
- elsif ch == "\n "
1018
- break
1019
- end
1020
- end
1021
-
1022
- output_heredoc = reserve . join =~ /\A \r ?\n \z /
1041
+ @heredoc_queue << {
1042
+ quoted : quoted ,
1043
+ lt : lt ,
1044
+ indent : indent ,
1045
+ started : false
1046
+ }
1047
+ @lex_state = :EXPR_BEG
1048
+ Token ( RDoc ::RubyLex ::TkHEREDOCBEG , start_token )
1049
+ end
1023
1050
1024
- if output_heredoc then
1025
- doc = '<<'
1026
- doc << '-' if indent
1027
- doc << "#{ user_quote } #{ quoted } #{ user_quote } \n "
1028
- else
1029
- doc = '"'
1030
- end
1051
+ def identify_here_document_body ( quoted , lt , indent )
1052
+ ltback , @ltype = @ltype , lt
1031
1053
1032
- @current_readed = @readed
1054
+ doc = ""
1055
+ heredoc_end = nil
1033
1056
while l = gets
1034
1057
l = l . sub ( /(:?\r )?\n \z / , "\n " )
1035
1058
if ( indent ? l . strip : l . chomp ) == quoted
1059
+ heredoc_end = l
1036
1060
break
1037
1061
end
1038
1062
doc << l
1039
1063
end
1064
+ raise Error , "Missing terminating #{ quoted } for string" unless heredoc_end
1040
1065
1041
- if output_heredoc then
1042
- raise Error , "Missing terminating #{ quoted } for string" unless l
1043
-
1044
- doc << l . chomp
1045
- else
1046
- doc << '"'
1047
- end
1048
-
1049
- @current_readed = @here_readed
1050
- @here_readed . concat reserve
1051
- while ch = reserve . pop
1052
- ungetc ch
1053
- end
1054
-
1055
- token_class = output_heredoc ? RDoc ::RubyLex ::TkHEREDOC : Ltype2Token [ lt ]
1056
1066
@ltype = ltback
1057
- @lex_state = :EXPR_END
1058
- Token ( token_class , doc )
1067
+ @lex_state = :EXPR_BEG
1068
+ [ Token ( RDoc :: RubyLex :: TkHEREDOC , doc ) , heredoc_end ]
1059
1069
end
1060
1070
1061
1071
def identify_quotation
0 commit comments