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