yaparc 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +36 -36
- data/lib/yaparc.rb +121 -199
- data/tests/test_abc.rb +40 -41
- data/tests/test_calc.rb +24 -29
- data/tests/test_owl.rb +986 -15
- data/tests/test_parser.rb +94 -45
- data/tests/test_sql.rb +98 -106
- data/tests/test_uri.rb +100 -100
- metadata +2 -2
    
        data/README
    CHANGED
    
    | @@ -19,39 +19,39 @@ All parsers has 'parse' method, each of which takes input string as its argument | |
| 19 19 |  | 
| 20 20 | 
             
            == Primitive Parsers
         | 
| 21 21 |  | 
| 22 | 
            -
            *  | 
| 23 | 
            -
            *  | 
| 24 | 
            -
            *  | 
| 25 | 
            -
            *  | 
| 22 | 
            +
            * Succeed
         | 
| 23 | 
            +
            * Fail
         | 
| 24 | 
            +
            * Item
         | 
| 25 | 
            +
            * Satisfy
         | 
| 26 26 |  | 
| 27 | 
            -
            ===  | 
| 27 | 
            +
            === Succeed class
         | 
| 28 28 |  | 
| 29 | 
            -
            The parser  | 
| 30 | 
            -
            In the following example,  | 
| 29 | 
            +
            The parser Succeed always succeeds with the result value, without consuming any of the input string.
         | 
| 30 | 
            +
            In the following example, Succeed#parse takes an input string "blah, blah, blah" and returns the singleton array [[1, "blah, blah, blah"]].
         | 
| 31 31 |  | 
| 32 | 
            -
                parser = Yaparc:: | 
| 32 | 
            +
                parser = Yaparc::Succeed.new(1)
         | 
| 33 33 | 
             
                parser.parse("blah, blah, blah")
         | 
| 34 34 | 
             
                => #<Yaparc::Result::OK:0xb7aaaf5c @input="blah, blah, blah", @value=1>
         | 
| 35 35 |  | 
| 36 | 
            -
            ===  | 
| 36 | 
            +
            === Fail class
         | 
| 37 37 |  | 
| 38 | 
            -
            The parser  | 
| 38 | 
            +
            The parser Fail always fails, regardless of the contents of the input string.
         | 
| 39 39 |  | 
| 40 | 
            -
                parser = Yaparc:: | 
| 40 | 
            +
                parser = Yaparc::Fail.new
         | 
| 41 41 | 
             
                parser.parse("abc")
         | 
| 42 42 | 
             
                => #<Yaparc::Result::Fail:0xb7aa56b0 @value=nil>
         | 
| 43 43 |  | 
| 44 | 
            -
            ===  | 
| 44 | 
            +
            === Item class
         | 
| 45 45 |  | 
| 46 | 
            -
            The parser  | 
| 46 | 
            +
            The parser Item fails if the input string is empty, and succeeds with the first character as the result value otherwise.
         | 
| 47 47 |  | 
| 48 | 
            -
                parser = Yaparc:: | 
| 48 | 
            +
                parser = Yaparc::Item.new
         | 
| 49 49 | 
             
                parser.parse("abc")
         | 
| 50 50 | 
             
                => #<Yaparc::Result::OK:0xb7a9fdb4 @input="bc", @value="a">
         | 
| 51 51 |  | 
| 52 | 
            -
            ===  | 
| 52 | 
            +
            === Satisfy class
         | 
| 53 53 |  | 
| 54 | 
            -
            The parser  | 
| 54 | 
            +
            The parser Satisfy recognizes a single input via predicate which determines if an arbitrary input is suitable for the predicate.
         | 
| 55 55 |  | 
| 56 56 | 
             
                is_integer = lambda do |i|
         | 
| 57 57 | 
             
                  begin
         | 
| @@ -61,31 +61,31 @@ The parser SatisfyParser recognizes a single input via predicate which determine | |
| 61 61 | 
             
                    false
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 | 
             
                end
         | 
| 64 | 
            -
                parser = Yaparc:: | 
| 64 | 
            +
                parser = Yaparc::Satisfy.new(is_integer)
         | 
| 65 65 | 
             
                parser.parse("123")
         | 
| 66 66 | 
             
                => #<Yaparc::Result::OK:0xb7a8f284 @input="23", @value="1">
         | 
| 67 67 |  | 
| 68 68 |  | 
| 69 69 | 
             
            == Combining Parsers
         | 
| 70 70 |  | 
| 71 | 
            -
            *  | 
| 72 | 
            -
            *  | 
| 73 | 
            -
            *  | 
| 74 | 
            -
            *  | 
| 71 | 
            +
            * Alt
         | 
| 72 | 
            +
            * Seq
         | 
| 73 | 
            +
            * Many
         | 
| 74 | 
            +
            * ManyOne
         | 
| 75 75 |  | 
| 76 76 |  | 
| 77 77 |  | 
| 78 78 | 
             
            === Sequencing parser
         | 
| 79 79 |  | 
| 80 | 
            -
            The  | 
| 80 | 
            +
            The Seq corresponds to sequencing in BNF. The following parser recognizes anything that Symbol.new('+') or Natural.new would if placed in succession.
         | 
| 81 81 |  | 
| 82 | 
            -
              parser =  | 
| 82 | 
            +
              parser = Seq.new(Symbol.new('+'), Natural.new)
         | 
