kpeg 0.9.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|