Skip to content

Commit 32faaed

Browse files
committed
Removed all regexes as they don't work on compile-time
1 parent a4218c5 commit 32faaed

File tree

1 file changed

+90
-28
lines changed

1 file changed

+90
-28
lines changed

protobuf.nim

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,46 @@ when isMainModule:
5151
import "../combparser/combparser"
5252
import lists
5353

54-
proc charmatch(charsets: varargs[set[char]]): StringParser[string] =
55-
(proc (input: string): Maybe[(string, string), string] =
56-
var pos = 0
57-
for c in input:
58-
for s in charsets:
59-
if c in s: pos += 1
60-
if pos > 0:
61-
Just[(string, string), string]((input[0 .. pos], input[(pos + 1) .. input.len]))
62-
else:
63-
Nothing[(string, string), string](`pos` & ": Couldn't match regex \"" & `regexStr` & "\"", input)
64-
)
54+
macro charmatch(charset: set[char]): untyped =
55+
let pos = lineInfo(callsite())
56+
result = quote do:
57+
(proc (input: string): Maybe[(string, string), string] =
58+
var pos = 0
59+
for c in input:
60+
if c in `charset`: pos += 1
61+
else: break
62+
if pos > 0:
63+
Just[(string, string), string]((input[0 .. pos-1], input[pos .. input.len]))
64+
else:
65+
Nothing[(string, string), string](`pos` & ": Couldn't match characters \"" & (if `charset` == Whitespace: "Whitespace" else: $`charset`) & "\"", input)
66+
)
6567

68+
macro allbut(but: string): untyped =
69+
let pos = lineInfo(callsite())
70+
result = quote do:
71+
(proc (input: string): Maybe[(string, string), string] =
72+
var pos = input.find(`but`)
73+
if pos == -1:
74+
pos = input.len
75+
if pos > 0:
76+
Just[(string, string), string]((input[0 .. pos-1], input[pos .. input.len]))
77+
else:
78+
Nothing[(string, string), string](`pos` & ": All-but \"" & `but` & "\" failed", input)
79+
)
6680

6781
proc ignorefirst[T](first: StringParser[string], catch: StringParser[T]): StringParser[T] =
6882
(first + catch).map(proc(input: tuple[f1: string, f2: T]): T = input.f2) / catch
6983

7084
proc ignorelast[T](catch: StringParser[T], last: StringParser[string]): StringParser[T] =
7185
(catch + last).map(proc(input: tuple[f1: T, f2: string]): T = input.f1) / catch
7286

87+
proc ignoresides[T](first: StringParser[string], catch: StringParser[T], last: StringParser[string]): StringParser[T] =
88+
ignorefirst(first, catch).ignorelast(last)
89+
7390
proc andor(first, last: StringParser[string]): StringParser[string] =
7491
(first + last).map(proc(input: tuple[f1, f2: string]): string = input.f1 & input.f2) /
7592
(first / last)
7693

77-
proc ws(value: string): StringParser[string] =
78-
regex(r"\s*" & value & r"\s*")
79-
8094
proc combine(list: seq[string], sep: string): string =
8195
result = ""
8296
for entry in list:
@@ -86,49 +100,97 @@ when isMainModule:
86100
proc combine(list: seq[string]): string =
87101
list.combine("")
88102

89-
proc combine(t: tuple[f1, f2: string]): string = t.f1 & t.f2
103+
proc combine(t: tuple[f1, f2: string]): string =
104+
if t.f1 == nil:
105+
t.f2
106+
elif t.f2 == nil:
107+
t.f1
108+
else:
109+
t.f1 & t.f2
90110

91-
proc combine[T](t: tuple[f1: T, f2: string]): string = t.f1.combine() & t.f2
111+
proc combine[T](t: tuple[f1: T, f2: string]): string =
112+
if t.f2 == nil:
113+
t.f1.combine()
114+
else:
115+
t.f1.combine() & t.f2
92116

93-
proc combine[T](t: tuple[f1: string, f2: T]): string = t.f1 & t.f2.combine()
117+
proc combine[T](t: tuple[f1: string, f2: T]): string =
118+
if t.f1 == nil:
119+
t.f2.combine()
120+
else:
121+
t.f1 & t.f2.combine()
94122

95123
proc combine[T, U](t: tuple[f1: T, f2: U]): string = t.f1.combine() & t.f2.combine()
96124

