From 58011496071a49e8f5f916a0416c36806ee94614 Mon Sep 17 00:00:00 2001 From: Thibaut Horel Date: Tue, 15 Mar 2016 22:12:44 -0400 Subject: Add crossref resolution, minor api changes, first template inspired by plain.bst --- database.go | 186 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 145 insertions(+), 41 deletions(-) (limited to 'database.go') diff --git a/database.go b/database.go index 57d2008..945f9eb 100644 --- a/database.go +++ b/database.go @@ -6,68 +6,172 @@ import ( "strings" ) -type Literal interface{} +type Value interface { + Marshal() string + String() string +} type BraceLiteral string type StringLiteral string type NumberLiteral int -type VariableLiteral struct { +type VarLiteral struct { Name string Value *Value } -func Marshal(l Literal) (res string) { - switch v := l.(type) { - case BraceLiteral: - res = "{" + string(v) + "}" - case StringLiteral: - res = "\"" + string(v) + "\"" - case NumberLiteral: - res = strconv.Itoa(int(v)) - case VariableLiteral: - res = v.Name - } - return +type LiteralList []Value + +func (l BraceLiteral) String() string { + return string(l) +} + +func (l BraceLiteral) Marshal() string { + return "{" + string(l) + "}" +} + +func (l StringLiteral) String() string { + return string(l) +} + +func (l StringLiteral) Marshal() string { + return "\"" + string(l) + "\"" +} + +func (l NumberLiteral) Marshal() string { + return strconv.Itoa(int(l)) +} + +func (l NumberLiteral) String() string { + return strconv.Itoa(int(l)) +} + +func (l VarLiteral) String() string { + return (*l.Value).String() } -type Value []Literal +func (l VarLiteral) Marshal() string { + return l.Name +} + +func (l LiteralList) String() string { + var buf bytes.Buffer + for _, lit := range l { + buf.WriteString(lit.String()) + } + return buf.String() +} -func (v Value) Marshal() string { - res := make([]string, len(v)) - for i, l := range v { - res[i] = Marshal(l) +func (l LiteralList) Marshal() string { + res := make([]string, len(l)) + for i, lit := range l { + res[i] = lit.Marshal() } return strings.Join(res, " # ") } -func (v Value) String() string { - var buf bytes.Buffer - for _, l := range v { - switch lit := l.(type) { - case BraceLiteral: - buf.WriteString(string(lit)) - case StringLiteral: - buf.WriteString(string(lit)) - case NumberLiteral: - buf.WriteString(strconv.Itoa(int(lit))) - case VariableLiteral: - buf.WriteString(lit.Value.String()) +func flatten(v Value) Value { + switch t := v.(type) { + case LiteralList: + if len(t) == 1 { + return flatten(t[0]) + } else { + return BraceLiteral(t.String()) } + case VarLiteral: + return flatten(*t.Value) + default: + return v } - return buf.String() } type Entry struct { - Type string - Key string - Fields map[string]Value - FNames []string + Type string `json:"type"` + Key string `json:"key"` + Fields map[string]Value `json:"fields"` + FNames []string `json:"-"` +} + +func (e Entry) Marshal() string { + var buf bytes.Buffer + temp := make([]string, len(e.FNames)) + open, close := "{", "}" + if strings.Contains(e.Key, "}") { + open, close = "(", ")" + } + buf.WriteString("@" + e.Type + open + e.Key + ",") + if len(e.FNames) == 0 { + buf.WriteString(close) + return buf.String() + } else { + buf.WriteString("\n\t") + } + + for i, field := range e.FNames { + temp[i] = field + " = " + e.Fields[field].Marshal() + } + buf.WriteString(strings.Join(temp, ",\n\t")) + buf.WriteString("\n" + close) + return buf.String() } type Database struct { - SNames []string - Strings map[string]Value - Entries map[string]Entry - Preamble Value - EKeys []string + SNames []string `json:"-"` + Strings map[string]Value `json:"strings,omitempty"` + Entries map[string]Entry `json:"entries"` + Preamble Value `json:"preamble,omitempty"` + EKeys []string `json:"-"` + CrossRefs map[string]int `json:"crossrefs,omitempty"` +} + +func (d *Database) UnTex() { + for _, entry := range d.Entries { + for field, value := range entry.Fields { + switch v := value.(type) { + case BraceLiteral: + entry.Fields[field] = BraceLiteral(UnTex(v.String())) + case StringLiteral: + entry.Fields[field] = StringLiteral(UnTex(v.String())) + case Names: + v.untex() + } + } + } +} + +func (d *Database) Flatten() { + for _, entry := range d.Entries { + for field, value := range entry.Fields { + entry.Fields[field] = flatten(value) + } + } +} + +func (d *Database) SplitNames() { + for _, entry := range d.Entries { + for field, value := range entry.Fields { + if field == "author" || field == "editor" { + entry.Fields[field] = SplitNames(value.String()) + } + } + } +} + +func (d *Database) Resolve() { + var key string + var ref Entry + for _, entry := range d.Entries { + for field, value := range entry.Fields { + if field != "crossref" { + continue + } + key = strings.ToLower(value.String()) + ref = d.Entries[key] + for f, v := range ref.Fields { + if _, in := entry.Fields[f]; !in { + entry.Fields[f] = v + entry.FNames = append(entry.FNames, f) + } + } + } + } } -- cgit v1.2.3-70-g09d2