diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2017-11-01 17:56:52 +0200 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2017-11-01 17:56:52 +0200 |
| commit | aa23bdaf994e84e92ea99fed2d1a024bee8589e1 (patch) | |
| tree | ff98d8c92bb4c6fbbe81e9c00daac0e60dc14f1f | |
| parent | f27c02d9b77d1f179ba676e711c79ed53bceb218 (diff) | |
| download | nimrec-aa23bdaf994e84e92ea99fed2d1a024bee8589e1.tar.gz nimrec-aa23bdaf994e84e92ea99fed2d1a024bee8589e1.zip | |
Reorganize code
| -rw-r--r-- | nimrec/parser.nim (renamed from nimrec.nim) | 74 | ||||
| -rw-r--r-- | nimrec/record.nim | 64 | ||||
| -rw-r--r-- | nimrec/utils.nim | 22 | ||||
| -rw-r--r-- | tests/test.nim | 8 |
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": |
