summaryrefslogtreecommitdiff
path: root/test/racc/assets/edtf.y
diff options
context:
space:
mode:
Diffstat (limited to 'test/racc/assets/edtf.y')
-rw-r--r--test/racc/assets/edtf.y583
1 files changed, 0 insertions, 583 deletions
diff --git a/test/racc/assets/edtf.y b/test/racc/assets/edtf.y
deleted file mode 100644
index 4f5f6bb4fd..0000000000
--- a/test/racc/assets/edtf.y
+++ /dev/null
@@ -1,583 +0,0 @@
-# -*- racc -*-
-
-# Copyright 2011 Sylvester Keil. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-# EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are
-# those of the authors and should not be interpreted as representing official
-# policies, either expressed or implied, of the copyright holder.
-
-class EDTF::Parser
-
-token T Z E X U UNKNOWN OPEN LONGYEAR UNMATCHED DOTS UA PUA
-
-expect 0
-
-rule
-
- edtf : level_0_expression
- | level_1_expression
- | level_2_expression
- ;
-
- # ---- Level 0 / ISO 8601 Rules ----
-
- # NB: level 0 intervals are covered by the level 1 interval rules
- level_0_expression : date
- | date_time
- ;
-
- date : positive_date
- | negative_date
- ;
-
- positive_date :
- year { result = Date.new(val[0]).year_precision! }
- | year_month { result = Date.new(*val.flatten).month_precision! }
- | year_month_day { result = Date.new(*val.flatten).day_precision! }
- ;
-
- negative_date : '-' positive_date { result = -val[1] }
-
-
- date_time : date T time {
- result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2])
- result.skip_timezone = (val[2].length == 3)
- }
-
- time : base_time
- | base_time zone_offset { result = val.flatten }
-
- base_time : hour ':' minute ':' second { result = val.values_at(0, 2, 4) }
- | midnight
-
- midnight : '2' '4' ':' '0' '0' ':' '0' '0' { result = [24, 0, 0] }
-
- zone_offset : Z { result = 0 }
- | '-' zone_offset_hour { result = -1 * val[1] }
- | '+' positive_zone_offset { result = val[1] }
- ;
-
- positive_zone_offset : zone_offset_hour
- | '0' '0' ':' '0' '0' { result = 0 }
- ;
-
-
- zone_offset_hour : d01_13 ':' minute { result = Rational(val[0] * 60 + val[2], 1440) }
- | '1' '4' ':' '0' '0' { result = Rational(840, 1440) }
- | '0' '0' ':' d01_59 { result = Rational(val[3], 1440) }
- ;
-
- year : digit digit digit digit {
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
-
- month : d01_12
- day : d01_31
-
- year_month : year '-' month { result = [val[0], val[2]] }
-
- # We raise an exception if there are two many days for the month, but
- # do not consider leap years, as the EDTF BNF did not either.
- # NB: an exception will be raised regardless, because the Ruby Date
- # implementation calculates leap years.
- year_month_day : year_month '-' day {
- result = val[0] << val[2]
- if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2)
- raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})"
- end
- }
-
- hour : d00_23
- minute : d00_59
- second : d00_59
-
- # Completely covered by level_1_interval
- # level_0_interval : date '/' date { result = Interval.new(val[0], val[1]) }
-
-
- # ---- Level 1 Extension Rules ----
-
- # NB: Uncertain/approximate Dates are covered by the Level 2 rules
- level_1_expression : unspecified | level_1_interval | long_year_simple | season
-
- # uncertain_or_approximate_date : date UA { result = uoa(val[0], val[1]) }
-
- unspecified : unspecified_year
- {
- result = Date.new(val[0][0]).year_precision!
- result.unspecified.year[2,2] = val[0][1]
- }
- | unspecified_month
- | unspecified_day
- | unspecified_day_and_month
- ;
-
- unspecified_year :
- digit digit digit U
- {
- result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]]
- }
- | digit digit U U
- {
- result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]]
- }
-
- unspecified_month : year '-' U U {
- result = Date.new(val[0]).unspecified!(:month)
- result.precision = :month
- }
-
- unspecified_day : year_month '-' U U {
- result = Date.new(*val[0]).unspecified!(:day)
- }
-
- unspecified_day_and_month : year '-' U U '-' U U {
- result = Date.new(val[0]).unspecified!([:day,:month])
- }
-
-
- level_1_interval : level_1_start '/' level_1_end {
- result = Interval.new(val[0], val[2])
- }
-
- level_1_start : date | partial_uncertain_or_approximate | unspecified | partial_unspecified | UNKNOWN
-
- level_1_end : level_1_start | OPEN
-
-
- long_year_simple :
- LONGYEAR long_year
- {
- result = Date.new(val[1])
- result.precision = :year
- }
- | LONGYEAR '-' long_year
- {
- result = Date.new(-1 * val[2])
- result.precision = :year
- }
- ;
-
- long_year :
- positive_digit digit digit digit digit {
- result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- | long_year digit { result = 10 * val[0] + val[1] }
- ;
-
-
- season : year '-' season_number ua {
- result = Season.new(val[0], val[2])
- val[3].each { |ua| result.send(ua) }
- }
-
- season_number : '2' '1' { result = 21 }
- | '2' '2' { result = 22 }
- | '2' '3' { result = 23 }
- | '2' '4' { result = 24 }
- ;
-
-
- # ---- Level 2 Extension Rules ----
-
- # NB: Level 2 Intervals are covered by the Level 1 Interval rules.
- level_2_expression : season_qualified
- | partial_uncertain_or_approximate
- | partial_unspecified
- | choice_list
- | inclusive_list
- | masked_precision
- | date_and_calendar
- | long_year_scientific
- ;
-
-
- season_qualified : season '^' { result = val[0]; result.qualifier = val[1] }
-
-
- long_year_scientific :
- long_year_simple E integer
- {
- result = Date.new(val[0].year * 10 ** val[2]).year_precision!
- }
- | LONGYEAR int1_4 E integer
- {
- result = Date.new(val[1] * 10 ** val[3]).year_precision!
- }
- | LONGYEAR '-' int1_4 E integer
- {
- result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision!
- }
- ;
-
-
- date_and_calendar : date '^' { result = val[0]; result.calendar = val[1] }
-
-
- masked_precision :
- digit digit digit X
- {
- d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Decade.new(d)
- }
- | digit digit X X
- {
- d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Century.new(d)
- }
- ;
-
-
- choice_list : '[' list ']' { result = val[1].choice! }
-
- inclusive_list : '{' list '}' { result = val[1] }
-
- list : earlier { result = EDTF::Set.new(val[0]).earlier! }
- | earlier ',' list_elements ',' later { result = EDTF::Set.new([val[0]] + val[2] + [val[4]]).earlier!.later! }
- | earlier ',' list_elements { result = EDTF::Set.new([val[0]] + val[2]).earlier! }
- | earlier ',' later { result = EDTF::Set.new([val[0]] + [val[2]]).earlier!.later! }
- | list_elements ',' later { result = EDTF::Set.new(val[0] + [val[2]]).later! }
- | list_elements { result = EDTF::Set.new(*val[0]) }
- | later { result = EDTF::Set.new(val[0]).later! }
- ;
-
- list_elements : list_element { result = [val[0]].flatten }
- | list_elements ',' list_element { result = val[0] + [val[2]].flatten }
- ;
-
- list_element : atomic
- | consecutives
- ;
-
- atomic : date
- | partial_uncertain_or_approximate
- | unspecified
- ;
-
- earlier : DOTS date { result = val[1] }
-
- later : year_month_day DOTS { result = Date.new(*val[0]).year_precision! }
- | year_month DOTS { result = Date.new(*val[0]).month_precision! }
- | year DOTS { result = Date.new(val[0]).year_precision! }
- ;
-
- consecutives : year_month_day DOTS year_month_day { result = (Date.new(val[0]).day_precision! .. Date.new(val[2]).day_precision!) }
- | year_month DOTS year_month { result = (Date.new(val[0]).month_precision! .. Date.new(val[2]).month_precision!) }
- | year DOTS year { result = (Date.new(val[0]).year_precision! .. Date.new(val[2]).year_precision!) }
- ;
-
- partial_unspecified :
- unspecified_year '-' month '-' day
- {
- result = Date.new(val[0][0], val[2], val[4])
- result.unspecified.year[2,2] = val[0][1]
- }
- | unspecified_year '-' U U '-' day
- {
- result = Date.new(val[0][0], 1, val[5])
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:month)
- }
- | unspecified_year '-' U U '-' U U
- {
- result = Date.new(val[0][0], 1, 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!([:month, :day])
- }
- | unspecified_year '-' month '-' U U
- {
- result = Date.new(val[0][0], val[2], 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:day)
- }
- | year '-' U U '-' day
- {
- result = Date.new(val[0], 1, val[5])
- result.unspecified!(:month)
- }
- ;
-
-
- partial_uncertain_or_approximate : pua_base
- | '(' pua_base ')' UA { result = uoa(val[1], val[3]) }
-
- pua_base :
- pua_year { result = val[0].year_precision! }
- | pua_year_month { result = val[0][0].month_precision! }
- | pua_year_month_day { result = val[0].day_precision! }
-
- pua_year : year UA { result = uoa(Date.new(val[0]), val[1], :year) }
-
- pua_year_month :
- pua_year '-' month ua {
- result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])]
- }
- | year '-' month UA {
- result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])]
- }
- | year '-(' month ')' UA {
- result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true]
- }
- | pua_year '-(' month ')' UA {
- result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true]
- }
- ;
-
- pua_year_month_day :
- pua_year_month '-' day ua {
- result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil)
- }
- | pua_year_month '-(' day ')' UA {
- result = uoa(val[0][0].change(:day => val[2]), val[4], [:day])
- }
- | year '-(' month ')' UA day ua {
- result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day)
- }
- | year_month '-' day UA {
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3])
- }
- | year_month '-(' day ')' UA {
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day])
- }
- | year '-(' month '-' day ')' UA {
- result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day])
- }
- | year '-(' month '-(' day ')' UA ')' UA {
- result = Date.new(val[0], val[2], val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
- }
- | pua_year '-(' month '-' day ')' UA {
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:month, :day])
- }
- | pua_year '-(' month '-(' day ')' UA ')' UA {
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
- }
- # | '(' pua_year '-(' month ')' UA ')' UA '-' day ua {
- # result = val[1].change(:month => val[3], :day => val[9])
- # result = uoa(result, val[5], [:month])
- # result = [uoa(result, val[7], [:year]), true]
- # }
- ;
-
- ua : { result = [] } | UA
-
- # ---- Auxiliary Rules ----
-
- digit : '0' { result = 0 }
- | positive_digit
- ;
-
- positive_digit : '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
-
- d01_12 : '0' positive_digit { result = val[1] }
- | '1' '0' { result = 10 }
- | '1' '1' { result = 11 }
- | '1' '2' { result = 12 }
- ;
-
- d01_13 : d01_12
- | '1' '3' { result = 13 }
- ;
-
- d01_23 : '0' positive_digit { result = val[1] }
- | '1' digit { result = 10 + val[1] }
- | '2' '0' { result = 20 }
- | '2' '1' { result = 21 }
- | '2' '2' { result = 22 }
- | '2' '3' { result = 23 }
- ;
-
- d00_23 : '0' '0'
- | d01_23
- ;
-
- d01_29 : d01_23
- | '2' '4' { result = 24 }
- | '2' '5' { result = 25 }
- | '2' '6' { result = 26 }
- | '2' '7' { result = 27 }
- | '2' '8' { result = 28 }
- | '2' '9' { result = 29 }
- ;
-
- d01_30 : d01_29
- | '3' '0' { result = 30 }
- ;
-
- d01_31 : d01_30
- | '3' '1' { result = 31 }
- ;
-
- d01_59 : d01_29
- | '3' digit { result = 30 + val[1] }
- | '4' digit { result = 40 + val[1] }
- | '5' digit { result = 50 + val[1] }
- ;
-
- d00_59 : '0' '0'
- | d01_59
- ;
-
- int1_4 : positive_digit { result = val[0] }
- | positive_digit digit { result = 10 * val[0] + val[1] }
- | positive_digit digit digit
- {
- result = val.zip([100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- | positive_digit digit digit digit
- {
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- ;
-
- integer : positive_digit { result = val[0] }
- | integer digit { result = 10 * val[0] + val[1] }
- ;
-
-
-
----- header
-require 'strscan'
-
----- inner
-
- @defaults = {
- :level => 2,
- :debug => false
- }.freeze
-
- class << self; attr_reader :defaults; end
-
- attr_reader :options
-
- def initialize(options = {})
- @options = Parser.defaults.merge(options)
- end
-
- def debug?
- !!(options[:debug] || ENV['DEBUG'])
- end
-
- def parse(input)
- parse!(input)
- rescue => e
- warn e.message if debug?
- nil
- end
-
- def parse!(input)
- @yydebug = debug?
- @src = StringScanner.new(input)
- do_parse
- end
-
- def on_error(tid, value, stack)
- raise ArgumentError,
- "failed to parse date: unexpected '#{value}' at #{stack.inspect}"
- end
-
- def apply_uncertainty(date, uncertainty, scope = nil)
- uncertainty.each do |u|
- scope.nil? ? date.send(u) : date.send(u, scope)
- end
- date
- end
-
- alias uoa apply_uncertainty
-
- def next_token
- case
- when @src.eos?
- nil
- # when @src.scan(/\s+/)
- # ignore whitespace
- when @src.scan(/\(/)
- ['(', @src.matched]
- # when @src.scan(/\)\?~-/)
- # [:PUA, [:uncertain!, :approximate!]]
- # when @src.scan(/\)\?-/)
- # [:PUA, [:uncertain!]]
- # when @src.scan(/\)~-/)
- # [:PUA, [:approximate!]]
- when @src.scan(/\)/)
- [')', @src.matched]
- when @src.scan(/\[/)
- ['[', @src.matched]
- when @src.scan(/\]/)
- [']', @src.matched]
- when @src.scan(/\{/)
- ['{', @src.matched]
- when @src.scan(/\}/)
- ['}', @src.matched]
- when @src.scan(/T/)
- [:T, @src.matched]
- when @src.scan(/Z/)
- [:Z, @src.matched]
- when @src.scan(/\?~/)
- [:UA, [:uncertain!, :approximate!]]
- when @src.scan(/\?/)
- [:UA, [:uncertain!]]
- when @src.scan(/~/)
- [:UA, [:approximate!]]
- when @src.scan(/open/i)
- [:OPEN, :open]
- when @src.scan(/unkn?own/i) # matches 'unkown' typo too
- [:UNKNOWN, :unknown]
- when @src.scan(/u/)
- [:U, @src.matched]
- when @src.scan(/x/i)
- [:X, @src.matched]
- when @src.scan(/y/)
- [:LONGYEAR, @src.matched]
- when @src.scan(/e/)
- [:E, @src.matched]
- when @src.scan(/\+/)
- ['+', @src.matched]
- when @src.scan(/-\(/)
- ['-(', @src.matched]
- when @src.scan(/-/)
- ['-', @src.matched]
- when @src.scan(/:/)
- [':', @src.matched]
- when @src.scan(/\//)
- ['/', @src.matched]
- when @src.scan(/\s*\.\.\s*/)
- [:DOTS, '..']
- when @src.scan(/\s*,\s*/)
- [',', ',']
- when @src.scan(/\^\w+/)
- ['^', @src.matched[1..-1]]
- when @src.scan(/\d/)
- [@src.matched, @src.matched.to_i]
- else @src.scan(/./)
- [:UNMATCHED, @src.rest]
- end
- end
-
-
-# -*- racc -*-