summary refs log tree commit diff stats
path: root/compiler/prefixmatches.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/prefixmatches.nim')
-rw-r--r--compiler/prefixmatches.nim56
1 files changed, 56 insertions, 0 deletions
diff --git a/compiler/prefixmatches.nim b/compiler/prefixmatches.nim
new file mode 100644
index 000000000..bfbe3d888
--- /dev/null
+++ b/compiler/prefixmatches.nim
@@ -0,0 +1,56 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2017 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+from std/strutils import toLowerAscii
+
+type
+  PrefixMatch* {.pure.} = enum
+    None,   ## no prefix detected
+    Abbrev  ## prefix is an abbreviation of the symbol
+    Substr, ## prefix is a substring of the symbol
+    Prefix, ## prefix does match the symbol
+
+proc prefixMatch*(p, s: string): PrefixMatch =
+  template eq(a, b): bool = a.toLowerAscii == b.toLowerAscii
+  if p.len > s.len: return PrefixMatch.None
+  var i = 0
+  # check for prefix/contains:
+  while i < s.len:
+    if s[i] == '_': inc i
+    if i < s.len and eq(s[i], p[0]):
+      var ii = i+1
+      var jj = 1
+      while ii < s.len and jj < p.len:
+        if p[jj] == '_': inc jj
+        if s[ii] == '_': inc ii
+        if not eq(s[ii], p[jj]): break
+        inc ii
+        inc jj
+
+      if jj >= p.len:
+        if i == 0: return PrefixMatch.Prefix
+        else: return PrefixMatch.Substr
+    inc i
+  # check for abbrev:
+  if eq(s[0], p[0]):
+    i = 1
+    var j = 1
+    while i < s.len:
+      if i < s.len-1 and s[i] == '_':
+        if j < p.len and eq(p[j], s[i+1]): inc j
+        else: return PrefixMatch.None
+      if i < s.len and s[i] in {'A'..'Z'} and s[i-1] notin {'A'..'Z'}:
+        if j < p.len and eq(p[j], s[i]): inc j
+        else: return PrefixMatch.None
+      inc i
+    if j >= p.len:
+      return PrefixMatch.Abbrev
+    else:
+      return PrefixMatch.None
+  return PrefixMatch.None