1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Lexical
9
10 module Lexer
11
12 module String
13
14 class Abstract < Lexer::Abstract
15 attr_reader :buf
16
17
18 def self.deconstruct_keys
19 {
20 :buf => ::String
21 }
22 end
23
24
25 def initialize(loc, braket_stack, buf)
26 ASSERT.kind_of loc, LOC::Entry
27 ASSERT.kind_of braket_stack, ::Array
28 ASSERT.kind_of buf, ::String
29
30 super(loc, braket_stack)
31
32 @buf = buf
33 end
34
35
36 def to_s
37 format("%s {braket_stack=%s, buf=%s} -- %s",
38 E::Tracer.class_to_string(self.class),
39 self.braket_stack.inspect,
40 self.buf.inspect,
41 self.loc.to_s
42 )
43 end
44
45
46 def lex(scanner)
47 ASSERT.kind_of scanner, ::StringScanner
48
49 case
50 # End-String
51 when scanner.scan(/"/)
52 [
53 :EndString,
54
55 scanner.matched,
56
57 [__make_token__(loc, self.buf)],
58
59 __make_separator__
60 ]
61
62 # New-line
63 when scanner.skip(/\n/)
64 raise X::LexicalError.new(
65 self.loc,
66 "Unexpected end-string: '\"%s'", self.buf
67 )
68
69 # Escapes
70 when scanner.scan(/\\./)
71 opt_esc = Escape.opt_escape scanner.matched
72 unless opt_esc
73 raise X::LexicalError.new(
74 self.loc,
75 "Unknown escape-character: '%s' after '\"%s'",
76 scanner.matched, self.buf
77 )
78 end
79
80 [
81 :Escape,
82
83 scanner.matched,
84
85 [],
86
87 __make_state__(self.buf + opt_esc)
88 ]
89
90 # Others
91 when scanner.scan(/./)
92 [
93 :Other,
94
95 scanner.matched,
96
97 [],
98
99 __make_state__(self.buf + scanner.matched)
100 ]
101
102 else
103 ASSERT.abort scanner.inspect
104 end
105 end
106
107
108 private
109
110 def __make_token__(loc, val)
111 ASSERT.kind_of loc, LOC::Entry
112 ASSERT.kind_of val, ::String
113
114 raise X::InternalSubclassResponsibility
115 end
116
117
118 def __make_state__(buf)
119 ASSERT.kind_of buf, ::String
120
121 raise X::InternalSubclassResponsibility
122 end
123 end
124
125
126
127 class Basic < Abstract
128 def __make_token__(loc, val)
129 ASSERT.kind_of loc, LOC::Entry
130 ASSERT.kind_of val, ::String
131
132 LT.make_string loc, val
133 end
134
135
136 def __make_state__(buf)
137 ASSERT.kind_of buf, ::String
138
139 __make_string__ buf
140 end
141 end
142
143
144
145 class Symbolized < Abstract
146 def __make_token__(loc, val)
147 ASSERT.kind_of loc, LOC::Entry
148 ASSERT.kind_of val, ::String
149
150 esc_char = Escape.find_escape val
151 if esc_char
152 raise X::LexicalError.new(
153 loc,
154 "Escape character in symbolized string: '%s'",
155 Escape.unescape(esc_char)
156 )
157 end
158
159 LT.make_symbol loc, val
160 end
161
162
163 def __make_state__(buf)
164 ASSERT.kind_of buf, ::String
165
166 __make_symbolized_string__ buf
167 end
168 end
169
170 end # Umu::Lexical::Lexer::String
171
172 end # Umu::Lexical::Lexer
173
174 end # Umu::Lexical
175
176 end # Umu