@@ -60,19 +60,88 @@ fun diagFailure(message: String): ResultWithDiagnostics.Failure {
60
60
return ResultWithDiagnostics .Failure (ScriptDiagnostic (ScriptDiagnostic .unspecifiedError, message))
61
61
}
62
62
63
- fun parseLibraryArgument (str : String ): Variable {
64
- val eq = str.indexOf(' =' )
65
- return if (eq == - 1 ) Variable (" " , str.trim())
66
- else Variable (str.substring(0 , eq).trim(), str.substring(eq + 1 ).trim())
63
+ data class ArgParseResult (
64
+ val variable : Variable ,
65
+ val end : Int
66
+ )
67
+
68
+ fun parseLibraryArgument (str : String , argEndChars : List <Char >, begin : Int ): ArgParseResult ? {
69
+ val eq = str.indexOf(' =' , begin)
70
+ val untrimmedName = if (eq < 0 ) " " else str.substring(begin, eq)
71
+ val name = untrimmedName.trim()
72
+
73
+ var argBegan = false
74
+ var argEnded = false
75
+ var quoteOpened = false
76
+ var escape = false
77
+
78
+ val builder = StringBuilder ()
79
+
80
+ var i = if (eq < 0 ) begin - 1 else eq
81
+ while ((++ i) < str.length) {
82
+ val c = str[i]
83
+
84
+ if (escape) {
85
+ builder.append(c)
86
+ escape = false
87
+ continue
88
+ }
89
+
90
+ when (c) {
91
+ ' \\ ' -> {
92
+ if (quoteOpened) escape = true
93
+ else builder.append(c)
94
+ }
95
+ ' "' -> {
96
+ if (argBegan) {
97
+ quoteOpened = false
98
+ argEnded = true
99
+ } else {
100
+ quoteOpened = true
101
+ argBegan = true
102
+ }
103
+ }
104
+ in argEndChars -> {
105
+ if (quoteOpened) builder.append(c)
106
+ else break
107
+ }
108
+ else -> {
109
+ if (! c.isWhitespace()) {
110
+ if (argEnded) {
111
+ throw ReplCompilerException (
112
+ " Cannot parse library arguments: unexpected char '$c ' " +
113
+ " on position $i " +
114
+ " in arguments string '$str '"
115
+ )
116
+ }
117
+ argBegan = true
118
+ builder.append(c)
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ val value = builder.toString().trim()
125
+ if (eq == - 1 && value.isEmpty()) return null
126
+
127
+ val nextIndex = if (i == str.length) i else i + 1
128
+ return ArgParseResult (Variable (name, value), nextIndex)
67
129
}
68
130
69
131
fun parseCall (str : String , brackets : Brackets ): Pair <String , List <Variable >> {
70
132
val openBracketIndex = str.indexOf(brackets.open)
71
133
if (openBracketIndex == - 1 ) return str.trim() to emptyList()
72
134
val name = str.substring(0 , openBracketIndex).trim()
73
- val args = str.substring(openBracketIndex + 1 , str.indexOf(brackets.close, openBracketIndex))
74
- .split(' ,' )
75
- .map(::parseLibraryArgument)
135
+ val argsString = str.substring(openBracketIndex + 1 , str.indexOfLast { it == brackets.close })
136
+
137
+ val endChars = listOf (brackets.close, ' ,' )
138
+ val firstArg = parseLibraryArgument(argsString, endChars, 0 )
139
+ val args = generateSequence(firstArg) {
140
+ parseLibraryArgument(argsString, endChars, it.end)
141
+ }.map {
142
+ it.variable
143
+ }.toList()
144
+
76
145
return name to args
77
146
}
78
147
0 commit comments