review-peg 0.1.3 → 0.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 +4 -4
- data/Rakefile +0 -2
- data/lib/review/compiler.rb +38 -57
- data/lib/review/latexbuilder.rb +17 -9
- data/lib/review/review.kpeg +11 -10
- data/lib/review/version.rb +1 -1
- metadata +2 -4
- data/lib/review/compiler/literals_1_9.kpeg +0 -22
- data/lib/review/compiler/literals_1_9.rb +0 -435
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02a8314cbab450277e8afa8b82587710657765c4
|
4
|
+
data.tar.gz: 2a1eb42ee5b296e430b1c8a4f24ca5aee7daa592
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c9daa8c4e7649c01b8fd4579f1b894ad140ee6c6adba721c063cd4633bf3190e2f85bc0eed84aad79a9d1a1b28fd28e27f86a057099f9cbe6d9506dc21ac6ea
|
7
|
+
data.tar.gz: a94b8dcae6985bdef5bfc5e91a617d962f60003db27f7725029720b694a8309b627425410b56b8fed42be8e91e7fcc9e8b4ab4176453eb48e9d742c92aaef334
|
data/Rakefile
CHANGED
@@ -15,8 +15,6 @@ task :default => [:test]
|
|
15
15
|
|
16
16
|
task :kpeg do
|
17
17
|
FileUtils.rm_f "lib/review/compiler.rb"
|
18
|
-
FileUtils.rm_f "lib/review/compiler/literals_1_9.rb"
|
19
|
-
sh "kpeg -s lib/review/compiler/literals_1_9.kpeg -o lib/review/compiler/literals_1_9.rb"
|
20
18
|
sh "kpeg -s lib/review/review.kpeg -o lib/review/compiler.rb"
|
21
19
|
end
|
22
20
|
|
data/lib/review/compiler.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: UTF-8
|
1
2
|
class ReVIEW::Compiler
|
2
3
|
# :stopdoc:
|
3
4
|
|
@@ -35,22 +36,16 @@ class ReVIEW::Compiler
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def current_line(target=pos)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
cur_line += 1
|
43
|
-
cur_offset += line.size
|
44
|
-
return cur_line if cur_offset >= target
|
45
|
-
end
|
39
|
+
offset = @sizes_memo.bsearch{|line, cur_offset| cur_offset >= target}
|
40
|
+
if offset
|
41
|
+
return offset[0]
|
42
|
+
end
|
46
43
|
|
47
44
|
-1
|
48
45
|
end
|
49
46
|
|
50
47
|
def lines
|
51
|
-
|
52
|
-
string.each_line { |l| lines << l }
|
53
|
-
lines
|
48
|
+
@lines_memo
|
54
49
|
end
|
55
50
|
|
56
51
|
|
@@ -61,9 +56,22 @@ class ReVIEW::Compiler
|
|
61
56
|
|
62
57
|
# Sets the string and current parsing position for the parser.
|
63
58
|
def set_string string, pos
|
64
|
-
@string = string
|
65
|
-
@string_size = string ? string.size : 0
|
59
|
+
@string = string.freeze
|
66
60
|
@pos = pos
|
61
|
+
@sizes_memo = []
|
62
|
+
if string
|
63
|
+
@string_size = string.size
|
64
|
+
@lines_memo = string.lines
|
65
|
+
cur_offset = cur_line = 0
|
66
|
+
@lines_memo.each do |line|
|
67
|
+
cur_line += 1
|
68
|
+
cur_offset += line.size
|
69
|
+
@sizes_memo << [cur_line, cur_offset]
|
70
|
+
end
|
71
|
+
else
|
72
|
+
@string_size = 0
|
73
|
+
@lines_memo = []
|
74
|
+
end
|
67
75
|
end
|
68
76
|
|
69
77
|
def show_pos
|
@@ -373,7 +381,7 @@ require 'review/preprocessor'
|
|
373
381
|
require 'review/exception'
|
374
382
|
require 'review/node'
|
375
383
|
require 'lineinput'
|
376
|
-
require 'review/compiler/literals_1_9'
|
384
|
+
# require 'review/compiler/literals_1_9'
|
377
385
|
# require 'review/compiler/literals_1_8'
|
378
386
|
|
379
387
|
## redifine Compiler.new
|
@@ -1194,9 +1202,7 @@ require 'review/node'
|
|
1194
1202
|
end
|
1195
1203
|
end
|
1196
1204
|
include ::ReVIEWConstruction
|
1197
|
-
def setup_foreign_grammar
|
1198
|
-
@_grammar_literals = ReVIEW::Compiler::Literals.new(nil)
|
1199
|
-
end
|
1205
|
+
def setup_foreign_grammar; end
|
1200
1206
|
|
1201
1207
|
# root = Start
|
1202
1208
|
def _root
|
@@ -5036,48 +5042,40 @@ require 'review/node'
|
|
5036
5042
|
return _tmp
|
5037
5043
|
end
|
5038
5044
|
|
5039
|
-
#
|
5040
|
-
def _Alphanumeric
|
5041
|
-
_tmp = @_grammar_literals.external_invoke(self, :_Alphanumeric)
|
5042
|
-
set_failed_rule :_Alphanumeric unless _tmp
|
5043
|
-
return _tmp
|
5044
|
-
end
|
5045
|
-
|
5046
|
-
# AlphanumericAscii = %literals.AlphanumericAscii
|
5045
|
+
# AlphanumericAscii = /[A-Za-z0-9]/
|
5047
5046
|
def _AlphanumericAscii
|
5048
|
-
_tmp =
|
5047
|
+
_tmp = scan(/\A(?-mix:[A-Za-z0-9])/)
|
5049
5048
|
set_failed_rule :_AlphanumericAscii unless _tmp
|
5050
5049
|
return _tmp
|
5051
5050
|
end
|
5052
5051
|
|
5053
|
-
# LowerAlphabetAscii =
|
5052
|
+
# LowerAlphabetAscii = /[a-z]/
|
5054
5053
|
def _LowerAlphabetAscii
|
5055
|
-
_tmp =
|
5054
|
+
_tmp = scan(/\A(?-mix:[a-z])/)
|
5056
5055
|
set_failed_rule :_LowerAlphabetAscii unless _tmp
|
5057
5056
|
return _tmp
|
5058
5057
|
end
|
5059
5058
|
|
5060
|
-
# Digit =
|
5059
|
+
# Digit = /[0-9]/
|
5061
5060
|
def _Digit
|
5062
|
-
_tmp =
|
5061
|
+
_tmp = scan(/\A(?-mix:[0-9])/)
|
5063
5062
|
set_failed_rule :_Digit unless _tmp
|
5064
5063
|
return _tmp
|
5065
5064
|
end
|
5066
5065
|
|
5067
|
-
# BOM =
|
5066
|
+
# BOM = "uFEFF"
|
5068
5067
|
def _BOM
|
5069
|
-
_tmp =
|
5068
|
+
_tmp = match_string("uFEFF")
|
5070
5069
|
set_failed_rule :_BOM unless _tmp
|
5071
5070
|
return _tmp
|
5072
5071
|
end
|
5073
5072
|
|
5074
|
-
# Newline =
|
5073
|
+
# Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ {newline(self, position, "\n")}
|
5075
5074
|
def _Newline
|
5076
5075
|
|
5077
5076
|
_save = self.pos
|
5078
5077
|
while true # sequence
|
5079
|
-
_tmp =
|
5080
|
-
n = @result
|
5078
|
+
_tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
|
5081
5079
|
unless _tmp
|
5082
5080
|
self.pos = _save
|
5083
5081
|
break
|
@@ -5094,20 +5092,6 @@ require 'review/node'
|
|
5094
5092
|
return _tmp
|
5095
5093
|
end
|
5096
5094
|
|
5097
|
-
# NonAlphanumeric = %literals.NonAlphanumeric
|
5098
|
-
def _NonAlphanumeric
|
5099
|
-
_tmp = @_grammar_literals.external_invoke(self, :_NonAlphanumeric)
|
5100
|
-
set_failed_rule :_NonAlphanumeric unless _tmp
|
5101
|
-
return _tmp
|
5102
|
-
end
|
5103
|
-
|
5104
|
-
# Spacechar = %literals.Spacechar
|
5105
|
-
def _Spacechar
|
5106
|
-
_tmp = @_grammar_literals.external_invoke(self, :_Spacechar)
|
5107
|
-
set_failed_rule :_Spacechar unless _tmp
|
5108
|
-
return _tmp
|
5109
|
-
end
|
5110
|
-
|
5111
5095
|
Rules = {}
|
5112
5096
|
Rules[:_root] = rule_info("root", "Start")
|
5113
5097
|
Rules[:_Start] = rule_info("Start", "&. { @list_stack = Array.new } Document:c { @strategy.ast = c }")
|
@@ -5171,13 +5155,10 @@ require 'review/node'
|
|
5171
5155
|
Rules[:_EOL] = rule_info("EOL", "(Newline | EOF)")
|
5172
5156
|
Rules[:_EOF] = rule_info("EOF", "!.")
|
5173
5157
|
Rules[:_ElementName] = rule_info("ElementName", "< LowerAlphabetAscii+ > { text }")
|
5174
|
-
Rules[:
|
5175
|
-
Rules[:
|
5176
|
-
Rules[:
|
5177
|
-
Rules[:
|
5178
|
-
Rules[:
|
5179
|
-
Rules[:_Newline] = rule_info("Newline", "%literals.Newline:n {newline(self, position, \"\\n\")}")
|
5180
|
-
Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "%literals.NonAlphanumeric")
|
5181
|
-
Rules[:_Spacechar] = rule_info("Spacechar", "%literals.Spacechar")
|
5158
|
+
Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/")
|
5159
|
+
Rules[:_LowerAlphabetAscii] = rule_info("LowerAlphabetAscii", "/[a-z]/")
|
5160
|
+
Rules[:_Digit] = rule_info("Digit", "/[0-9]/")
|
5161
|
+
Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"")
|
5162
|
+
Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/ {newline(self, position, \"\\n\")}")
|
5182
5163
|
# :startdoc:
|
5183
5164
|
end
|
data/lib/review/latexbuilder.rb
CHANGED
@@ -654,8 +654,9 @@ module ReVIEW
|
|
654
654
|
'\noindent'
|
655
655
|
end
|
656
656
|
|
657
|
-
def
|
658
|
-
|
657
|
+
def node_inline_chapref(node)
|
658
|
+
id = node[0].to_raw
|
659
|
+
title = @book.chapter_index.display_string(id)
|
659
660
|
if @book.config["chapterlink"]
|
660
661
|
"\\hyperref[chap:#{id}]{#{title}}"
|
661
662
|
else
|
@@ -666,7 +667,8 @@ module ReVIEW
|
|
666
667
|
nofunc_text("[UnknownChapter:#{id}]")
|
667
668
|
end
|
668
669
|
|
669
|
-
def
|
670
|
+
def node_inline_chap(node)
|
671
|
+
id = node[0].to_raw
|
670
672
|
if @book.config["chapterlink"]
|
671
673
|
"\\hyperref[chap:#{id}]{#{@book.chapter_index.number(id)}}"
|
672
674
|
else
|
@@ -677,7 +679,8 @@ module ReVIEW
|
|
677
679
|
nofunc_text("[UnknownChapter:#{id}]")
|
678
680
|
end
|
679
681
|
|
680
|
-
def
|
682
|
+
def node_inline_title(node)
|
683
|
+
id = node[0].to_raw
|
681
684
|
title = super
|
682
685
|
if @book.config["chapterlink"]
|
683
686
|
"\\hyperref[chap:#{id}]{#{title}}"
|
@@ -697,12 +700,14 @@ module ReVIEW
|
|
697
700
|
macro('reviewlistref', "#{chapter.number}.#{chapter.list(id).number}")
|
698
701
|
end
|
699
702
|
|
700
|
-
def
|
703
|
+
def node_inline_table(node)
|
704
|
+
id = node[0].to_raw
|
701
705
|
chapter, id = extract_chapter_id(id)
|
702
706
|
macro('reviewtableref', "#{chapter.number}.#{chapter.table(id).number}", table_label(id, chapter))
|
703
707
|
end
|
704
708
|
|
705
|
-
def
|
709
|
+
def node_inline_img(node)
|
710
|
+
id = node[0].to_raw
|
706
711
|
chapter, id = extract_chapter_id(id)
|
707
712
|
macro('reviewimageref', "#{chapter.number}.#{chapter.image(id).number}", image_label(id, chapter))
|
708
713
|
end
|
@@ -812,7 +817,8 @@ module ReVIEW
|
|
812
817
|
macro('texttt', macro('textbf', str))
|
813
818
|
end
|
814
819
|
|
815
|
-
def
|
820
|
+
def node_inline_bib(node)
|
821
|
+
id = node[0].to_raw
|
816
822
|
macro('reviewbibref', "[#{@chapter.bibpaper(id).number}]", bib_label(id))
|
817
823
|
end
|
818
824
|
|
@@ -831,7 +837,8 @@ module ReVIEW
|
|
831
837
|
end
|
832
838
|
end
|
833
839
|
|
834
|
-
def
|
840
|
+
def node_inline_column(node)
|
841
|
+
id = node[0].to_raw
|
835
842
|
macro('reviewcolumnref', "#{@chapter.column(id).caption}", column_label(id))
|
836
843
|
end
|
837
844
|
|
@@ -863,7 +870,8 @@ module ReVIEW
|
|
863
870
|
macro('reviewami', str)
|
864
871
|
end
|
865
872
|
|
866
|
-
def
|
873
|
+
def node_inline_icon(node)
|
874
|
+
id = node[0].to_raw
|
867
875
|
macro('includegraphics', @chapter.image(id).path)
|
868
876
|
end
|
869
877
|
|
data/lib/review/review.kpeg
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
%% name = ReVIEW::Compiler
|
2
2
|
|
3
|
+
%% header {
|
4
|
+
# coding: UTF-8
|
5
|
+
|
6
|
+
}
|
7
|
+
|
3
8
|
%% {
|
4
9
|
class Error; end
|
5
10
|
class Position
|
@@ -18,7 +23,7 @@ require 'review/preprocessor'
|
|
18
23
|
require 'review/exception'
|
19
24
|
require 'review/node'
|
20
25
|
require 'lineinput'
|
21
|
-
require 'review/compiler/literals_1_9'
|
26
|
+
# require 'review/compiler/literals_1_9'
|
22
27
|
# require 'review/compiler/literals_1_8'
|
23
28
|
|
24
29
|
## redifine Compiler.new
|
@@ -734,12 +739,8 @@ EOF = !.
|
|
734
739
|
|
735
740
|
ElementName = < LowerAlphabetAscii+ > { text }
|
736
741
|
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
BOM = %literals.BOM
|
743
|
-
Newline = %literals.Newline:n ~newline(self, position, "\n")
|
744
|
-
NonAlphanumeric = %literals.NonAlphanumeric
|
745
|
-
Spacechar = %literals.Spacechar
|
742
|
+
AlphanumericAscii = /[A-Za-z0-9]/
|
743
|
+
LowerAlphabetAscii = /[a-z]/
|
744
|
+
Digit = /[0-9]/
|
745
|
+
BOM = "\uFEFF"
|
746
|
+
Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/ ~newline(self, position, "\n")
|
data/lib/review/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: review-peg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kmuto
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-11-
|
12
|
+
date: 2015-11-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -171,8 +171,6 @@ files:
|
|
171
171
|
- lib/review/builder.rb
|
172
172
|
- lib/review/catalog.rb
|
173
173
|
- lib/review/compiler.rb
|
174
|
-
- lib/review/compiler/literals_1_9.kpeg
|
175
|
-
- lib/review/compiler/literals_1_9.rb
|
176
174
|
- lib/review/configure.rb
|
177
175
|
- lib/review/epubbuilder.rb
|
178
176
|
- lib/review/epubmaker.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
%% name = ReVIEW::Compiler::Literals
|
2
|
-
|
3
|
-
%% header {
|
4
|
-
# coding: UTF-8
|
5
|
-
|
6
|
-
##
|
7
|
-
#--
|
8
|
-
# This set of literals is for Ruby 1.9 regular expressions and gives full
|
9
|
-
# unicode support.
|
10
|
-
#
|
11
|
-
# Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric
|
12
|
-
# characters, newlines and spaces.
|
13
|
-
}
|
14
|
-
|
15
|
-
Alphanumeric = /\p{Word}/
|
16
|
-
AlphanumericAscii = /[A-Za-z0-9]/
|
17
|
-
LowerAlphabetAscii = /[a-z]/
|
18
|
-
Digit = /[0-9]/
|
19
|
-
BOM = "\uFEFF"
|
20
|
-
Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
|
21
|
-
NonAlphanumeric = /\p{^Word}/
|
22
|
-
Spacechar = /\t|\p{Zs}/
|
@@ -1,435 +0,0 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
##
|
4
|
-
#--
|
5
|
-
# This set of literals is for Ruby 1.9 regular expressions and gives full
|
6
|
-
# unicode support.
|
7
|
-
#
|
8
|
-
# Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric
|
9
|
-
# characters, newlines and spaces.
|
10
|
-
class ReVIEW::Compiler::Literals
|
11
|
-
# :stopdoc:
|
12
|
-
|
13
|
-
# This is distinct from setup_parser so that a standalone parser
|
14
|
-
# can redefine #initialize and still have access to the proper
|
15
|
-
# parser setup code.
|
16
|
-
def initialize(str, debug=false)
|
17
|
-
setup_parser(str, debug)
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# Prepares for parsing +str+. If you define a custom initialize you must
|
23
|
-
# call this method before #parse
|
24
|
-
def setup_parser(str, debug=false)
|
25
|
-
set_string str, 0
|
26
|
-
@memoizations = Hash.new { |h,k| h[k] = {} }
|
27
|
-
@result = nil
|
28
|
-
@failed_rule = nil
|
29
|
-
@failing_rule_offset = -1
|
30
|
-
|
31
|
-
setup_foreign_grammar
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_reader :string
|
35
|
-
attr_reader :failing_rule_offset
|
36
|
-
attr_accessor :result, :pos
|
37
|
-
|
38
|
-
def current_column(target=pos)
|
39
|
-
if c = string.rindex("\n", target-1)
|
40
|
-
return target - c - 1
|
41
|
-
end
|
42
|
-
|
43
|
-
target + 1
|
44
|
-
end
|
45
|
-
|
46
|
-
def current_line(target=pos)
|
47
|
-
cur_offset = 0
|
48
|
-
cur_line = 0
|
49
|
-
|
50
|
-
string.each_line do |line|
|
51
|
-
cur_line += 1
|
52
|
-
cur_offset += line.size
|
53
|
-
return cur_line if cur_offset >= target
|
54
|
-
end
|
55
|
-
|
56
|
-
-1
|
57
|
-
end
|
58
|
-
|
59
|
-
def lines
|
60
|
-
lines = []
|
61
|
-
string.each_line { |l| lines << l }
|
62
|
-
lines
|
63
|
-
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def get_text(start)
|
68
|
-
@string[start..@pos-1]
|
69
|
-
end
|
70
|
-
|
71
|
-
# Sets the string and current parsing position for the parser.
|
72
|
-
def set_string string, pos
|
73
|
-
@string = string
|
74
|
-
@string_size = string ? string.size : 0
|
75
|
-
@pos = pos
|
76
|
-
end
|
77
|
-
|
78
|
-
def show_pos
|
79
|
-
width = 10
|
80
|
-
if @pos < width
|
81
|
-
"#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
|
82
|
-
else
|
83
|
-
"#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def failure_info
|
88
|
-
l = current_line @failing_rule_offset
|
89
|
-
c = current_column @failing_rule_offset
|
90
|
-
|
91
|
-
if @failed_rule.kind_of? Symbol
|
92
|
-
info = self.class::Rules[@failed_rule]
|
93
|
-
"line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
|
94
|
-
else
|
95
|
-
"line #{l}, column #{c}: failed rule '#{@failed_rule}'"
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def failure_caret
|
100
|
-
l = current_line @failing_rule_offset
|
101
|
-
c = current_column @failing_rule_offset
|
102
|
-
|
103
|
-
line = lines[l-1]
|
104
|
-
"#{line}\n#{' ' * (c - 1)}^"
|
105
|
-
end
|
106
|
-
|
107
|
-
def failure_character
|
108
|
-
l = current_line @failing_rule_offset
|
109
|
-
c = current_column @failing_rule_offset
|
110
|
-
lines[l-1][c-1, 1]
|
111
|
-
end
|
112
|
-
|
113
|
-
def failure_oneline
|
114
|
-
l = current_line @failing_rule_offset
|
115
|
-
c = current_column @failing_rule_offset
|
116
|
-
|
117
|
-
char = lines[l-1][c-1, 1]
|
118
|
-
|
119
|
-
if @failed_rule.kind_of? Symbol
|
120
|
-
info = self.class::Rules[@failed_rule]
|
121
|
-
"@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
|
122
|
-
else
|
123
|
-
"@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class ParseError < RuntimeError
|
128
|
-
end
|
129
|
-
|
130
|
-
def raise_error
|
131
|
-
raise ParseError, failure_oneline
|
132
|
-
end
|
133
|
-
|
134
|
-
def show_error(io=STDOUT)
|
135
|
-
error_pos = @failing_rule_offset
|
136
|
-
line_no = current_line(error_pos)
|
137
|
-
col_no = current_column(error_pos)
|
138
|
-
|
139
|
-
io.puts "On line #{line_no}, column #{col_no}:"
|
140
|
-
|
141
|
-
if @failed_rule.kind_of? Symbol
|
142
|
-
info = self.class::Rules[@failed_rule]
|
143
|
-
io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
|
144
|
-
else
|
145
|
-
io.puts "Failed to match rule '#{@failed_rule}'"
|
146
|
-
end
|
147
|
-
|
148
|
-
io.puts "Got: #{string[error_pos,1].inspect}"
|
149
|
-
line = lines[line_no-1]
|
150
|
-
io.puts "=> #{line}"
|
151
|
-
io.print(" " * (col_no + 3))
|
152
|
-
io.puts "^"
|
153
|
-
end
|
154
|
-
|
155
|
-
def set_failed_rule(name)
|
156
|
-
if @pos > @failing_rule_offset
|
157
|
-
@failed_rule = name
|
158
|
-
@failing_rule_offset = @pos
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
attr_reader :failed_rule
|
163
|
-
|
164
|
-
def match_string(str)
|
165
|
-
len = str.size
|
166
|
-
if @string[pos,len] == str
|
167
|
-
@pos += len
|
168
|
-
return str
|
169
|
-
end
|
170
|
-
|
171
|
-
return nil
|
172
|
-
end
|
173
|
-
|
174
|
-
def scan(reg)
|
175
|
-
if m = reg.match(@string[@pos..-1])
|
176
|
-
width = m.end(0)
|
177
|
-
@pos += width
|
178
|
-
return true
|
179
|
-
end
|
180
|
-
|
181
|
-
return nil
|
182
|
-
end
|
183
|
-
|
184
|
-
if "".respond_to? :ord
|
185
|
-
def get_byte
|
186
|
-
if @pos >= @string_size
|
187
|
-
return nil
|
188
|
-
end
|
189
|
-
|
190
|
-
s = @string[@pos].ord
|
191
|
-
@pos += 1
|
192
|
-
s
|
193
|
-
end
|
194
|
-
else
|
195
|
-
def get_byte
|
196
|
-
if @pos >= @string_size
|
197
|
-
return nil
|
198
|
-
end
|
199
|
-
|
200
|
-
s = @string[@pos]
|
201
|
-
@pos += 1
|
202
|
-
s
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def parse(rule=nil)
|
207
|
-
# We invoke the rules indirectly via apply
|
208
|
-
# instead of by just calling them as methods because
|
209
|
-
# if the rules use left recursion, apply needs to
|
210
|
-
# manage that.
|
211
|
-
|
212
|
-
if !rule
|
213
|
-
apply(:_root)
|
214
|
-
else
|
215
|
-
method = rule.gsub("-","_hyphen_")
|
216
|
-
apply :"_#{method}"
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
class MemoEntry
|
221
|
-
def initialize(ans, pos)
|
222
|
-
@ans = ans
|
223
|
-
@pos = pos
|
224
|
-
@result = nil
|
225
|
-
@set = false
|
226
|
-
@left_rec = false
|
227
|
-
end
|
228
|
-
|
229
|
-
attr_reader :ans, :pos, :result, :set
|
230
|
-
attr_accessor :left_rec
|
231
|
-
|
232
|
-
def move!(ans, pos, result)
|
233
|
-
@ans = ans
|
234
|
-
@pos = pos
|
235
|
-
@result = result
|
236
|
-
@set = true
|
237
|
-
@left_rec = false
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
def external_invoke(other, rule, *args)
|
242
|
-
old_pos = @pos
|
243
|
-
old_string = @string
|
244
|
-
|
245
|
-
set_string other.string, other.pos
|
246
|
-
|
247
|
-
begin
|
248
|
-
if val = __send__(rule, *args)
|
249
|
-
other.pos = @pos
|
250
|
-
other.result = @result
|
251
|
-
else
|
252
|
-
other.set_failed_rule "#{self.class}##{rule}"
|
253
|
-
end
|
254
|
-
val
|
255
|
-
ensure
|
256
|
-
set_string old_string, old_pos
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def apply_with_args(rule, *args)
|
261
|
-
memo_key = [rule, args]
|
262
|
-
if m = @memoizations[memo_key][@pos]
|
263
|
-
@pos = m.pos
|
264
|
-
if !m.set
|
265
|
-
m.left_rec = true
|
266
|
-
return nil
|
267
|
-
end
|
268
|
-
|
269
|
-
@result = m.result
|
270
|
-
|
271
|
-
return m.ans
|
272
|
-
else
|
273
|
-
m = MemoEntry.new(nil, @pos)
|
274
|
-
@memoizations[memo_key][@pos] = m
|
275
|
-
start_pos = @pos
|
276
|
-
|
277
|
-
ans = __send__ rule, *args
|
278
|
-
|
279
|
-
lr = m.left_rec
|
280
|
-
|
281
|
-
m.move! ans, @pos, @result
|
282
|
-
|
283
|
-
# Don't bother trying to grow the left recursion
|
284
|
-
# if it's failing straight away (thus there is no seed)
|
285
|
-
if ans and lr
|
286
|
-
return grow_lr(rule, args, start_pos, m)
|
287
|
-
else
|
288
|
-
return ans
|
289
|
-
end
|
290
|
-
|
291
|
-
return ans
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
def apply(rule)
|
296
|
-
if m = @memoizations[rule][@pos]
|
297
|
-
@pos = m.pos
|
298
|
-
if !m.set
|
299
|
-
m.left_rec = true
|
300
|
-
return nil
|
301
|
-
end
|
302
|
-
|
303
|
-
@result = m.result
|
304
|
-
|
305
|
-
return m.ans
|
306
|
-
else
|
307
|
-
m = MemoEntry.new(nil, @pos)
|
308
|
-
@memoizations[rule][@pos] = m
|
309
|
-
start_pos = @pos
|
310
|
-
|
311
|
-
ans = __send__ rule
|
312
|
-
|
313
|
-
lr = m.left_rec
|
314
|
-
|
315
|
-
m.move! ans, @pos, @result
|
316
|
-
|
317
|
-
# Don't bother trying to grow the left recursion
|
318
|
-
# if it's failing straight away (thus there is no seed)
|
319
|
-
if ans and lr
|
320
|
-
return grow_lr(rule, nil, start_pos, m)
|
321
|
-
else
|
322
|
-
return ans
|
323
|
-
end
|
324
|
-
|
325
|
-
return ans
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
def grow_lr(rule, args, start_pos, m)
|
330
|
-
while true
|
331
|
-
@pos = start_pos
|
332
|
-
@result = m.result
|
333
|
-
|
334
|
-
if args
|
335
|
-
ans = __send__ rule, *args
|
336
|
-
else
|
337
|
-
ans = __send__ rule
|
338
|
-
end
|
339
|
-
return nil unless ans
|
340
|
-
|
341
|
-
break if @pos <= m.pos
|
342
|
-
|
343
|
-
m.move! ans, @pos, @result
|
344
|
-
end
|
345
|
-
|
346
|
-
@result = m.result
|
347
|
-
@pos = m.pos
|
348
|
-
return m.ans
|
349
|
-
end
|
350
|
-
|
351
|
-
class RuleInfo
|
352
|
-
def initialize(name, rendered)
|
353
|
-
@name = name
|
354
|
-
@rendered = rendered
|
355
|
-
end
|
356
|
-
|
357
|
-
attr_reader :name, :rendered
|
358
|
-
end
|
359
|
-
|
360
|
-
def self.rule_info(name, rendered)
|
361
|
-
RuleInfo.new(name, rendered)
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
# :startdoc:
|
366
|
-
# :stopdoc:
|
367
|
-
def setup_foreign_grammar; end
|
368
|
-
|
369
|
-
# Alphanumeric = /\p{Word}/
|
370
|
-
def _Alphanumeric
|
371
|
-
_tmp = scan(/\A(?-mix:\p{Word})/)
|
372
|
-
set_failed_rule :_Alphanumeric unless _tmp
|
373
|
-
return _tmp
|
374
|
-
end
|
375
|
-
|
376
|
-
# AlphanumericAscii = /[A-Za-z0-9]/
|
377
|
-
def _AlphanumericAscii
|
378
|
-
_tmp = scan(/\A(?-mix:[A-Za-z0-9])/)
|
379
|
-
set_failed_rule :_AlphanumericAscii unless _tmp
|
380
|
-
return _tmp
|
381
|
-
end
|
382
|
-
|
383
|
-
# LowerAlphabetAscii = /[a-z]/
|
384
|
-
def _LowerAlphabetAscii
|
385
|
-
_tmp = scan(/\A(?-mix:[a-z])/)
|
386
|
-
set_failed_rule :_LowerAlphabetAscii unless _tmp
|
387
|
-
return _tmp
|
388
|
-
end
|
389
|
-
|
390
|
-
# Digit = /[0-9]/
|
391
|
-
def _Digit
|
392
|
-
_tmp = scan(/\A(?-mix:[0-9])/)
|
393
|
-
set_failed_rule :_Digit unless _tmp
|
394
|
-
return _tmp
|
395
|
-
end
|
396
|
-
|
397
|
-
# BOM = "uFEFF"
|
398
|
-
def _BOM
|
399
|
-
_tmp = match_string("uFEFF")
|
400
|
-
set_failed_rule :_BOM unless _tmp
|
401
|
-
return _tmp
|
402
|
-
end
|
403
|
-
|
404
|
-
# Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
|
405
|
-
def _Newline
|
406
|
-
_tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
|
407
|
-
set_failed_rule :_Newline unless _tmp
|
408
|
-
return _tmp
|
409
|
-
end
|
410
|
-
|
411
|
-
# NonAlphanumeric = /\p{^Word}/
|
412
|
-
def _NonAlphanumeric
|
413
|
-
_tmp = scan(/\A(?-mix:\p{^Word})/)
|
414
|
-
set_failed_rule :_NonAlphanumeric unless _tmp
|
415
|
-
return _tmp
|
416
|
-
end
|
417
|
-
|
418
|
-
# Spacechar = /\t|\p{Zs}/
|
419
|
-
def _Spacechar
|
420
|
-
_tmp = scan(/\A(?-mix:\t|\p{Zs})/)
|
421
|
-
set_failed_rule :_Spacechar unless _tmp
|
422
|
-
return _tmp
|
423
|
-
end
|
424
|
-
|
425
|
-
Rules = {}
|
426
|
-
Rules[:_Alphanumeric] = rule_info("Alphanumeric", "/\\p{Word}/")
|
427
|
-
Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/")
|
428
|
-
Rules[:_LowerAlphabetAscii] = rule_info("LowerAlphabetAscii", "/[a-z]/")
|
429
|
-
Rules[:_Digit] = rule_info("Digit", "/[0-9]/")
|
430
|
-
Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"")
|
431
|
-
Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/")
|
432
|
-
Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "/\\p{^Word}/")
|
433
|
-
Rules[:_Spacechar] = rule_info("Spacechar", "/\\t|\\p{Zs}/")
|
434
|
-
# :startdoc:
|
435
|
-
end
|