summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2000-03-23 08:37:35 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2000-03-23 08:37:35 +0000
commit688169fd83b24564b653c03977c168cea50ccd35 (patch)
treeb4724e5397cf5da5b554ab5795842a93145a88be /lib
parent5c13dd59db1ee6c04cdac4ce2ee97d5934115439 (diff)
2000-03-23
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@648 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/date2.rb15
-rw-r--r--lib/getopts.rb206
-rw-r--r--lib/parsedate.rb661
3 files changed, 696 insertions, 186 deletions
diff --git a/lib/date2.rb b/lib/date2.rb
index ef8bf832c1..706fec744e 100644
--- a/lib/date2.rb
+++ b/lib/date2.rb
@@ -1,5 +1,5 @@
-# date2.rb: Written by Tadayoshi Funaba 1998, 1999
-# $Id: date2.rb,v 1.17 1999/09/15 05:34:07 tadf Exp $
+# date2.rb: Written by Tadayoshi Funaba 1998-2000
+# $Id: date2.rb,v 1.18 2000/03/20 16:23:32 tadf Exp $
class Date
@@ -110,6 +110,10 @@ class Date
def jd_to_mjd(jd) jd - 2400000.5 end
def tjd_to_jd(tjd) tjd + 2440000.5 end
def jd_to_tjd(jd) jd - 2440000.5 end
+ def tjd2_to_jd(cycle, tjd) tjd_to_jd(cycle * 10000 + tjd) end
+ def jd_to_tjd2(jd) clfloor(jd_to_tjd(jd), 10000) end
+ def ld_to_jd(ld) ld + 2299160 end
+ def jd_to_ld(jd) jd - 2299160 end
def julian_leap? (y) y % 4 == 0 end
def gregorian_leap? (y) y % 4 == 0 and y % 100 != 0 or y % 400 == 0 end
@@ -213,15 +217,18 @@ class Date
def rjd() @rjd end
def rmjd() Date.jd_to_mjd(@rjd) end
def rtjd() Date.jd_to_tjd(@rjd) end
+ def rtjd2() Date.jd_to_tjd2(@rjd) end
- once :rmjd, :rtjd
+ once :rmjd, :rtjd, :rtjd2
def jd() Date.rjd_to_jd(@rjd)[0] end
def fr1() Date.rjd_to_jd(@rjd)[1] end
def mjd() Date.jd_to_mjd(jd) end
def tjd() Date.jd_to_tjd(jd) end
+ def tjd2() Date.jd_to_tjd2(jd) end
+ def ld() Date.jd_to_ld(jd) end
- once :jd, :fr1, :mjd, :tjd
+ once :jd, :fr1, :mjd, :tjd, :tjd2, :ld
def civil() Date.jd_to_civil(jd, @sg) end
def ordinal() Date.jd_to_ordinal(jd, @sg) end
diff --git a/lib/getopts.rb b/lib/getopts.rb
index b513f89f31..490523b878 100644
--- a/lib/getopts.rb
+++ b/lib/getopts.rb
@@ -1,141 +1,127 @@
#
-# getopts.rb -
-# $Release Version: $
-# $Revision$
-# $Date$
-# by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
+# getopts.rb -
+# $Release Version: $
+# $Revision$
+# $Date$
+# by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
#
# --
# this is obsolete; use getoptlong
#
+# 2000-03-21
+# modified by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
$RCS_ID=%q$Header$
-def isSingle(lopt)
- if lopt.index(":")
- if lopt.split(":")[0].length == 1
- return true
- end
- end
- return nil
-end
-def getOptionName(lopt)
- return lopt.split(":")[0]
-end
+def getopts( single_opts, *options )
+ single_opts_exp = (single_opts && !single_opts.empty?) ?
+ /[#{single_opts}]/ : nil
+ single_colon_exp = nil
+ single_colon = nil
+ opt = arg = val = nil
+ boolopts = {}
+ valopts = {}
+ argv = ARGV
+ newargv = []
-def getDefaultOption(lopt)
- od = lopt.split(":")[1]
- if od
- return od
+ #
+ # set default
+ #
+ if single_opts then
+ single_opts.each_byte do |byte|
+ boolopts[ byte.chr ] = false
end
- return nil
end
+ unless options.empty? then
+ single_colon = ''
-def setOption(name, value)
- eval("$OPT_" + name + " = " + 'value')
+ options.each do |opt|
+ m = /\A([^:]+):(.*)\z/.match( opt )
+ if m then
+ valopts[ m[1] ] = m[2].empty? ? 0 : m[2]
+ else
+ boolopts[ opt ] = false
end
-
-def setDefaultOption(lopt)
- d = getDefaultOption(lopt)
- if d
- setOption(getOptionName(lopt), d)
end
+ valopts.each do |opt, dflt|
+ if opt.size == 1 then
+ single_colon << opt
end
-
-def setNewArgv(newargv)
- ARGV.clear
- for na in newargv
- ARGV << na
end
-end
-
-def getopts(single_opts, *options)
- if options
- single_colon = ""
- long_opts = []
- sc = 0
- for o in options
- setDefaultOption(o)
- if isSingle(o)
- single_colon[sc, 0] = getOptionName(o)
- sc += 1
+ if single_colon.empty? then
+ single_colon = single_colon_exp = nil
else
- long_opts.push(o)
- end
+ single_colon_exp = /[#{single_colon}]/
end
end
- opts = {}
- count = 0
- newargv = []
- while ARGV.length != 0
- compare = nil
- case ARGV[0]
- when /^--?$/
- ARGV.shift
- newargv += ARGV
+ #
+ # scan
+ #
+ c = 0
+ arg = argv.shift
+ while arg do
+ case arg
+ when /\A--?\z/ # xinit -- -bpp 24
+ newargv.concat argv
break
- when /^--.*/
- compare = ARGV[0][2, (ARGV[0].length - 2)]
- if long_opts != ""
- for lo in long_opts
- if lo.index(":") && getOptionName(lo) == compare
- if ARGV.length <= 1
- return nil
- end
- setOption(compare, ARGV[1])
- opts[compare] = true
- ARGV.shift
- count += 1
- break
- elsif lo == compare
- setOption(compare, true)
- opts[compare] = true
- count += 1
- break
- end
- end
- end
- if compare.length <= 1
- return nil
+
+ when /\A--(.*)/
+ opt = $1
+ if valopts.key? opt then # imclean --src +trash
+ return nil if argv.empty?
+ valopts[ opt ] = argv.shift
+ elsif boolopts.key? opt then # ruby --verbose
+ boolopts[ opt ] = true
+ else
+ return nil
+ end
+ c += 1
+
+ when /\A-(.+)/
+ arg = $1
+ 0.upto( arg.size - 1 ) do |idx|
+ opt = arg[idx, 1]
+ if single_opts and single_opts_exp === opt then
+ boolopts[ opt ] = true # ruby -h
+ c += 1
+
+ elsif single_colon and single_colon_exp === opt then
+ val = arg[ (idx+1)..-1 ]
+ if val.empty? then # ruby -e 'p $:'
+ return nil if argv.empty?
+ valopts[ opt ] = argv.shift
+ else # cc -ohello ...
+ valopts[ opt ] = val
end
- when /^-.*/
- for idx in 1..(ARGV[0].length - 1)
- compare = ARGV[0][idx, 1]
- if single_opts && compare =~ "[" + single_opts + "]"
- setOption(compare, true)
- opts[compare] = true
- count += 1
- elsif single_colon != "" && compare =~ "[" + single_colon + "]"
- if ARGV[0][idx..-1].length > 1
- setOption(compare, ARGV[0][(idx + 1)..-1])
- opts[compare] = true
- count += 1
- elsif ARGV.length <= 1
- return nil
- else
- setOption(compare, ARGV[1])
- opts[compare] = true
- ARGV.shift
- count += 1
- end
- break
- end
+ c += 1
+
+ break
+ else
+ return nil
+ end
+ end
+
+ else # ruby test.rb
+ newargv.push arg
end
- else
- compare = ARGV[0]
- opts[compare] = true
- newargv << ARGV[0]
+
+ arg = argv.shift
end
- ARGV.shift
- if !opts.has_key?(compare)
- return nil
+ #
+ # set
+ #
+ boolopts.each do |opt, val|
+ eval "$OPT_#{opt} = val"
end
+ valopts.each do |opt, val|
+ eval "$OPT_#{opt} = #{val == 0 ? 'nil' : 'val'}"
end
- setNewArgv(newargv)
- return count
+ argv.replace newargv
+
+ c
end
diff --git a/lib/parsedate.rb b/lib/parsedate.rb
index 35fffcfe98..59a8b4f3b4 100644
--- a/lib/parsedate.rb
+++ b/lib/parsedate.rb
@@ -1,78 +1,590 @@
-module ParseDate
+# parsedate2.ry: Written by Tadayoshi Funaba 1999, 2000
+# $Id: parsedate2.ry,v 1.5 2000/03/20 16:23:46 tadf Exp $
+## Generated by rbison version 0.0.5.
+
+class ParseDatePar
+
+ class ParseError < StandardError ; end
+ class LexError < StandardError ; end
+ NULL = nil
+
+ attr :yydebug, true
+
+ DAY = 257
+ DIGITS = 258
+ MON = 259
+ LETTERS = 260
+ MERID = 261
+
+ ## Parser declarations begin
+ ## Parser declarations end
+
+ YYFINAL = 84
+ YYFLAG = -32768
+ YYNTBASE = 14
+ YYTRANSLATE = [ 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 13, 8, 9, 10, 11, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 12, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7
+ ]
+ YYPRHS = [ 0,
+ 0, 1, 3, 6, 8, 12, 14, 20, 26, 32,
+ 34, 38, 40, 44, 45, 48, 50, 51, 53, 55,
+ 57, 60, 63, 65, 67, 69, 71, 73, 80, 88,
+ 94, 98, 104, 108, 115, 116, 119, 122, 123, 125,
+ 128, 129, 131, 132, 134, 136, 139, 142, 147, 149
+ ]
+ YYRHS = [ -1,
+ 17, 0, 16, 15, 0, 19, 0, 19, 18, 22,
+ 0, 28, 0, 28, 18, 19, 18, 22, 0, 19,
+ 18, 28, 18, 22, 0, 19, 18, 22, 18, 28,
+ 0, 23, 0, 23, 18, 28, 0, 30, 0, 30,
+ 18, 32, 0, 0, 17, 18, 0, 3, 0, 0,
+ 8, 0, 20, 0, 21, 0, 4, 5, 0, 5,
+ 4, 0, 4, 0, 24, 0, 25, 0, 26, 0,
+ 27, 0, 4, 9, 4, 9, 4, 31, 0, 6,
+ 4, 10, 4, 10, 4, 31, 0, 4, 9, 5,
+ 9, 4, 0, 4, 11, 4, 0, 4, 11, 4,
+ 11, 4, 0, 4, 7, 34, 0, 4, 12, 4,
+ 29, 33, 34, 0, 0, 12, 4, 0, 4, 31,
+ 0, 0, 6, 0, 4, 34, 0, 0, 7, 0,
+ 0, 35, 0, 6, 0, 6, 6, 0, 36, 4,
+ 0, 36, 4, 12, 4, 0, 9, 0, 13, 0
+ ]
+ YYRLINE = [ 0,
+ 14, 14, 14, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 28, 28, 30, 32, 32, 34, 34,
+ 36, 38, 40, 42, 42, 42, 42, 44, 58, 72,
+ 86, 91, 105, 109, 116, 116, 118, 141, 141, 143,
+ 156, 156, 158, 158, 160, 161, 166, 167, 170, 170
+ ]
+ YYTNAME = [ "$","error","$undefined.","DAY","DIGITS",
+"MON","LETTERS","MERID","','","'-'","'.'","'/'","':'","'+'","repr","dat","odaycom",
+"day","ocom","woy","eu","us","year","wy","iso","jis","vms","sla","time","osec",
+"ddd","otee","ttt","omerid","ozone","zone","sign", NULL
+ ]
+ YYR1 = [ 0,
+ 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 16, 16, 17, 18, 18, 19, 19,
+ 20, 21, 22, 23, 23, 23, 23, 24, 25, 26,
+ 27, 27, 28, 28, 29, 29, 30, 31, 31, 32,
+ 33, 33, 34, 34, 35, 35, 35, 35, 36, 36
+ ]
+ YYR2 = [ 0,
+ 0, 1, 2, 1, 3, 1, 5, 5, 5, 1,
+ 3, 1, 3, 0, 2, 1, 0, 1, 1, 1,
+ 2, 2, 1, 1, 1, 1, 1, 6, 7, 5,
+ 3, 5, 3, 6, 0, 2, 2, 0, 1, 2,
+ 0, 1, 0, 1, 1, 2, 2, 4, 1, 1
+ ]
+ YYDEFACT = [ 14,
+ 16, 0, 17, 38, 0, 0, 3, 4, 19, 20,
+ 10, 24, 25, 26, 27, 17, 12, 18, 15, 21,
+ 39, 43, 0, 0, 0, 37, 22, 0, 0, 0,
+ 0, 0, 45, 49, 50, 33, 44, 0, 0, 0,
+ 31, 35, 0, 23, 5, 17, 0, 11, 0, 17,
+ 43, 13, 46, 47, 0, 0, 0, 0, 41, 0,
+ 0, 0, 0, 40, 0, 38, 30, 32, 36, 42,
+ 43, 0, 9, 23, 8, 7, 48, 28, 34, 38,
+ 29, 0, 0, 0
+ ]
+ YYDEFGOTO = [ 82,
+ 7, 2, 3, 19, 8, 9, 10, 45, 11, 12,
+ 13, 14, 15, 16, 59, 17, 26, 52, 71, 36,
+ 37, 38
+ ]
+ YYPACT = [ 10,
+-32768, 30, 6, 11, 37, 39,-32768, 23,-32768,-32768,
+ 23,-32768,-32768,-32768,-32768, 7, 23,-32768,-32768,-32768,
+-32768, 19, 25, 40, 41,-32768,-32768, 36, 43, 44,
+ 35, 45, 46,-32768,-32768,-32768,-32768, 47, 48, 49,
+ 42, 38, 50, 14, 23, 51, 14,-32768, 55, 51,
+ 19,-32768,-32768, 52, 57, 58, 59, 61, 60, 56,
+ 44, 64, 64,-32768, 65, 66,-32768,-32768,-32768,-32768,
+ 19, 67,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 66,
+-32768, 70, 73,-32768
+ ]
+ YYPGOTO = [ -32768,
+-32768,-32768,-32768, -8, 24,-32768,-32768, -51,-32768,-32768,
+-32768,-32768,-32768, -28,-32768,-32768, -61,-32768,-32768, -47,
+-32768,-32768
+ ]
+ YYLAST = 73
+ YYTABLE = [ 29,
+ 46, 48, 30, 64, 78, -2, -6, 31, 32, -1,
+ 75, 76, 1, 18, 18, 20, 21, 22, 81, 23,
+ 22, 24, 25, 79, 33, 25, -17, 34, 39, 40,
+ 18, 35, 73, 4, 5, 6, 61, 62, 49, 5,
+ 27, 63, 28, 41, 42, 43, 44, 47, 51, 58,
+ 54, 53, 57, 60, 50, 0, 55, 56, 18, 20,
+ 66, 67, 68, 65, 69, 72, 70, 74, 77, 83,
+ 80, 21, 84
+ ]
+ YYCHECK = [ 8,
+ 29, 30, 11, 51, 66, 0, 0, 16, 17, 0,
+ 62, 63, 3, 8, 8, 5, 6, 7, 80, 9,
+ 7, 11, 12, 71, 6, 12, 4, 9, 4, 5,
+ 8, 13, 61, 4, 5, 6, 45, 46, 4, 5,
+ 4, 50, 4, 4, 4, 10, 4, 4, 4, 12,
+ 4, 6, 11, 4, 31, -1, 9, 9, 8, 5,
+ 4, 4, 4, 12, 4, 10, 7, 4, 4, 0,
+ 4, 6, 0
+ ]
+ YYEMPTY = -2
+ YYEOF = 0
+ YYTERROR = 1
+
+ def initialize
+ @yydebug = false
+ end
+
+ def yyparse(lexer)
+ yyerrstatus = 0
+ yychar = YYEMPTY
+ yystate = 0
+ yyss = []
+ yyvs = ["nil"]
+ yyval = 0
+ jump = :YYNEWSTATE
+
+ while true
+
+ case jump
+
+ when :YYNEWSTATE
+ if @yydebug
+ printf($stderr, "Entering state %d\n", yystate)
+ end
+ yyss.push(yystate)
+ jump = :YYBACKUP
+ next
+
+ when :YYBACKUP
+ yyn = YYPACT[yystate]
+ if yyn == YYFLAG
+ jump = :YYDEFAULT
+ next
+ end
+
+ ## get a lookahead token if we don't already have one
+ if yychar == YYEMPTY
+ if @yydebug
+ printf($stderr, "Reading a token: ")
+ end
+ begin
+ yychar, yylval = lexer.yylex
+ rescue LexError
+ raise ParseError, "lex error"
+ end
+ end
+
+ ## if lookahead <= 0, end of input
+ if yychar <= 0
+ yychar1 = 0
+ yychar = YYEOF
+ if @yydebug
+ printf($stderr, "Now at end of input.\n")
+ end
+ else
+ yychar1 = yychar < 0 || yychar > 261 ? 37 : YYTRANSLATE[yychar]
+ if @yydebug
+ printf($stderr, "Next token is %d (%s,%s)\n", yychar,
+ YYTNAME[yychar1], yylval)
+ end
+ end
+
+ ## see if we know what to do with this token in this state
+ yyn += yychar1
+ if yyn < 0 || yyn > YYLAST || YYCHECK[yyn] != yychar1
+ jump = :YYDEFAULT
+ next
+ end
+
+ ## yyn is what to do for this token type in this state
+ ## negative -> reduce, - yyn is the rule number
+ ## positive -> shift, yyn is the new state
+ ## New state is final state, don't bother to shift, just
+ ## return success
+ ## 0, or most negative number -> error
+ yyn = YYTABLE[yyn]
+ if yyn < 0
+ if yyn == YYFLAG
+ jump = :YYERRLAB
+ next
+ end
+ yyn = - yyn
+ jump = :YYREDUCE
+ next
+ elsif yyn == 0
+ jump = :YYERRLAB
+ next
+ end
+
+ if yyn == YYFINAL
+ return ## accept
+ end
+
+ ## shift the lookahead token
+ if @yydebug
+ printf($stderr, "Shifting token %d (%s), ", yychar,
+ YYTNAME[yychar1])
+ end
+
+ ## discard the token being shifted unless it is eof
+ if yychar != YYEOF
+ yychar = YYEMPTY
+ end
+ yyvs.push(yylval)
+
+ ## count tokens shifted since error; after, three turn off
+ ## error status
+ yyerrstatus -= 1 if yyerrstatus > 0
+
+ yystate = yyn
+ jump = :YYNEWSTATE
+ next
+
+ when :YYDEFAULT
+ yyn = YYDEFACT[yystate]
+ if yyn == 0
+ jump = :YYERRLAB
+ next
+ else
+ jump = :YYREDUCE
+ next
+ end
+
+ ## do a reduction. yyn is the number of the rule to reduce with
+ when :YYREDUCE
+ yylen = YYR2[yyn]
+ if yylen > 0
+ yyval = yyvs[yyvs.size - yylen]
+ end
+
+ if @yydebug
+ printf($stderr, "Reducing via rule %d (line %d), ", yyn,
+ YYRLINE[yyn])
+ i = YYPRHS[yyn]
+ while YYRHS[i] > 0
+ printf($stderr, "%s ", YYTNAME[YYRHS[i]])
+ i += 1
+ end
+ printf($stderr, " -> %s\n", YYTNAME[YYR1[yyn]])
+ end
+
+ case yyn
+ when 16
+ store(:wday, yyvs[-1].to_i)
+ when 21
+ store(:mday, yyvs[-2].to_i); store(:mon, yyvs[-1])
+ when 22
+ store(:mon, yyvs[-2]); store(:mday, yyvs[-1].to_i)
+ when 23
+ store(:year, yyvs[-1].to_i)
+ when 28
+
+ if yyvs[-1 + -1].size >= 4
+ store(:mday, yyvs[-1 + -5].to_i)
+ store(:mon, yyvs[-1 + -3].to_i)
+ store(:year, yyvs[-1 + -1].to_i)
+ else
+ store(:year, yyvs[-1 + -5].to_i)
+ store(:mon, yyvs[-1 + -3].to_i)
+ store(:mday, yyvs[-1 + -1].to_i)
+ end
+
+ when 29
+
+ e = { 'M'=>1867,
+ 'T'=>1911,
+ 'S'=>1925,
+ 'H'=>1988
+ }[yyvs[-1 + -6]]
+ raise ParseError, 'YYERROR' unless e
+ store(:year, yyvs[-1 + -5].to_i + e)
+ store(:mon, yyvs[-1 + -3].to_i)
+ store(:mday, yyvs[-1 + -1].to_i)
+
+ when 30
+
+ if yyvs[-1 + -4].size >= 4
+ store(:year, yyvs[-1 + -4].to_i)
+ store(:mon, yyvs[-1 + -2])
+ store(:mday, yyvs[-1 + 0].to_i)
+ else
+ store(:mday, yyvs[-1 + -4].to_i)
+ store(:mon, yyvs[-1 + -2])
+ store(:year, yyvs[-1 + 0].to_i)
+ end
+
+ when 31
+
+ store(:mon, yyvs[-1 + -2].to_i)
+ store(:mday, yyvs[-1 + 0].to_i)
+
+ when 32
+
+ if yyvs[-1 + -4].size >= 4
+ store(:year, yyvs[-1 + -4].to_i)
+ store(:mon, yyvs[-1 + -2].to_i)
+ store(:mday, yyvs[-1 + 0].to_i)
+ else
+ store(:mon, yyvs[-1 + -4].to_i)
+ store(:mday, yyvs[-1 + -2].to_i)
+ store(:year, yyvs[-1 + 0].to_i)
+ end
+
+ when 33
+
+ store(:hour, yyvs[-1 + -2].to_i + yyvs[-1 + -1])
+
+ when 34
+
+ store(:hour, yyvs[-1 + -5].to_i + yyvs[-1 + -1])
+ store(:min, yyvs[-1 + -3].to_i)
+
+ when 36
+ store(:sec, yyvs[-1].to_i)
+ when 37
+
+ case yyvs[-1 + -1].size
+ when 4
+ store(:mon, yyvs[-1 + -1][ 0, 2].to_i)
+ store(:mday, yyvs[-1 + -1][ 2, 2].to_i)
+ when 6
+ store(:year, yyvs[-1 + -1][ 0, 2].to_i)
+ store(:mon, yyvs[-1 + -1][ 2, 2].to_i)
+ store(:mday, yyvs[-1 + -1][ 4, 2].to_i)
+ when 8, 10, 12, 14
+ store(:year, yyvs[-1 + -1][ 0, 4].to_i)
+ store(:mon, yyvs[-1 + -1][ 4, 2].to_i)
+ store(:mday, yyvs[-1 + -1][ 6, 2].to_i)
+ store(:hour, yyvs[-1 + -1][ 8, 2].to_i) if yyvs[-1 + -1].size >= 10
+ store(:min, yyvs[-1 + -1][10, 2].to_i) if yyvs[-1 + -1].size >= 12
+ store(:sec, yyvs[-1 + -1][12, 2].to_i) if yyvs[-1 + -1].size >= 14
+ else
+ raise ParseError, 'YYERROR'
+ end
+
+ when 39
+ raise ParseError, 'YYERROR' unless yyvs[-1] == 'T'
+ when 40
+
+ case yyvs[-1 + -1].size
+ when 2, 4, 6
+ store(:hour, yyvs[-1 + -1][ 0, 2].to_i)
+ store(:min, yyvs[-1 + -1][ 2, 2].to_i) if yyvs[-1 + -1].size >= 4
+ store(:sec, yyvs[-1 + -1][ 4, 2].to_i) if yyvs[-1 + -1].size >= 6
+ else
+ raise ParseError, 'YYERROR'
+ end
+
+ when 41
+ yyval = 0
+ when 45
+ store(:zone, yyvs[-1])
+ when 46
+
+ raise ParseError, 'YYERROR' unless yyvs[-1 + 0] == 'DST'
+ store(:zone, yyvs[-1 + -1] + ' ' + yyvs[-1 + 0])
+
+ when 47
+ store(:zone, yyvs[-2] + yyvs[-1])
+ when 48
+ store(:zone, yyvs[-4] + yyvs[-3] + yyvs[-2] + yyvs[-1])
+ when -65536 ## never used, placeholder for ruby
+ end
+
+ if yylen > 0
+ yyss[(yyss.size - yylen) .. (yyss.size - 1)] = []
+ yyvs[(yyvs.size - yylen) .. (yyvs.size - 1)] = []
+ end
+
+ yyvs.push(yyval)
+
+ if @yydebug
+ printf($stderr, "State stack now: %s\n", yyss.join(' '))
+ printf($stderr, "Value stack now: %s\n", yyvs.join(' '))
+ end
+
+ ## "Shift" the result of the reduction.
+ yyn = YYR1[yyn]
+ yystate = YYPGOTO[yyn - YYNTBASE] + yyss[-1]
+ if yystate >=0 && yystate <= YYLAST &&
+ YYCHECK[yystate] == yyss[-1]
+ yystate = YYTABLE[yystate]
+ else
+ yystate = YYDEFGOTO[yyn - YYNTBASE]
+ end
+ jump = :YYNEWSTATE
+ next
+
+ when :YYERRLAB
+ if yyerrstatus == 0 && @yydebug
+ printf($stderr, "Parse error!\n")
+ end
+ jump = :YYERRLAB1
+ next
+
+ when :YYERRLAB1
+ if yyerrstatus == 3
+ if yychar == YYEOF
+ raise ParseError, "parse error"
+ end
+ if @yydebug
+ printf($stderr, "Discarding token %d (%s).\n", yychar,
+ YYTNAME[yychar1])
+ end
+ yychar = YYEMPTY
+ end
+
+ yyerrstatus = 3
+ jump = :YYERRHANDLE
+ next
+
+ when :YYERRPOP
+ if yyvs.empty?
+ raise ParseError, "parse error"
+ end
+ ## don't pop if the state on top of the stack can handle
+ ## the error token
+ yystate = yyss[-1]
+ if YYCHECK[YYPACT[yystate] + YYTERROR] != YYTERROR
+ yyvs.pop
+ yyss.pop
+ if @yydebug
+ printf($stderr, "Error: state stack now: %s\n",
+ yyss.join(' '))
+ printf($stderr, "Error: Value stack now: %s\n",
+ yyvs.join(' '))
+ end
+ end
+ jump = :YYERRHANDLE
+ next
+
+ when :YYERRHANDLE
+ yyn = YYPACT[yystate]
+ if yyn == YYFLAG
+ jump = :YYERRPOP
+ next
+ end
+
+ yyn += YYTERROR
+ if yyn < 0 || yyn > YYLAST || YYCHECK[yyn] != YYTERROR
+ jump = :YYERRPOP
+ next
+ end
+
+ yyn = YYTABLE[yyn]
+ if yyn < 0
+ if yyn == YYFLAG
+ jump = :YYERRPOP
+ next
+ end
+ yyn = -yyn
+ jump = :YYREDUCE
+ next
+ elsif yyn == 0
+ jump = :YYERRPOP
+ next
+ end
+
+ if yyn == YYFINAL
+ return ## accept
+ end
+
+ if @yydebug
+ printf($stderr, "Shifting error token, ")
+ end
+
+ yyvs.push(yylval)
+ yystate = yyn
+ jump = :YYNEWSTATE
+ next
+
+ end ## case
+
+ end ## while true
+
+ end ## yyparse
+
+end ## class
+
+## Additional user code
+class ParseDateLex
MONTHS = {
'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
'may' => 5, 'jun' => 6, 'jul' => 7, 'aug' => 8,
- 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12 }
- MONTHPAT = MONTHS.keys.join('|')
+ 'sep' => 9, 'oct' =>10, 'nov' =>11, 'dec' =>12
+ }
+ MONTHPAT = MONTHS.keys.sort.reverse.join('|')
DAYS = {
'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
- 'thu' => 4, 'fri' => 5, 'sat' => 6 }
- DAYPAT = DAYS.keys.join('|')
-
- def parsedate(date, guess=false)
- # part of ISO 8601
- # yyyy-mm-dd | yyyy-mm | yyyy
- # date hh:mm:ss | date Thh:mm:ss
- if date =~ /^(\d\d\d\d)-?(?:(\d\d)-?(\d\d)?)? *T?(?:(\d\d):?(\d\d):?(\d\d)?)?$/
- return $1.to_i,
- if $2 then $2.to_i else 1 end,
- if $3 then $3.to_i else 1 end,
- if $4 then $4.to_i end,
- if $5 then $5.to_i end,
- if $6 then $6.to_i end,
- nil,
- nil
+ 'thu' => 4, 'fri' => 5, 'sat' => 6
+ }
+ DAYPAT = DAYS.keys.sort.reverse.join('|')
+ def initialize(str) @str = str end
+ def reset(str) @str = str end
+ def yylex
+ @str = @str.sub(/\A\s+/, '')
+ return [-1, nil] if @str.size == 0
+ if /\A(#{DAYPAT})[a-z]*\.?/i =~ @str
+ @str = $'
+ return [ParseDatePar::DAY, DAYS[$1[0, 3].downcase]]
end
- date = date.dup
- if date.sub!(/(#{DAYPAT})[a-z]*,?/i, ' ')
- wday = DAYS[$1.downcase]
+ if /\A(\d+)(?:(?:th|st|nd|rd)\b)?/ =~ @str
+ @str = $'
+ return [ParseDatePar::DIGITS, $1]
end
- if date.sub!(/(\d+):(\d+)(?::(\d+))?(?:\s*(am|pm))?(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4}|[-+]\d{4})?|[-+]\d{4}))?/i, ' ')
- hour = $1.to_i
- min = $2.to_i
- if $3
- sec = $3.to_i
- end
- if $4 == 'pm'
- hour += 12
- end
- if $5
- zone = $5
- end
+ if /\A(#{MONTHPAT})[a-z]*\.?/i =~ @str
+ @str = $'
+ return [ParseDatePar::MON, MONTHS[$1[0, 3].downcase]]
end
- if date.sub!(/(\d+)\S*\s+(#{MONTHPAT})\S*(?:\s+(\d+))?/i, ' ')
- mday = $1.to_i
- mon = MONTHS[$2.downcase]
- if $3
- year = $3.to_i
- end
- elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*,?(?:\s+(\d+))?/i, ' ')
- mon = MONTHS[$1.downcase]
- mday = $2.to_i
- if $3
- year = $3.to_i
- end
- elsif date.sub!(/(\d+)\/(\d+)(?:\/(\d+))/, ' ')
- mon = $1.to_i
- mday = $2.to_i
- if $3
- year = $3.to_i
- end
- elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
- mday = $1.to_i
- mon = MONTHS[$2.downcase]
- year = $3.to_i
- elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
- mday = $1.to_i
- mon = MONTHS[$2.downcase]
- year = $3.to_i
+ if /\A([ap]\.?m\.?\b)/i =~ @str
+ @str = $'
+ return [ParseDatePar::MERID,
+ if $1[0, 1].downcase == 'a' then 0 else 12 end]
+ end
+ if /\A([a-z]+)/i =~ @str
+ @str = $'
+ return [ParseDatePar::LETTERS, $1]
end
- if date.sub!(/\d{4}/i, ' ')
- year = $&.to_i
- elsif date.sub!(/\d\d/i, ' ')
- year = $&.to_i
+ if /\A(.)/ =~ @str
+ @str = $'
+ return [$1[0], $1]
end
- if guess and year
+ end
+end
+class ParseDatePar
+ def clear() @values = {} end
+ def store(key, val) @values[key] = val end
+ def values(cyear)
+ year = @values[:year]
+ if cyear and year
if year < 100
if year >= 69
year += 1900
@@ -81,13 +593,18 @@ module ParseDate
end
end
end
- return year, mon, mday, hour, min, sec, zone, wday
+ @values[:year] = year
+ @values.indexes(:year, :mon, :mday,
+ :hour, :min, :sec, :zone, :wday)
end
-
- module_function :parsedate
end
-
-if __FILE__ == $0
- p Time.now.asctime
- p ParseDate.parsedate(Time.now.asctime)
+module ParseDate
+ def parsedate(date, cyear=false)
+ lex = ParseDateLex.new(date)
+ par = ParseDatePar.new
+ par.clear
+ begin par.yyparse(lex); rescue; end
+ par.values(cyear)
+ end
+ module_function :parsedate
end