emfrp 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -12
  3. data/bin/emfrp +4 -1
  4. data/examples/LCDClock/LCDClock.mfrp +93 -93
  5. data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
  6. data/examples/LCDClock/README.md +24 -24
  7. data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
  8. data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
  9. data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
  10. data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
  11. data/lib/emfrp/compile/c/alloc.rb +200 -200
  12. data/lib/emfrp/compile/c/codegen.rb +18 -18
  13. data/lib/emfrp/compile/c/codegen_context.rb +218 -218
  14. data/lib/emfrp/compile/c/monofy.rb +185 -185
  15. data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
  16. data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
  17. data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
  18. data/lib/emfrp/compile_error.rb +95 -95
  19. data/lib/emfrp/interpreter/command_manager.rb +367 -367
  20. data/lib/emfrp/interpreter/evaluater.rb +146 -146
  21. data/lib/emfrp/interpreter/file_loader.rb +52 -52
  22. data/lib/emfrp/interpreter/interpreter.rb +200 -195
  23. data/lib/emfrp/parser/expression.rb +386 -386
  24. data/lib/emfrp/parser/misc.rb +184 -184
  25. data/lib/emfrp/parser/newnode_convert.rb +72 -72
  26. data/lib/emfrp/parser/operator.rb +25 -25
  27. data/lib/emfrp/parser/parser.rb +150 -150
  28. data/lib/emfrp/parser/parsing_error.rb +49 -49
  29. data/lib/emfrp/parser/toplevel.rb +555 -555
  30. data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
  31. data/lib/emfrp/syntax.rb +171 -171
  32. data/lib/emfrp/typing/typing_error.rb +47 -47
  33. data/lib/emfrp/typing/union_type.rb +197 -197
  34. data/lib/emfrp/version.rb +1 -1
  35. data/mfrp_include/Std.mfrp +122 -122
  36. data/tests/Rakefile +8 -8
  37. data/tests/Rakefile.common +27 -27
  38. data/tests/command/Rakefile +2 -2
  39. data/tests/command/ReplaceNode.mfrp +39 -39
  40. data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
  41. data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
  42. data/tests/compiler/ComplexDataType/Rakefile +2 -2
  43. data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
  44. data/tests/compiler/ComplexDataType/in.txt +5 -5
  45. data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
  46. data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
  47. data/tests/compiler/LCDClock/Rakefile +2 -2
  48. data/tests/compiler/LCDClock/expected_out.txt +0 -0
  49. data/tests/compiler/LCDClock/in.txt +0 -0
  50. data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
  51. data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
  52. data/tests/compiler/LCDPositioner/Rakefile +2 -2
  53. data/tests/compiler/LCDPositioner/graph.dot +0 -0
  54. data/tests/compiler/LCDPositioner/graph.png +0 -0
  55. data/tests/compiler/Rakefile +8 -8
  56. data/tests/compiler/Rakefile.common +23 -23
  57. data/tests/compiler/UseData/Rakefile +2 -2
  58. data/tests/compiler/UseData/UseData.mfrp +8 -8
  59. data/tests/compiler/UseSubModule/Rakefile +2 -2
  60. data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
  61. data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
  62. data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
  63. data/tests/core/FromAnnotation.mfrp +18 -18
  64. data/tests/core/Last.mfrp +10 -10
  65. data/tests/core/Rakefile +2 -2
  66. data/tests/core/TypingTest.mfrp +11 -11
  67. data/tests/core/WithoutInputs.mfrp +19 -19
  68. data/tests/load_time_error/Rakefile +32 -32
  69. data/tests/load_time_error/TypeMismatch.mfrp +4 -4
  70. metadata +3 -3
