kpeg 0.9.0 → 1.2.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.
- checksums.yaml +7 -0
- data/.hoeignore +12 -0
- data/Gemfile +2 -11
- data/History.txt +22 -1
- data/Manifest.txt +10 -3
- data/README.rdoc +40 -8
- data/Rakefile +12 -3
- data/bin/kpeg +9 -2
- data/examples/lua_string/lua_string.kpeg.rb +0 -2
- data/examples/tiny_markdown/Rakefile +3 -0
- data/examples/tiny_markdown/driver.rb +10 -0
- data/examples/tiny_markdown/node.rb +107 -0
- data/examples/tiny_markdown/sample.md +51 -0
- data/examples/tiny_markdown/tiny_markdown.kpeg +199 -0
- data/examples/tiny_markdown/tiny_markdown.kpeg.rb +3892 -0
- data/kpeg.gemspec +20 -20
- data/lib/hoe/kpeg.rb +6 -5
- data/lib/kpeg/code_generator.rb +81 -45
- data/lib/kpeg/compiled_parser.rb +32 -28
- data/lib/kpeg/format_parser.kpeg +22 -10
- data/lib/kpeg/format_parser.rb +94 -73
- data/lib/kpeg/grammar.rb +2 -2
- data/lib/kpeg/grammar_renderer.rb +14 -0
- data/lib/kpeg/position.rb +25 -8
- data/lib/kpeg/string_escape.kpeg +1 -0
- data/lib/kpeg/string_escape.rb +399 -13
- data/lib/kpeg.rb +1 -1
- data/test/test_kpeg.rb +1 -1
- data/test/test_kpeg_code_generator.rb +186 -14
- data/test/test_kpeg_compiled_parser.rb +1 -1
- data/test/test_kpeg_format.rb +25 -6
- data/test/{test_file_parser_roundtrip.rb → test_kpeg_format_parser_round_trip.rb} +1 -1
- data/test/{test_gen_calc.rb → test_kpeg_grammar.rb} +48 -5
- data/test/test_kpeg_grammar_renderer.rb +47 -6
- data/test/test_kpeg_string_escape.rb +42 -0
- metadata +90 -101
- data/.gemtest +0 -0
- data/test/test_left_recursion.rb +0 -50
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8addf56b471f186a44651884101f4159a94927b8c27d5c5eaed867388797fb49
|
4
|
+
data.tar.gz: cb1c89881fc980f4fd1bedd485a6f4cc0ac2e8aa9df8ffeb9690b9839be6b8be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7207c6d8774c8eec993b962306df6fd529ae7910b279e98dda4f4d2000c4c2dd5183ca5d1ee28ba377fa4664d4b5c417c283fd539cf1b8c80db3ff9f6d66be1b
|
7
|
+
data.tar.gz: c6980f3355fb4a64cb49ae29ab050e09039074aea8720fab12000e6ce7716749276f4d4cf3a5831982e263de7b3c25c22f5850d4edc4fb06e5468be75943e41c
|
data/.hoeignore
ADDED
data/Gemfile
CHANGED
@@ -1,12 +1,3 @@
|
|
1
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
source :gemcutter
|
6
|
-
|
7
|
-
|
8
|
-
gem "minitest", "~>2.11", :group => [:development, :test]
|
9
|
-
gem "rdoc", "~>3.10", :group => [:development, :test]
|
10
|
-
gem "hoe", "~>2.15", :group => [:development, :test]
|
11
|
-
|
12
|
-
# vim: syntax=ruby
|
3
|
+
gemspec
|
data/History.txt
CHANGED
@@ -1,4 +1,25 @@
|
|
1
|
-
=== 1.0 /
|
1
|
+
=== 1.2.0 / 2021-10-20
|
2
|
+
|
3
|
+
* Speed up current_line
|
4
|
+
|
5
|
+
|
6
|
+
=== (entries lost to time)
|
7
|
+
|
8
|
+
=== 0.10 / 2012-04-16
|
9
|
+
|
10
|
+
* Minor enhancements
|
11
|
+
* In standalone parsers generation of a default initialize method may be
|
12
|
+
disabled with the custom_initialize variable:
|
13
|
+
|
14
|
+
%% custom_initialize = true
|
15
|
+
* Added a pre-class directive for adding class comments
|
16
|
+
* Generated code is now surrounded by startdoc/stopdoc.
|
17
|
+
|
18
|
+
* Bug fixes
|
19
|
+
* Hoe plugin now overwrites generated files
|
20
|
+
* Directives and variables now round-trip through KPeg::GrammarRenderer
|
21
|
+
|
22
|
+
=== 0.9 / 2012-04-06
|
2
23
|
|
3
24
|
* Minor enhancements
|
4
25
|
* Added arbitrary directives to the kpeg grammar
|
data/Manifest.txt
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
.autotest
|
2
|
+
.hoeignore
|
2
3
|
Gemfile
|
3
4
|
History.txt
|
4
5
|
LICENSE
|
@@ -17,6 +18,12 @@ examples/lua_string/lua_string.kpeg.rb
|
|
17
18
|
examples/phone_number/README.md
|
18
19
|
examples/phone_number/phone_number.kpeg
|
19
20
|
examples/phone_number/phone_number.rb
|
21
|
+
examples/tiny_markdown/Rakefile
|
22
|
+
examples/tiny_markdown/driver.rb
|
23
|
+
examples/tiny_markdown/node.rb
|
24
|
+
examples/tiny_markdown/sample.md
|
25
|
+
examples/tiny_markdown/tiny_markdown.kpeg
|
26
|
+
examples/tiny_markdown/tiny_markdown.kpeg.rb
|
20
27
|
examples/upper/README.md
|
21
28
|
examples/upper/upper.kpeg
|
22
29
|
examples/upper/upper.rb
|
@@ -35,13 +42,13 @@ lib/kpeg/position.rb
|
|
35
42
|
lib/kpeg/string_escape.kpeg
|
36
43
|
lib/kpeg/string_escape.rb
|
37
44
|
test/inputs/comments.kpeg
|
38
|
-
test/test_file_parser_roundtrip.rb
|
39
|
-
test/test_gen_calc.rb
|
40
45
|
test/test_kpeg.rb
|
41
46
|
test/test_kpeg_code_generator.rb
|
42
47
|
test/test_kpeg_compiled_parser.rb
|
43
48
|
test/test_kpeg_format.rb
|
49
|
+
test/test_kpeg_format_parser_round_trip.rb
|
50
|
+
test/test_kpeg_grammar.rb
|
44
51
|
test/test_kpeg_grammar_renderer.rb
|
45
|
-
test/
|
52
|
+
test/test_kpeg_string_escape.rb
|
46
53
|
vim/syntax_kpeg/ftdetect/kpeg.vim
|
47
54
|
vim/syntax_kpeg/syntax/kpeg.vim
|
data/README.rdoc
CHANGED
@@ -143,13 +143,13 @@ Once you have the generated parser, include that file into your new grammar
|
|
143
143
|
Then create a variable to hold to foreign interface and pass it the class name
|
144
144
|
of your parser. In this case my parser class name is Literal
|
145
145
|
|
146
|
-
%
|
146
|
+
%foreign_grammar = Literal
|
147
147
|
|
148
148
|
You can then use rules defined in the foreign grammar in the local grammar
|
149
149
|
file like so
|
150
150
|
|
151
|
-
sentence = (%
|
152
|
-
%
|
151
|
+
sentence = (%foreign_grammar.alpha %foreign_grammar.space*)+
|
152
|
+
%foreign_grammar.period
|
153
153
|
|
154
154
|
=== Comments
|
155
155
|
|
@@ -157,6 +157,38 @@ Kpeg allows comments to be added to the grammar file by using the # symbol
|
|
157
157
|
|
158
158
|
# This is a comment in my grammar
|
159
159
|
|
160
|
+
=== Variables
|
161
|
+
|
162
|
+
A variable looks like this:
|
163
|
+
|
164
|
+
%% name = value
|
165
|
+
|
166
|
+
Kpeg allows the following variables that control the output parser:
|
167
|
+
|
168
|
+
name::
|
169
|
+
The class name of the generated parser.
|
170
|
+
custom_initialize::
|
171
|
+
When built as a standalone parser a default initialize method will not be
|
172
|
+
included.
|
173
|
+
|
174
|
+
=== Directives
|
175
|
+
|
176
|
+
A directive looks like this:
|
177
|
+
|
178
|
+
%% header {
|
179
|
+
...
|
180
|
+
}
|
181
|
+
|
182
|
+
Kpeg allows the following directives:
|
183
|
+
|
184
|
+
header::
|
185
|
+
Placed before any generated code
|
186
|
+
pre-class::
|
187
|
+
Placed before the class definition to provide a class comment
|
188
|
+
footer::
|
189
|
+
Placed after the end of the class (for requiring files dependent upon the
|
190
|
+
parser's namespace
|
191
|
+
|
160
192
|
== Generating and running your parser
|
161
193
|
|
162
194
|
Before you can generate your parser you will need to define a root rule. This
|
@@ -208,15 +240,15 @@ For a good example of usage check out Talon[https://github.com/evanphx/talon]
|
|
208
240
|
There are several examples available in the /examples directory. The upper
|
209
241
|
parser has a readme with a step by step description of the grammar.
|
210
242
|
|
211
|
-
== Projects
|
243
|
+
== Projects
|
212
244
|
|
213
|
-
Dang[https://github.com/veganstraightedge/dang]
|
245
|
+
{Dang}[https://github.com/veganstraightedge/dang]
|
214
246
|
|
215
247
|
{Email Address Validator}[https://github.com/larb/email_address_validator]
|
216
248
|
|
217
|
-
Callisto[https://github.com/dwaite/Callisto]
|
249
|
+
{Callisto}[https://github.com/dwaite/Callisto]
|
218
250
|
|
219
|
-
Doodle[https://github.com/vito/doodle]
|
251
|
+
{Doodle}[https://github.com/vito/doodle]
|
220
252
|
|
221
|
-
Kanbanpad[https://kanbanpad.com] (uses kpeg for parsing of the 'enter
|
253
|
+
{Kanbanpad}[https://kanbanpad.com] (uses kpeg for parsing of the 'enter
|
222
254
|
something' bar)
|
data/Rakefile
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
5
|
|
6
|
-
Hoe.plugin :bundler
|
7
6
|
Hoe.plugin :gemspec
|
8
7
|
Hoe.plugin :git
|
9
8
|
Hoe.plugin :minitest
|
@@ -12,6 +11,8 @@ Hoe.plugin :travis
|
|
12
11
|
Hoe.spec 'kpeg' do
|
13
12
|
self.readme_file = "README.rdoc"
|
14
13
|
developer 'Evan Phoenix', 'evan@fallingsnow.net'
|
14
|
+
|
15
|
+
dependency 'minitest', '~> 5.0', :dev
|
15
16
|
end
|
16
17
|
|
17
18
|
task :test => :parser
|
@@ -29,10 +30,18 @@ rule ".rb" => ".kpeg" do |t|
|
|
29
30
|
ruby "-Ilib bin/kpeg -s -o #{t.name} -f #{t.source}"
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
-
task :parser => %w[
|
33
|
+
PARSER_FILES = %w[
|
34
34
|
lib/kpeg/string_escape.rb
|
35
35
|
lib/kpeg/format_parser.rb
|
36
36
|
]
|
37
37
|
|
38
|
+
PARSER_FILES.map do |parser_file|
|
39
|
+
file parser_file => 'lib/kpeg/compiled_parser.rb'
|
40
|
+
file parser_file => 'lib/kpeg/code_generator.rb'
|
41
|
+
file parser_file => 'lib/kpeg/position.rb'
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "build the parser"
|
45
|
+
task :parser => PARSER_FILES
|
46
|
+
|
38
47
|
# vim: syntax=ruby
|
data/bin/kpeg
CHANGED
@@ -8,7 +8,7 @@ require 'kpeg/grammar_renderer'
|
|
8
8
|
require 'optparse'
|
9
9
|
|
10
10
|
options = {}
|
11
|
-
OptionParser.new do |o|
|
11
|
+
optparser = OptionParser.new do |o|
|
12
12
|
o.banner = "Usage: kpeg [options]"
|
13
13
|
|
14
14
|
o.on("-t", "--test", "Syntax check the file only") do |v|
|
@@ -42,7 +42,14 @@ OptionParser.new do |o|
|
|
42
42
|
o.on("-d", "--debug", "Debug parsing the file") do |v|
|
43
43
|
options[:debug] = v
|
44
44
|
end
|
45
|
-
end
|
45
|
+
end
|
46
|
+
|
47
|
+
optparser.parse!
|
48
|
+
|
49
|
+
if ARGV.empty?
|
50
|
+
puts optparser.help
|
51
|
+
exit 1
|
52
|
+
end
|
46
53
|
|
47
54
|
file = ARGV.shift
|
48
55
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module TinyMarkdown
|
2
|
+
class Node
|
3
|
+
def to_html
|
4
|
+
if !self.respond_to?(:content)
|
5
|
+
return ""
|
6
|
+
end
|
7
|
+
if self.content.kind_of?(Array)
|
8
|
+
self.content.map(&:to_html).join("")
|
9
|
+
elsif self.content.kind_of?(TinyMarkdown::Node)
|
10
|
+
self.content.to_html
|
11
|
+
elsif self.content
|
12
|
+
self.content.to_s
|
13
|
+
else
|
14
|
+
""
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
if self.respond_to?(:content)
|
20
|
+
'#<'+self.class.to_s+' content="'+self.content.to_s+'">'
|
21
|
+
else
|
22
|
+
'#<'+self.class.to_s+'>'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class HeadlineNode
|
28
|
+
def to_html
|
29
|
+
children = self.content.map(&:to_html).join("")
|
30
|
+
"<h#{level}>#{children}</h#{level}>\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TextNode
|
35
|
+
def to_html
|
36
|
+
self.content.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class BlockQuoteNode
|
41
|
+
def to_html
|
42
|
+
children = self.content.map(&:to_html).join("")
|
43
|
+
"<blockquote>#{children}</blockquote>\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class BulletListNode
|
48
|
+
def to_html
|
49
|
+
children = self.content.map(&:to_html).join("")
|
50
|
+
"<ul>\n#{children}</ul>\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class BulletListItemNode
|
55
|
+
def to_html
|
56
|
+
children = self.content.map(&:to_html).join("")
|
57
|
+
"<li>#{children}</li>\n"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class PlainNode
|
62
|
+
def to_html
|
63
|
+
self.content.map(&:to_html).join("")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class ParaNode
|
68
|
+
def to_html
|
69
|
+
children = self.content.map(&:to_html).join("")
|
70
|
+
"<p>#{children}</p>\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class VerbatimNode
|
75
|
+
def to_html
|
76
|
+
children = self.content.map(&:to_html).join("")
|
77
|
+
"<pre><code>#{children}</code></pre>\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class InlineElementNode
|
82
|
+
def to_html
|
83
|
+
children = self.content.map(&:to_html).join("")
|
84
|
+
"<#{self.name}>#{children}</#{self.name}>"
|
85
|
+
end
|
86
|
+
|
87
|
+
def inspect
|
88
|
+
'#<'+self.class.to_s+' name="'+self.name.to_s+'" content="'+self.content.to_s+'">'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class LineBreakNode
|
93
|
+
def to_html
|
94
|
+
"<br />\n"
|
95
|
+
end
|
96
|
+
|
97
|
+
def inspect
|
98
|
+
"\\n"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class HorizontalRuleNode
|
103
|
+
def to_html
|
104
|
+
"<hr />\n"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# test
|
2
|
+
|
3
|
+
## inline
|
4
|
+
|
5
|
+
### strong1
|
6
|
+
|
7
|
+
aaa **bbb** cc *dd*
|
8
|
+
|
9
|
+
### strong2
|
10
|
+
|
11
|
+
ee _fff_ gg __hhh__
|
12
|
+
|
13
|
+
### code
|
14
|
+
|
15
|
+
iii `jjjjj` kk `lll`
|
16
|
+
|
17
|
+
## block
|
18
|
+
|
19
|
+
### bullet
|
20
|
+
|
21
|
+
* mmm
|
22
|
+
* nnnnn
|
23
|
+
* ooo
|
24
|
+
|
25
|
+
### quote
|
26
|
+
|
27
|
+
> pppp
|
28
|
+
> qqqq
|
29
|
+
> rrrr
|
30
|
+
>
|
31
|
+
> inlines are ignored **sss** ttt __uuu__
|
32
|
+
|
33
|
+
### verbatim
|
34
|
+
|
35
|
+
before verbatim.
|
36
|
+
|
37
|
+
yyyy
|
38
|
+
zzzz
|
39
|
+
1111
|
40
|
+
|
41
|
+
this is verbatim
|
42
|
+
2222
|
43
|
+
this is verbatim
|
44
|
+
|
45
|
+
after verbatim.
|
46
|
+
|
47
|
+
### Horizontal Rule
|
48
|
+
|
49
|
+
|
50
|
+
- - - - -
|
51
|
+
|
@@ -0,0 +1,199 @@
|
|
1
|
+
%% name = TinyMarkdown::Parser
|
2
|
+
%% ast-location = ::TinyMarkdown
|
3
|
+
%% document = ast DocumentNode(compiler, position, content)
|
4
|
+
%% para = ast ParaNode(compiler, position, content)
|
5
|
+
%% plain = ast PlainNode(compiler, position, content)
|
6
|
+
%% text = ast TextNode(compiler, position, content)
|
7
|
+
%% headline = ast HeadlineNode(compiler, position, level, content)
|
8
|
+
%% block_quote = ast BlockQuoteNode(compiler, position, content)
|
9
|
+
%% verbatim = ast VerbatimNode(compiler, position, content)
|
10
|
+
%% horizontal_rule = ast HorizontalRuleNode(compiler, position)
|
11
|
+
%% bullet_list = ast BulletListNode(compiler, position, content)
|
12
|
+
%% list = ast ListNode(compiler, position, content)
|
13
|
+
%% bullet_list_item = ast BulletListItemNode(compiler, position, content)
|
14
|
+
%% linebreak = ast LineBreakNode(compiler, position)
|
15
|
+
%% inline_element = ast InlineElementNode(compiler, position, name, content)
|
16
|
+
|
17
|
+
%% {
|
18
|
+
attr_reader :ast
|
19
|
+
|
20
|
+
class Position
|
21
|
+
attr_accessor :pos, :line, :col
|
22
|
+
def initialize(compiler)
|
23
|
+
@pos = compiler.pos
|
24
|
+
@line = compiler.current_line
|
25
|
+
@col = compiler.current_column
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def position
|
30
|
+
Position.new(self)
|
31
|
+
end
|
32
|
+
}
|
33
|
+
|
34
|
+
root = Start
|
35
|
+
|
36
|
+
Start = &. Doc:c { @ast = c }
|
37
|
+
|
38
|
+
Doc = Block*:c
|
39
|
+
~document(self, position, c)
|
40
|
+
|
41
|
+
Block = BlankLine*
|
42
|
+
( BlockQuote
|
43
|
+
| Verbatim
|
44
|
+
| HorizontalRule
|
45
|
+
| Heading
|
46
|
+
| BulletList
|
47
|
+
| Para
|
48
|
+
| Plain )
|
49
|
+
|
50
|
+
Para = NonindentSpace Inlines:a BlankLine+ ~para(self, position, a)
|
51
|
+
|
52
|
+
Plain = Inlines:a ~plain(self, position, a)
|
53
|
+
|
54
|
+
AtxInline = !Newline !(Sp '#'* Sp Newline) Inline:c { c }
|
55
|
+
|
56
|
+
AtxStart = < /######|#####|####|###|##|#/ > { text.length }
|
57
|
+
|
58
|
+
AtxHeading = AtxStart:level Sp AtxInline+:c (Sp "#"* Sp)? Newline ~headline(self, position, level, c)
|
59
|
+
|
60
|
+
Heading = AtxHeading
|
61
|
+
|
62
|
+
BlockQuote = BlockQuoteRaw:c ~block_quote(self, position, c)
|
63
|
+
|
64
|
+
BlockQuoteRaw = ( '>' ' '? Line:c { c })+:cc { cc }
|
65
|
+
|
66
|
+
NonblankIndentedLine = !BlankLine IndentedLine:c { c }
|
67
|
+
|
68
|
+
VerbatimChunk = (BlankLine { text(self,position,"\n") } )*:c1
|
69
|
+
(NonblankIndentedLine:c { [c, text(self,position,"\n")] })+:c2 { c1 + c2.flatten }
|
70
|
+
|
71
|
+
Verbatim = VerbatimChunk+:cc ~verbatim(self, position, cc.flatten)
|
72
|
+
|
73
|
+
HorizontalRule = NonindentSpace
|
74
|
+
( '*' Sp '*' Sp '*' (Sp '*')*
|
75
|
+
| '-' Sp '-' Sp '-' (Sp '-')*
|
76
|
+
| '_' Sp '_' Sp '_' (Sp '_')*)
|
77
|
+
Sp Newline BlankLine+ ~horizontal_rule(self, position)
|
78
|
+
|
79
|
+
Bullet = !HorizontalRule NonindentSpace ('+' | '*' | '-') Spacechar+
|
80
|
+
|
81
|
+
BulletList = &Bullet ListTight:c ~bullet_list(self, position, c)
|
82
|
+
|
83
|
+
ListTight = ListItemTight+:cc
|
84
|
+
BlankLine* !Bullet
|
85
|
+
{ cc }
|
86
|
+
|
87
|
+
ListItemTight = Bullet ListBlock:c ~bullet_list_item(self, position, c)
|
88
|
+
|
89
|
+
ListBlock = !BlankLine Line:c ListBlockLine*:cc { cc.unshift(c) }
|
90
|
+
|
91
|
+
ListBlockLine = !BlankLine
|
92
|
+
!( Indent? Bullet )
|
93
|
+
!HorizontalRule
|
94
|
+
OptionallyIndentedLine
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
Inlines = ( !Endline Inline:c { c }
|
99
|
+
| Endline:c &Inline { c } )+:cc Endline?
|
100
|
+
{ cc }
|
101
|
+
|
102
|
+
Inline = Str
|
103
|
+
| Endline
|
104
|
+
| Space
|
105
|
+
| Strong
|
106
|
+
| Emph
|
107
|
+
| Code
|
108
|
+
| Symbol
|
109
|
+
|
110
|
+
Space = Spacechar+:c ~text(self, position, c.join(""))
|
111
|
+
|
112
|
+
Str = NormalChar+:c1
|
113
|
+
StrChunk*:c2
|
114
|
+
~text(self, position, (c1+c2).join(""))
|
115
|
+
|
116
|
+
StrChunk = (NormalChar:c { [c] } | '_'+:c1 NormalChar:c2 { c1.push(c2) } )+:cc { cc.flatten }
|
117
|
+
|
118
|
+
|
119
|
+
Endline = LineBreak | TerminalEndline | NormalEndline
|
120
|
+
|
121
|
+
NormalEndline = Sp Newline !BlankLine !'>' !AtxStart
|
122
|
+
!(Line ('='+ | '-'+) Newline)
|
123
|
+
~text(self, position, "\n")
|
124
|
+
|
125
|
+
TerminalEndline = Sp Newline Eof ~text(self, position, "\n")
|
126
|
+
|
127
|
+
LineBreak = " " NormalEndline ~linebreak(self, position)
|
128
|
+
|
129
|
+
Symbol = SpecialChar:c ~text(self, position, c)
|
130
|
+
|
131
|
+
|
132
|
+
Emph = EmphStar | EmphUl
|
133
|
+
|
134
|
+
Whitespace = Spacechar | Newline
|
135
|
+
|
136
|
+
EmphStar = '*' !Whitespace
|
137
|
+
( !'*' Inline:b { b }
|
138
|
+
| StrongStar:b { b }
|
139
|
+
)+:c
|
140
|
+
'*'
|
141
|
+
~inline_element(self, position, :em, c)
|
142
|
+
|
143
|
+
EmphUl = '_' !Whitespace
|
144
|
+
( !'_' Inline:b { b }
|
145
|
+
| StrongUl:b { b }
|
146
|
+
)+:c
|
147
|
+
'_'
|
148
|
+
~inline_element(self, position, :em, c)
|
149
|
+
|
150
|
+
Strong = StrongStar | StrongUl
|
151
|
+
|
152
|
+
StrongStar = "**" !Whitespace
|
153
|
+
( !"**" Inline:b { b })+:c
|
154
|
+
"**"
|
155
|
+
~inline_element(self, position, :strong, c)
|
156
|
+
|
157
|
+
StrongUl = "__" !Whitespace
|
158
|
+
( !"__" Inline:b { b })+:c
|
159
|
+
"__"
|
160
|
+
~inline_element(self, position, :strong, c)
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
Ticks1 = < /`/ > !'`' { text }
|
165
|
+
Ticks2 = < /``/ > !'`' { text }
|
166
|
+
|
167
|
+
Code = ( Ticks1 Sp
|
168
|
+
( !'`' Nonspacechar )+:c
|
169
|
+
Sp Ticks1 ~text(self, position, c.join(""))
|
170
|
+
| Ticks2 Sp
|
171
|
+
( !'``' Nonspacechar )+:c
|
172
|
+
Sp Ticks2 ~text(self, position, c.join(""))
|
173
|
+
):cc
|
174
|
+
~inline_element(self, position, :code, [cc])
|
175
|
+
|
176
|
+
|
177
|
+
BlankLine = Sp Newline
|
178
|
+
|
179
|
+
Quoted = '"' (!'"' .)* '"' | '\'' (!'\'' .)* '\''
|
180
|
+
Eof = !.
|
181
|
+
Spacechar = < / |\t/ > { text }
|
182
|
+
Nonspacechar = !Spacechar !Newline <.> { text }
|
183
|
+
Newline = "\n" | "\r" "\n"?
|
184
|
+
Sp = Spacechar*
|
185
|
+
Spnl = Sp (Newline Sp)?
|
186
|
+
##SpecialChar = '~' | '*' | '_' | '`' | '&' | '[' | ']' | '(' | ')' | '<' | '!' | '#' | "\\" | "'" | '"'
|
187
|
+
SpecialChar = < /[~*_`&\[\]()<!#\\'"]/ > { text }
|
188
|
+
NormalChar = !( SpecialChar | Spacechar | Newline ) <.> { text }
|
189
|
+
AlphanumericAscii = < /[A-Za-z0-9]/ > { text }
|
190
|
+
Digit = < /[0-9]/ > { text }
|
191
|
+
|
192
|
+
NonindentSpace = < / | | |/ > { text }
|
193
|
+
Indent = < /\t| / > { text }
|
194
|
+
IndentedLine = Indent Line:c { c }
|
195
|
+
OptionallyIndentedLine = Indent? Line
|
196
|
+
|
197
|
+
Line = RawLine:c { c }
|
198
|
+
RawLine = (( < /[^\r\n]*/ > ) Newline { text } | < /.+/ > Eof { text }):c ~text(self, position, c)
|
199
|
+
|