fancy 0.3.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.
Files changed (242) hide show
  1. data/AUTHORS +7 -0
  2. data/LICENSE +19 -0
  3. data/README +173 -0
  4. data/Rakefile +255 -0
  5. data/bin/fancy +40 -0
  6. data/bin/fdoc +23 -0
  7. data/bin/fyi +22 -0
  8. data/bin/ifancy +46 -0
  9. data/boot/README +12 -0
  10. data/boot/code_loader.rb +165 -0
  11. data/boot/compile.fy +3 -0
  12. data/boot/fancy_ext.rb +13 -0
  13. data/boot/fancy_ext/block_env.rb +29 -0
  14. data/boot/fancy_ext/class.rb +26 -0
  15. data/boot/fancy_ext/kernel.rb +12 -0
  16. data/boot/fancy_ext/module.rb +89 -0
  17. data/boot/fancy_ext/object.rb +34 -0
  18. data/boot/fancy_ext/string_helper.rb +10 -0
  19. data/boot/load.rb +72 -0
  20. data/boot/rbx-compiler/README +12 -0
  21. data/boot/rbx-compiler/compiler.rb +24 -0
  22. data/boot/rbx-compiler/compiler/ast.rb +23 -0
  23. data/boot/rbx-compiler/compiler/ast/README +11 -0
  24. data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
  25. data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
  26. data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
  27. data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
  28. data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
  29. data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
  30. data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
  31. data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
  32. data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
  33. data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
  34. data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
  35. data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
  36. data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
  37. data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
  38. data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
  39. data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
  40. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
  41. data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
  42. data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
  43. data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
  44. data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
  45. data/boot/rbx-compiler/compiler/command.rb +39 -0
  46. data/boot/rbx-compiler/compiler/compiler.rb +83 -0
  47. data/boot/rbx-compiler/compiler/stages.rb +99 -0
  48. data/boot/rbx-compiler/parser.rb +2 -0
  49. data/boot/rbx-compiler/parser/README +15 -0
  50. data/boot/rbx-compiler/parser/Rakefile +54 -0
  51. data/boot/rbx-compiler/parser/extconf.rb +3 -0
  52. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  53. data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
  54. data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
  55. data/boot/rbx-compiler/parser/lexer.lex +180 -0
  56. data/boot/rbx-compiler/parser/parser.rb +356 -0
  57. data/boot/rbx-compiler/parser/parser.y +711 -0
  58. data/boot/rsexp_pretty_printer.rb +76 -0
  59. data/doc/api/fancy.css +93 -0
  60. data/doc/api/fancy.jsonp +1 -0
  61. data/doc/api/fdoc.js +187 -0
  62. data/doc/api/index.html +57 -0
  63. data/doc/api/underscore-min.js +18 -0
  64. data/doc/features.md +228 -0
  65. data/examples/argv.fy +8 -0
  66. data/examples/arithmetic.fy +7 -0
  67. data/examples/armstrong_numbers.fy +33 -0
  68. data/examples/array.fy +52 -0
  69. data/examples/blocks.fy +15 -0
  70. data/examples/boolean.fy +24 -0
  71. data/examples/call_with_receiver.fy +9 -0
  72. data/examples/class.fy +68 -0
  73. data/examples/closures.fy +24 -0
  74. data/examples/constant_access.fy +15 -0
  75. data/examples/default_args.fy +17 -0
  76. data/examples/define_methods.fy +15 -0
  77. data/examples/documentation.fy +57 -0
  78. data/examples/documentation_formatters.fy +25 -0
  79. data/examples/echo.fy +16 -0
  80. data/examples/empty_catch.fy +4 -0
  81. data/examples/exception.fy +9 -0
  82. data/examples/factorial.fy +12 -0
  83. data/examples/fibonacci.fy +16 -0
  84. data/examples/files.fy +23 -0
  85. data/examples/finally.fy +5 -0
  86. data/examples/game_of_life.fy +148 -0
  87. data/examples/hashes.fy +7 -0
  88. data/examples/hello_world.fy +6 -0
  89. data/examples/html_generator.fy +54 -0
  90. data/examples/implicit_return.fy +3 -0
  91. data/examples/matchers.fy +6 -0
  92. data/examples/methods.fy +29 -0
  93. data/examples/nested_classes.fy +27 -0
  94. data/examples/nested_try.fy +9 -0
  95. data/examples/numbers.fy +12 -0
  96. data/examples/pattern_matching.fy +40 -0
  97. data/examples/person.fy +65 -0
  98. data/examples/project-euler/01.fy +8 -0
  99. data/examples/project-euler/02.fy +21 -0
  100. data/examples/project-euler/28.fy +33 -0
  101. data/examples/rbx/and_or.fy +7 -0
  102. data/examples/rbx/blocks.fy +22 -0
  103. data/examples/rbx/classes.fy +32 -0
  104. data/examples/rbx/hello.fy +8 -0
  105. data/examples/rbx/include.fy +12 -0
  106. data/examples/rbx/inherit.fy +11 -0
  107. data/examples/rbx/methods.fy +15 -0
  108. data/examples/rbx/nested_classes.fy +9 -0
  109. data/examples/rbx/require.fy +3 -0
  110. data/examples/rbx/strings.fy +5 -0
  111. data/examples/regex.fy +7 -0
  112. data/examples/require.fy +7 -0
  113. data/examples/retry.fy +12 -0
  114. data/examples/return.fy +13 -0
  115. data/examples/ruby_require.fy +7 -0
  116. data/examples/ruby_send.fy +3 -0
  117. data/examples/singleton_methods.fy +21 -0
  118. data/examples/stupid_quicksort.fy +12 -0
  119. data/examples/threads.fy +18 -0
  120. data/examples/tuple.fy +8 -0
  121. data/examples/webserver/webserver.fy +18 -0
  122. data/lib/argv.fy +36 -0
  123. data/lib/array.fy +207 -0
  124. data/lib/block.fy +88 -0
  125. data/lib/boot.fy +41 -0
  126. data/lib/class.fy +106 -0
  127. data/lib/compiler.fy +14 -0
  128. data/lib/compiler/ast.fy +40 -0
  129. data/lib/compiler/ast/assign.fy +96 -0
  130. data/lib/compiler/ast/block.fy +84 -0
  131. data/lib/compiler/ast/class_def.fy +33 -0
  132. data/lib/compiler/ast/expression_list.fy +47 -0
  133. data/lib/compiler/ast/identifier.fy +113 -0
  134. data/lib/compiler/ast/literals.fy +122 -0
  135. data/lib/compiler/ast/match.fy +88 -0
  136. data/lib/compiler/ast/message_send.fy +110 -0
  137. data/lib/compiler/ast/method_def.fy +90 -0
  138. data/lib/compiler/ast/node.fy +7 -0
  139. data/lib/compiler/ast/range.fy +16 -0
  140. data/lib/compiler/ast/require.fy +15 -0
  141. data/lib/compiler/ast/return.fy +23 -0
  142. data/lib/compiler/ast/script.fy +52 -0
  143. data/lib/compiler/ast/singleton_method_def.fy +35 -0
  144. data/lib/compiler/ast/super.fy +17 -0
  145. data/lib/compiler/ast/try_catch.fy +176 -0
  146. data/lib/compiler/ast/tuple_literal.fy +34 -0
  147. data/lib/compiler/command.fy +51 -0
  148. data/lib/compiler/compiler.fy +73 -0
  149. data/lib/compiler/stages.fy +81 -0
  150. data/lib/directory.fy +17 -0
  151. data/lib/documentation.fy +115 -0
  152. data/lib/enumerable.fy +269 -0
  153. data/lib/eval.fy +31 -0
  154. data/lib/fancy_spec.fy +202 -0
  155. data/lib/fdoc.fy +359 -0
  156. data/lib/fdoc_hook.fy +10 -0
  157. data/lib/file.fy +54 -0
  158. data/lib/hash.fy +56 -0
  159. data/lib/main.fy +80 -0
  160. data/lib/method.fy +22 -0
  161. data/lib/nil_class.fy +56 -0
  162. data/lib/number.fy +87 -0
  163. data/lib/object.fy +170 -0
  164. data/lib/package.fy +61 -0
  165. data/lib/package/dependency.fy +24 -0
  166. data/lib/package/installer.fy +180 -0
  167. data/lib/package/specification.fy +55 -0
  168. data/lib/package/uninstaller.fy +15 -0
  169. data/lib/parser.fy +4 -0
  170. data/lib/parser/ext/README +15 -0
  171. data/lib/parser/ext/ext.c +42 -0
  172. data/lib/parser/ext/ext.h +8 -0
  173. data/lib/parser/ext/extconf.rb +3 -0
  174. data/lib/parser/ext/lexer.lex +187 -0
  175. data/lib/parser/ext/parser.y +744 -0
  176. data/lib/parser/methods.fy +297 -0
  177. data/lib/rbx.fy +37 -0
  178. data/lib/rbx/array.fy +237 -0
  179. data/lib/rbx/bignum.fy +23 -0
  180. data/lib/rbx/block.fy +9 -0
  181. data/lib/rbx/class.fy +129 -0
  182. data/lib/rbx/code_loader.fy +192 -0
  183. data/lib/rbx/console.fy +63 -0
  184. data/lib/rbx/directory.fy +46 -0
  185. data/lib/rbx/documentation.fy +64 -0
  186. data/lib/rbx/environment_variables.fy +3 -0
  187. data/lib/rbx/exception.fy +30 -0
  188. data/lib/rbx/false_class.fy +58 -0
  189. data/lib/rbx/fiber.fy +25 -0
  190. data/lib/rbx/file.fy +191 -0
  191. data/lib/rbx/fixnum.fy +25 -0
  192. data/lib/rbx/float.fy +14 -0
  193. data/lib/rbx/hash.fy +38 -0
  194. data/lib/rbx/integer.fy +15 -0
  195. data/lib/rbx/io.fy +30 -0
  196. data/lib/rbx/match_data.fy +9 -0
  197. data/lib/rbx/method.fy +22 -0
  198. data/lib/rbx/name_error.fy +3 -0
  199. data/lib/rbx/no_method_error.fy +15 -0
  200. data/lib/rbx/object.fy +117 -0
  201. data/lib/rbx/range.fy +15 -0
  202. data/lib/rbx/regexp.fy +9 -0
  203. data/lib/rbx/string.fy +63 -0
  204. data/lib/rbx/symbol.fy +12 -0
  205. data/lib/rbx/system.fy +37 -0
  206. data/lib/rbx/tcp_server.fy +6 -0
  207. data/lib/rbx/tcp_socket.fy +7 -0
  208. data/lib/rbx/thread.fy +75 -0
  209. data/lib/rbx/tuple.fy +37 -0
  210. data/lib/set.fy +61 -0
  211. data/lib/stack.fy +51 -0
  212. data/lib/string.fy +58 -0
  213. data/lib/struct.fy +13 -0
  214. data/lib/symbol.fy +23 -0
  215. data/lib/true_class.fy +43 -0
  216. data/lib/tuple.fy +68 -0
  217. data/lib/version.fy +6 -0
  218. data/tests/argv.fy +13 -0
  219. data/tests/array.fy +343 -0
  220. data/tests/assignment.fy +53 -0
  221. data/tests/block.fy +103 -0
  222. data/tests/class.fy +409 -0
  223. data/tests/control_flow.fy +79 -0
  224. data/tests/documentation.fy +24 -0
  225. data/tests/exception.fy +115 -0
  226. data/tests/file.fy +86 -0
  227. data/tests/hash.fy +101 -0
  228. data/tests/method.fy +131 -0
  229. data/tests/nil_class.fy +55 -0
  230. data/tests/number.fy +128 -0
  231. data/tests/object.fy +125 -0
  232. data/tests/parsing/sexp.fy +50 -0
  233. data/tests/pattern_matching.fy +82 -0
  234. data/tests/range.fy +11 -0
  235. data/tests/set.fy +10 -0
  236. data/tests/stack.fy +22 -0
  237. data/tests/string.fy +102 -0
  238. data/tests/symbol.fy +17 -0
  239. data/tests/true_class.fy +63 -0
  240. data/tests/tuple.fy +21 -0
  241. data/tools/fancy-mode.el +63 -0
  242. metadata +321 -0
