rparsec 0.4.1 → 0.4.2

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.
@@ -1,11 +1,13 @@
1
- class IdMonad
2
- def value v
3
- v
4
- end
5
- def bind prev
6
- yield prev
7
- end
8
- def mplus a, b
9
- a
10
- end
11
- end
1
+ class IdMonad
2
+ def value v
3
+ v
4
+ end
5
+
6
+ def bind prev
7
+ yield prev
8
+ end
9
+
10
+ def mplus a, b
11
+ a
12
+ end
13
+ end
@@ -1,90 +1,102 @@
1
- require 'rparsec/parser'
2
-
3
- #
4
- # This class helps building lexers and parsers for keywords.
5
- #
6
- class Keywords
7
- extend Parsers
8
- private_class_method :new
9
- attr_reader :keyword_symbol, :lexer
10
- #
11
- # Do we lex case sensitively?
12
- #
13
- def case_sensitive?
14
- @case_sensitive
15
- end
16
- #
17
- # To create an instance that lexes the given keywords
18
- # case sensitively.
19
- # _default_lexer_ is used to lex a token first, the token text is then compared with
20
- # the given keywords. If it matches any of the keyword, a keyword token is generated instead
21
- # using _keyword_symbol_.
22
- # The _block_ parameter, if present, is used to convert the token text to another object
23
- # when the token is recognized during grammar parsing phase.
24
- #
25
- def self.case_sensitive(words, default_lexer=word.token(:word), keyword_symbol=:keyword, &block)
26
- new(words, true, default_lexer, keyword_symbol, &block)
27
- end
28
- #
29
- # To create an instance that lexes the given keywords
30
- # case insensitively.
31
- # _default_lexer_ is used to lex a token first, the token text is then compared with
32
- # the given keywords. If it matches any of the keyword, a keyword token is generated instead
33
- # using _keyword_symbol_.
34
- # The _block_ parameter, if present, is used to convert the token text to another object
35
- # when the token is recognized during parsing phase.
36
- #
37
- def self.case_insensitive(words, default_lexer=word.token(:word), keyword_symbol=:keyword, &block)
38
- new(words, false, default_lexer, keyword_symbol, &block)
39
- end
40
- # scanner has to return a string
41
- def initialize(words, case_sensitive, default_lexer, keyword_symbol, &block)
42
- @default_lexer, @case_sensitive, @keyword_symbol = default_lexer, case_sensitive, keyword_symbol
43
- # this guarantees that we have copy of the words array and all the word strings.
44
- words = copy_words(words, case_sensitive)
45
- @name_map = {}
46
- @symbol_map = {}
47
- word_map = {}
48
- words.each do |w|
49
- symbol = "#{keyword_symbol}:#{w}".to_sym
50
- word_map[w] = symbol
51
- parser = Parsers.token(symbol, &block)
52
- @symbol_map["#{w}".to_sym] = parser
53
- @name_map[w] = parser
54
- end
55
- @lexer = make_lexer(default_lexer, word_map)
56
- end
57
- #
58
- # Get the parser that recognizes the token of the given keyword during the parsing phase.
59
- #
60
- def parser(key)
61
- result = nil
62
- if key.kind_of? String
63
- name = canonical_name(key)
64
- result = @name_map[name]
65
- else
66
- result = @symbol_map[key]
67
- end
68
- raise ArgumentError, "parser not found for #{key}" if result.nil?
69
- result
70
- end
71
- alias [] parser
72
- private
73
- def make_lexer(default_lexer, word_map)
74
- default_lexer.map do |tok|
75
- text,ind = tok.text, tok.index
76
- key = canonical_name(text)
77
- my_symbol = word_map[key]
78
- case when my_symbol.nil? : tok
79
- else Token.new(my_symbol, text, ind) end
80
- end
81
- end
82
- def canonical_name(name)
83
- case when @case_sensitive: name else name.downcase end
84
- end
85
- def copy_words(words, case_sensitive)
86
- words.map do |w|
87
- case when case_sensitive: w.dup else w.downcase end
88
- end
89
- end
1
+ require 'rparsec/parser'
2
+
3
+ #
4
+ # This class helps building lexers and parsers for keywords.
5
+ #
6
+ class Keywords
7
+ extend Parsers
8
+
9
+ private_class_method :new
10
+
11
+ attr_reader :keyword_symbol, :lexer
12
+
13
+ #
14
+ # Do we lex case sensitively?
15
+ #
16
+ def case_sensitive?
17
+ @case_sensitive
18
+ end
19
+
20
+ #
21
+ # To create an instance that lexes the given keywords
22
+ # case sensitively.
23
+ # _default_lexer_ is used to lex a token first, the token text is then compared with
24
+ # the given keywords. If it matches any of the keyword, a keyword token is generated instead
25
+ # using _keyword_symbol_.
26
+ # The _block_ parameter, if present, is used to convert the token text to another object
27
+ # when the token is recognized during grammar parsing phase.
28
+ #
29
+ def self.case_sensitive(words, default_lexer=word.token(:word), keyword_symbol=:keyword, &block)
30
+ new(words, true, default_lexer, keyword_symbol, &block)
31
+ end
32
+
33
+ #
34
+ # To create an instance that lexes the given keywords
35
+ # case insensitively.
36
+ # _default_lexer_ is used to lex a token first, the token text is then compared with
37
+ # the given keywords. If it matches any of the keyword, a keyword token is generated instead
38
+ # using _keyword_symbol_.
39
+ # The _block_ parameter, if present, is used to convert the token text to another object
40
+ # when the token is recognized during parsing phase.
41
+ #
42
+ def self.case_insensitive(words, default_lexer=word.token(:word), keyword_symbol=:keyword, &block)
43
+ new(words, false, default_lexer, keyword_symbol, &block)
44
+ end
45
+
46
+ # scanner has to return a string
47
+ def initialize(words, case_sensitive, default_lexer, keyword_symbol, &block)
48
+ @default_lexer, @case_sensitive, @keyword_symbol = default_lexer, case_sensitive, keyword_symbol
49
+ # this guarantees that we have copy of the words array and all the word strings.
50
+ words = copy_words(words, case_sensitive)
51
+ @name_map = {}
52
+ @symbol_map = {}
53
+ word_map = {}
54
+ words.each do |w|
55
+ symbol = "#{keyword_symbol}:#{w}".to_sym
56
+ word_map[w] = symbol
57
+ parser = Parsers.token(symbol, &block)
58
+ @symbol_map["#{w}".to_sym] = parser
59
+ @name_map[w] = parser
60
+ end
61
+ @lexer = make_lexer(default_lexer, word_map)
62
+ end
63
+
64
+ #
65
+ # Get the parser that recognizes the token of the given keyword during the parsing phase.
66
+ #
67
+ def parser(key)
68
+ result = nil
69
+ if key.kind_of? String
70
+ name = canonical_name(key)
71
+ result = @name_map[name]
72
+ else
73
+ result = @symbol_map[key]
74
+ end
75
+ raise ArgumentError, "parser not found for #{key}" if result.nil?
76
+ result
77
+ end
78
+
79
+ alias [] parser
80
+
81
+ private
82
+
83
+ def make_lexer(default_lexer, word_map)
84
+ default_lexer.map do |tok|
85
+ text,ind = tok.text, tok.index
86
+ key = canonical_name(text)
87
+ my_symbol = word_map[key]
88
+ case when my_symbol.nil? then tok
89
+ else Token.new(my_symbol, text, ind) end
90
+ end
91
+ end
92
+
93
+ def canonical_name(name)
94
+ case when @case_sensitive then name else name.downcase end
95
+ end
96
+
97
+ def copy_words(words, case_sensitive)
98
+ words.map do |w|
99
+ case when case_sensitive then w.dup else w.downcase end
100
+ end
101
+ end
90
102
  end
