Class: Utopia::XNode::Scanner

Inherits:
StringScanner
  • Object
show all
Defined in:
lib/utopia/xnode/scanner.rb

Constant Summary collapse

CDATA =
/[^<]+/m
TAG_PARAMETER =
/\s*([^\s=\/>]*)=((['"])(.*?)\3)/um

Instance Method Summary collapse

Constructor Details

#initialize(callback, string) ⇒ Scanner

Returns a new instance of Scanner.



42
43
44
45
# File 'lib/utopia/xnode/scanner.rb', line 42

def initialize(callback, string)
	@callback = callback
	super(string)
end

Instance Method Details

#calculate_line_number(at = pos) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/utopia/xnode/scanner.rb', line 47

def calculate_line_number(at = pos)
	line_no = 1
	line_offset = offset = 0
	
	string.lines.each do |line|
		line_offset = offset
		offset += line.size
		
		if offset >= at
			return [line_no, line_offset, at - line_offset, offset, line]
		end
		
		line_no += 1
	end
	
	return nil
end

#parseObject



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/utopia/xnode/scanner.rb', line 65

def parse
	until eos?
		pos = self.pos

		scan_cdata
		scan_tag

		if pos == self.pos
			raise ScanError.new("Scanner didn't move", self)
		end
	end
end

#scan_attributesObject



98
99
100
101
102
# File 'lib/utopia/xnode/scanner.rb', line 98

def scan_attributes
	while scan(TAG_PARAMETER)
		@callback.attribute(self[1], self[4])
	end
end

#scan_cdataObject



78
79
80
81
82
# File 'lib/utopia/xnode/scanner.rb', line 78

def scan_cdata
	if scan(CDATA)
		@callback.cdata(matched)
	end
end

#scan_tagObject



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/utopia/xnode/scanner.rb', line 84

def scan_tag
	if scan(/</)
		if scan(/\//)
			scan_tag_normal(CLOSED_TAG)
		elsif scan(/!/)
			scan_tag_comment
		elsif scan(/\?/)
			scan_tag_instruction
		else
			scan_tag_normal
		end
	end
end

#scan_tag_commentObject



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/utopia/xnode/scanner.rb', line 130

def scan_tag_comment
	if scan(/--/)
		if scan_until(/(.*?)-->/m)
			@callback.comment("--" + self[1] + "--")
		else
			raise ScanError.new("Comment is not closed!", self)
		end
	else
		if scan_until(/(.*?)>/)
			@callback.comment(self[1])
		else
			raise ScanError.new("Comment is not closed!", self)
		end
	end
end

#scan_tag_instructionObject



146
147
148
149
150
# File 'lib/utopia/xnode/scanner.rb', line 146

def scan_tag_instruction
	if scan_until(/(.*)\?>/)
		@callback.instruction(self[1])
	end
end

#scan_tag_normal(begin_tag_type = OPENED_TAG) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/utopia/xnode/scanner.rb', line 104

def scan_tag_normal(begin_tag_type = OPENED_TAG)
	if scan(/[^\s\/>]+/)
		@callback.begin_tag(matched, begin_tag_type)
	
		scan(/\s*/)
	
		scan_attributes
	
		scan(/\s*/)
	
		if scan(/\/>/)
			if begin_tag_type == CLOSED_TAG
				raise ScanError.new("Tag cannot be closed at both ends!", self)
			else
				@callback.finish_tag(begin_tag_type, CLOSED_TAG)
			end
		elsif scan(/>/)
			@callback.finish_tag(begin_tag_type, OPENED_TAG)
		else
			raise ScanError.new("Invalid characters in tag!", self)
		end
	else
		raise ScanError.new("Invalid tag!", self)
	end
end