rubylexer 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +0 -0
- data/History.txt +16 -1
- data/Manifest.txt +0 -0
- data/README.txt +0 -0
- data/Rakefile +1 -1
- data/howtouse.txt +0 -0
- data/lib/assert.rb +0 -0
- data/lib/rubylexer.rb +156 -45
- data/lib/rubylexer/0.6.2.rb +0 -0
- data/lib/rubylexer/0.6.rb +0 -0
- data/lib/rubylexer/0.7.0.rb +0 -0
- data/lib/rubylexer/0.7.1.rb +0 -0
- data/lib/rubylexer/charhandler.rb +0 -0
- data/lib/rubylexer/charset.rb +0 -0
- data/lib/rubylexer/context.rb +6 -0
- data/lib/rubylexer/rubycode.rb +0 -0
- data/lib/rubylexer/rulexer.rb +3 -2
- data/lib/rubylexer/symboltable.rb +0 -0
- data/lib/rubylexer/token.rb +3 -3
- data/lib/rubylexer/tokenprinter.rb +0 -0
- data/lib/rubylexer/version.rb +1 -1
- data/rubylexer.vpj +39 -29
- data/test/code/all_the_gems.rb +0 -0
- data/test/code/all_the_raas.rb +0 -0
- data/test/code/all_the_rubies.rb +0 -0
- data/test/code/deletewarns.rb +0 -0
- data/test/code/dumptokens.rb +6 -2
- data/test/code/errscan +0 -0
- data/test/code/isolate_error.rb +0 -0
- data/test/code/lexloop +0 -0
- data/test/code/locatetest +0 -0
- data/test/code/locatetest.rb +0 -0
- data/test/code/regression.rb +0 -2
- data/test/code/rubylexervsruby.rb +0 -0
- data/test/code/strgen.rb +0 -0
- data/test/code/tarball.rb +0 -0
- data/test/code/testcases.rb +0 -0
- data/test/code/tokentest.rb +0 -0
- data/test/code/torment +0 -0
- data/test/data/1.rb.broken +0 -0
- data/test/data/23.rb +0 -0
- data/test/data/__end__.rb +0 -0
- data/test/data/__end__2.rb +0 -0
- data/test/data/__eof2.rb +0 -0
- data/test/data/__eof5.rb +0 -0
- data/test/data/__eof6.rb +0 -0
- data/test/data/and.rb +0 -0
- data/test/data/blockassigntest.rb +0 -0
- data/test/data/chunky.plain.rb +0 -0
- data/test/data/chunky_bacon.rb +0 -0
- data/test/data/chunky_bacon2.rb +0 -0
- data/test/data/chunky_bacon3.rb +0 -0
- data/test/data/chunky_bacon4.rb +0 -0
- data/test/data/cvtesc.rb +0 -0
- data/test/data/for.rb +0 -0
- data/test/data/format.rb +0 -0
- data/test/data/g.rb +0 -0
- data/test/data/hd0.rb +0 -0
- data/test/data/hdateof.rb +0 -0
- data/test/data/hdempty.rb +0 -0
- data/test/data/hdr.rb +0 -0
- data/test/data/hdr_dos.rb +0 -0
- data/test/data/hdr_dos2.rb +0 -0
- data/test/data/heart.rb +0 -0
- data/test/data/here_escnl.rb +0 -0
- data/test/data/here_escnl_dos.rb +0 -0
- data/test/data/here_squote.rb +0 -0
- data/test/data/heremonsters.rb +0 -0
- data/test/data/heremonsters.rb.broken +0 -0
- data/test/data/heremonsters.rb.broken.save +0 -0
- data/test/data/heremonsters_dos.rb +0 -0
- data/test/data/heremonsters_dos.rb.broken +0 -0
- data/test/data/if.rb +0 -0
- data/test/data/jarh.rb +0 -0
- data/test/data/lbrace.rb +0 -0
- data/test/data/lbrack.rb +0 -0
- data/test/data/make_ws_strdelim.rb +0 -0
- data/test/data/maven2_builer_test.rb +0 -0
- data/test/data/migration.rb +0 -0
- data/test/data/modl.rb +0 -0
- data/test/data/modl_dos.rb +0 -0
- data/test/data/modl_fails.rb +0 -0
- data/test/data/multilinestring.rb +0 -0
- data/test/data/newsyntax.rb +0 -0
- data/test/data/noeolatend.rb +0 -0
- data/test/data/oneliners.rb +1 -1
- data/test/data/p-op.rb +0 -0
- data/test/data/p.rb +0 -0
- data/test/data/pleac.rb.broken +0 -0
- data/test/data/pre.rb +0 -0
- data/test/data/pre.unix.rb +0 -0
- data/test/data/regtest.rb +0 -0
- data/test/data/rescue.rb +0 -0
- data/test/data/s.rb +0 -0
- data/test/data/simple.rb +0 -0
- data/test/data/simple_dos.rb +0 -0
- data/test/data/stanzas.rb +0 -0
- data/test/data/strdelim_crlf.rb +0 -0
- data/test/data/strinc.rb +0 -0
- data/test/data/stuff.rb +0 -0
- data/test/data/stuff2.rb +0 -0
- data/test/data/stuff3.rb +0 -0
- data/test/data/tkweird.rb +0 -0
- data/test/data/tokentest.assert.rb.can +0 -0
- data/test/data/unending_stuff.rb +0 -0
- data/test/data/untermed_here.rb.broken +0 -0
- data/test/data/untermed_string.rb.broken +0 -0
- data/test/data/untitled1.rb +0 -0
- data/test/data/w.rb +0 -0
- data/test/data/whatnot.rb +0 -0
- data/test/data/ws_strdelim.rb +0 -0
- data/test/data/wsdlDriver.rb +0 -0
- data/test/test.sh +0 -0
- data/testing.txt +0 -0
- metadata +64 -149
data/COPYING
CHANGED
File without changes
|
data/History.txt
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
=== 0.7.
|
1
|
+
=== 0.7.2/10-12-2008
|
2
|
+
* 12 Minor Enhancements:
|
3
|
+
* a new context for then kw expected
|
4
|
+
* disable all backtracking when scanning string interiors
|
5
|
+
* ternary flag distinguishes ternary : from other uses
|
6
|
+
* EndDefHeaderToken renamed to EndHeaderToken
|
7
|
+
* ^ now gets its own scanning method
|
8
|
+
* correct # of parens emitted after of kw used as (or like) method
|
9
|
+
* more special casing for break return and next
|
10
|
+
* abort_noparens! now better if When context on the stack
|
11
|
+
* semicolon may now be omitted after module header
|
12
|
+
* { and } in BEGIN/END expr masquerade as do and end
|
13
|
+
* trying to make 'rake test' work right
|
14
|
+
* certain other changes of no importance whatsoever
|
15
|
+
|
16
|
+
=== 0.7.1/8-29-2008
|
2
17
|
* 6 Major Enhancements:
|
3
18
|
* handling of empty string fragments now more closely mirrors ruby; this resolves many warnings
|
4
19
|
* yet more hacks in aid of string inclusions
|
data/Manifest.txt
CHANGED
File without changes
|
data/README.txt
CHANGED
File without changes
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ require 'lib/rubylexer/version.rb'
|
|
15
15
|
_.email = "rubylexer-owner @at@ inforadical .dot. net"
|
16
16
|
_.url = ["http://rubylexer.rubyforge.org/", "http://rubyforge.org/projects/rubylexer/"]
|
17
17
|
_.extra_deps << ['sequence', '>= 0.2.0']
|
18
|
-
_.test_globs=["test/
|
18
|
+
_.test_globs=["test/code/regression.rb"]
|
19
19
|
_.description=desc
|
20
20
|
_.summary=desc[/\A[^.]+\./]
|
21
21
|
_.spec_extras={:bindir=>''}
|
data/howtouse.txt
CHANGED
File without changes
|
data/lib/assert.rb
CHANGED
File without changes
|
data/lib/rubylexer.rb
CHANGED
@@ -83,7 +83,7 @@ class RubyLexer
|
|
83
83
|
?, => :comma,
|
84
84
|
?; => :semicolon,
|
85
85
|
|
86
|
-
?^ => :
|
86
|
+
?^ => :caret,
|
87
87
|
?~ => :tilde,
|
88
88
|
?= => :equals,
|
89
89
|
?! => :exclam,
|
@@ -130,6 +130,9 @@ class RubyLexer
|
|
130
130
|
@in_def_name=false
|
131
131
|
@last_operative_token=nil
|
132
132
|
@last_token_maybe_implicit=nil
|
133
|
+
@enable_macro=nil
|
134
|
+
@base_file=nil
|
135
|
+
@progress_thread=nil
|
133
136
|
|
134
137
|
@toptable=CharHandler.new(self, :illegal_char, CHARMAPPINGS)
|
135
138
|
|
@@ -442,12 +445,12 @@ private
|
|
442
445
|
end
|
443
446
|
|
444
447
|
#-----------------------------------
|
445
|
-
def in_lvar_define_state
|
448
|
+
def in_lvar_define_state lasttok=@last_operative_token
|
446
449
|
#@defining_lvar is a hack
|
447
450
|
@defining_lvar or case ctx=@parsestack.last
|
448
451
|
#when ForSMContext; ctx.state==:for
|
449
452
|
when RescueSMContext
|
450
|
-
|
453
|
+
lasttok.ident=="=>" and @file.match? /\A[\s\v]*([:;#\n]|then[^a-zA-Z0-9_])/m
|
451
454
|
#when BlockParamListLhsContext; true
|
452
455
|
end
|
453
456
|
end
|
@@ -472,7 +475,7 @@ private
|
|
472
475
|
|
473
476
|
assert String===name
|
474
477
|
|
475
|
-
was_in_lvar_define_state=in_lvar_define_state
|
478
|
+
was_in_lvar_define_state=in_lvar_define_state(lasttok)
|
476
479
|
#maybe_local really means 'maybe local or constant'
|
477
480
|
maybe_local=case name
|
478
481
|
when /[^a-z_0-9]$/i #do nothing
|
@@ -500,8 +503,6 @@ private
|
|
500
503
|
if /^[a-z_][a-zA-Z_0-9]*$/===name
|
501
504
|
assert !(lasttok===/^(\.|::)$/)
|
502
505
|
localvars[name]=true
|
503
|
-
else
|
504
|
-
lexerror tok,"not a valid variable name: #{name}"
|
505
506
|
end
|
506
507
|
return result.unshift(tok)
|
507
508
|
elsif maybe_local
|
@@ -534,7 +535,6 @@ private
|
|
534
535
|
if (assignment_coming && !(lasttok===/^(\.|::)$/) or was_in_lvar_define_state)
|
535
536
|
tok=assign_lvar_type! VarNameToken.new(name,pos)
|
536
537
|
if /[^a-z_0-9]$/i===name
|
537
|
-
lexerror tok,"not a valid variable name: #{name}"
|
538
538
|
elsif /^[a-z_]/===name and !(lasttok===/^(\.|::)$/)
|
539
539
|
localvars[name]=true
|
540
540
|
end
|
@@ -573,7 +573,7 @@ private
|
|
573
573
|
!(KeywordToken===oldlast and oldlast===/\A(\.|::)\Z/)
|
574
574
|
x
|
575
575
|
=end
|
576
|
-
when ?(
|
576
|
+
when ?(
|
577
577
|
maybe_local=false
|
578
578
|
lastid=lasttok&&lasttok.ident
|
579
579
|
case lastid
|
@@ -595,10 +595,12 @@ private
|
|
595
595
|
# ignored_tokens(true)
|
596
596
|
# want_parens=false if nextchar==?)
|
597
597
|
# @file.pos=afterparen
|
598
|
-
|
598
|
+
want_parens=true if /^(return|break|next)$/===@last_operative_token.ident and not(
|
599
|
+
KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
|
600
|
+
)
|
599
601
|
want_parens ? 1 : 0
|
600
|
-
when ?},?],?)
|
601
|
-
when ?+, ?-, ?%,
|
602
|
+
when ?},?],?),?;,(?^ unless @enable_macro), ?|, ?>, ?,, ?., ?=; 2
|
603
|
+
when ?+, ?-, ?%, ?/, (?^ if @enable_macro)
|
602
604
|
if /^(return|break|next)$/===@last_operative_token.ident and not(
|
603
605
|
KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
|
604
606
|
)
|
@@ -607,7 +609,7 @@ private
|
|
607
609
|
(ws_toks.empty? || readahead(2)[/^.[#{WHSPLF}]/o]) ? 2 : 3
|
608
610
|
end
|
609
611
|
when ?*, ?&
|
610
|
-
|
612
|
+
# lasttok=@last_operative_token
|
611
613
|
if /^(return|break|next)$/===@last_operative_token.ident and not(
|
612
614
|
KeywordToken===lasttok and /^(.|::)$/===lasttok.ident
|
613
615
|
)
|
@@ -626,7 +628,12 @@ private
|
|
626
628
|
/^\?([#{WHSPLF}]|[a-z_][a-z_0-9])/io===next3 ? 2 : 3
|
627
629
|
# when ?:,??; (readahead(2)[/^.[#{WHSPLF}]/o]) ? 2 : 3
|
628
630
|
when ?<; (!ws_toks.empty? && readahead(4)[/^<<-?["'`a-zA-Z_0-9]/]) ? 3 : 2
|
629
|
-
when ?[;
|
631
|
+
when ?[;
|
632
|
+
if ws_toks.empty?
|
633
|
+
(KeywordToken===oldlast and /^(return|break|next)$/===oldlast.ident) ? 3 : 2
|
634
|
+
else
|
635
|
+
3
|
636
|
+
end
|
630
637
|
when ?\\, ?\s, ?\t, ?\n, ?\r, ?\v, ?#; raise 'failure'
|
631
638
|
else raise "unknown char after ident: #{nc=nextchar ? nc.chr : "<<EOF>>"}"
|
632
639
|
end
|
@@ -704,8 +711,8 @@ private
|
|
704
711
|
CONTEXT2ENDTOK={
|
705
712
|
AssignmentRhsContext=>AssignmentRhsListEndToken,
|
706
713
|
ParamListContextNoParen=>ImplicitParamListEndToken,
|
707
|
-
KWParamListContextNoParen=>ImplicitParamListEndToken,
|
708
|
-
WhenParamListContext=>KwParamListEndToken,
|
714
|
+
KWParamListContextNoParen=>ImplicitParamListEndToken, #break,next,return
|
715
|
+
WhenParamListContext=>KwParamListEndToken,
|
709
716
|
RescueSMContext=>KwParamListEndToken
|
710
717
|
}
|
711
718
|
def abort_noparens!(str='')
|
@@ -713,7 +720,8 @@ private
|
|
713
720
|
result=[]
|
714
721
|
while klass=CONTEXT2ENDTOK[@parsestack.last.class]
|
715
722
|
result << klass.new(input_position-str.length)
|
716
|
-
break if RescueSMContext===@parsestack.last
|
723
|
+
break if RescueSMContext===@parsestack.last #and str==':'
|
724
|
+
break if WhenParamListContext===@parsestack.last and str==':'
|
717
725
|
@parsestack.pop
|
718
726
|
end
|
719
727
|
return result
|
@@ -724,7 +732,7 @@ private
|
|
724
732
|
AssignmentRhsContext=>AssignmentRhsListEndToken,
|
725
733
|
ParamListContextNoParen=>ImplicitParamListEndToken,
|
726
734
|
KWParamListContextNoParen=>ImplicitParamListEndToken,
|
727
|
-
WhenParamListContext=>KwParamListEndToken,
|
735
|
+
WhenParamListContext=>KwParamListEndToken, #I think this isn't needed...
|
728
736
|
RescueSMContext=>KwParamListEndToken
|
729
737
|
}
|
730
738
|
def abort_noparens_for_rescue!(str='')
|
@@ -791,6 +799,39 @@ private
|
|
791
799
|
return result
|
792
800
|
end
|
793
801
|
|
802
|
+
#-----------------------------------
|
803
|
+
def enable_macros!
|
804
|
+
@enable_macro="macro"
|
805
|
+
end
|
806
|
+
public :enable_macros!
|
807
|
+
|
808
|
+
|
809
|
+
#-----------------------------------
|
810
|
+
@@SPACES=/[\ \t\v\f\v]/
|
811
|
+
@@WSTOK=/\r?\n|\r*#@@SPACES+(?:#@@SPACES|\r(?!\n))*|\#[^\n]*\n|\\\r?\n|
|
812
|
+
^=begin[\s\n](?:(?!=end).*\n)*=end[\s\n].*\n/x
|
813
|
+
@@WSTOKS=/(?!=begin)#@@WSTOK+/o
|
814
|
+
def divide_ws(ws,offset)
|
815
|
+
result=[]
|
816
|
+
ws.scan(/\G#@@WSTOK/o){|ws|
|
817
|
+
incr= $~.begin(0)
|
818
|
+
klass=case ws
|
819
|
+
when /\A[\#=]/: CommentToken
|
820
|
+
when /\n\Z/: EscNlToken
|
821
|
+
else WsToken
|
822
|
+
end
|
823
|
+
result << klass.new(ws,offset+incr)
|
824
|
+
}
|
825
|
+
result.each_with_index{|ws,i|
|
826
|
+
if WsToken===ws
|
827
|
+
ws.ident << result.delete(i+1).ident while WsToken===result[i+1]
|
828
|
+
end
|
829
|
+
}
|
830
|
+
return result
|
831
|
+
end
|
832
|
+
|
833
|
+
|
834
|
+
|
794
835
|
#-----------------------------------
|
795
836
|
#parse keywords now, to prevent confusion over bare symbols
|
796
837
|
#and match end with corresponding preceding def or class or whatever.
|
@@ -823,7 +864,33 @@ private
|
|
823
864
|
result.first.has_end!
|
824
865
|
@parsestack.push WantsEndContext.new(str,@linenum)
|
825
866
|
@localvars_stack.push SymbolTable.new
|
826
|
-
|
867
|
+
offset=input_position
|
868
|
+
@file.scan(/\A(#@@WSTOKS)?(::)?/o)
|
869
|
+
md=@file.last_match
|
870
|
+
all,ws,dc=*md
|
871
|
+
fail if all.empty?
|
872
|
+
@moretokens.concat divide_ws(ws,offset) if ws
|
873
|
+
@moretokens.push KeywordToken.new('::',offset+md.end(0)-2) if dc
|
874
|
+
loop do
|
875
|
+
offset=input_position
|
876
|
+
@file.scan(/\A(#@@WSTOKS)?([A-Z][a-zA-Z_0-9]*)(::)?/o)
|
877
|
+
#this regexp---^ will need to change in order to support utf8 properly.
|
878
|
+
md=@file.last_match
|
879
|
+
all,ws,name,dc=*md
|
880
|
+
if ws
|
881
|
+
@moretokens.concat divide_ws(ws,offset)
|
882
|
+
incr=ws.size
|
883
|
+
else
|
884
|
+
incr=0
|
885
|
+
end
|
886
|
+
@moretokens.push VarNameToken.new(name,offset+incr)
|
887
|
+
break unless dc
|
888
|
+
@moretokens.push KeywordToken.new('::',offset+md.end(0)-2)
|
889
|
+
end
|
890
|
+
@moretokens.push EndHeaderToken.new(input_position)
|
891
|
+
|
892
|
+
|
893
|
+
|
827
894
|
when "class"
|
828
895
|
result.first.has_end!
|
829
896
|
@parsestack.push ClassContext.new(str,@linenum)
|
@@ -832,11 +899,12 @@ private
|
|
832
899
|
if after_nonid_op?{false} #prefix form
|
833
900
|
result.first.has_end!
|
834
901
|
@parsestack.push WantsEndContext.new(str,@linenum)
|
835
|
-
|
836
|
-
|
902
|
+
@parsestack.push ExpectThenOrNlContext.new(str,@linenum)
|
837
903
|
else #infix form
|
838
904
|
result.unshift(*abort_noparens!(str))
|
839
905
|
end
|
906
|
+
when "elsif"
|
907
|
+
@parsestack.push ExpectThenOrNlContext.new(str,@linenum)
|
840
908
|
when "begin","case"
|
841
909
|
result.first.has_end!
|
842
910
|
@parsestack.push WantsEndContext.new(str,@linenum)
|
@@ -868,12 +936,12 @@ private
|
|
868
936
|
localvars.start_block
|
869
937
|
block_param_list_lookahead
|
870
938
|
end
|
871
|
-
when "def"
|
939
|
+
when "def",@enable_macro
|
872
940
|
result.first.has_end!
|
873
941
|
@parsestack.push ctx=DefContext.new(@linenum)
|
874
942
|
ctx.state=:saw_def
|
875
943
|
safe_recurse { |aa|
|
876
|
-
set_last_token KeywordToken.new
|
944
|
+
set_last_token KeywordToken.new str #hack
|
877
945
|
result.concat ignored_tokens
|
878
946
|
|
879
947
|
#read an expr like a.b.c or a::b::c
|
@@ -957,7 +1025,7 @@ private
|
|
957
1025
|
else
|
958
1026
|
ofs+=listend.to_s.size
|
959
1027
|
end
|
960
|
-
result.insert end_index+1,
|
1028
|
+
result.insert end_index+1,EndHeaderToken.new(ofs)
|
961
1029
|
break
|
962
1030
|
end
|
963
1031
|
|
@@ -983,7 +1051,7 @@ private
|
|
983
1051
|
if endofs
|
984
1052
|
result.insert -2,ImplicitParamListEndToken.new(tok.offset)
|
985
1053
|
end
|
986
|
-
result.insert -2,
|
1054
|
+
result.insert -2, EndHeaderToken.new(tok.offset)
|
987
1055
|
break
|
988
1056
|
else
|
989
1057
|
lexerror(tok, "bizarre token in def name: " +
|
@@ -1060,6 +1128,11 @@ private
|
|
1060
1128
|
when "then"
|
1061
1129
|
result.unshift(*abort_noparens!(str))
|
1062
1130
|
@parsestack.last.see self,:then
|
1131
|
+
|
1132
|
+
if ExpectThenOrNlContext===@parsestack.last
|
1133
|
+
@parsestack.pop
|
1134
|
+
else #error... does anyone care?
|
1135
|
+
end
|
1063
1136
|
|
1064
1137
|
when "in"
|
1065
1138
|
result.unshift KwParamListEndToken.new( offset)
|
@@ -1083,7 +1156,7 @@ private
|
|
1083
1156
|
#END blocks are visible to subsequent code. (Why??)
|
1084
1157
|
#That difference forces a custom parsing.
|
1085
1158
|
if @last_operative_token===/^(\.|::)$/
|
1086
|
-
result=yield
|
1159
|
+
result=yield MethNameToken.new(str) #should pass a methname token here
|
1087
1160
|
else
|
1088
1161
|
safe_recurse{
|
1089
1162
|
old=result.first
|
@@ -1096,17 +1169,18 @@ private
|
|
1096
1169
|
getchar=='{' or lexerror(result.first,"expected { after #{str}")
|
1097
1170
|
result.push KeywordToken.new('{',input_position-1)
|
1098
1171
|
result.last.set_infix!
|
1172
|
+
result.last.as="do"
|
1099
1173
|
@parsestack.push BeginEndContext.new(str,offset)
|
1100
1174
|
}
|
1101
1175
|
end
|
1102
1176
|
|
1103
1177
|
when FUNCLIKE_KEYWORDS
|
1104
|
-
result=yield
|
1178
|
+
result=yield MethNameToken.new(str) #should be a keyword token?
|
1105
1179
|
|
1106
1180
|
when RUBYKEYWORDS
|
1107
1181
|
#do nothing
|
1108
1182
|
|
1109
|
-
else result=yield
|
1183
|
+
else result=yield MethNameToken.new(str)
|
1110
1184
|
|
1111
1185
|
end
|
1112
1186
|
|
@@ -1307,7 +1381,7 @@ end
|
|
1307
1381
|
# if !eof? and nextchar.chr[/[iuw\/<|>+\-*&%?:({]/] and
|
1308
1382
|
# !(NewlineToken===@last_operative_token) and
|
1309
1383
|
# !(/^(end|;)$/===@last_operative_token)
|
1310
|
-
#result<<
|
1384
|
+
#result<<EndHeaderToken.new(result.last.offset+result.last.to_s.size)
|
1311
1385
|
set_last_token KeywordToken.new ';'
|
1312
1386
|
result<< get1token
|
1313
1387
|
# end
|
@@ -1426,10 +1500,18 @@ end
|
|
1426
1500
|
#-----------------------------------
|
1427
1501
|
def symbol_or_op(ch)
|
1428
1502
|
startpos= input_position
|
1503
|
+
|
1504
|
+
|
1429
1505
|
qe= colon_quote_expected?(ch)
|
1430
1506
|
lastchar=prevchar
|
1431
1507
|
eat_next_if(ch[0]) or raise "needed: "+ch
|
1432
1508
|
|
1509
|
+
if nextchar==?( and @enable_macro
|
1510
|
+
result= OperatorToken.new(':', startpos)
|
1511
|
+
result.unary=true
|
1512
|
+
return result
|
1513
|
+
end
|
1514
|
+
|
1433
1515
|
#handle quoted symbols like :"foobar", :"[]"
|
1434
1516
|
qe and return symbol(':')
|
1435
1517
|
|
@@ -1437,17 +1519,23 @@ end
|
|
1437
1519
|
unless eat_next_if(?:)
|
1438
1520
|
#cancel implicit contexts...
|
1439
1521
|
@moretokens.push(*abort_noparens!(':'))
|
1440
|
-
@moretokens.push KeywordToken.new(':',startpos)
|
1522
|
+
@moretokens.push tok=KeywordToken.new(':',startpos)
|
1441
1523
|
|
1442
1524
|
case @parsestack.last
|
1443
|
-
when TernaryContext:
|
1525
|
+
when TernaryContext:
|
1526
|
+
tok.ternary=true
|
1527
|
+
@parsestack.pop #should be in the context's see handler
|
1444
1528
|
when ExpectDoOrNlContext: #should be in the context's see handler
|
1445
1529
|
@parsestack.pop
|
1446
1530
|
assert @parsestack.last.starter[/^(while|until|for)$/]
|
1447
|
-
|
1531
|
+
tok.as=";"
|
1532
|
+
when ExpectThenOrNlContext,WhenParamListContext:
|
1533
|
+
#should be in the context's see handler
|
1534
|
+
@parsestack.pop
|
1535
|
+
tok.as="then"
|
1448
1536
|
when RescueSMContext:
|
1449
|
-
|
1450
|
-
else @
|
1537
|
+
tok.as=";"
|
1538
|
+
else fail ": not expected in #{@parsestack.last.class}->#{@parsestack.last.starter}"
|
1451
1539
|
end
|
1452
1540
|
|
1453
1541
|
#end ternary context, if any
|
@@ -1503,7 +1591,9 @@ end
|
|
1503
1591
|
/[A-Z_0-9]$/i===result and klass=VarNameToken
|
1504
1592
|
end
|
1505
1593
|
result
|
1506
|
-
else
|
1594
|
+
else
|
1595
|
+
error= "unexpected char starting symbol: #{nc.chr}"
|
1596
|
+
'_'
|
1507
1597
|
end
|
1508
1598
|
result= lexerror(klass.new(result,start,notbare ? ':' : ''),error)
|
1509
1599
|
if open
|
@@ -1843,7 +1933,10 @@ end
|
|
1843
1933
|
then #hack-o-rama: probly cases left out above
|
1844
1934
|
@offset_adjust=@min_offset_adjust
|
1845
1935
|
a= abort_noparens!
|
1846
|
-
|
1936
|
+
case @parsestack.last #these should be in the see:semi handler
|
1937
|
+
when ExpectDoOrNlContext: @parsestack.pop
|
1938
|
+
when ExpectThenOrNlContext: @parsestack.pop
|
1939
|
+
end
|
1847
1940
|
assert !@parsestack.empty?
|
1848
1941
|
@parsestack.last.see self,:semi
|
1849
1942
|
|
@@ -2011,7 +2104,7 @@ end
|
|
2011
2104
|
when /^(#{RUBYOPERATORREX}|#{INNERBOUNDINGWORDS}|do)$/o.token_pat
|
2012
2105
|
#regexs above must match whole string
|
2013
2106
|
#assert(@last_operative_token==$&) #disabled 'cause $& is now always nil :(
|
2014
|
-
return true
|
2107
|
+
return true if OperatorToken===@last_operative_token || KeywordToken===@last_operative_token
|
2015
2108
|
when NewlineToken, nil, #nil means we're still at beginning of file
|
2016
2109
|
/^([({\[]|or|not|and|if|unless|then|elsif|else|class|module|def|
|
2017
2110
|
while|until|begin|for|in|case|when|ensure|defined\?)$
|
@@ -2065,15 +2158,31 @@ end
|
|
2065
2158
|
end
|
2066
2159
|
|
2067
2160
|
|
2068
|
-
|
2069
|
-
|
2161
|
+
#-----------------------------------
|
2162
|
+
def caret(ch) #match /^=?/ (^ or ^=) (maybe unary ^ too)
|
2163
|
+
if @enable_macro and (@last_token_maybe_implicit and
|
2164
|
+
@last_token_maybe_implicit.ident=='(') || unary_op_expected?(ch)
|
2165
|
+
result=OperatorToken.new(read(1),input_position)
|
2166
|
+
result.unary=true
|
2167
|
+
result
|
2168
|
+
else
|
2169
|
+
biop ch
|
2170
|
+
end
|
2171
|
+
end
|
2172
|
+
|
2173
|
+
#-----------------------------------
|
2174
|
+
def biop(ch) #match /%=?/ (% or %=)
|
2070
2175
|
assert(ch[/^[%^]$/])
|
2176
|
+
oldpos=input_position
|
2071
2177
|
result=getchar
|
2072
2178
|
if eat_next_if(?=)
|
2073
2179
|
result << ?=
|
2074
2180
|
end
|
2075
|
-
|
2181
|
+
result= operator_or_methname_token( result)
|
2182
|
+
result.offset=oldpos
|
2183
|
+
return result
|
2076
2184
|
end
|
2185
|
+
|
2077
2186
|
#-----------------------------------
|
2078
2187
|
def tilde(ch) #match ~
|
2079
2188
|
assert(ch=='~')
|
@@ -2322,10 +2431,8 @@ end
|
|
2322
2431
|
lexerror kw,"mismatched braces: #{origch}#{ch}\n" +
|
2323
2432
|
"matching brace location", @filename, line
|
2324
2433
|
end
|
2325
|
-
if BlockContext===ctx
|
2326
|
-
|
2327
|
-
@moretokens.last.as="end"
|
2328
|
-
end
|
2434
|
+
localvars.end_block if BlockContext===ctx
|
2435
|
+
@moretokens.last.as="end" if BlockContext===ctx or BeginEndContext===ctx
|
2329
2436
|
if ParamListContext==ctx.class
|
2330
2437
|
assert ch==')'
|
2331
2438
|
kw.set_callsite! #not needed?
|
@@ -2372,6 +2479,7 @@ end
|
|
2372
2479
|
ParamListContext===@parsestack[-2] ||
|
2373
2480
|
ParamListContextNoParen===@parsestack[-2] ||
|
2374
2481
|
WhenParamListContext===@parsestack[-2] ||
|
2482
|
+
ListImmedContext===@parsestack[-2] ||
|
2375
2483
|
(RescueSMContext===@parsestack[-2] && @parsestack[-2].state==:rescue) ||
|
2376
2484
|
(DefContext===@parsestack[-2] && !@parsestack[-2].in_body)
|
2377
2485
|
@parsestack.pop
|
@@ -2394,7 +2502,10 @@ end
|
|
2394
2502
|
assert @moretokens.empty?
|
2395
2503
|
@moretokens.push(*abort_noparens!)
|
2396
2504
|
@parsestack.last.see self,:semi
|
2397
|
-
|
2505
|
+
case @parsestack.last #should be in context's see:semi handler
|
2506
|
+
when ExpectThenOrNlContext
|
2507
|
+
@parsestack.pop
|
2508
|
+
when ExpectDoOrNlContext
|
2398
2509
|
@parsestack.pop
|
2399
2510
|
assert @parsestack.last.starter[/^(while|until|for)$/]
|
2400
2511
|
end
|
@@ -2417,7 +2528,7 @@ end
|
|
2417
2528
|
#-----------------------------------
|
2418
2529
|
#tokenify_results_of :identifier
|
2419
2530
|
save_offsets_in(*CHARMAPPINGS.values.uniq-[
|
2420
|
-
:symbol_or_op,:open_brace,:whitespace,:exclam,:backquote
|
2531
|
+
:symbol_or_op,:open_brace,:whitespace,:exclam,:backquote,:caret
|
2421
2532
|
])
|
2422
2533
|
#save_offsets_in :symbol
|
2423
2534
|
|