aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2017-11-01 17:56:52 +0200
committerOskari Timperi <oskari.timperi@iki.fi>2017-11-01 17:56:52 +0200
commitaa23bdaf994e84e92ea99fed2d1a024bee8589e1 (patch)
treeff98d8c92bb4c6fbbe81e9c00daac0e60dc14f1f
parentf27c02d9b77d1f179ba676e711c79ed53bceb218 (diff)
downloadnimrec-aa23bdaf994e84e92ea99fed2d1a024bee8589e1.tar.gz
nimrec-aa23bdaf994e84e92ea99fed2d1a024bee8589e1.zip
Reorganize code
-rw-r--r--nimrec/parser.nim (renamed from nimrec.nim)74
-rw-r--r--nimrec/record.nim64
-rw-r--r--nimrec/utils.nim22
-rw-r--r--tests/test.nim8
4 files changed, 97 insertions, 71 deletions
diff --git a/nimrec.nim b/nimrec/parser.nim
index 034bbfc..de3a7f5 100644
--- a/nimrec.nim
+++ b/nimrec/parser.nim
@@ -1,15 +1,9 @@
+import record
+
import streams
import strutils
-import tables
type
- Field* = ref object
- label*: string
- value*: string
-
- Record* = ref object
- fields: OrderedTableRef[string, seq[string]]
-
ParseState {.pure.} = enum
Initial
Comment
@@ -23,7 +17,7 @@ type
field: Field
record: Record
- RecParseError* = object of Exception
+ ParseError* = object of Exception
const
LabelFirstChar = {'a'..'z', 'A'..'Z', '%'}
@@ -36,20 +30,6 @@ proc newRecParser*(): RecParser =
new(result)
result.state = ParseState.Initial
-proc newField(): Field =
- new(result)
- result.label = ""
- result.value = ""
-
-proc newField(label, value: string): Field =
- new(result)
- result.label = label
- result.value = value
-
-proc newRecord(): Record =
- new(result)
- result.fields = newOrderedTable[string, seq[string]]()
-
proc feed*(parser: RecParser, ch: char, record: var Record): bool =
while true:
case parser.state
@@ -67,7 +47,7 @@ proc feed*(parser: RecParser, ch: char, record: var Record): bool =
parser.field = newField()
parser.field.label &= ch
else:
- raise newException(RecParseError, "parse error: expected a comment, a label or an empty line")
+ raise newException(ParseError, "parse error: expected a comment, a label or an empty line")
of ParseState.Comment:
case ch
of '\l':
@@ -80,7 +60,7 @@ proc feed*(parser: RecParser, ch: char, record: var Record): bool =
of LabelChar:
parser.field.label &= ch
else:
- raise newException(RecParseError,
+ raise newException(ParseError,
"parse error: invalid label char: " & ch)
of ParseState.Value:
case ch
@@ -91,7 +71,7 @@ proc feed*(parser: RecParser, ch: char, record: var Record): bool =
else:
parser.state = ParseState.FieldReady
of EofMarker:
- raise newException(RecParseError,
+ raise newException(ParseError,
"parse error: value must be terminated by a newline")
else:
parser.field.value &= ch
@@ -110,49 +90,9 @@ proc feed*(parser: RecParser, ch: char, record: var Record): bool =
else:
if parser.record == nil:
parser.record = newRecord()
- if hasKey(parser.record.fields, parser.field.label):
- add(parser.record.fields[parser.field.label], parser.field.value)
- else:
- add(parser.record.fields, parser.field.label,
- @[parser.field.value])
+ addField(parser.record, parser.field)
parser.field = nil
parser.state = ParseState.Initial
continue
break
-
-proc `[]`*(record: Record, label: string): string =
- result = record.fields[label][0]
-
-proc len*(record: Record): int =
- result = len(record.fields)
-
-iterator records*(stream: Stream): Record =
- let parser = newRecParser()
- var record: Record
-
- while true:
- var ch = readChar(stream)
-
- if feed(parser, ch, record):
- yield record
-
- if ch == EofMarker:
- break
-
-iterator pairs*(record: Record): (string, string) =
- for label, values in record.fields:
- for value in values:
- yield (label, value)
-
-iterator items*(record: Record): Field =
- for label, value in record:
- yield newField(label, value)
-
-proc hasField*(record: Record, label: string): bool =
- for field in record:
- if field.label == label:
- return true
-
-proc contains*(record: Record, label: string): bool =
- result = hasField(record, label)
diff --git a/nimrec/record.nim b/nimrec/record.nim
new file mode 100644
index 0000000..d8cbc8e
--- /dev/null
+++ b/nimrec/record.nim
@@ -0,0 +1,64 @@
+import times
+import strutils
+
+type
+ Field* = ref object
+ value*: string
+ label*: string
+
+ Record* = ref object
+ fields: seq[Field]
+
+proc newField*(): Field =
+ new(result)
+ result.label = ""
+ result.value = ""
+
+proc newField*(label, value: string): Field =
+ new(result)
+ result.label = label
+ result.value = value
+
+proc newRecord*(): Record =
+ new(result)
+ result.fields = @[]
+
+proc getField*(record: Record, label: string): Field =
+ for field in record.fields:
+ if field.label == label:
+ return field
+ raise newException(KeyError, format("no such field: $1", label))
+
+proc `[]`*(record: Record, label: string): string =
+ result = getField(record, label).value
+
+proc len*(record: Record): int =
+ result = len(record.fields)
+
+iterator pairs*(record: Record): (string, string) =
+ for field in record.fields:
+ yield (field.label, field.value)
+
+iterator items*(record: Record): Field =
+ for field in record.fields:
+ yield field
+
+iterator values*(record: Record, label: string): string =
+ for k, v in record:
+ if label == k:
+ yield v
+
+iterator labels*(record: Record): string =
+ for field in record:
+ yield field.label
+
+proc hasField*(record: Record, label: string): bool =
+ for field in record:
+ if field.label == label:
+ return true
+
+proc contains*(record: Record, label: string): bool =
+ result = hasField(record, label)
+
+proc addField*(record: Record, field: Field) =
+ add(record.fields, field)
diff --git a/nimrec/utils.nim b/nimrec/utils.nim
new file mode 100644
index 0000000..021a821
--- /dev/null
+++ b/nimrec/utils.nim
@@ -0,0 +1,22 @@
+import parser
+import record
+
+import streams
+
+iterator records*(stream: Stream): Record =
+ let parser = newRecParser()
+ var record: Record
+
+ while true:
+ var ch = readChar(stream)
+
+ if feed(parser, ch, record):
+ yield record
+
+ if ch == '\0':
+ break
+
+iterator records*(filename: string): Record =
+ let stream = newFileStream(filename)
+ for record in records(stream):
+ yield record
diff --git a/tests/test.nim b/tests/test.nim
index 5fb9821..70a9665 100644
--- a/tests/test.nim
+++ b/tests/test.nim
@@ -2,7 +2,7 @@ import unittest
import streams
import sequtils
-import nimrec
+import nimrec/[parser, record, recordset, utils]
suite "parsing":
test "basics":
@@ -95,12 +95,12 @@ Name: Foobar!
test "parse error if colon missing":
let ss = newStringStream("Name\nAge: 34\n")
- expect(RecParseError):
+ expect(ParseError):
discard toSeq(records(ss))
test "parse error if invalid label":
let ss = newStringStream("Name: John Doe\nFoo-bar: 111")
- expect(RecParseError):
+ expect(ParseError):
discard toSeq(records(ss))
test "label can start with %":
@@ -114,7 +114,7 @@ Name: Foobar!
test "field must be terminated by newline":
let ss = newStringStream("%rec: Entry\n%type: Id int")
- expect(RecParseError):
+ expect(ParseError):
discard toSeq(records(ss))
test "multiple fields with same label":