rparsec 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/rparsec.rb CHANGED
@@ -1,3 +1,3 @@
1
- %w{
2
- parsers operators keywords expressions
1
+ %w{
2
+ parsers operators keywords expressions
3
3
  }.each {|lib| require "rparsec/#{lib}"}
@@ -1,66 +1,81 @@
1
-
2
-
3
- class ParseContext
4
- attr_reader :error, :src, :index, :result
5
- attr_writer :error, :index, :result
6
- def initialize(src, index=0, error=nil)
7
- @src, @index, @error = src, index, error
8
- end
9
-
10
- def scanner
11
- @scanner = StringScanner.new(src) if @scanner.nil?
12
- @scanner.pos= @index
13
- @scanner
14
- end
15
- def prepare_error
16
- @error.flatten! if @error.kind_of?(Array)
17
- end
18
- def to_msg
19
- return '' if @error.nil?
20
- return @error.msg unless @error.kind_of?(Array)
21
- @error.map{|e|e.msg}.join(' or ')
22
- end
23
- def error_input
24
- return nil if @error.nil?
25
- err = @error
26
- err = err.last if err.kind_of? Array
27
- err.input
28
- end
29
- def reset_error
30
- @error = nil
31
- end
32
- def current
33
- @src[@index]
34
- end
35
- def eof
36
- @index >= @src.length
37
- end
38
- def available
39
- @src.length - @index
40
- end
41
- def peek i
42
- @src[@index+i]
43
- end
44
- def next
45
- @index += 1
46
- end
47
- def advance n
48
- @index += n
49
- end
50
- def retn(val)
51
- @result = val
52
- true
53
- end
54
- def failure(msg=nil)
55
- @error = Failure.new(@index, get_current_input, msg)
56
- return false
57
- end
58
- def expecting(expected=nil)
59
- @error = Expected.new(@index, get_current_input, expected)
60
- return false
61
- end
62
- def get_current_input
63
- return nil if eof
64
- current
65
- end
66
- end
1
+
2
+
3
+ class ParseContext
4
+ attr_reader :error, :src, :index, :result
5
+ attr_writer :error, :index, :result
6
+
7
+ def initialize(src, index=0, error=nil)
8
+ @src, @index, @error = src, index, error
9
+ end
10
+
11
+ def scanner
12
+ @scanner = StringScanner.new(src) if @scanner.nil?
13
+ @scanner.pos= @index
14
+ @scanner
15
+ end
16
+
17
+ def prepare_error
18
+ @error.flatten! if @error.kind_of?(Array)
19
+ end
20
+
21
+ def to_msg
22
+ return '' if @error.nil?
23
+ return @error.msg unless @error.kind_of?(Array)
24
+ @error.map{|e|e.msg}.join(' or ')
25
+ end
26
+
27
+ def error_input
28
+ return nil if @error.nil?
29
+ err = @error
30
+ err = err.last if err.kind_of? Array
31
+ err.input
32
+ end
33
+
34
+ def reset_error
35
+ @error = nil
36
+ end
37
+
38
+ def current
39
+ @src[@index]
40
+ end
41
+
42
+ def eof
43
+ @index >= @src.length
44
+ end
45
+
46
+ def available
47
+ @src.length - @index
48
+ end
49
+
50
+ def peek i
51
+ @src[@index+i]
52
+ end
53
+
54
+ def next
55
+ @index += 1
56
+ end
57
+
58
+ def advance n
59
+ @index += n
60
+ end
61
+
62
+ def retn(val)
63
+ @result = val
64
+ true
65
+ end
66
+
67
+ def failure(msg=nil)
68
+ @error = Failure.new(@index, get_current_input, msg)
69
+ return false
70
+ end
71
+
72
+ def expecting(expected=nil)
73
+ @error = Expected.new(@index, get_current_input, expected)
74
+ return false
75
+ end
76
+
77
+ def get_current_input
78
+ return nil if eof
79
+ current
80
+ end
81
+ end
@@ -1,20 +1,23 @@
1
- require 'rparsec/misc'
2
- class ParserException < StandardError
3
- extend DefHelper
4
- def_readable :index
5
- end
6
- class Failure
7
- def initialize(ind, input, msg=nil)
8
- @index, @input, @msg = ind, input, msg
9
- end
10
- attr_reader :index, :input
11
- attr_writer :index
12
- def msg
13
- return @msg.to_s
14
- end
15
- Precedence = 100
16
- end
17
-
18
- class Expected < Failure
19
- Precedence = 100
1
+ require 'rparsec/misc'
2
+ class ParserException < StandardError
3
+ extend DefHelper
4
+ def_readable :index
5
+ end
6
+ class Failure
7
+ def initialize(ind, input, message=nil)
8
+ @index, @input, @msg = ind, input, message
9
+ end
10
+
11
+ attr_reader :index, :input
12
+ attr_writer :index
13
+
14
+ def msg
15
+ return @msg.to_s
16
+ end
17
+
18
+ Precedence = 100
19
+ end
20
+
21
+ class Expected < Failure
22
+ Precedence = 100
20
23
  end
@@ -1,137 +1,180 @@
1
- require 'rparsec/parser'
2
-
3
- Associativities = [:prefix, :postfix, :infixn, :infixr, :infixl]
4
- #
5
- # This class holds information about operator precedences
6
- # and associativities.
7
- # prefix, postfix, infixl, infixr, infixn can be called
8
- # to register operators.
9
- #
10
- class OperatorTable
11
- #
12
- # operators attribute is used internally. Do not access it.
13
- #
14
- attr_reader :operators
15
- #
16
- # Re-initialize the operator table.
17
- #
18
- def reinit
19
- @operators = []
20
- end
21
- #
22
- # To create an OperatorTable instance.
23
- # If a block is given, it is invoked to do post-instantiation.
24
- # For example:
25
- #
26
- # OperatorTable.new do |tbl|
27
- # tbl.infixl(char(?+) >> Plus)
28
- # tbl.infixl(char(?-) >> Minus)
29
- # tbl.prefix(char(?-) >> Neg)
30
- # end
31
- #
32
- def self.new
33
- this = allocate
34
- this.reinit
35
- if block_given?
36
- yield this
37
- end
38
- this
39
- end
40
- private
41
- #
42
- # To define methods for registering operator.
43
- # This is typically used internally.
44
- #
45
- def self.def_operator(*kinds)
46
- kinds.each do |kind|
47
- define_method(kind) do |op, precedence|
48
- add(kind, op, precedence)
49
- end
50
- end
51
- end
52
- def_operator(*Associativities)
53
- def add(*entry)
54
- @operators << entry
55
- self
56
- end
57
- end
58
-
59
- #
60
- # This module helps build an expression parser
61
- # using an OperatorTable instance and a parser
62
- # that parses the term expression.
63
- #
64
- module Expressions
65
- private
66
- def self.array_to_dict arr
67
- result = {}
68
- arr.each_with_index do |key,i|
69
- result [key] = i unless result.include? key
70
- end
71
- result
72
- end
73
- KindPrecedence = array_to_dict Associativities
74
- public
75
- #
76
- # build an expression parser using the given term parser
77
- # and operator table.
78
- # When _delim_ is specified, patterns recognized by _delim_
79
- # is automatically ignored.
80
- #
81
- def self.build(term, table, delim=nil)
82
- # sort so that higher precedence first.
83
- apply_operators(term, prepare_suites(table).sort, delim)
84
- end
85
- private
86
- def self.apply_operators(term, entries, delim)
87
- # apply operators stored in [[precedence,associativity],[op...]] starting from beginning.
88
- entries.inject(term) do |result, entry|
89
- key, ops = *entry
90
- null, kind_index = *key
91
- op = ops[0]
92
- op = Parsers.sum(*ops) if ops.length>1
93
- apply_operator(result, op, Associativities[kind_index], delim)
94
- end
95
- end
96
- def self.apply_operator(term, op, kind, delim)
97
- term, op = ignore_rest(term, delim), ignore_rest(op, delim)
98
- # we could use send here,
99
- # but explicit case stmt is more straight forward and less coupled with names.
100
- # performance might be another benefit,
101
- # though it is not clear whether meta-code is indeed slower than regular ones at all.
102
- case kind
103
- when :prefix
104
- term.prefix(op)
105
- when :postfix
106
- term.postfix(op)
107
- when :infixl
108
- term.infixl(op)
109
- when :infixr
110
- term.infixr(op)
111
- when :infixn
112
- term.infixn(op)
113
- else
114
- raise ArgumentError, "unknown associativity: #{kind}"
115
- end
116
- end
117
- def self.ignore_rest(parser, delim)
118
- return parser if delim.nil?
119
- parser << delim
120
- end
121
- def self.prepare_suites(table)
122
- # create a hash with [precedence, associativity] as key, and op as value.
123
- suites = {}
124
- table.operators.each do |entry|
125
- kind, op, precedence = *entry
126
- key = [-precedence, KindPrecedence[kind]]
127
- suite = suites[key]
128
- if suite.nil?
129
- suite = [op]
130
- suites[key] = suite
131
- else
132
- suite << op
133
- end
134
- end
135
- suites
136
- end
1
+ require 'rparsec/parser'
2
+
3
+ Associativities = [:prefix, :postfix, :infixn, :infixr, :infixl]
4
+ #
5
+ # This class holds information about operator precedences
6
+ # and associativities.
7
+ # prefix, postfix, infixl, infixr, infixn can be called
8
+ # to register operators.
9
+ #
10
+ class OperatorTable
11
+ #
12
+ # operators attribute is used internally. Do not access it.
13
+ #
14
+ attr_reader :operators
15
+
16
+ #
17
+ # Re-initialize the operator table. Internal use only.
18
+ #
19
+ def reinit
20
+ @operators = []
21
+ end
22
+
23
+ #
24
+ # To create an OperatorTable instance.
25
+ # If a block is given, it is invoked to do post-instantiation.
26
+ # For example:
27
+ #
28
+ # OperatorTable.new do |tbl|
29
+ # tbl.infixl(char(?+) >> Plus, 10)
30
+ # tbl.infixl(char(?-) >> Minus, 10)
31
+ # tbl.infixl(char(?*) >> Mul, 20)
32
+ # tbl.infixl(char(?/) >> Div, 20)
33
+ # tbl.prefix(char(?-) >> Neg, 50)
34
+ # end
35
+ #
36
+ def self.new
37
+ this = allocate
38
+ this.reinit
39
+ if block_given?
40
+ yield this
41
+ end
42
+ this
43
+ end
44
+
45
+ #
46
+ # Defines a prefix operator that returns a unary Proc object with a precedence associated.
47
+ # Returns self.
48
+ #
49
+ def prefix(op, precedence)
50
+ add(:prefix, op, precedence)
51
+ end
52
+
53
+ #
54
+ # Defines a postfix operator that returns a unary Proc object with a precedence associated.
55
+ # Returns self.
56
+ #
57
+ def postfix(op, precedence)
58
+ add(:postfix, op, precedence)
59
+ end
60
+
61
+ #
62
+ # Defines a left associative infix operator that returns a binary Proc object with a precedence
63
+ # associated. Returns self.
64
+ #
65
+ def infixl(op, precedence)
66
+ add(:infixl, op, precedence)
67
+ end
68
+
69
+ #
70
+ # Defines a right associative infix operator that returns a binary Proc object with a precedence
71
+ # associated. Returns self.
72
+ #
73
+ def infixr(op, precedence)
74
+ add(:infixr, op, precedence)
75
+ end
76
+
77
+ #
78
+ # Defines a non-associative infix operator that returns a binary Proc object with a precedence
79
+ # associated. Returns self.
80
+ #
81
+ def infixn(op, precedence)
82
+ add(:infixn, op, precedence)
83
+ end
84
+
85
+ private
86
+
87
+ def add(*entry)
88
+ @operators << entry
89
+ self
90
+ end
91
+ end
92
+
93
+ #
94
+ # This module helps build an expression parser
95
+ # using an OperatorTable instance and a parser
96
+ # that parses the term expression.
97
+ #
98
+ module Expressions
99
+ private
100
+
101
+ def self.array_to_dict arr
102
+ result = {}
103
+ arr.each_with_index do |key,i|
104
+ result [key] = i unless result.include? key
105
+ end
106
+ result
107
+ end
108
+
109
+ KindPrecedence = array_to_dict Associativities
110
+
111
+ public
112
+
113
+ #
114
+ # build an expression parser using the given term parser
115
+ # and operator table.
116
+ # When _delim_ is specified, patterns recognized by _delim_
117
+ # is automatically ignored.
118
+ #
119
+ def self.build(term, table, delim=nil)
120
+ # sort so that higher precedence first.
121
+ apply_operators(term, prepare_suites(table).sort, delim)
122
+ end
123
+
124
+ private
125
+
126
+ def self.apply_operators(term, entries, delim)
127
+ # apply operators stored in [[precedence,associativity],[op...]] starting from beginning.
128
+ entries.inject(term) do |result, entry|
129
+ key, ops = *entry
130
+ null, kind_index = *key
131
+ op = ops[0]
132
+ op = Parsers.sum(*ops) if ops.length>1
133
+ apply_operator(result, op, Associativities[kind_index], delim)
134
+ end
135
+ end
136
+
137
+ def self.apply_operator(term, op, kind, delim)
138
+ term, op = ignore_rest(term, delim), ignore_rest(op, delim)
139
+ # we could use send here,
140
+ # but explicit case stmt is more straight forward and less coupled with names.
141
+ # performance might be another benefit,
142
+ # though it is not clear whether meta-code is indeed slower than regular ones at all.
143
+ case kind
144
+ when :prefix
145
+ term.prefix(op)
146
+ when :postfix
147
+ term.postfix(op)
148
+ when :infixl
149
+ term.infixl(op)
150
+ when :infixr
151
+ term.infixr(op)
152
+ when :infixn
153
+ term.infixn(op)
154
+ else
155
+ raise ArgumentError, "unknown associativity: #{kind}"
156
+ end
157
+ end
158
+
159
+ def self.ignore_rest(parser, delim)
160
+ return parser if delim.nil?
161
+ parser << delim
162
+ end
163
+
164
+ def self.prepare_suites(table)
165
+ # create a hash with [precedence, associativity] as key, and op as value.
166
+ suites = {}
167
+ table.operators.each do |entry|
168
+ kind, op, precedence = *entry
169
+ key = [-precedence, KindPrecedence[kind]]
170
+ suite = suites[key]
171
+ if suite.nil?
172
+ suite = [op]
173
+ suites[key] = suite
174
+ else
175
+ suite << op
176
+ end
177
+ end
178
+ suites
179
+ end
137
180
  end