File: parser.rb

package info (click to toggle)
ruby-eim-xml 0.0.4-3
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 192 kB
  • ctags: 171
  • sloc: ruby: 1,993; makefile: 7
file content (87 lines) | stat: -rw-r--r-- 1,617 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# XML parser for EimXML
#
# Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
# You can redistribute it and/or modify it under GPL2.
#

require "eim_xml"
require "strscan"

module EimXML
	class ParseError < StandardError
	end

	class Parser
		attr_reader :scanner
		module RE
			EMPTY_ELEMENT = /<([^>]*?)\/>/
			START_TAG = /<([^>]*?([^\/>]\s*))>/
			END_TAG = /<\/(\S+?)\s*>/
			ATTRIBUTE = /\s+([^=\s]+)\s*=\s*('(.*?)'|"(.*?)")/m
			STRING = /[^<]+/
		end

		def initialize(src)
			@scanner = StringScanner.new(src)
			@scanner.scan(/\s*<\?.*?\?>\s*/)
		end

		def parse
			if @scanner.scan(RE::EMPTY_ELEMENT)
				parse_empty_element
			elsif @scanner.scan(RE::START_TAG)
				parse_start_tag
			elsif @scanner.scan(RE::STRING)
				parse_string
			else
				nil
			end
		end

		def parse_tag
			s = StringScanner.new(@scanner[1])
			e = Element.new(s.scan(/\S+/))
			e[s[1]] = s[3] ? s[3] : s[4] while s.scan(RE::ATTRIBUTE)
			e
		end
		protected :parse_tag

		def parse_empty_element
			parse_tag
		end
		protected :parse_empty_element

		def parse_start_tag
			e = parse_tag

			until @scanner.scan(RE::END_TAG)
				c = parse
				raise ParseError.new("Syntax error.") unless c
				e << c
			end
			raise ParseError.new("End tag mismatched.") unless @scanner[1].to_sym==e.name
			e
		end
		protected :parse_start_tag

		def parse_string
			s = @scanner[0]
			s = s.gsub(/&(amp|quot|apos|lt|gt);/) do
				case $1
				when "amp"
					"&"
				when "quot"
					'"'
				when "apos"
					"'"
				when "lt"
					"<"
				when "gt"
					">"
				end
			end
			PCString.new(s)
		end
		protected :parse_string
	end
end