@@ -1,150 +1,150 @@
1
- require 'parser_combinator/string_parser'
2
-
3
- require 'emfrp/syntax'
4
- require 'emfrp/parser/toplevel'
5
- require 'emfrp/parser/expression'
6
- require 'emfrp/parser/misc'
7
- require 'emfrp/parser/operator'
8
- require 'emfrp/parser/parsing_error'
9
- require 'emfrp/parser/newnode_convert'
10
-
11
- module Emfrp
12
- class Parser < ParserCombinator::StringParser
13
- def self.parse_input(path, file_loader, file_type=module_file)
14
- if file_loader.loaded?(path)
15
- return Top.new
16
- end
17
- src_str, file_name = file_loader.load(path)
18
- parse_src(src_str, file_name, file_loader, file_type)
19
- end
20
-
21
- def self.parse_src(src_str, file_name, file_loader, file_type=module_file)
22
- case res = file_type.parse_from_string(convert_case_group(src_str), file_name)
23
- when Fail
24
- raise ParsingError.new(src_str, file_name, res.status)
25
- when Ok
26
- newnode_tops = res.parsed[:newnodes].map do |newnode|
27
- NewNodeConvert.parse_module(res.parsed[:module_name][:desc], newnode, file_loader)
28
- end
29
- res.parsed[:newnodes] = []
30
- tops = res.parsed[:uses].map do |use_path|
31
- parse_input(use_path.map{|x| x[:desc]}, file_loader, material_file)
32
- end
33
- return Top.new(*tops, res.parsed, *newnode_tops)
34
- else
35
- raise "unexpected return of parser (bug)"
36
- end
37
- end
38
-
39
- def self.parse(src_str, file_name, parser)
40
- case res = parser.parse_from_string(convert_case_group(src_str), file_name)
41
- when Fail
42
- raise ParsingError.new(src_str, file_name, res.status)
43
- when Ok
44
- return res.parsed
45
- else
46
- raise "unexpected return of parser (bug)"
47
- end
48
- end
49
-
50
- def self.convert_case_group(src_str)
51
- raise ParsingError.new("TAB is not allowed to use in sources.") if src_str.chars.include?("\t")
52
- lines = src_str.each_line.to_a.map(&:chomp)
53
- len = lines.length
54
- len.times do |ln|
55
- if lines[ln].strip.chars.last == ":"
56
- width = lines[ln].chars.take_while{|c| c == "\s"}.size
57
- ((ln+1)..(len-1)).each do |ln2|
58
- width2 = lines[ln2].chars.take_while{|c| c == "\s"}.size
59
- if lines[ln2].strip == ""
60
- next
61
- elsif width2 <= width
62
- lines[ln2 - 1] << " :endcase"
63
- break
64
- elsif ln2 == len - 1
65
- lines[ln2] << " :endcase"
66
- break
67
- end
68
- end
69
- end
70
- end
71
- lines.map{|l| l + "\n"}.join
72
- end
73
-
74
- def self.from_infixes_to_parser(infixes)
75
- priority_listl = [[], [], [], [], [], [], [], [], [], []]
76
- priority_listr = [[], [], [], [], [], [], [], [], [], []]
77
- priority_listn = [[], [], [], [], [], [], [], [], [], []]
78
- defined_op = {}
79
- infixes.reverse.each do |id|
80
- if defined_op[id[:op][:desc]]
81
- next
82
- else
83
- defined_op[id[:op][:desc]] = true
84
- end
85
- if id[:priority] == nil || ("0" <= id[:priority][:desc] && id[:priority][:desc] <= "9")
86
- priority = id[:priority] == nil ? 9 : id[:priority][:desc].to_i
87
- opp = sat{|i| i.is_a?(SSymbol) && i[:desc] == id[:op][:desc]}.map(&:item)
88
- if id[:type][:desc] == "infix"
89
- priority_listn[priority] << opp
90
- elsif id[:type][:desc] == "infixl"
91
- priority_listl[priority] << opp
92
- elsif id[:type][:desc] == "infixr"
93
- priority_listr[priority] << opp
94
- else
95
- raise "invalid infix type"
96
- end
97
- else
98
- raise "invalid prirority"
99
- end
100
- end
101
- priority_list = [{:op => sat{|i| i.is_a?(SSymbol)}.map(&:item), :dir => "left"}]
102
- 10.times do |i|
103
- if priority_listl[i].length > 0
104
- priority_list << {:op => priority_listl[i].inject(&:|), :dir => "left"}
105
- end
106
- if priority_listr[i].length > 0
107
- priority_list << {:op => priority_listr[i].inject(&:|), :dir => "right"}
108
- end
109
- if priority_listn[i].length > 0
110
- priority_list << {:op => priority_listn[i].inject(&:|), :dir => "left"}
111
- end
112
- end
113
- return OpParser.make_op_parser(priority_list)
114
- end
115
-
116
- def self.infix_rearrange(top)
117
- infix_parser = from_infixes_to_parser(top[:infixes])
118
- return infix_convert(top, infix_parser)
119
- end
120
-
121
- def self.infix_convert(s, parser)
122
- case s
123
- when Syntax
124
- new_s = s.class[s.map{|k, v| [k, infix_convert(v, parser)]}]
125
- if s.is_a?(OperatorSeq)
126
- items = Items.new(new_s[:seq].map{|c| Item.new(c, nil)})
127
- res = parser.parse(items)
128
- if res.is_a?(Fail)
129
- raise "operator parsing fail!!"
130
- end
131
- res.parsed
132
- else
133
- new_s
134
- end
135
- when Array
136
- s.map{|c| infix_convert(c, parser)}
137
- else
138
- s
139
- end
140
- end
141
-
142
- def err(place, required, code=nil)
143
- self.onfail(:place => place, :required => required, :code => code)
144
- end
145
-
146
- def to_nil
147
- self.map{|x| x[0]}
148
- end
149
- end
150
- end
1
+ require 'parser_combinator/string_parser'
2
+
3
+ require 'emfrp/syntax'
4
+ require 'emfrp/parser/toplevel'
5
+ require 'emfrp/parser/expression'
6
+ require 'emfrp/parser/misc'
7
+ require 'emfrp/parser/operator'
8
+ require 'emfrp/parser/parsing_error'
9
+ require 'emfrp/parser/newnode_convert'
10
+
11
+ module Emfrp
12
+ class Parser < ParserCombinator::StringParser
13
+ def self.parse_input(path, file_loader, file_type=module_file)
14
+ if file_loader.loaded?(path)
15
+ return Top.new
16
+ end
17
+ src_str, file_name = file_loader.load(path)
18
+ parse_src(src_str, file_name, file_loader, file_type)
19
+ end
20
+
21
+ def self.parse_src(src_str, file_name, file_loader, file_type=module_file)
22
+ case res = file_type.parse_from_string(convert_case_group(src_str), file_name)
23
+ when Fail
24
+ raise ParsingError.new(src_str, file_name, res.status)
25
+ when Ok
26
+ newnode_tops = res.parsed[:newnodes].map do |newnode|
27
+ NewNodeConvert.parse_module(res.parsed[:module_name][:desc], newnode, file_loader)
28
+ end
29
+ res.parsed[:newnodes] = []
30
+ tops = res.parsed[:uses].map do |use_path|
31
+ parse_input(use_path.map{|x| x[:desc]}, file_loader, material_file)
32
+ end
33
+ return Top.new(*tops, res.parsed, *newnode_tops)
34
+ else
35
+ raise "unexpected return of parser (bug)"
36
+ end
37
+ end
38
+
39
+ def self.parse(src_str, file_name, parser)
40
+ case res = parser.parse_from_string(convert_case_group(src_str), file_name)
41
+ when Fail
42
+ raise ParsingError.new(src_str, file_name, res.status)
43
+ when Ok
44
+ return res.parsed
45
+ else
46
+ raise "unexpected return of parser (bug)"
47
+ end
48
+ end
49
+
50
+ def self.convert_case_group(src_str)
51
+ raise ParsingError.new("TAB is not allowed to use in sources.") if src_str.chars.include?("\t")
52
+ lines = src_str.each_line.to_a.map(&:chomp)
53
+ len = lines.length
54
+ len.times do |ln|
55
+ if lines[ln].strip.chars.last == ":"
56
+ width = lines[ln].chars.take_while{|c| c == "\s"}.size
57
+ ((ln+1)..(len-1)).each do |ln2|
58
+ width2 = lines[ln2].chars.take_while{|c| c == "\s"}.size
59
+ if lines[ln2].strip == ""
60
+ next
61
+ elsif width2 <= width
62
+ lines[ln2 - 1] << " :endcase"
63
+ break
64
+ elsif ln2 == len - 1
65
+ lines[ln2] << " :endcase"
66
+ break
67
+ end
68
+ end
69
+ end
70
+ end
71
+ lines.map{|l| l + "\n"}.join
72
+ end
73
+
74
+ def self.from_infixes_to_parser(infixes)
75
+ priority_listl = [[], [], [], [], [], [], [], [], [], []]
76
+ priority_listr = [[], [], [], [], [], [], [], [], [], []]
77
+ priority_listn = [[], [], [], [], [], [], [], [], [], []]
78
+ defined_op = {}
79
+ infixes.reverse.each do |id|
80
+ if defined_op[id[:op][:desc]]
81
+ next
82
+ else
83
+ defined_op[id[:op][:desc]] = true
84
+ end
85
+ if id[:priority] == nil || ("0" <= id[:priority][:desc] && id[:priority][:desc] <= "9")
86
+ priority = id[:priority] == nil ? 9 : id[:priority][:desc].to_i
87
+ opp = sat{|i| i.is_a?(SSymbol) && i[:desc] == id[:op][:desc]}.map(&:item)
88
+ if id[:type][:desc] == "infix"
89
+ priority_listn[priority] << opp
90
+ elsif id[:type][:desc] == "infixl"
91
+ priority_listl[priority] << opp
92
+ elsif id[:type][:desc] == "infixr"
93
+ priority_listr[priority] << opp
94
+ else
95
+ raise "invalid infix type"
96
+ end
97
+ else
98
+ raise "invalid prirority"
99
+ end
100
+ end
101
+ priority_list = [{:op => sat{|i| i.is_a?(SSymbol)}.map(&:item), :dir => "left"}]
102
+ 10.times do |i|
103
+ if priority_listl[i].length > 0
104
+ priority_list << {:op => priority_listl[i].inject(&:|), :dir => "left"}
105
+ end
106
+ if priority_listr[i].length > 0
107
+ priority_list << {:op => priority_listr[i].inject(&:|), :dir => "right"}
108
+ end
109
+ if priority_listn[i].length > 0
110
+ priority_list << {:op => priority_listn[i].inject(&:|), :dir => "left"}
111
+ end
112
+ end
113
+ return OpParser.make_op_parser(priority_list)
114
+ end
115
+
116
+ def self.infix_rearrange(top)
117
+ infix_parser = from_infixes_to_parser(top[:infixes])
118
+ return infix_convert(top, infix_parser)
119
+ end
120
+
121
+ def self.infix_convert(s, parser)
122
+ case s
123
+ when Syntax
124
+ new_s = s.class[s.map{|k, v| [k, infix_convert(v, parser)]}]
125
+ if s.is_a?(OperatorSeq)
126
+ items = Items.new(new_s[:seq].map{|c| Item.new(c, nil)})
127
+ res = parser.parse(items)
128
+ if res.is_a?(Fail)
129
+ raise "operator parsing fail!!"
130
+ end
131
+ res.parsed
132
+ else
133
+ new_s
134
+ end
135
+ when Array
136
+ s.map{|c| infix_convert(c, parser)}
137
+ else
138
+ s
139
+ end
140
+ end
141
+
142
+ def err(place, required, code=nil)
143
+ self.onfail(:place => place, :required => required, :code => code)
144
+ end
145
+
146
+ def to_nil
147
+ self.map{|x| x[0]}
148
+ end
149
+ end
150
+ end
@@ -1,49 +1,49 @@
1
- require 'colorize'
2
-
3
- module Emfrp
4
- class Parser
5
- class ParsingError < StandardError
6
- def initialize(src_str, file_name, status)
7
- @src_str = src_str
8
- @file_name = file_name
9
- @status = status
10
- end
11
-
12
- def code
13
- @status.message[:code] || :noname
14
- end
15
-
16
- def line_number
17
- if @status.rest.length > 0
18
- @status.rest[0].tag[:line_number]
19
- else
20
- @src_str.each_line.count
21
- end
22
- end
23
-
24
- def column_number
25
- if @status.rest.length > 0
26
- @status.rest[0].tag[:column_number]
27
- else
28
- @src_str.each_line.last.length
29
- end
30
- end
31
-
32
- def line
33
- @src_str.each_line.to_a[line_number - 1]
34
- end
35
-
36
- def print_error(output_io)
37
- output_io << "#{@file_name}:#{line_number}: "
38
- output_io << "SyntaxError, in `#{@status.message[:place]}`: "
39
- output_io << "#{@status.message[:required]} is expected"
40
- if @status.rest.length == 0
41
- output_io << ", but parser reached end-of-file\n"
42
- else
43
- output_io << "\n#{line.chomp}\n"
44
- output_io << "#{" " * (column_number - 1)}#{"^".colorize(:green)}\n"
45
- end
46
- end
47
- end
48
- end
49
- end
1
+ require 'colorize'
2
+
3
+ module Emfrp
4
+ class Parser
5
+ class ParsingError < StandardError
6
+ def initialize(src_str, file_name, status)
7
+ @src_str = src_str
8
+ @file_name = file_name
9
+ @status = status
10
+ end
11
+
12
+ def code
13
+ @status.message[:code] || :noname
14
+ end
15
+
16
+ def line_number
17
+ if @status.rest.length > 0
18
+ @status.rest[0].tag[:line_number]
19
+ else
20
+ @src_str.each_line.count
21
+ end
22
+ end
23
+
24
+ def column_number
25
+ if @status.rest.length > 0
26
+ @status.rest[0].tag[:column_number]
27
+ else
28
+ @src_str.each_line.last.length
29
+ end
30
+ end
31
+
32
+ def line
33
+ @src_str.each_line.to_a[line_number - 1]
34
+ end
35
+
36
+ def print_error(output_io)
37
+ output_io << "#{@file_name}:#{line_number}: "
38
+ output_io << "SyntaxError, in `#{@status.message[:place]}`: "
39
+ output_io << "#{@status.message[:required]} is expected"
40
+ if @status.rest.length == 0
41
+ output_io << ", but parser reached end-of-file\n"
42
+ else
43
+ output_io << "\n#{line.chomp}\n"
44
+ output_io << "#{" " * (column_number - 1)}#{"^".colorize(:green)}\n"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end