rparsec 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+