3
3
package com.amazon.ion.impl
4
4
5
5
import com.amazon.ion.*
6
+ import com.amazon.ion.SystemSymbols.*
6
7
import com.amazon.ion.impl.macro.*
7
8
import com.amazon.ion.impl.macro.MacroRef.Companion.byId
8
9
import com.amazon.ion.impl.macro.MacroRef.Companion.byName
@@ -28,22 +29,39 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
28
29
var isMacroTableAlreadyClassified = false
29
30
30
31
private enum class State {
31
- IN_ION_ENCODING_SEXP ,
32
+ IN_DIRECTIVE_SEXP ,
33
+ IN_MODULE_DIRECTIVE_SEXP_AWAITING_MODULE_NAME ,
34
+ IN_MODULE_DIRECTIVE_SEXP ,
32
35
IN_SYMBOL_TABLE_SEXP ,
33
36
IN_SYMBOL_TABLE_LIST ,
34
37
IN_MACRO_TABLE_SEXP ,
35
38
COMPILING_MACRO ,
36
39
READING_VALUE
37
40
}
38
41
39
- private fun classifySexpWithinEncodingDirective () {
42
+ private fun classifyDirective () {
43
+ errorIf(reader.type != IonType .SYMBOL ) { " Ion encoding directives must start with a directive keyword; found ${reader.type} " }
44
+ val name: String = reader.stringValue()
45
+ // TODO: Add support for `import` and `encoding` directives
46
+ if (SystemSymbols_1_1 .MODULE .text == name) {
47
+ state = State .IN_MODULE_DIRECTIVE_SEXP_AWAITING_MODULE_NAME
48
+ } else if (SystemSymbols_1_1 .IMPORT .text == name) {
49
+ throw IonException (" 'import' directive not yet supported" )
50
+ } else if (SystemSymbols_1_1 .ENCODING .text == name) {
51
+ throw IonException (" 'encoding' directive not yet supported" )
52
+ } else {
53
+ throw IonException (String .format(" '%s' is not a valid directive keyword" , name))
54
+ }
55
+ }
56
+
57
+ private fun classifySexpWithinModuleDirective () {
40
58
val name: String = reader.stringValue()
41
59
state = if (SystemSymbols_1_1 .SYMBOL_TABLE .text == name) {
42
60
State .IN_SYMBOL_TABLE_SEXP
43
61
} else if (SystemSymbols_1_1 .MACRO_TABLE .text == name) {
44
62
State .IN_MACRO_TABLE_SEXP
45
63
} else {
46
- throw IonException (String .format( " \$ ion_encoding expressions '%s' not supported. " , name) )
64
+ throw IonException (" ' $name ' clause not supported in module definition " )
47
65
}
48
66
}
49
67
@@ -64,7 +82,7 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
64
82
}
65
83
isSymbolTableAlreadyClassified = true
66
84
if (IonType .isText(type)) {
67
- if (SystemSymbols . ION_ENCODING == reader.stringValue() && ! isSymbolTableAppend) {
85
+ if (DEFAULT_MODULE == reader.stringValue() && ! isSymbolTableAppend) {
68
86
isSymbolTableAppend = true
69
87
if (reader.next() == null ) {
70
88
return true
@@ -73,10 +91,10 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
73
91
throw IonException (" symbol_table s-expression must begin with a list." )
74
92
}
75
93
} else {
76
- throw IonException (" symbol_table s-expression must begin with either \$ ion_encoding or a list." )
94
+ throw IonException (" symbol_table s-expression must begin with either '_' or a list." )
77
95
}
78
96
} else if (type != IonType .LIST ) {
79
- throw IonException (" symbol_table s-expression must begin with either \$ ion_encoding or a list." )
97
+ throw IonException (" symbol_table s-expression must begin with either '_' or a list." )
80
98
}
81
99
reader.stepIn()
82
100
state = State .IN_SYMBOL_TABLE_LIST
@@ -98,7 +116,7 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
98
116
}
99
117
isMacroTableAlreadyClassified = true
100
118
if (IonType .isText(type)) {
101
- if (SystemSymbols .ION_ENCODING == reader.stringValue() && ! isMacroTableAppend) {
119
+ if (SystemSymbols .DEFAULT_MODULE == reader.stringValue() && ! isMacroTableAppend) {
102
120
isMacroTableAppend = true
103
121
if (reader.next() == null ) {
104
122
return true
@@ -107,16 +125,27 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
107
125
throw IonException (" macro_table s-expression must begin with s-expression(s)." )
108
126
}
109
127
} else {
110
- throw IonException (" macro_table s-expression must begin with either \$ ion_encoding or s-expression(s)." )
128
+ throw IonException (" macro_table s-expression must begin with either '_' or s-expression(s)." )
111
129
}
112
130
} else if (type == IonType .SEXP ) {
113
131
localMacroMaxOffset = - 1
114
132
} else {
115
- throw IonException (" macro_table s-expression must begin with either \$ ion_encoding or s-expression(s)." )
133
+ throw IonException (" macro_table s-expression must begin with either '_' or s-expression(s)." )
116
134
}
117
135
return false
118
136
}
119
137
138
+ /* *
139
+ * Utility function to make error cases more concise.
140
+ * @param condition the condition under which an IonException should be thrown
141
+ * @param lazyErrorMessage the message to use in the exception
142
+ */
143
+ private inline fun errorIf (condition : Boolean , lazyErrorMessage : () -> String ) {
144
+ if (condition) {
145
+ throw IonException (lazyErrorMessage())
146
+ }
147
+ }
148
+
120
149
/* *
121
150
* Reads an encoding directive. After this method returns, the caller should access this class's properties to
122
151
* retrieve the symbols and macros declared within the directive.
@@ -126,30 +155,41 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
126
155
val macroCompiler = MacroCompiler ({ key -> resolveMacro(encodingContext, key) }, readerAdapter)
127
156
128
157
reader.stepIn()
129
- state = State .IN_ION_ENCODING_SEXP
158
+ state = State .IN_DIRECTIVE_SEXP
130
159
while (true ) {
131
160
when (state) {
132
161
133
- State .IN_ION_ENCODING_SEXP -> {
162
+ State .IN_DIRECTIVE_SEXP -> {
163
+ errorIf(reader.next() == null ) { " invalid Ion directive; missing directive keyword" }
164
+ classifyDirective()
165
+ }
166
+ State .IN_MODULE_DIRECTIVE_SEXP_AWAITING_MODULE_NAME -> {
167
+ errorIf(reader.next() == null ) { " invalid module directive; missing module name" }
168
+ errorIf(reader.type != IonType .SYMBOL ) { " invalid module directive; module name must be a symbol" }
169
+ // TODO: Support other module names
170
+ errorIf(DEFAULT_MODULE != reader.stringValue()) { " IonJava currently supports only the default module" }
171
+ state = State .IN_MODULE_DIRECTIVE_SEXP
172
+ }
173
+ State .IN_MODULE_DIRECTIVE_SEXP -> {
134
174
if (reader.next() == null ) {
135
175
reader.stepOut()
136
176
state = State .READING_VALUE
137
177
return
138
178
}
139
179
if (reader.type != IonType .SEXP ) {
140
- throw IonException (" Ion encoding directives must contain only s-expressions." )
180
+ throw IonException (" module definition must contain only s-expressions." )
141
181
}
142
182
reader.stepIn()
143
183
if (reader.next() == null || ! IonType .isText(reader.type)) {
144
- throw IonException (" S-expressions within encoding directives must begin with a text token." )
184
+ throw IonException (" S-expressions within module definitions must begin with a text token." )
145
185
}
146
- classifySexpWithinEncodingDirective ()
186
+ classifySexpWithinModuleDirective ()
147
187
}
148
188
149
189
State .IN_SYMBOL_TABLE_SEXP -> {
150
190
if (reader.next() == null || classifySymbolTable()) {
151
191
reader.stepOut()
152
- state = State .IN_ION_ENCODING_SEXP
192
+ state = State .IN_MODULE_DIRECTIVE_SEXP
153
193
continue
154
194
}
155
195
}
@@ -169,7 +209,7 @@ internal class EncodingDirectiveReader(private val reader: IonReader, private va
169
209
State .IN_MACRO_TABLE_SEXP -> {
170
210
if (reader.next() == null || classifyMacroTable()) {
171
211
reader.stepOut()
172
- state = State .IN_ION_ENCODING_SEXP
212
+ state = State .IN_MODULE_DIRECTIVE_SEXP
173
213
continue
174
214
}
175
215
state = State .COMPILING_MACRO
0 commit comments