97-
proc endcomment(): StringParser[string] = regex(r"\s*//.*\s*").repeat(1).map(combine)
125+
proc combine[T, U](t: tuple[f1: T, f2: StringParser[U]]): string = t.f1.combine() & t.f2.map(combine)
98126

99-
proc inlinecomment(): StringParser[string] = regex(r"\s*/\*.*\*/\s*").repeat(1).map(combine)
127+
proc combine[T, U](t: tuple[f1: StringParser[T], f2: StringParser[U]]): string = t.f1.map(combine) & t.f2.map(combine)
128+
129+
proc combine[T](list: seq[T]): string =
130+
result = ""
131+
for entry in list:
132+
result = result & entry.combine()
133+
134+
proc optwhitespace[T](parser: StringParser[T]): StringParser[T] =
135+
ignorefirst(charmatch(Whitespace), parser).ignorelast(charmatch(Whitespace))
136+
137+
proc ws(value: string): StringParser[string] =
138+
optwhitespace(s(value))
139+
140+
proc endcomment(): StringParser[string] =
141+
ignorefirst(charmatch(Whitespace), s("//") + allbut("\n") + s("\n")).repeat(1).map(combine)
142+
143+
proc inlinecomment(): StringParser[string] =
144+
ignorefirst(charmatch(Whitespace), s("/*") + allbut("*/") + s("*/")).repeat(1).map(combine)
100145

101146
proc comment(): StringParser[string] = andor(endcomment(), inlinecomment()).repeat(1).map(combine)
102147

103148
proc endstatement(): StringParser[string] =
104149
ignorefirst(inlinecomment(), ws(";")).ignorelast(comment())
105150

106151
proc str(): StringParser[string] =
107-
ignorefirst(inlinecomment(), regex(r"\s*\""[^""]*\""\s*")).map(
108-
proc(n: string): string =
109-
n.strip()[1..^2]
152+
ignorefirst(inlinecomment(), optwhitespace(s("\"") + allbut("\"") + s("\""))).map(
153+
proc(n: auto): string =
154+
n[0][1]
110155
).ignorelast(comment())
111156

112-
proc number(): StringParser[string] = regex(r"\s*[0-9]+\s*").map(proc(n: string): string =
113-
n.strip())
157+
proc number(): StringParser[string] =
158+
#n.strip())
159+
optwhitespace(charmatch(Digits))
114160

115161
proc strip(input: string): string =
116162
input.strip(true, true)
117163

118164
proc enumname(): StringParser[string] =
119-
ignorefirst(comment(), regex(r"\s*[A-Z]*\s*")).ignorelast(comment()).map(strip)
165+
ignorefirst(comment(),
166+
optwhitespace(charmatch({'A'..'Z'}))
167+
).ignorelast(comment())
120168

121169
proc token(): StringParser[string] =
122-
ignorefirst(comment(), regex(r"\s*[a-z][a-zA-Z0-9_]*\s*")).ignorelast(comment()).map(strip)
170+
ignorefirst(comment(),
171+
(
172+
ignorefirst(charmatch(Whitespace), charmatch({'a'..'z'})) +
173+
ignorelast(optional(charmatch({'a'..'z', 'A'..'Z', '0'..'9', '_'})), charmatch(Whitespace))
174+
).map(combine)
175+
).ignorelast(comment())
123176

124177
proc token(name: string): StringParser[string] =
125178
ignorefirst(comment(), ws(name)).ignorelast(comment()).map(strip)
126179

127180
proc class(): StringParser[string] =
128-
ignorefirst(comment(), regex(r"\s*[A-Z][a-zA-Z0-9_]*\s*")).ignorelast(comment()).map(strip)
181+
ignorefirst(comment(),
182+
(
183+
ignorefirst(charmatch(Whitespace), charmatch({'A'..'Z'})) +
184+
ignorelast(optional(charmatch({'a'..'z', 'A'..'Z', '0'..'9', '_'})), charmatch(Whitespace))
185+
).map(combine)
186+
).ignorelast(comment())
129187

130188
proc typespecifier(): StringParser[string] =
131-
ignorefirst(comment(), regex(r"\s*[A-Za-z0-9_\.]*\s*")).ignorelast(comment()).map(strip)
189+
ignorefirst(comment(),
190+
(
191+
optwhitespace(charmatch({'a'..'z', 'A'..'Z', '0'..'9', '_', '.'}))
192+
)
193+
).ignorelast(comment())
132194

133195
type
134196
ReservedType = enum

0 commit comments

Comments
 (0)