@@ -1,32 +1,36 @@
1
- require 'rparsec/misc'
2
-
3
- class CodeLocator
4
- extend DefHelper
5
- def_readable :code
6
- LF = ?\n
7
- def locate(ind)
8
- return _locateEof if ind >= code.length
9
- line, col = 1,1
10
- return line,col if ind<=0
11
- for i in (0...ind)
12
- c = code[i]
13
- if c == LF
14
- line, col = line+1, 1
15
- else
16
- col = col+1
17
- end
18
- end
19
- return line, col
20
- end
21
- def _locateEof
22
- line, col = 1, 1
23
- code.each_byte do |c|
24
- if c == LF
25
- line, col = line+1, 1
26
- else
27
- col = col+1
28
- end
29
- end
30
- return line, col
31
- end
32
- end
1
+ require 'rparsec/misc'
2
+
3
+ class CodeLocator
4
+ extend DefHelper
5
+
6
+ def_readable :code
7
+
8
+ LF = ?\n
9
+
10
+ def locate(ind)
11
+ return _locateEof if ind >= code.length
12
+ line, col = 1,1
13
+ return line,col if ind<=0
14
+ for i in (0...ind)
15
+ c = code[i]
16
+ if c == LF
17
+ line, col = line+1, 1
18
+ else
19
+ col = col+1
20
+ end
21
+ end
22
+ return line, col
23
+ end
24
+
25
+ def _locateEof
26
+ line, col = 1, 1
27
+ code.each_byte do |c|
28
+ if c == LF
29
+ line, col = line+1, 1
30
+ else
31
+ col = col+1
32
+ end
33
+ end
34
+ return line, col
35
+ end
36
+ end
@@ -1,102 +1,109 @@
1
- #
2
- # Helpers for defining ctor.
3
- #
4
- module DefHelper
5
- def def_ctor(*vars)
6
- define_method(:initialize) do |*params|
7
- vars.each_with_index do |var, i|
8
- instance_variable_set("@"+var.to_s, params[i])
9
- end
10
- end
11
- end
12
-
13
- def def_readable(*vars)
14
- attr_reader(*vars)
15
- def_ctor(*vars)
16
- end
17
-
18
- def def_mutable(*vars)
19
- attr_accessor(*vars)
20
- def_ctor(*vars)
21
- end
22
- end
23
-
24
- #
25
- # To type check method parameters.
26
- #
27
- module TypeChecker
28
- private
29
- def nth n
30
- th = case n when 0: 'st' when 1: 'nd' else 'th' end
31
- "#{n+1}#{th}"
32
- end
33
- public
34
- def check_arg_type expected, obj, mtd, n=0
35
- unless obj.kind_of? expected
36
- raise ArgumentError,
37
- "#{obj.class} assigned to #{expected} for the #{nth n} argument of #{mtd}."
38
- end
39
- end
40
- def check_arg_array_type elem_type, arg, mtd, n=0
41
- check_arg_type Array, arg, mtd, n
42
- arg.each_with_index do |x, i|
43
- unless x.kind_of? elem_type
44
- raise ArgumentError,
45
- "#{x.class} assigned to #{elem_type} for the #{nth i} element of the #{nth n} argument of #{mtd}."
46
- end
47
- end
48
- end
49
- def check_vararg_type expected, args, mtd, n = 0
50
- (n...args.length).each do |i|
51
- check_arg_type expected, args[i], mtd, i
52
- end
53
- end
54
- extend self
55
- end
56
-
57
- #
58
- # To add declarative signature support.
59
- #
60
- module Signature
61
- # Signatures = {}
62
- def def_sig sym, *types
63
- types.each_with_index do |t,i|
64
- unless t.kind_of? Class
65
- TypeChecker.check_arg_type Class, t, :def_sig, i unless t.kind_of? Array
66
- TypeChecker.check_arg_type Class, t, :def_sig, i unless t.length <= 1
67
- TypeChecker.check_arg_array_type Class, t, :def_sig, i
68
- end
69
- end
70
- # Signatures[sym] = types
71
- __intercept_method_to_check_param_types__(sym, types)
72
- end
73
- private
74
-
75
- def __intercept_method_to_check_param_types__(sym, types)
76
- mtd = instance_method(sym)
77
- helper = "_#{sym}_param_types_checked_helper".to_sym
78
- define_method(helper) do |*params|
79
- star_type, star_ind = nil, nil
80
- types.each_with_index do |t, i|
81
- t = star_type unless star_type.nil?
82
- arg = params[i]
83
- if t.kind_of? Class
84
- TypeChecker.check_arg_type t, arg, sym, i
85
- elsif t.empty?
86
- TypeChecker.check_arg_type Array, arg, sym, i
87
- else
88
- star_type, star_ind = t[0], i
89
- break
90
- end
91
- end
92
- TypeChecker.check_vararg_type star_type, params, sym, star_ind unless star_ind.nil?
93
- mtd.bind(self)
94
- end
95
- module_eval """
96
- def #{sym}(*params, &block)
97
- #{helper}(*params).call(*params, &block)
98
- end
99
- """
100
- end
101
- end
102
-
1
+ #
2
+ # Helpers for defining ctor.
3
+ #
4
+ module DefHelper
5
+ def def_ctor(*vars)
6
+ define_method(:initialize) do |*params|
7
+ vars.each_with_index do |var, i|
8
+ instance_variable_set("@"+var.to_s, params[i])
9
+ end
10
+ end
11
+ end
12
+
13
+ def def_readable(*vars)
14
+ attr_reader(*vars)
15
+ def_ctor(*vars)
16
+ end
17
+
18
+ def def_mutable(*vars)
19
+ attr_accessor(*vars)
20
+ def_ctor(*vars)
21
+ end
22
+ end
23
+
24
+ #
25
+ # To type check method parameters.
26
+ #
27
+ module TypeChecker
28
+ private
29
+
30
+ def nth n
31
+ th = case n when 0 then 'st' when 1 then 'nd' else 'th' end
32
+ "#{n+1}#{th}"
33
+ end
34
+
35
+ public
36
+
37
+ def check_arg_type expected, obj, mtd, n=0
38
+ unless obj.kind_of? expected
39
+ raise ArgumentError,
40
+ "#{obj.class} assigned to #{expected} for the #{nth n} argument of #{mtd}."
41
+ end
42
+ end
43
+
44
+ def check_arg_array_type elem_type, arg, mtd, n=0
45
+ check_arg_type Array, arg, mtd, n
46
+ arg.each_with_index do |x, i|
47
+ unless x.kind_of? elem_type
48
+ raise ArgumentError,
49
+ "#{x.class} assigned to #{elem_type} for the #{nth i} element of the #{nth n} argument of #{mtd}."
50
+ end
51
+ end
52
+ end
53
+
54
+ def check_vararg_type expected, args, mtd, n = 0
55
+ (n...args.length).each do |i|
56
+ check_arg_type expected, args[i], mtd, i
57
+ end
58
+ end
59
+
60
+ extend self
61
+ end
62
+
63
+ #
64
+ # To add declarative signature support.
65
+ #
66
+ module Signature
67
+ # Signatures = {}
68
+ def def_sig sym, *types
69
+ types.each_with_index do |t,i|
70
+ unless t.kind_of? Class
71
+ TypeChecker.check_arg_type Class, t, :def_sig, i unless t.kind_of? Array
72
+ TypeChecker.check_arg_type Class, t, :def_sig, i unless t.length <= 1
73
+ TypeChecker.check_arg_array_type Class, t, :def_sig, i
74
+ end
75
+ end
76
+ # Signatures[sym] = types
77
+ __intercept_method_to_check_param_types__(sym, types)
78
+ end
79
+
80
+ private
81
+
82
+ def __intercept_method_to_check_param_types__(sym, types)
83
+ mtd = instance_method(sym)
84
+ helper = "_#{sym}_param_types_checked_helper".to_sym
85
+ define_method(helper) do |*params|
86
+ star_type, star_ind = nil, nil
87
+ types.each_with_index do |t, i|
88
+ t = star_type unless star_type.nil?
89
+ arg = params[i]
90
+ if t.kind_of? Class
91
+ TypeChecker.check_arg_type t, arg, sym, i
92
+ elsif t.empty?
93
+ TypeChecker.check_arg_type Array, arg, sym, i
94
+ else
95
+ star_type, star_ind = t[0], i
96
+ break
97
+ end
98
+ end
99
+ TypeChecker.check_vararg_type star_type, params, sym, star_ind unless star_ind.nil?
100
+ mtd.bind(self)
101
+ end
102
+ module_eval """
103
+ def #{sym}(*params, &block)
104
+ #{helper}(*params).call(*params, &block)
105
+ end
106
+ """
107
+ end
108
+ end
109
+