data/lib/package.fy ADDED
@@ -0,0 +1,61 @@
1
+ require: "package/installer"
2
+ require: "package/uninstaller"
3
+ require: "package/dependency"
4
+ require: "package/specification"
5
+
6
+ class Fancy Package {
7
+ """
8
+
9
+ The Fancy Package System.
10
+
11
+ This class is used for installing and uninstalling fancy packages on
12
+ the system.
13
+
14
+ Example:
15
+ $ fancy install bakkdoor/mongo.fy
16
+
17
+ Will install the mongo.fy package from http://github.com/bakkdoor/mongo.fy
18
+ in the latest released version or get the current HEAD (master
19
+ branch) revision.
20
+
21
+ You can then load the package in your source file via
22
+ require: \"mongo.fy\"
23
+
24
+ """
25
+
26
+ ENV_PACKAGE_DIR_VAR = "FANCY_PACKAGE_DIR"
27
+
28
+ def self install: package_name {
29
+ """
30
+ Installs a package with a given name.
31
+ Expects package_name to be a string in the form of:
32
+ user/repo
33
+ Which would get the package code from github.com/user/repo
34
+ """
35
+
36
+ Installer new: package_name . run
37
+ }
38
+
39
+ def self uninstall: package_name {
40
+ Uninstaller new: package_name . run
41
+ }
42
+
43
+ def self package_root_dir {
44
+ if: (ENV[ENV_PACKAGE_DIR_VAR]) then: |path| {
45
+ return path
46
+ } else: {
47
+ return Fancy Package Installer DEFAULT_PACKAGES_PATH
48
+ }
49
+ }
50
+
51
+ def self add_to_loadpath {
52
+ """
53
+ Adds the Fancy Package install dir to the loadpath so you can
54
+ easily @require: packages into your code.
55
+ """
56
+
57
+ root = Fancy Package package_root_dir
58
+ Fancy CodeLoader push_loadpath: root
59
+ Fancy CodeLoader push_loadpath: (root ++ "/lib")
60
+ }
61
+ }
@@ -0,0 +1,24 @@
1
+ class Fancy Package {
2
+ class Dependency {
3
+ """
4
+ Package Dependency.
5
+ Represents a Dependency to another Package with a given version.
6
+ """
7
+
8
+ read_slots: ['name, 'version]
9
+
10
+ def initialize: @name version: @version ('latest) {
11
+ }
12
+ }
13
+
14
+ class RubyDependency {
15
+ """
16
+ Same as @Fancy::Package::Dependency@, just for rubygem packages.
17
+ """
18
+
19
+ read_slots: ['gem_name, 'version]
20
+
21
+ def initialize: @gem_name version: @version ('latest) {
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,180 @@
1
+ require("yaml")
2
+ require("open-uri")
3
+
4
+ class Fancy Package {
5
+ class Installer {
6
+ """
7
+
8
+ @Fancy::Package@ installer.
9
+
10
+ Downloads packages from Github (usually the latest tagged version,
11
+ if no version is specified, or the latest HEAD revision in the
12
+ master branch) and install it to the @FANCY_PACKAGE_DIR.
13
+
14
+ """
15
+
16
+ DEFAULT_FANCY_ROOT = ENV["HOME"] ++ "/.fancy"
17
+ DEFAULT_PACKAGES_PATH = DEFAULT_FANCY_ROOT ++ "/packages"
18
+ DEFAULT_PACKAGES_LIB_PATH = DEFAULT_PACKAGES_PATH ++ "/lib"
19
+
20
+ def initialize: @package_name version: @version ("latest") install_path: @install_path (ENV["FANCY_PACKAGE_DIR"]) {
21
+ """
22
+ Creates a new @Package Installer@ for a given package name, an
23
+ optional version (default is 'latest') and an optional
24
+ installation path (default is the standard installation path for
25
+ Fancy packages).
26
+ """
27
+
28
+ splitted = @package_name split: "/"
29
+ @user = splitted first
30
+ @repository = splitted second
31
+
32
+ @install_path if_nil: {
33
+ @install_path = DEFAULT_PACKAGES_PATH
34
+ Directory create!: DEFAULT_FANCY_ROOT
35
+ Directory create!: DEFAULT_PACKAGES_PATH
36
+ Directory create!: DEFAULT_PACKAGES_LIB_PATH
37
+ Directory create!: $ DEFAULT_PACKAGES_PATH ++ "/downloads"
38
+ }
39
+
40
+ @download_path = @install_path ++ "/downloads"
41
+ }
42
+
43
+ def run {
44
+ """
45
+ Runs the installer & installs the package into
46
+ @$FANCY_PACKAGE_DIR.
47
+ """
48
+
49
+ filename = nil
50
+ if: (@version == "latest") then: {
51
+ if: (self latest_tag) then: |tag| {
52
+ @version = tag
53
+ } else: {
54
+ @version = "master"
55
+ }
56
+ filename = self download_tgz: @version
57
+ }
58
+
59
+ # now unpack & check for dependencies
60
+ unpack_dir = unpack_file: filename
61
+ rename_dir: unpack_dir
62
+ self load_fancypack
63
+ }
64
+
65
+ def latest_tag {
66
+ "Returns the latest tag (sorted alphabetically)."
67
+
68
+ tags = self tags
69
+ if: (tags size > 0) then: {
70
+ tags keys sort last
71
+ }
72
+ }
73
+
74
+ def tags {
75
+ "Returns a list of tags the repository has on Github."
76
+
77
+ url = "http://github.com/api/v2/yaml/repos/show/" ++ @package_name ++ "/tags/"
78
+ YAML load_stream(open(url)) documents() first at: "tags"
79
+ }
80
+
81
+ def download_url: version {
82
+ """
83
+ Returns the download url for a given version of the package
84
+ to be installed.
85
+ """
86
+
87
+ "https://github.com/" ++ @package_name ++ "/tarball/" ++ version
88
+ }
89
+
90
+ def download_tgz: version {
91
+ """
92
+ Downloads the .tar.gz file from Github with the given version
93
+ (tag or branch name) and saves it to the specified @install_path.
94
+
95
+
96
+ The Default install_path is ~/.fancy/packages/.
97
+ If an environment variable @FANCY_PACKAGE_DIR is defined, it
98
+ will get used.
99
+ """
100
+
101
+ download_url = download_url: version
102
+ ["Downloading ", @package_name, " version ", version, " from: ", download_url] join println
103
+
104
+ filename = [@user, "_", @repository, "-", version, ".tar.gz"] join
105
+
106
+ # run curl to get the .tar.gz file
107
+ cmd = ["curl -o ", @download_path, "/", filename, " -L -O ", download_url] join
108
+ System do: cmd
109
+
110
+ filename
111
+ }
112
+
113
+ def unpack_file: filename {
114
+ "Unpacking " ++ filename println
115
+ System do: $ ["tar xf ", @download_path, "/", filename, " -C ", @install_path, "/"] join
116
+ output = System pipe: $ ["tar tf ", @download_path, "/", filename] join
117
+ dirname = output readlines first chomp
118
+ }
119
+
120
+ def installed_path {
121
+ @install_path + "/" + @user + "_" + @repository + "-" + @version
122
+ }
123
+
124
+ def lib_path {
125
+ @install_path + "/lib"
126
+ }
127
+
128
+ def rename_dir: dirname {
129
+ """
130
+ Renames a given directory to a common way within the install path.
131
+ => It will rename the given dirname to $user/$repo-$version.
132
+ """
133
+
134
+ System do: $ ["mv ", @install_path, "/", dirname, " ", self installed_path] join
135
+ }
136
+
137
+ def load_fancypack {
138
+ """
139
+ Loads the @.fancypack file within the downloaded package directory.
140
+ If no @.fancypack file is found, raise an error.
141
+ """
142
+
143
+ Dir glob(self installed_path ++ "/*.fancypack") first if_do: |fpackfile| {
144
+ require: fpackfile
145
+ }
146
+
147
+ if: (Specification[@repository]) then: |spec| {
148
+ fulfill_spec: spec
149
+ } else: {
150
+ "Something wen't wrong. Did not find a fancypack specification for package: " ++ @repository . raise!
151
+ }
152
+ }
153
+
154
+ def fulfill_spec: spec {
155
+ unless: (spec include_files empty?) do: {
156
+ File open: (self lib_path + "/" + (spec package_name)) modes: ['write] with: |f| {
157
+ spec include_files each: |if| {
158
+ f write: "require: \""
159
+ f write: (self installed_path)
160
+ f write: "/"
161
+ f write: if
162
+ f writeln: "\""
163
+ }
164
+ }
165
+ }
166
+
167
+ spec dependencies each: |dep| {
168
+ Package install: dep
169
+ }
170
+
171
+ spec rubygem_dependencies each: |dep| {
172
+ if: (dep version == 'latest) then: {
173
+ System do: $ "rbx gem install " ++ (dep gem_name)
174
+ } else: {
175
+ System do: $ "rbx gem install -v=" ++ (dep version) ++ " " ++ (dep gem_name)
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
@@ -0,0 +1,55 @@
1
+ class Fancy Package {
2
+ class Specification {
3
+ @@specs = <[]>
4
+
5
+ read_write_slots: ['author, 'email, 'include_files, 'bin_files,
6
+ 'description, 'homepage, 'version]
7
+
8
+ read_slots: ['package_name, 'dependencies, 'rubygem_dependencies]
9
+
10
+ def initialize: @package_name with: block {
11
+ @dependencies = []
12
+ @rubygem_dependencies = []
13
+ @include_files = []
14
+ @bin_files = []
15
+
16
+ block call_with_receiver: self
17
+
18
+ @@specs at: @package_name put: self
19
+ }
20
+
21
+ def dependencies: dependencies {
22
+ dependencies each: |d| {
23
+ name = d first
24
+ version = d second
25
+ { version = 'latest } unless: version
26
+ dep = Dependency new: name version: version
27
+ @dependencies << dep
28
+ }
29
+ }
30
+
31
+ def ruby_dependencies: dependencies {
32
+ dependencies each: |d| {
33
+ gem_name = d first
34
+ version = d second
35
+ { version = 'latest } unless: version
36
+ dep = RubyDependency new: gem_name version: version
37
+ @rubygem_dependencies << dep
38
+ }
39
+ }
40
+
41
+ def add_dependency: name version: version ('latest) {
42
+ dep = Dependency new: name version: version
43
+ @dependencies << dep
44
+ }
45
+
46
+ def add_ruby_dependency: gem_name version: version ('latest) {
47
+ dep = RubyDependency new: gem_name version: version
48
+ @rubygem_dependencies << dep
49
+ }
50
+
51
+ def self [] package_name {
52
+ @@specs[package_name]
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,15 @@
1
+ class Fancy Package {
2
+ class Uninstaller {
3
+ """
4
+
5
+ @Fancy Package@ Uninstaller.
6
+
7
+ """
8
+
9
+ def initialize: @package_name {
10
+ }
11
+
12
+ def run {
13
+ }
14
+ }
15
+ }
data/lib/parser.fy ADDED
@@ -0,0 +1,4 @@
1
+
2
+ require: "parser/methods"
3
+ require(File.expand_path("parser/ext/fancy_parser", File.dirname(__FILE__)))
4
+
@@ -0,0 +1,15 @@
1
+ This directory contains all the code that deals with parsing Fancy
2
+ source files (.fy) and creating an object-oriented representation (a
3
+ so-called AST - Abstract Syntax Tree) from it to be used in the
4
+ compiler for further processing (mostly to .fyc bytecode files).
5
+
6
+ The parser.y file contains the grammar rules in GNU Bison (YACC
7
+ compatible) syntax, which make up the parser. The parser actions are
8
+ written in C and call out to Ruby methods defined in parser.rb via
9
+ rbx's C-extension interface to build the actual AST objects.
10
+
11
+ The lexer.y contains the lexer rules in GNU Flex syntax for scanning a
12
+ source file for tokens.
13
+
14
+ The parser.rb file contains all the methods used by the parser to
15
+ create AST objects.
@@ -0,0 +1,42 @@
1
+ #include "ext.h"
2
+ #include "ruby.h"
3
+ #include "lexer.h"
4
+
5
+ static VALUE
6
+ fancy_parse_string(VALUE self, VALUE code) {
7
+ VALUE filename = rb_funcall(self, rb_intern(":filename"), 0);
8
+ VALUE lineno = rb_funcall(self, rb_intern(":line"), 0);
9
+ char *str = StringValueCStr(code);
10
+ YY_BUFFER_STATE buffstate = yy_scan_string(str);
11
+ yy_switch_to_buffer(buffstate);
12
+ yylineno = NUM2INT(lineno);
13
+ yyparse(self);
14
+ yy_delete_buffer(buffstate);
15
+ return self;
16
+ }
17
+
18
+ static VALUE
19
+ fancy_parse_file(VALUE self) {
20
+ VALUE filename = rb_funcall(self, rb_intern(":filename"), 0);
21
+ VALUE lineno = rb_funcall(self, rb_intern(":line"), 0);
22
+ char *str = StringValueCStr(filename);
23
+ FILE *f = fopen(str, "r");
24
+ if(!f) {
25
+ rb_funcall(self, rb_intern("ast:file_error:"), 2, INT2NUM(0), rb_str_new2("Could not open file"));
26
+ return Qnil;
27
+ }
28
+ YY_BUFFER_STATE buffstate = yy_create_buffer(f, YY_BUF_SIZE);
29
+ yy_switch_to_buffer(buffstate);
30
+ yylineno = NUM2INT(lineno);
31
+ yyparse(self);
32
+ yy_delete_buffer(buffstate);
33
+ return self;
34
+ }
35
+
36
+ void
37
+ Init_fancy_parser() {
38
+ VALUE fancy = rb_const_get(rb_cObject, rb_intern("Fancy"));
39
+ VALUE parser = rb_const_get(fancy, rb_intern("Parser"));
40
+ rb_define_method(parser, "parse_string:", fancy_parse_string, 1);
41
+ rb_define_method(parser, ":parse_file", fancy_parse_file, 0);
42
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef _FANCY_PARSER_EXT_H_
2
+ #define _FANCY_PARSER_EXT_H_
3
+
4
+ /* Size of default input buffer. */
5
+ #define YY_BUF_SIZE 16384
6
+
7
+
8
+ #endif /* _FANCY_PARSER_EXT_H_ */
@@ -0,0 +1,3 @@
1
+ require('mkmf')
2
+ have_library("fl")
3
+ create_makefile('fancy_parser')
@@ -0,0 +1,187 @@
1
+ %{
2
+ #include "ruby.h"
3
+ #include "parser.h"
4
+
5
+ int yyerror(char *s);
6
+ %}
7
+
8
+ %option yylineno
9
+
10
+ digit [0-9]
11
+ octdigit [0-7]
12
+ hexdigit [0-9a-fA-F]
13
+ bindigit [01]
14
+ capital [A-Z]
15
+ lower [a-z]
16
+ letter [A-Za-z]
17
+ special [-+?!=*/^><%&~]
18
+ special_under ({special}|"_")
19
+ operator ({special}+|"||"{special_under}*)
20
+ int_lit [-+]?{digit}({digit}|_{digit})*
21
+ double_lit {int_lit}\.{digit}+
22
+ hex_lit 0[xX]{hexdigit}+
23
+ bin_lit 0[bB]{bindigit}+
24
+ oct_lit 0[oO]{octdigit}+
25
+ string_lit L?\"(\\.|[^\\"])*\"
26
+ multiline_string L?\"\"\"(\\.|[^\\"])*\"\"\"
27
+ lparen \(
28
+ rparen \)
29
+ at_lcurly "@{"
30
+ lcurly "{"
31
+ rcurly "}"
32
+ lbracket "["
33
+ rbracket "]"
34
+ lhash "<["
35
+ rhash "]>"
36
+ stab "|"
37
+ arrow "=>"
38
+ thin_arrow "->"
39
+ delimiter [ \n\r\t\(\)]
40
+ return_local "return_local"
41
+ return "return"
42
+ require "require:"
43
+ try "try"
44
+ catch "catch"
45
+ finally "finally"
46
+ retry "retry"
47
+ super "super"
48
+ private "private"
49
+ protected "protected"
50
+ self "self"
51
+ match "match"
52
+ case "case"
53
+ identifier @?@?({lower}|[_&*])({letter}|{digit}|{special_under})*
54
+ selector ({letter}|[_&*])({letter}|{digit}|{special_under})*":"
55
+ constant {capital}({letter}|{digit}|{special_under})*
56
+ nested_constant ({constant}::)+{constant}
57
+ symbol_lit \'({identifier}|{operator}|:|"[]")+
58
+ ruby_send_open {identifier}{lparen}
59
+ ruby_oper_open {operator}{lparen}
60
+ regexp_lit "/".*"/"
61
+ comma ,
62
+
63
+ semi ;
64
+ equals =
65
+ colon :
66
+ class "class"
67
+ def "def"
68
+ dot "."
69
+ dollar "$"
70
+ comment #[^\n]*
71
+ escaped_newline "\\".*\n
72
+
73
+ %%
74
+
75
+ {class} { return CLASS; }
76
+ {def} { return DEF; }
77
+ {hex_lit} {
78
+ yylval.object = rb_str_new2(yytext);
79
+ return HEX_LITERAL;
80
+ }
81
+ {oct_lit} {
82
+ yylval.object = rb_str_new2(yytext);
83
+ return OCT_LITERAL;
84
+ }
85
+ {bin_lit} {
86
+ yylval.object = rb_str_new2(yytext);
87
+ return BIN_LITERAL;
88
+ }
89
+ {int_lit} {
90
+ yylval.object = rb_str_new2(yytext);
91
+ return INTEGER_LITERAL;
92
+ }
93
+ {double_lit} {
94
+ yylval.object = rb_str_new2(yytext);
95
+ return DOUBLE_LITERAL;
96
+ }
97
+ {string_lit} {
98
+ yylval.object = rb_str_new2(yytext);
99
+ return STRING_LITERAL;
100
+ }
101
+ {multiline_string} {
102
+ yylval.object = rb_str_new2(yytext);
103
+ return MULTI_STRING_LITERAL;
104
+ }
105
+ {lparen} { return LPAREN; }
106
+ {rparen} { return RPAREN; }
107
+ {at_lcurly} { return AT_LCURLY; }
108
+ {lcurly} { return LCURLY; }
109
+ {rcurly} { return RCURLY; }
110
+ {lbracket} { return LBRACKET; }
111
+ {rbracket} { return RBRACKET; }
112
+ {lhash} { return LHASH; }
113
+ {rhash} { return RHASH; }
114
+ {stab} { return STAB; }
115
+ {arrow} { return ARROW; }
116
+ {thin_arrow} { return THIN_ARROW; }
117
+ {equals} { return EQUALS; }
118
+ {operator} {
119
+ yylval.object = rb_str_new2(yytext);
120
+ return OPERATOR;
121
+ }
122
+ {return_local} { return RETURN_LOCAL; }
123
+ {return} { return RETURN; }
124
+ {require} { return REQUIRE; }
125
+ {try} { return TRY; }
126
+ {catch} { return CATCH; }
127
+ {finally} { return FINALLY; }
128
+ {retry} { return RETRY; }
129
+ {super} { return SUPER; }
130
+ {private} { return PRIVATE; }
131
+ {protected} { return PROTECTED; }
132
+ {self} {
133
+ yylval.object = rb_str_new2(yytext);
134
+ return IDENTIFIER;
135
+ }
136
+ {match} {
137
+ return MATCH;
138
+ }
139
+ {case} {
140
+ return CASE;
141
+ }
142
+ {identifier} {
143
+ yylval.object = rb_str_new2(yytext);
144
+ return IDENTIFIER;
145
+ }
146
+ {selector} {
147
+ yylval.object = rb_str_new2(yytext);
148
+ return SELECTOR;
149
+ }
150
+ {ruby_send_open} {
151
+ yylval.object = rb_str_new2(yytext);
152
+ return RUBY_SEND_OPEN;
153
+ }
154
+ {ruby_oper_open} {
155
+ yylval.object = rb_str_new2(yytext);
156
+ return RUBY_OPER_OPEN;
157
+ }
158
+ {constant} {
159
+ yylval.object = rb_str_new2(yytext);
160
+ return CONSTANT;
161
+ }
162
+ {nested_constant} {
163
+ yylval.object = rb_str_new2(yytext);
164
+ return CONSTANT;
165
+ }
166
+ {symbol_lit} {
167
+ yylval.object = rb_str_new2(yytext);
168
+ return SYMBOL_LITERAL;
169
+ }
170
+ {regexp_lit} {
171
+ yylval.object = rb_str_new2(yytext);
172
+ return REGEX_LITERAL;
173
+ }
174
+ {comma} { return COMMA; }
175
+ {semi} { return SEMI; }
176
+ {colon} { return COLON; }
177
+ {dot} { return DOT; }
178
+ {dollar} { return DOLLAR; }
179
+
180
+ {comment} {}
181
+
182
+ [ \t]* {}
183
+ {escaped_newline} {}
184
+ [\n] { return NL; }
185
+
186
+ . { fprintf(stderr, "SCANNER %d", yyerror("")); exit(1); }
187
+