| 83 83 | 
             
              parser.parse("+321")
         | 
| 84 84 | 
             
              => #<Yaparc::Result::OK:0xb7a81ae4 @input="", @value=321>
         | 
| 85 85 |  | 
| 86 | 
            -
            if a block given to  | 
| 86 | 
            +
            if a block given to Seq, it analyses input string to construct its logical structure.
         | 
| 87 87 |  | 
| 88 | 
            -
              parser = Yaparc:: | 
| 88 | 
            +
              parser = Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | plus, nat|
         | 
| 89 89 | 
             
                nat
         | 
| 90 90 | 
             
              end
         | 
| 91 91 | 
             
              parser.parse("+1234")
         | 
| @@ -95,11 +95,11 @@ It produces a parse tree which expounds the semantic structure of the program. | |
| 95 95 |  | 
| 96 96 | 
             
            === Alternation parser
         | 
| 97 97 |  | 
| 98 | 
            -
            The parser  | 
| 98 | 
            +
            The parser Alt class is an alternation parser, which returns the result of the first parser to succeed, and failure if neither does.
         | 
| 99 99 |  | 
| 100 100 |  | 
| 101 | 
            -
              parser = Yaparc:: | 
| 102 | 
            -
                                      Yaparc:: | 
| 101 | 
            +
              parser = Yaparc::Alt.new(
         | 
| 102 | 
            +
                                      Yaparc::Seq.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | _, nat|
         | 
| 103 103 | 
             
                                        nat
         | 
| 104 104 | 
             
                                      end,
         | 
| 105 105 | 
             
                                      Yaparc::Natural.new
         | 
| @@ -110,17 +110,17 @@ The parser AltParser class is an alternation parser, which returns the result of | |
| 110 110 | 
             
              => #<Yaparc::Result::Fail:0xb7a57ba4 @value=nil>
         | 
| 111 111 |  | 
| 112 112 |  | 
| 113 | 
            -
            ===  | 
| 113 | 
            +
            === Many
         | 
| 114 114 |  | 
| 115 | 
            -
            In  | 
| 115 | 
            +
            In Many, zero or more applications of parser are admissible.
         | 
| 116 116 |  | 
| 117 | 
            -
                parser = Yaparc:: | 
| 117 | 
            +
                parser = Yaparc::Many.new(Yaparc::Satisfy.new(lambda {|i| i > '0' and i < '9'}))
         | 
| 118 118 | 
             
                parser.parse("123abc")
         | 
| 119 119 | 
             
                => #<Yaparc::Result::OK:0xb7a49dc4 @input="abc", @value="123">
         | 
| 120 120 |  | 
| 121 | 
            -
            ===  | 
| 121 | 
            +
            === ManyOne
         | 
| 122 122 |  | 
| 123 | 
            -
            The  | 
| 123 | 
            +
            The ManyOne requires at least one successfull application of parser.
         | 
| 124 124 |  | 
| 125 125 |  | 
| 126 126 | 
             
            == Tokenized parser
         | 
| @@ -143,7 +143,7 @@ In order to construct parsers, you make parser class to be inherited from Yaparc | |
| 143 143 | 
             
              class Identifier < Yaparc::AbstractParser
         | 
| 144 144 | 
             
                def initialize
         | 
| 145 145 | 
             
                  @parser = lambda do
         | 
| 146 | 
            -
                    Yaparc:: | 
| 146 | 
            +
                    Yaparc::Tokenize.new(Yaparc::Ident.new)
         | 
| 147 147 | 
             
                  end
         | 
| 148 148 | 
             
                end
         | 
| 149 149 | 
             
              end
         | 
| @@ -154,8 +154,8 @@ In the following example, note that Expr class is instantiated inside Expr#initi | |
| 154 154 | 
             
              class Expr < Yaparc::AbstractParser
         | 
| 155 155 | 
             
                def initialize
         | 
| 156 156 | 
             
                  @parser = lambda do
         | 
| 157 | 
            -
                    Yaparc:: | 
| 158 | 
            -
                                          Yaparc:: | 
| 157 | 
            +
                    Yaparc::Alt.new(
         | 
| 158 | 
            +
                                          Yaparc::Seq.new(Term.new,
         | 
| 159 159 | 
             
                                                                Yaparc::Symbol.new('+'),
         | 
| 160 160 | 
             
                                                                Expr.new) do |term, _, expr|
         | 
| 161 161 | 
             
                                            ['+', term,expr]
         | 
    
        data/lib/yaparc.rb
    CHANGED
    
    | @@ -56,18 +56,13 @@ module Yaparc | |
| 56 56 | 
             
                module ClassMethods
         | 
| 57 57 | 
             
                  def included(mod)
         | 
| 58 58 | 
             
                  end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
            #       def define_parser(&block)
         | 
| 61 | 
            -
            #         @@cparser = lambda do
         | 
| 62 | 
            -
            #           yield
         | 
| 63 | 
            -
            #         end
         | 
| 64 | 
            -
            #       end
         | 
| 65 59 | 
             
                end
         | 
| 66 60 | 
             
              end # of Module Parsable
         | 
| 67 61 |  | 
| 68 62 |  | 
| 69 63 |  | 
| 70 | 
            -
              class SucceedParser
         | 
| 64 | 
            +
            #  class SucceedParser
         | 
| 65 | 
            +
              class Succeed
         | 
| 71 66 | 
             
                include Parsable
         | 
| 72 67 | 
             
                attr_reader :remaining
         | 
| 73 68 | 
             
                def initialize(value, remaining = nil)
         | 
| @@ -78,7 +73,8 @@ module Yaparc | |
| 78 73 | 
             
                end
         | 
| 79 74 | 
             
              end
         | 
| 80 75 |  | 
| 81 | 
            -
              class FailParser
         | 
| 76 | 
            +
            #  class FailParser
         | 
| 77 | 
            +
              class Fail
         | 
| 82 78 | 
             
                include Parsable
         | 
| 83 79 | 
             
                def initialize
         | 
| 84 80 | 
             
                  @parser = lambda do |input|
         | 
| @@ -89,7 +85,8 @@ module Yaparc | |
| 89 85 |  | 
| 90 86 |  | 
| 91 87 |  | 
| 92 | 
            -
              class ItemParser
         | 
| 88 | 
            +
            #  class ItemParser
         | 
| 89 | 
            +
              class Item
         | 
| 93 90 | 
             
                include Parsable
         | 
| 94 91 | 
             
                def initialize
         | 
| 95 92 | 
             
                  @parser = lambda do |input|
         | 
| @@ -102,13 +99,15 @@ module Yaparc | |
| 102 99 | 
             
                end
         | 
| 103 100 | 
             
              end
         | 
| 104 101 |  | 
| 105 | 
            -
              class ZeroOneParser
         | 
| 102 | 
            +
            #  class ZeroOneParser
         | 
| 103 | 
            +
              class ZeroOne
         | 
| 106 104 | 
             
                include Parsable
         | 
| 107 105 | 
             
                def initialize(parser, identity = [])
         | 
| 108 106 | 
             
                  @parser = lambda do |input|
         | 
| 109 107 | 
             
                    case result = parser.parse(input)
         | 
| 110 108 | 
             
                    when Result::Fail
         | 
| 111 | 
            -
                       | 
| 109 | 
            +
                      Result::OK.new(:value => identity, :input => input)
         | 
| 110 | 
            +
            #          Succeed.new(identity)
         | 
| 112 111 | 
             
                    when Result::Error
         | 
| 113 112 | 
             
                      Result::Error.new(:value => result.value, :input => result.input)
         | 
| 114 113 | 
             
                    when Result::OK
         | 
| @@ -117,8 +116,8 @@ module Yaparc | |
| 117 116 | 
             
                      raise
         | 
| 118 117 | 
             
                    end
         | 
| 119 118 |  | 
| 120 | 
            -
            #        AltParser.new(parser,  | 
| 121 | 
            -
            #         case result = AltParser.new(parser,  | 
| 119 | 
            +
            #        AltParser.new(parser, Succeed.new(identity))
         | 
| 120 | 
            +
            #         case result = AltParser.new(parser, Succeed.new(identity)).parse(input)
         | 
| 122 121 | 
             
            #         if input.nil? or input.empty?
         | 
| 123 122 | 
             
            #           Result::Fail.new(:input => input)
         | 
| 124 123 | 
             
            #         else
         | 
| @@ -129,30 +128,31 @@ module Yaparc | |
| 129 128 | 
             
                end
         | 
| 130 129 | 
             
              end
         | 
| 131 130 |  | 
| 132 | 
            -
              class SatisfyParser
         | 
| 131 | 
            +
            #  class SatisfyParser
         | 
| 132 | 
            +
              class Satisfy
         | 
| 133 133 | 
             
                include Parsable
         | 
| 134 134 | 
             
                def initialize(predicate)
         | 
| 135 135 | 
             
                  raise unless predicate.instance_of?(Proc)
         | 
| 136 136 |  | 
| 137 137 | 
             
                  @parser = lambda do |input|
         | 
| 138 | 
            -
                    case result =  | 
| 138 | 
            +
                    case result = Item.new.parse(input)
         | 
| 139 139 | 
             
                    when Result::OK
         | 
| 140 140 | 
             
                      parser = if predicate.call(result.value)
         | 
| 141 | 
            -
                                  | 
| 141 | 
            +
                                 Succeed.new(result.value, result.input)
         | 
| 142 142 | 
             
                               else
         | 
| 143 | 
            -
                                  | 
| 143 | 
            +
                                 Fail.new
         | 
| 144 144 | 
             
                               end
         | 
| 145 145 | 
             
                    else # Result::Fail or Result::Error
         | 
| 146 | 
            -
                       | 
| 146 | 
            +
                      Fail.new
         | 
| 147 147 | 
             
                    end
         | 
| 148 148 | 
             
                  end
         | 
| 149 149 | 
             
                end
         | 
| 150 150 |  | 
| 151 151 | 
             
                def parse(input)
         | 
| 152 152 | 
             
                  case parser = @parser.call(input)
         | 
| 153 | 
            -
                  when  | 
| 153 | 
            +
                  when Succeed
         | 
| 154 154 | 
             
                    parser.parse(parser.remaining)
         | 
| 155 | 
            -
                  when  | 
| 155 | 
            +
                  when Fail
         | 
| 156 156 | 
             
                    parser.parse(input)
         | 
| 157 157 | 
             
                  else
         | 
| 158 158 | 
             
                    raise
         | 
| @@ -171,9 +171,9 @@ module Yaparc | |
| 171 171 | 
             
                    when Result::Fail
         | 
| 172 172 | 
             
                      Result::Error.new(:value => result.value, :input => result.input)
         | 
| 173 173 | 
             
                    when Result::OK
         | 
| 174 | 
            -
                       | 
| 174 | 
            +
                      Succeed.new(result.value)
         | 
| 175 175 | 
             
                    else
         | 
| 176 | 
            -
                       | 
| 176 | 
            +
                      Succeed.new(result.value)
         | 
| 177 177 | 
             
            #          Result::OK.new(:value => result.value,:input => result.input)
         | 
| 178 178 | 
             
                    end
         | 
| 179 179 | 
             
                  end
         | 
| @@ -181,7 +181,8 @@ module Yaparc | |
| 181 181 | 
             
              end # of NoFail
         | 
| 182 182 |  | 
| 183 183 |  | 
| 184 | 
            -
              class SeqParser
         | 
| 184 | 
            +
            #  class SeqParser
         | 
| 185 | 
            +
              class Seq
         | 
| 185 186 | 
             
                include Parsable
         | 
| 186 187 | 
             
                def initialize(*parsers, &block)
         | 
| 187 188 | 
             
                  @parser = lambda do |input|
         | 
| @@ -191,6 +192,8 @@ module Yaparc | |
| 191 192 | 
             
                      case result = parser.parse(subsequent.input)
         | 
| 192 193 | 
             
                      when Result::Fail
         | 
| 193 194 | 
             
                        break Result::Fail.new(:input => subsequent.input)
         | 
| 195 | 
            +
            #           when Result::Error
         | 
| 196 | 
            +
            #             break Result::Error.new(:input => subsequent.input)
         | 
| 194 197 | 
             
                      else
         | 
| 195 198 | 
             
                        args << result.value
         | 
| 196 199 | 
             
                        result
         | 
| @@ -212,10 +215,11 @@ module Yaparc | |
| 212 215 | 
             
                    end
         | 
| 213 216 | 
             
                  end
         | 
| 214 217 | 
             
                end # of initialize
         | 
| 215 | 
            -
              end # of  | 
| 218 | 
            +
              end # of Seq
         | 
| 216 219 |  | 
| 217 220 |  | 
| 218 | 
            -
              class AltParser
         | 
| 221 | 
            +
            #  class AltParser
         | 
| 222 | 
            +
              class Alt
         | 
| 219 223 | 
             
                include Parsable
         | 
| 220 224 | 
             
                def initialize(*parsers)
         | 
| 221 225 | 
             
                  @parser = lambda do |input|
         | 
| @@ -239,48 +243,48 @@ module Yaparc | |
| 239 243 | 
             
                end # of initialize
         | 
| 240 244 | 
             
              end
         | 
| 241 245 |  | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
              class ApplyParser
         | 
| 246 | 
            +
            #  class ApplyParser
         | 
| 247 | 
            +
              class Apply
         | 
| 245 248 | 
             
                include Parsable
         | 
| 246 249 | 
             
                def initialize(parser, &block)
         | 
| 247 250 | 
             
                  @parser = lambda do |input|
         | 
| 248 251 | 
             
                    case result = parser.parse(input)
         | 
| 249 252 | 
             
                    when Result::OK
         | 
| 250 | 
            -
                       | 
| 253 | 
            +
                      Succeed.new(yield(result.value)).parse(result.input)
         | 
| 251 254 | 
             
                    else
         | 
| 252 | 
            -
                       | 
| 255 | 
            +
                      Fail.new.parse(input)
         | 
| 253 256 | 
             
                    end
         | 
| 254 257 | 
             
                  end
         | 
| 255 258 | 
             
                end # of initialize
         | 
| 256 | 
            -
              end # of  | 
| 259 | 
            +
              end # of Apply
         | 
| 257 260 |  | 
| 258 261 |  | 
| 259 | 
            -
              class  | 
| 262 | 
            +
              class String
         | 
| 260 263 | 
             
                include Parsable
         | 
| 261 264 | 
             
                def initialize(string)
         | 
| 262 265 | 
             
                  @parser = lambda do |input|
         | 
| 263 | 
            -
                    case result =  | 
| 266 | 
            +
                    case result = Item.new.parse(string)
         | 
| 264 267 | 
             
                    when Result::OK
         | 
| 265 | 
            -
                       | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 268 | 
            +
                      Seq.new(
         | 
| 269 | 
            +
                              Char.new(result.value),
         | 
| 270 | 
            +
                              Yaparc::String.new(result.input),
         | 
| 271 | 
            +
                              Succeed.new(result.value + result.input)
         | 
| 272 | 
            +
                              ) do |char_result, string_result, succeed_result|
         | 
| 270 273 | 
             
                        succeed_result
         | 
| 271 274 | 
             
                      end
         | 
| 272 275 | 
             
                    else
         | 
| 273 | 
            -
                       | 
| 276 | 
            +
                      Succeed.new(result) # Is it OK?
         | 
| 274 277 | 
             
                    end
         | 
| 275 278 | 
             
                  end
         | 
| 276 279 | 
             
                end
         | 
| 277 280 |  | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            +
            #     def parse(input)
         | 
| 282 | 
            +
            #       @parser.call(input).parse(input)
         | 
| 283 | 
            +
            #     end
         | 
| 281 284 | 
             
              end
         | 
| 282 285 |  | 
| 283 | 
            -
              class RegexParser
         | 
| 286 | 
            +
            #  class RegexParser
         | 
| 287 | 
            +
              class Regex
         | 
| 284 288 | 
             
                include Parsable
         | 
| 285 289 |  | 
| 286 290 | 
             
                def initialize(regex, &block)
         | 
| @@ -288,7 +292,7 @@ module Yaparc | |
| 288 292 | 
             
                  @parser = lambda do |input|
         | 
| 289 293 | 
             
                    if match = Regexp.new(regex).match(input)
         | 
| 290 294 | 
             
                      if block_given?
         | 
| 291 | 
            -
                         | 
| 295 | 
            +
                        Succeed.new(yield(*match.to_a[1..match.to_a.length])).parse(match.post_match)
         | 
| 292 296 | 
             
                      else
         | 
| 293 297 | 
             
                        Result::OK.new(:value => match[0], :input => match.post_match)
         | 
| 294 298 | 
             
                      end
         | 
| @@ -310,89 +314,93 @@ module Yaparc | |
| 310 314 | 
             
                  end
         | 
| 311 315 | 
             
                end
         | 
| 312 316 | 
             
              end
         | 
| 313 | 
            -
            #   class RegexParser
         | 
| 314 | 
            -
            #     include Parsable
         | 
| 315 | 
            -
             | 
| 316 | 
            -
            #     def initialize(regex)
         | 
| 317 | 
            -
            #       @parser = lambda do |input|
         | 
| 318 | 
            -
            #         if match = Regexp.new(regex).match(input)
         | 
| 319 | 
            -
            #           Result::OK.new(:value => match[0], :input => match.post_match)
         | 
| 320 | 
            -
            #         else
         | 
| 321 | 
            -
            #           Result::Fail.new(:input => input)
         | 
| 322 | 
            -
            #         end
         | 
| 323 | 
            -
            #       end
         | 
| 324 | 
            -
            #     end
         | 
| 325 | 
            -
            #   end
         | 
| 326 317 |  | 
| 327 318 | 
             
              # permits zero or more applications of parser.
         | 
| 328 | 
            -
              class ManyParser
         | 
| 319 | 
            +
            #  class ManyParser
         | 
| 320 | 
            +
              class Many
         | 
| 329 321 | 
             
                include Parsable
         | 
| 330 322 | 
             
                def initialize(parser, identity = [])
         | 
| 331 323 | 
             
                  @parser = lambda do |input|
         | 
| 332 | 
            -
                     | 
| 324 | 
            +
                    Alt.new(ManyOne.new(parser, identity), Succeed.new(identity))
         | 
| 333 325 | 
             
                  end
         | 
| 334 326 | 
             
                end
         | 
| 335 | 
            -
             | 
| 336 | 
            -
            #     def parse(input)
         | 
| 337 | 
            -
            #       @parser.call(input).parse(input)
         | 
| 338 | 
            -
            #     end
         | 
| 339 327 | 
             
              end
         | 
| 340 328 |  | 
| 341 329 | 
             
              # requires at least one successfull application of parser.
         | 
| 342 | 
            -
              class  | 
| 330 | 
            +
            #  class ManyOne
         | 
| 331 | 
            +
              class ManyOne
         | 
| 343 332 | 
             
                include Parsable
         | 
| 344 333 | 
             
                def initialize(parser, identity = [])
         | 
| 345 334 | 
             
                  @parser = lambda do |input|
         | 
| 346 | 
            -
                     | 
| 347 | 
            -
             | 
| 348 | 
            -
             | 
| 349 | 
            -
             | 
| 350 | 
            -
             | 
| 335 | 
            +
                    Seq.new(parser, Many.new(parser, identity)) do |head, tail|
         | 
| 336 | 
            +
                      case head
         | 
| 337 | 
            +
                      when ::String
         | 
| 338 | 
            +
                        if tail.instance_of?(::String)
         | 
| 339 | 
            +
                          head + tail
         | 
| 340 | 
            +
                        else
         | 
| 341 | 
            +
                          raise "Incompatible type: head => #{head}, tail => #{tail}"
         | 
| 342 | 
            +
                        end
         | 
| 343 | 
            +
                      when ::Array
         | 
| 344 | 
            +
                        if tail.instance_of?(Array)
         | 
| 345 | 
            +
                          head + tail
         | 
| 346 | 
            +
                        else
         | 
| 347 | 
            +
                          raise "Incompatible type: head => #{head}, tail => #{tail}"
         | 
| 348 | 
            +
                        end
         | 
| 349 | 
            +
                      when ::Hash
         | 
| 350 | 
            +
                        if tail.instance_of?(Hash)
         | 
| 351 | 
            +
                          head.merge(tail)
         | 
| 352 | 
            +
                        else
         | 
| 353 | 
            +
                          raise "Incompatible type: head => #{head}, tail => #{tail}"
         | 
| 354 | 
            +
                        end
         | 
| 355 | 
            +
                      when ::Integer
         | 
| 356 | 
            +
                        if tail.kind_of?(Integer)
         | 
| 357 | 
            +
                          head + tail
         | 
| 358 | 
            +
                        else
         | 
| 359 | 
            +
                          raise "Incompatible type: head => #{head}, tail => #{tail}"
         | 
| 360 | 
            +
                        end
         | 
| 361 | 
            +
                      else
         | 
| 362 | 
            +
                        raise "Incompatible type: head => #{head}"
         | 
| 363 | 
            +
                      end
         | 
| 364 | 
            +
                      #head + tail
         | 
| 351 365 | 
             
                    end
         | 
| 352 366 | 
             
                  end
         | 
| 353 367 | 
             
                end
         | 
| 354 | 
            -
             | 
| 355 | 
            -
                def parse(input)
         | 
| 356 | 
            -
                  @parser.call(input).parse(input)
         | 
| 357 | 
            -
                end
         | 
| 358 368 | 
             
              end
         | 
| 359 369 |  | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
             | 
| 363 | 
            -
              class SpaceParser
         | 
| 370 | 
            +
            #  class SpaceParser
         | 
| 371 | 
            +
              class Space
         | 
| 364 372 | 
             
                include Parsable
         | 
| 365 373 | 
             
                def initialize
         | 
| 366 374 | 
             
                  @parser = lambda do |input|
         | 
| 367 | 
            -
                     | 
| 375 | 
            +
                    Seq.new(Many.new(Satisfy.new(IS_SPACE),""))
         | 
| 368 376 | 
             
                  end
         | 
| 369 377 | 
             
                end
         | 
| 370 378 | 
             
              end
         | 
| 371 379 |  | 
| 372 | 
            -
              class  | 
| 380 | 
            +
              class WhiteSpace
         | 
| 373 381 | 
             
                include Parsable
         | 
| 374 382 | 
             
                def initialize
         | 
| 375 383 | 
             
                  @parser = lambda do |input|
         | 
| 376 | 
            -
                     | 
| 384 | 
            +
                    Seq.new(Many.new(Satisfy.new(IS_WHITESPACE),''))
         | 
| 377 385 | 
             
                  end
         | 
| 378 386 | 
             
                end
         | 
| 379 387 | 
             
              end
         | 
| 380 388 |  | 
| 381 | 
            -
              class  | 
| 389 | 
            +
              class Tokenize
         | 
| 382 390 | 
             
                include Parsable
         | 
| 383 391 | 
             
                attr_accessor :prefix, :postfix
         | 
| 384 392 |  | 
| 385 393 | 
             
                def initialize(parser, args = { }, &block)
         | 
| 386 394 | 
             
                  @parser = lambda do |input|
         | 
| 387 | 
            -
                    @prefix = args[:prefix] ? args[:prefix] :  | 
| 388 | 
            -
                    @postfix = args[:postfix] ? args[:postfix] :  | 
| 395 | 
            +
                    @prefix = args[:prefix] ? args[:prefix] : WhiteSpace.new 
         | 
| 396 | 
            +
                    @postfix = args[:postfix] ? args[:postfix] : WhiteSpace.new
         | 
| 389 397 | 
             
                    if block_given?
         | 
| 390 398 | 
             
                      yield self
         | 
| 391 | 
            -
                       | 
| 399 | 
            +
                      Seq.new(@prefix, parser, @postfix) do |_, vs, _|
         | 
| 392 400 | 
             
                        vs
         | 
| 393 401 | 
             
                      end
         | 
| 394 402 | 
             
                    else
         | 
| 395 | 
            -
                       | 
| 403 | 
            +
                      Seq.new(@prefix, parser, @postfix) do |_, vs, _|
         | 
| 396 404 | 
             
                        vs
         | 
| 397 405 | 
             
                      end
         | 
| 398 406 | 
             
                    end
         | 
| @@ -400,23 +408,12 @@ module Yaparc | |
| 400 408 | 
             
                end
         | 
| 401 409 | 
             
              end
         | 
| 402 410 |  | 
| 403 | 
            -
            # | 
| 404 | 
            -
             | 
| 405 | 
            -
             | 
| 406 | 
            -
            #     def initialize(parser, &block)
         | 
| 407 | 
            -
            #       @prefix, @postfix = WhiteSpace.new,WhiteSpace.new
         | 
| 408 | 
            -
            #       yield self
         | 
| 409 | 
            -
            #       @parser = SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
         | 
| 410 | 
            -
            #         vs
         | 
| 411 | 
            -
            #       end
         | 
| 412 | 
            -
            #     end
         | 
| 413 | 
            -
            #   end
         | 
| 414 | 
            -
             | 
| 415 | 
            -
              class LiteralParser
         | 
| 411 | 
            +
            #  class LiteralParser
         | 
| 412 | 
            +
              class Literal
         | 
| 416 413 | 
             
                include Parsable
         | 
| 417 414 | 
             
                def initialize(literal)
         | 
| 418 415 | 
             
                  @parser =  lambda do |input|
         | 
| 419 | 
            -
                     | 
| 416 | 
            +
                    Tokenize.new(Yaparc::String.new(literal))
         | 
| 420 417 | 
             
                  end
         | 
| 421 418 | 
             
                end
         | 
| 422 419 | 
             
              end
         | 
| @@ -425,23 +422,21 @@ module Yaparc | |
| 425 422 |  | 
| 426 423 | 
             
              class Identifier
         | 
| 427 424 | 
             
                include Yaparc::Parsable
         | 
| 428 | 
            -
                @@identifier_regex = ::Yaparc:: | 
| 425 | 
            +
                @@identifier_regex = ::Yaparc::Regex.new(/\A[a-zA-Z_]+[a-zA-Z0-9_]*/)
         | 
| 429 426 |  | 
| 430 427 | 
             
                def initialize(*keywords)
         | 
| 431 428 | 
             
                  if keywords == []
         | 
| 432 429 | 
             
                    @parser = lambda do |input|
         | 
| 433 | 
            -
                       | 
| 434 | 
            -
            #          Yaparc::Token.new(@@identifier_regex)
         | 
| 430 | 
            +
                      Tokenize.new(@@identifier_regex)
         | 
| 435 431 | 
             
                    end
         | 
| 436 432 | 
             
                  else
         | 
| 437 433 | 
             
                    @parser = lambda do |input|
         | 
| 438 | 
            -
                      keyword_parsers = keywords.map {|keyword| Yaparc:: | 
| 439 | 
            -
                      case result = Yaparc:: | 
| 434 | 
            +
                      keyword_parsers = keywords.map {|keyword| Yaparc::String.new(keyword)}
         | 
| 435 | 
            +
                      case result = Yaparc::Alt.new(*keyword_parsers).parse(input)
         | 
| 440 436 | 
             
                      when Yaparc::Result::OK
         | 
| 441 | 
            -
                        Yaparc:: | 
| 437 | 
            +
                        Yaparc::Fail.new
         | 
| 442 438 | 
             
                      else # Result::Fail or Result::Error
         | 
| 443 | 
            -
                         | 
| 444 | 
            -
            #            Yaparc::Token.new(@@identifier_regex)
         | 
| 439 | 
            +
                        Tokenize.new(@@identifier_regex)
         | 
| 445 440 | 
             
                      end
         | 
| 446 441 | 
             
                    end
         | 
| 447 442 | 
             
                  end
         | 
| @@ -452,69 +447,48 @@ module Yaparc | |
| 452 447 | 
             
                end
         | 
| 453 448 | 
             
              end
         | 
| 454 449 |  | 
| 455 | 
            -
            # | 
| 456 | 
            -
             | 
| 457 | 
            -
             | 
| 458 | 
            -
            #     def parse(input)
         | 
| 459 | 
            -
            #       @parser.parse(input)
         | 
| 460 | 
            -
            #     end
         | 
| 461 | 
            -
            #   end
         | 
| 462 | 
            -
             | 
| 463 | 
            -
              class CharParser
         | 
| 450 | 
            +
            #  class Char
         | 
| 451 | 
            +
              class Char
         | 
| 464 452 | 
             
                include Parsable
         | 
| 465 453 |  | 
| 466 454 | 
             
                def initialize(char)
         | 
| 467 455 | 
             
                  equal_char = lambda {|i| i == char}
         | 
| 468 456 | 
             
                  @parser =  lambda do |input|
         | 
| 469 | 
            -
                     | 
| 457 | 
            +
                    Satisfy.new(equal_char)
         | 
| 470 458 | 
             
                  end
         | 
| 471 459 | 
             
                end
         | 
| 472 460 | 
             
              end
         | 
| 473 | 
            -
            #   class CharParser < ParserBase
         | 
| 474 | 
            -
             | 
| 475 | 
            -
            #     def initialize(char)
         | 
| 476 | 
            -
            #       equal_char = lambda {|i| i == char}
         | 
| 477 | 
            -
            #       @parser = SatisfyParser.new(equal_char)
         | 
| 478 | 
            -
            #     end
         | 
| 479 | 
            -
            #   end
         | 
| 480 | 
            -
             | 
| 481 | 
            -
            #   class ZeroOneParser < ParserBase
         | 
| 482 | 
            -
            #     def initialize(parser, identity = [])
         | 
| 483 | 
            -
            #       @parser = AltParser.new(parser, SucceedParser.new(identity)) # Is it OK?
         | 
| 484 | 
            -
            #     end
         | 
| 485 | 
            -
            #   end
         | 
| 486 461 |  | 
| 487 462 | 
             
              class Ident
         | 
| 488 463 | 
             
                include Parsable
         | 
| 489 464 | 
             
                def initialize
         | 
| 490 465 | 
             
                  @parser = lambda do |input|
         | 
| 491 | 
            -
                     | 
| 492 | 
            -
                                   | 
| 493 | 
            -
                                   | 
| 466 | 
            +
                    Seq.new(
         | 
| 467 | 
            +
                                  Satisfy.new(IS_LOWER),
         | 
| 468 | 
            +
                                  Many.new(Satisfy.new(IS_ALPHANUM),"")
         | 
| 494 469 | 
             
                                  ) do |head, tail|
         | 
| 495 470 | 
             
                      head + tail
         | 
| 496 471 | 
             
                    end
         | 
| 497 472 | 
             
                  end
         | 
| 498 473 | 
             
                end
         | 
| 499 474 | 
             
              end
         | 
| 500 | 
            -
             | 
| 501 | 
            -
             | 
| 502 | 
            -
             | 
| 503 | 
            -
             | 
| 504 | 
            -
             | 
| 505 | 
            -
             | 
| 506 | 
            -
             | 
| 507 | 
            -
             | 
| 508 | 
            -
             | 
| 509 | 
            -
            #   end
         | 
| 475 | 
            +
             | 
| 476 | 
            +
              class Digit
         | 
| 477 | 
            +
                include Parsable
         | 
| 478 | 
            +
                def initialize
         | 
| 479 | 
            +
                  @parser = lambda do |input|
         | 
| 480 | 
            +
                    Satisfy.new(IS_DIGIT)
         | 
| 481 | 
            +
                  end
         | 
| 482 | 
            +
                end
         | 
| 483 | 
            +
              end
         | 
| 510 484 |  | 
| 511 485 | 
             
              class Nat
         | 
| 512 486 | 
             
                include Parsable
         | 
| 513 487 | 
             
                def initialize
         | 
| 514 488 | 
             
                  @parser = lambda do |input|
         | 
| 515 | 
            -
                     | 
| 489 | 
            +
                    Seq.new(ManyOne.new(Digit.new,'')) do |vs|
         | 
| 516 490 | 
             
                      if vs == ""
         | 
| 517 | 
            -
                        vs
         | 
| 491 | 
            +
                        0 #            vs
         | 
| 518 492 | 
             
                      else
         | 
| 519 493 | 
             
                        vs.to_i
         | 
| 520 494 | 
             
                      end
         | 
| @@ -523,77 +497,25 @@ module Yaparc | |
| 523 497 | 
             
                end
         | 
| 524 498 | 
             
              end
         | 
| 525 499 |  | 
| 526 | 
            -
            #   class Nat < ParserBase
         | 
| 527 | 
            -
            #     def initialize
         | 
| 528 | 
            -
            #       @parser = SeqParser.new(ManyOneParser.new(SatisfyParser.new(IS_DIGIT),"")) do |vs|
         | 
| 529 | 
            -
            #         if vs == ""
         | 
| 530 | 
            -
            #           vs
         | 
| 531 | 
            -
            #         else
         | 
| 532 | 
            -
            #           vs.to_i
         | 
| 533 | 
            -
            #         end
         | 
| 534 | 
            -
            #       end
         | 
| 535 | 
            -
            #     end
         | 
| 536 | 
            -
            #   end
         | 
| 537 | 
            -
             | 
| 538 | 
            -
            #   class Space < ParserBase
         | 
| 539 | 
            -
            #     def initialize
         | 
| 540 | 
            -
            #       @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_SPACE),"")) do |vs|
         | 
| 541 | 
            -
            #         SucceedParser.new([])
         | 
| 542 | 
            -
            #       end
         | 
| 543 | 
            -
            #     end
         | 
| 544 | 
            -
            #   end
         | 
| 545 | 
            -
             | 
| 546 | 
            -
            #   class WhiteSpace < ParserBase
         | 
| 547 | 
            -
            #     def initialize
         | 
| 548 | 
            -
            #       @parser = SeqParser.new(ManyParser.new(SatisfyParser.new(IS_WHITESPACE),"")) do |vs|
         | 
| 549 | 
            -
            #         SucceedParser.new([])
         | 
| 550 | 
            -
            #       end
         | 
| 551 | 
            -
            #     end
         | 
| 552 | 
            -
            #   end
         | 
| 553 | 
            -
             | 
| 554 | 
            -
            #   class Token < ParserBase
         | 
| 555 | 
            -
            #     attr_accessor :prefix, :postfix
         | 
| 556 | 
            -
             | 
| 557 | 
            -
            #     def initialize(parser, prefix = WhiteSpace.new, postfix = WhiteSpace.new)
         | 
| 558 | 
            -
            #       @prefix, @postfix  = prefix, postfix
         | 
| 559 | 
            -
            #       @parser = SeqParser.new(@prefix, parser, @postfix) do |_, vs, _|
         | 
| 560 | 
            -
            #         vs
         | 
| 561 | 
            -
            #       end
         | 
| 562 | 
            -
            #     end
         | 
| 563 | 
            -
            #   end
         | 
| 564 500 |  | 
| 565 501 | 
             
              class Natural
         | 
| 566 502 | 
             
                include Parsable
         | 
| 567 503 | 
             
                def initialize(args = {})
         | 
| 568 504 | 
             
                  @parser = lambda do |input|
         | 
| 569 | 
            -
                     | 
| 505 | 
            +
                    Tokenize.new(Nat.new, args)
         | 
| 570 506 | 
             
                  end
         | 
| 571 507 | 
             
                end
         | 
| 572 508 | 
             
              end
         | 
| 573 | 
            -
            #   class Natural < ParserBase
         | 
| 574 | 
            -
             | 
| 575 | 
            -
            #     def initialize
         | 
| 576 | 
            -
            #       @parser = Token.new(Nat.new)
         | 
| 577 | 
            -
            #     end
         | 
| 578 | 
            -
            #   end
         | 
| 579 | 
            -
             | 
| 580 509 |  | 
| 581 510 | 
             
              class Symbol
         | 
| 582 511 | 
             
                include Parsable
         | 
| 583 512 | 
             
                def initialize(literal, args = {})
         | 
| 584 513 | 
             
                  @parser = lambda do |input|
         | 
| 585 | 
            -
                     | 
| 514 | 
            +
                    Literal.new(literal)
         | 
| 586 515 | 
             
                  end
         | 
| 587 516 | 
             
                end
         | 
| 588 517 | 
             
              end
         | 
| 589 518 |  | 
| 590 | 
            -
            #   class Symbol < ParserBase
         | 
| 591 | 
            -
             | 
| 592 | 
            -
            #     def initialize(literal)
         | 
| 593 | 
            -
            #       @parser = Token.new(StringParser.new(literal))
         | 
| 594 | 
            -
            #     end
         | 
| 595 | 
            -
            #   end
         | 
| 596 | 
            -
             | 
| 597 519 | 
             
              class AbstractParser
         | 
| 598 520 | 
             
                include Parsable
         | 
| 599 521 |  |