selfml 0.0.1
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.
- data/.gitignore +7 -0
- data/README.markdown +20 -0
- data/lib/selfml/ast.rb +69 -0
- data/lib/selfml/parser.rb +54 -0
- data/lib/selfml/transformer.rb +49 -0
- data/lib/selfml.rb +21 -0
- data/spec/fixtures/basic.selfml +2 -0
- data/spec/fixtures/comments.selfml +12 -0
- data/spec/fixtures/output.basic.selfml +6 -0
- data/spec/fixtures/output.comments.selfml +11 -0
- data/spec/fixtures/output.strings.selfml +13 -0
- data/spec/fixtures/strings.selfml +10 -0
- data/spec/spec_helper.rb +9 -0
- data/testing.rb +44 -0
- metadata +141 -0
data/.gitignore
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
# Install
|
4
|
+
|
5
|
+
Comming really soon:
|
6
|
+
|
7
|
+
gem install self-ml
|
8
|
+
|
9
|
+
# Documentation
|
10
|
+
|
11
|
+
# How to Contribute
|
12
|
+
|
13
|
+
1. fork
|
14
|
+
2. code
|
15
|
+
3. pull request
|
16
|
+
|
17
|
+
# Credits
|
18
|
+
|
19
|
+
* devyn - helpful support
|
20
|
+
* alexgordon - clearing up self-ml grammar
|
data/lib/selfml/ast.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module SelfML::AST
|
2
|
+
|
3
|
+
class Document < Array
|
4
|
+
|
5
|
+
def to_s
|
6
|
+
a = self.map(&:serialize).reject {|n| n.nil? }
|
7
|
+
a.join("\n\n") + "\n"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
class Node
|
13
|
+
attr_accessor :head , :tail
|
14
|
+
|
15
|
+
def initialize( head , tail = [] )
|
16
|
+
@head , @tail = head , tail
|
17
|
+
end
|
18
|
+
|
19
|
+
def serialize level=1
|
20
|
+
tail = @tail.sort.map do |t|
|
21
|
+
case t
|
22
|
+
when Node
|
23
|
+
"\n" + " "*level*4 + "#{t.serialize level+1}"
|
24
|
+
when StringNode
|
25
|
+
" #{t.serialize}"
|
26
|
+
else
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
"(#{head.serialize}#{tail})"
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :to_s :serialize
|
35
|
+
|
36
|
+
def <=> rhs
|
37
|
+
case rhs when Node then 0
|
38
|
+
when StringNode then 1
|
39
|
+
else -1 end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class StringNode < String
|
45
|
+
|
46
|
+
def serialize
|
47
|
+
return "`#{self.gsub("`","``")}`" if self.count("[") != self.count("]")
|
48
|
+
return "[#{self}]" if self.match(/[#`()\[\]{} ]/)
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
alias :to_s :serialize
|
54
|
+
|
55
|
+
def <=> rhs
|
56
|
+
case rhs when StringNode then 0
|
57
|
+
when Node then -1
|
58
|
+
else 1 end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class Comment < String
|
64
|
+
def serialize; nil; end
|
65
|
+
|
66
|
+
alias :to_s :serialize
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
class Parslet::Parser
|
4
|
+
rule(:space) { match('\s').repeat(1) }
|
5
|
+
rule(:space?) { space.maybe }
|
6
|
+
|
7
|
+
rule(:word) { match('\w').repeat }
|
8
|
+
rule(:word?) { word.maybe }
|
9
|
+
end # monkey patching in a couple of helpers
|
10
|
+
|
11
|
+
class SelfML::Parser < Parslet::Parser
|
12
|
+
root(:top)
|
13
|
+
rule(:top) do
|
14
|
+
(space? >> node >> space?).repeat.as(:document)
|
15
|
+
end
|
16
|
+
|
17
|
+
rule(:node) { comment.as(:comment) | list.as(:list) | string.as(:string) }
|
18
|
+
|
19
|
+
# String
|
20
|
+
rule(:string) { backtick.as(:backticks) | bracketed.as(:brackets) | verbatim.as(:verbatim) }
|
21
|
+
rule(:backtick) do
|
22
|
+
str('`') >> (
|
23
|
+
str('``').as(:ticks) | match('``|[^`]').as(:text)
|
24
|
+
).repeat >> str('`')
|
25
|
+
end
|
26
|
+
rule(:bracketed) do
|
27
|
+
str('[') >> (
|
28
|
+
bracketed.as(:nested) | match('[^\]]').as(:text)
|
29
|
+
).repeat >> str(']')
|
30
|
+
end
|
31
|
+
rule(:verbatim) { str("#").absnt? >> match['^\[\](){}\s'].repeat(1) }
|
32
|
+
|
33
|
+
# List
|
34
|
+
rule(:tail) do
|
35
|
+
(node >> space?).repeat
|
36
|
+
end
|
37
|
+
rule(:list) do
|
38
|
+
str('(') >> space? >>
|
39
|
+
comment.as(:comment).maybe >> space? >>
|
40
|
+
string.as(:head) >> space? >>
|
41
|
+
tail.as(:tail) >> space? >>
|
42
|
+
space? >> str(')')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Comment
|
46
|
+
rule(:comment) { line.as(:line) | block.as(:block) }
|
47
|
+
rule(:line) { str('#') >> match['^\\n'].repeat.as(:text) >> (str("\n") | any.absnt?) }
|
48
|
+
rule(:block) do
|
49
|
+
str('{#') >> (
|
50
|
+
block.as(:block) | match['^#}'].as(:text)
|
51
|
+
).repeat >> str('#}')
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module SelfML
|
4
|
+
|
5
|
+
class HashTransformer < Parslet::Transform
|
6
|
+
rule(:document => sequence(:d)) { Array(d) }
|
7
|
+
rule(:list => subtree(:l)) do
|
8
|
+
head = String(l[:head]).to_sym
|
9
|
+
tail = Array(l[:tail])
|
10
|
+
|
11
|
+
{ head => tail }
|
12
|
+
end
|
13
|
+
|
14
|
+
rule(:string => simple(:s)) { String(s) }
|
15
|
+
rule(:verbatim => simple(:s)) { String(s) }
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class Transformer < Parslet::Transform
|
20
|
+
include AST
|
21
|
+
|
22
|
+
rule(:document => sequence(:doc)) { Document.new(doc) }
|
23
|
+
rule(:list => subtree(:l)) do
|
24
|
+
Node.new(
|
25
|
+
StringNode.new(l[:head]) , Array(l[:tail])
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Comments
|
30
|
+
rule(:comment => simple(:s) ) { Comment.new(s) }
|
31
|
+
rule(:block => simple(:blk) ) { Comment.new(blk) }
|
32
|
+
rule(:block => sequence(:blk)) { Comment.new(blk.reduce :+) }
|
33
|
+
rule(:line => simple(:ln) ) { Comment.new(ln) }
|
34
|
+
|
35
|
+
# Strings
|
36
|
+
rule(:string => simple(:s)) { StringNode.new(s) }
|
37
|
+
rule(:verbatim => simple(:s)) { StringNode.new(s) }
|
38
|
+
|
39
|
+
rule(:backticks => sequence(:s)) { StringNode.new("#{s}") }
|
40
|
+
rule(:ticks => simple(:s)) { "`" }
|
41
|
+
|
42
|
+
rule(:brackets => sequence(:b)) { StringNode.new("#{b}") }
|
43
|
+
rule(:nested => simple(:n)) { StringNode.new(n) }
|
44
|
+
rule(:nested => sequence(:n)) { StringNode.new("[#{n}]") }
|
45
|
+
|
46
|
+
rule(:text => simple(:t)) { StringNode.new(t) }
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/selfml.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'require_relative'
|
2
|
+
|
3
|
+
require_relative 'selfml/version'
|
4
|
+
|
5
|
+
['parser','ast','transformer'].each do |file|
|
6
|
+
require_relative "selfml/#{file}"
|
7
|
+
end
|
8
|
+
|
9
|
+
module SelfML
|
10
|
+
|
11
|
+
def self.parse(s, engine=nil)
|
12
|
+
transformer = engine.new if engine.instance_of? Class
|
13
|
+
|
14
|
+
parser = Parser.new
|
15
|
+
transformer ||= Transformer.new
|
16
|
+
|
17
|
+
tree = parser.parse(s)
|
18
|
+
out = transformer.apply(tree)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This is a line comment at the start of the document
|
2
|
+
|
3
|
+
({# This is a block comment with {# a nested block comment#}#}abc)
|
4
|
+
|
5
|
+
(# This is a line comment just after a bracket
|
6
|
+
def)
|
7
|
+
|
8
|
+
(foo{# bar #}bar)
|
9
|
+
|
10
|
+
(ghi){#{##}#}(jkl)
|
11
|
+
|
12
|
+
(mno)# This is a line comment at the end of the document
|
@@ -0,0 +1,13 @@
|
|
1
|
+
[This document tests all kinds of strings]
|
2
|
+
|
3
|
+
[back ` ticks]
|
4
|
+
|
5
|
+
verbatim-strings
|
6
|
+
|
7
|
+
[Strings with # signs in them]
|
8
|
+
|
9
|
+
[Strings with [nested brackets] in them]
|
10
|
+
|
11
|
+
[Strings with all # kinds ` of [shit] (like) {this} {# Should #} still work]
|
12
|
+
|
13
|
+
`As should [strings with back `` (ticks) {like} this`
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[This document tests all kinds of strings]
|
2
|
+
|
3
|
+
`back `` ticks`
|
4
|
+
|
5
|
+
verbatim-strings
|
6
|
+
|
7
|
+
[Strings with # signs in them]
|
8
|
+
[Strings with [nested brackets] in them]
|
9
|
+
[Strings with all # kinds ` of [shit] (like) {this} {# Should #} still work]
|
10
|
+
`As should [strings with back `` (ticks) {like} this`
|
data/spec/spec_helper.rb
ADDED
data/testing.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'require_relative'
|
4
|
+
require 'awesome_print'
|
5
|
+
require 'differ'
|
6
|
+
|
7
|
+
require_relative 'lib/selfml.rb'
|
8
|
+
|
9
|
+
### Testing Facilities
|
10
|
+
def load_tests(name)
|
11
|
+
[
|
12
|
+
File.read("spec/fixtures/#{name}.selfml") ,
|
13
|
+
File.read("spec/fixtures/output.#{name}.selfml")
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
t = <<-HERE
|
18
|
+
([don jon]
|
19
|
+
(music
|
20
|
+
iPod
|
21
|
+
(life)
|
22
|
+
iTunes)
|
23
|
+
(computers
|
24
|
+
iMac
|
25
|
+
[Mac mini])
|
26
|
+
(phones
|
27
|
+
iPhone)
|
28
|
+
(dishwashers))
|
29
|
+
HERE
|
30
|
+
|
31
|
+
|
32
|
+
basic_in , basic_out = load_tests("basic")
|
33
|
+
comments_in , comments_out = load_tests("comments")
|
34
|
+
strings_in , strings_out = load_tests("strings")
|
35
|
+
|
36
|
+
puts SelfML.parse(t).to_s
|
37
|
+
puts "---"
|
38
|
+
a = SelfML.parse(basic_in ).to_s
|
39
|
+
b = SelfML.parse(strings_in ).to_s
|
40
|
+
c = SelfML.parse(comments_in).to_s
|
41
|
+
|
42
|
+
puts a
|
43
|
+
puts "=="
|
44
|
+
puts basic_out
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: selfml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ricardo Mendes
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-05-07 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: parslet
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :development
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: require_relative
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :development
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: minitest
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :development
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: parslet
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id004
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: require_relative
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :runtime
|
79
|
+
version_requirements: *id005
|
80
|
+
description: Self-ML is, as the name implies, a self-ml parser. It also has some utilities to aid in building self-ml files.
|
81
|
+
email:
|
82
|
+
- rokusu@gmail.com
|
83
|
+
executables: []
|
84
|
+
|
85
|
+
extensions: []
|
86
|
+
|
87
|
+
extra_rdoc_files: []
|
88
|
+
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- README.markdown
|
92
|
+
- lib/selfml.rb
|
93
|
+
- lib/selfml/ast.rb
|
94
|
+
- lib/selfml/parser.rb
|
95
|
+
- lib/selfml/transformer.rb
|
96
|
+
- spec/fixtures/basic.selfml
|
97
|
+
- spec/fixtures/comments.selfml
|
98
|
+
- spec/fixtures/output.basic.selfml
|
99
|
+
- spec/fixtures/output.comments.selfml
|
100
|
+
- spec/fixtures/output.strings.selfml
|
101
|
+
- spec/fixtures/strings.selfml
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
- testing.rb
|
104
|
+
has_rdoc: true
|
105
|
+
homepage: ""
|
106
|
+
licenses: []
|
107
|
+
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
segments:
|
118
|
+
- 0
|
119
|
+
version: "0"
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
segments:
|
125
|
+
- 0
|
126
|
+
version: "0"
|
127
|
+
requirements: []
|
128
|
+
|
129
|
+
rubyforge_project: self-ml
|
130
|
+
rubygems_version: 1.3.6
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: self-ml parser
|
134
|
+
test_files:
|
135
|
+
- spec/fixtures/basic.selfml
|
136
|
+
- spec/fixtures/comments.selfml
|
137
|
+
- spec/fixtures/output.basic.selfml
|
138
|
+
- spec/fixtures/output.comments.selfml
|
139
|
+
- spec/fixtures/output.strings.selfml
|
140
|
+
- spec/fixtures/strings.selfml
|
141
|
+
- spec/spec_helper.rb
|