diff --git a/Makefile b/Makefile index 68afc50..4ff6224 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ build_no_peg: depend bindata go build build: depend peg bindata - go build + go build -mod=readonly peg: peg erd.peg diff --git a/README.md b/README.md index daf60e1..22761ca 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,20 @@ get binary from [releases page](https://github.com/kaishuu0123/erd-go/releases). or -``` +```shell go get github.com/kaishuu0123/erd-go ``` or (for Mac) -``` +```shell brew tap kaishuu0123/erd-go brew install erd-go ``` ## Usage -``` +```shell Usage: erd-go [OPTIONS] PATTERN [PATH] @@ -45,19 +45,19 @@ Help Options: support input from STDIN. -``` +```shell cat examples/nfldb.er | erd-go ``` ex.) convert to png from dot (use dot command) -``` +```shell cat examples/nfldb.er | erd-go | dot -Tpng -o nfldb.png ``` ## Usage (Used by Docker container) -``` +```shell cat examples/nfldb.er | docker run --rm -i kaishuu0123/erd-go | docker run --rm -i risaacson/graphviz dot -T png > nfldb.png ``` @@ -68,19 +68,26 @@ see [examples directory](https://github.com/kaishuu0123/erd-go/blob/master/examp ## Build Instruction 1. install glide - ``` + + ```shell go get github.com/Masterminds/glide ``` + 1. install go-bindata - ``` + + ```shell go get github.com/jteeuwen/go-bindata ``` + 1. install peg - ``` + + ```shell go get github.com/pointlander/peg ``` + 1. make - ``` + + ```shell make ``` @@ -89,7 +96,8 @@ see [examples directory](https://github.com/kaishuu0123/erd-go/blob/master/examp MIT ## Credits + This work is based off of several existing projects: -* https://github.com/BurntSushi/erd -* https://github.com/unok/erdm +* +* diff --git a/erd.go b/erd.go index 68ac640..ca5fb26 100644 --- a/erd.go +++ b/erd.go @@ -1,10 +1,16 @@ package main import ( + "bytes" + "fmt" + "io" "io/ioutil" "log" "os" + "os/exec" "path/filepath" + "runtime" + "strings" "syscall" "text/template" @@ -56,7 +62,11 @@ func main() { } parser := &Parser{Buffer: contents} - parser.Init() + err = parser.Init() + if err != nil { + logStderr.Println(err) + os.Exit(1) + } err = parser.Parse() if err != nil { logStderr.Println(err) @@ -68,12 +78,13 @@ func main() { if parser.Erd.IsError { os.Exit(1) } + parser.Erd.CalcIsolated() dot, _ := Asset("templates/dot.tmpl") tables, _ := Asset("templates/dot_tables.tmpl") relations, _ := Asset("templates/dot_relations.tmpl") templates := template.Must( - template.New("").Parse( + template.New("").Funcs(template.FuncMap{"StringsJoin": strings.Join}).Parse( string(dot) + string(tables) + string(relations))) @@ -87,5 +98,33 @@ func main() { } } - templates.ExecuteTemplate(fd, "dot", parser.Erd) + var erdbuf bytes.Buffer + err = templates.ExecuteTemplate(&erdbuf, "dot", parser.Erd) + if err != nil { + logStderr.Println(err) + os.Exit(1) + } + + // The OutFormat only works with Graphviz together + if opts.OutFormat != "" { + dotcmd := "dot" + if runtime.GOOS == "windows" { + dotcmd = "dot.exe" + } + cmd := exec.Command(dotcmd, fmt.Sprintf("-T%s", opts.OutFormat)) + cmd.Stdin = &erdbuf + cmd.Stdout = fd + cmd.Stderr = fd + err = cmd.Run() + if err != nil { + logStderr.Println(err) + os.Exit(1) + } + } else { + n, err := io.Copy(fd, &erdbuf) + if err != nil { + logStderr.Printf("failed to copy buffer: err: %v, copied %d bytes\n", err, n) + os.Exit(1) + } + } } diff --git a/erd.peg b/erd.peg index 20e46e6..f086907 100644 --- a/erd.peg +++ b/erd.peg @@ -10,11 +10,15 @@ root <- expression EOT / EOT <- !. expression <- - (title_info / relation_info / table_info / comment_line / empty_line)* + (title_info / color_info / relation_info / table_info / comment_line / empty_line)* -empty_line <- ws { p.ClearTableAndColumn() } +empty_line <- ws { p.ClearTableAndColumn() } comment_line <- space* '#' comment_string newline +color_info <- 'colors' ws* '{' ws* (color_key_value ws* attribute_sep? ws*)* ws* '}' newline +color_key_value <- + attribute_key space* ':' space* attribute_value { p.AddColorDefine() } + title_info <- 'title' ws* '{' ws* (title_attribute ws* attribute_sep? ws*)* ws* '}' newline table_info <- @@ -66,4 +70,4 @@ newline_or_eot <- newline / EOT space <- [ \t]+ string <- (!["\t\r\n/:,\[\]{} ].)+ string_in_quote <- (!["\t\r\n].)+ -cardinality <- [01*+] +cardinality <- [01?*+] diff --git a/erd.peg.go b/erd.peg.go index 14c0d13..44e76aa 100644 --- a/erd.peg.go +++ b/erd.peg.go @@ -8,6 +8,7 @@ import ( "os" "sort" "strconv" + "strings" ) const endSymbol rune = 1114112 @@ -22,6 +23,8 @@ const ( ruleexpression ruleempty_line rulecomment_line + rulecolor_info + rulecolor_key_value ruletitle_info ruletable_info ruletable_title @@ -67,6 +70,7 @@ const ( ruleAction14 ruleAction15 ruleAction16 + ruleAction17 ) var rul3s = [...]string{ @@ -76,6 +80,8 @@ var rul3s = [...]string{ "expression", "empty_line", "comment_line", + "color_info", + "color_key_value", "title_info", "table_info", "table_title", @@ -121,6 +127,7 @@ var rul3s = [...]string{ "Action14", "Action15", "Action16", + "Action17", } type token32 struct { @@ -149,7 +156,7 @@ func (node *node32) print(w io.Writer, pretty bool, buffer string) { if !pretty { fmt.Fprintf(w, "%v %v\n", rule, quote) } else { - fmt.Fprintf(w, "\x1B[34m%v\x1B[m %v\n", rule, quote) + fmt.Fprintf(w, "\x1B[36m%v\x1B[m %v\n", rule, quote) } if node.up != nil { print(node.up, depth+1) @@ -237,7 +244,7 @@ type Parser struct { Buffer string buffer []rune - rules [51]func() bool + rules [54]func() bool parse func(rule ...int) error reset func() Pretty bool @@ -324,6 +331,12 @@ func (p *Parser) WriteSyntaxTree(w io.Writer) { p.tokens32.WriteSyntaxTree(w, p.Buffer) } +func (p *Parser) SprintSyntaxTree() string { + var bldr strings.Builder + p.WriteSyntaxTree(&bldr) + return bldr.String() +} + func (p *Parser) Execute() { buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 for _, token := range p.Tokens() { @@ -340,33 +353,35 @@ func (p *Parser) Execute() { case ruleAction2: p.ClearTableAndColumn() case ruleAction3: - p.AddTable(text) + p.AddColorDefine() case ruleAction4: - p.AddColumn(text) + p.AddTable(text) case ruleAction5: - p.AddRelation() + p.AddColumn(text) case ruleAction6: - p.SetRelationLeft(text) + p.AddRelation() case ruleAction7: - p.SetCardinalityLeft(text) + p.SetRelationLeft(text) case ruleAction8: - p.SetRelationRight(text) + p.SetCardinalityLeft(text) case ruleAction9: - p.SetCardinalityRight(text) + p.SetRelationRight(text) case ruleAction10: - p.AddTitleKeyValue() + p.SetCardinalityRight(text) case ruleAction11: - p.AddTableKeyValue() + p.AddTitleKeyValue() case ruleAction12: - p.AddColumnKeyValue() + p.AddTableKeyValue() case ruleAction13: - p.AddRelationKeyValue() + p.AddColumnKeyValue() case ruleAction14: - p.SetKey(text) + p.AddRelationKeyValue() case ruleAction15: - p.SetValue(text) + p.SetKey(text) case ruleAction16: p.SetValue(text) + case ruleAction17: + p.SetValue(text) } } @@ -550,7 +565,7 @@ func (p *Parser) Init(options ...func(*Parser) error) error { position, tokenIndex = position11, tokenIndex11 return false }, - /* 2 expression <- <(title_info / relation_info / table_info / comment_line / empty_line)*> */ + /* 2 expression <- <(title_info / color_info / relation_info / table_info / comment_line / empty_line)*> */ func() bool { { position15 := position @@ -565,23 +580,29 @@ func (p *Parser) Init(options ...func(*Parser) error) error { goto l18 l19: position, tokenIndex = position18, tokenIndex18 - if !_rules[rulerelation_info]() { + if !_rules[rulecolor_info]() { goto l20 } goto l18 l20: position, tokenIndex = position18, tokenIndex18 - if !_rules[ruletable_info]() { + if !_rules[rulerelation_info]() { goto l21 } goto l18 l21: position, tokenIndex = position18, tokenIndex18 - if !_rules[rulecomment_line]() { + if !_rules[ruletable_info]() { goto l22 } goto l18 l22: + position, tokenIndex = position18, tokenIndex18 + if !_rules[rulecomment_line]() { + goto l23 + } + goto l18 + l23: position, tokenIndex = position18, tokenIndex18 if !_rules[ruleempty_line]() { goto l17 @@ -598,1702 +619,1878 @@ func (p *Parser) Init(options ...func(*Parser) error) error { }, /* 3 empty_line <- <(ws Action2)> */ func() bool { - position23, tokenIndex23 := position, tokenIndex + position24, tokenIndex24 := position, tokenIndex { - position24 := position + position25 := position if !_rules[rulews]() { - goto l23 + goto l24 } if !_rules[ruleAction2]() { - goto l23 + goto l24 } - add(ruleempty_line, position24) + add(ruleempty_line, position25) } return true - l23: - position, tokenIndex = position23, tokenIndex23 + l24: + position, tokenIndex = position24, tokenIndex24 return false }, /* 4 comment_line <- <(space* '#' comment_string newline)> */ func() bool { - position25, tokenIndex25 := position, tokenIndex + position26, tokenIndex26 := position, tokenIndex { - position26 := position - l27: + position27 := position + l28: { - position28, tokenIndex28 := position, tokenIndex + position29, tokenIndex29 := position, tokenIndex if !_rules[rulespace]() { - goto l28 + goto l29 } - goto l27 - l28: - position, tokenIndex = position28, tokenIndex28 + goto l28 + l29: + position, tokenIndex = position29, tokenIndex29 } if buffer[position] != rune('#') { - goto l25 + goto l26 } position++ if !_rules[rulecomment_string]() { - goto l25 + goto l26 + } + if !_rules[rulenewline]() { + goto l26 + } + add(rulecomment_line, position27) + } + return true + l26: + position, tokenIndex = position26, tokenIndex26 + return false + }, + /* 5 color_info <- <('c' 'o' 'l' 'o' 'r' 's' ws* '{' ws* (color_key_value ws* attribute_sep? ws*)* ws* '}' newline)> */ + func() bool { + position30, tokenIndex30 := position, tokenIndex + { + position31 := position + if buffer[position] != rune('c') { + goto l30 + } + position++ + if buffer[position] != rune('o') { + goto l30 + } + position++ + if buffer[position] != rune('l') { + goto l30 + } + position++ + if buffer[position] != rune('o') { + goto l30 + } + position++ + if buffer[position] != rune('r') { + goto l30 + } + position++ + if buffer[position] != rune('s') { + goto l30 + } + position++ + l32: + { + position33, tokenIndex33 := position, tokenIndex + if !_rules[rulews]() { + goto l33 + } + goto l32 + l33: + position, tokenIndex = position33, tokenIndex33 + } + if buffer[position] != rune('{') { + goto l30 + } + position++ + l34: + { + position35, tokenIndex35 := position, tokenIndex + if !_rules[rulews]() { + goto l35 + } + goto l34 + l35: + position, tokenIndex = position35, tokenIndex35 + } + l36: + { + position37, tokenIndex37 := position, tokenIndex + if !_rules[rulecolor_key_value]() { + goto l37 + } + l38: + { + position39, tokenIndex39 := position, tokenIndex + if !_rules[rulews]() { + goto l39 + } + goto l38 + l39: + position, tokenIndex = position39, tokenIndex39 + } + { + position40, tokenIndex40 := position, tokenIndex + if !_rules[ruleattribute_sep]() { + goto l40 + } + goto l41 + l40: + position, tokenIndex = position40, tokenIndex40 + } + l41: + l42: + { + position43, tokenIndex43 := position, tokenIndex + if !_rules[rulews]() { + goto l43 + } + goto l42 + l43: + position, tokenIndex = position43, tokenIndex43 + } + goto l36 + l37: + position, tokenIndex = position37, tokenIndex37 + } + l44: + { + position45, tokenIndex45 := position, tokenIndex + if !_rules[rulews]() { + goto l45 + } + goto l44 + l45: + position, tokenIndex = position45, tokenIndex45 + } + if buffer[position] != rune('}') { + goto l30 } + position++ if !_rules[rulenewline]() { - goto l25 + goto l30 + } + add(rulecolor_info, position31) + } + return true + l30: + position, tokenIndex = position30, tokenIndex30 + return false + }, + /* 6 color_key_value <- <(attribute_key space* ':' space* attribute_value Action3)> */ + func() bool { + position46, tokenIndex46 := position, tokenIndex + { + position47 := position + if !_rules[ruleattribute_key]() { + goto l46 + } + l48: + { + position49, tokenIndex49 := position, tokenIndex + if !_rules[rulespace]() { + goto l49 + } + goto l48 + l49: + position, tokenIndex = position49, tokenIndex49 + } + if buffer[position] != rune(':') { + goto l46 + } + position++ + l50: + { + position51, tokenIndex51 := position, tokenIndex + if !_rules[rulespace]() { + goto l51 + } + goto l50 + l51: + position, tokenIndex = position51, tokenIndex51 + } + if !_rules[ruleattribute_value]() { + goto l46 } - add(rulecomment_line, position26) + if !_rules[ruleAction3]() { + goto l46 + } + add(rulecolor_key_value, position47) } return true - l25: - position, tokenIndex = position25, tokenIndex25 + l46: + position, tokenIndex = position46, tokenIndex46 return false }, - /* 5 title_info <- <('t' 'i' 't' 'l' 'e' ws* '{' ws* (title_attribute ws* attribute_sep? ws*)* ws* '}' newline)> */ + /* 7 title_info <- <('t' 'i' 't' 'l' 'e' ws* '{' ws* (title_attribute ws* attribute_sep? ws*)* ws* '}' newline)> */ func() bool { - position29, tokenIndex29 := position, tokenIndex + position52, tokenIndex52 := position, tokenIndex { - position30 := position + position53 := position if buffer[position] != rune('t') { - goto l29 + goto l52 } position++ if buffer[position] != rune('i') { - goto l29 + goto l52 } position++ if buffer[position] != rune('t') { - goto l29 + goto l52 } position++ if buffer[position] != rune('l') { - goto l29 + goto l52 } position++ if buffer[position] != rune('e') { - goto l29 + goto l52 } position++ - l31: + l54: { - position32, tokenIndex32 := position, tokenIndex + position55, tokenIndex55 := position, tokenIndex if !_rules[rulews]() { - goto l32 + goto l55 } - goto l31 - l32: - position, tokenIndex = position32, tokenIndex32 + goto l54 + l55: + position, tokenIndex = position55, tokenIndex55 } if buffer[position] != rune('{') { - goto l29 + goto l52 } position++ - l33: + l56: { - position34, tokenIndex34 := position, tokenIndex + position57, tokenIndex57 := position, tokenIndex if !_rules[rulews]() { - goto l34 + goto l57 } - goto l33 - l34: - position, tokenIndex = position34, tokenIndex34 + goto l56 + l57: + position, tokenIndex = position57, tokenIndex57 } - l35: + l58: { - position36, tokenIndex36 := position, tokenIndex + position59, tokenIndex59 := position, tokenIndex if !_rules[ruletitle_attribute]() { - goto l36 + goto l59 } - l37: + l60: { - position38, tokenIndex38 := position, tokenIndex + position61, tokenIndex61 := position, tokenIndex if !_rules[rulews]() { - goto l38 + goto l61 } - goto l37 - l38: - position, tokenIndex = position38, tokenIndex38 + goto l60 + l61: + position, tokenIndex = position61, tokenIndex61 } { - position39, tokenIndex39 := position, tokenIndex + position62, tokenIndex62 := position, tokenIndex if !_rules[ruleattribute_sep]() { - goto l39 + goto l62 } - goto l40 - l39: - position, tokenIndex = position39, tokenIndex39 + goto l63 + l62: + position, tokenIndex = position62, tokenIndex62 } - l40: - l41: + l63: + l64: { - position42, tokenIndex42 := position, tokenIndex + position65, tokenIndex65 := position, tokenIndex if !_rules[rulews]() { - goto l42 + goto l65 } - goto l41 - l42: - position, tokenIndex = position42, tokenIndex42 + goto l64 + l65: + position, tokenIndex = position65, tokenIndex65 } - goto l35 - l36: - position, tokenIndex = position36, tokenIndex36 + goto l58 + l59: + position, tokenIndex = position59, tokenIndex59 } - l43: + l66: { - position44, tokenIndex44 := position, tokenIndex + position67, tokenIndex67 := position, tokenIndex if !_rules[rulews]() { - goto l44 + goto l67 } - goto l43 - l44: - position, tokenIndex = position44, tokenIndex44 + goto l66 + l67: + position, tokenIndex = position67, tokenIndex67 } if buffer[position] != rune('}') { - goto l29 + goto l52 } position++ if !_rules[rulenewline]() { - goto l29 + goto l52 } - add(ruletitle_info, position30) + add(ruletitle_info, position53) } return true - l29: - position, tokenIndex = position29, tokenIndex29 + l52: + position, tokenIndex = position52, tokenIndex52 return false }, - /* 6 table_info <- <('[' table_title ']' (space* '{' ws* (table_attribute ws* attribute_sep?)* ws* '}' space*)? newline_or_eot (table_column / empty_line)*)> */ + /* 8 table_info <- <('[' table_title ']' (space* '{' ws* (table_attribute ws* attribute_sep?)* ws* '}' space*)? newline_or_eot (table_column / empty_line)*)> */ func() bool { - position45, tokenIndex45 := position, tokenIndex + position68, tokenIndex68 := position, tokenIndex { - position46 := position + position69 := position if buffer[position] != rune('[') { - goto l45 + goto l68 } position++ if !_rules[ruletable_title]() { - goto l45 + goto l68 } if buffer[position] != rune(']') { - goto l45 + goto l68 } position++ { - position47, tokenIndex47 := position, tokenIndex - l49: + position70, tokenIndex70 := position, tokenIndex + l72: { - position50, tokenIndex50 := position, tokenIndex + position73, tokenIndex73 := position, tokenIndex if !_rules[rulespace]() { - goto l50 + goto l73 } - goto l49 - l50: - position, tokenIndex = position50, tokenIndex50 + goto l72 + l73: + position, tokenIndex = position73, tokenIndex73 } if buffer[position] != rune('{') { - goto l47 + goto l70 } position++ - l51: + l74: { - position52, tokenIndex52 := position, tokenIndex + position75, tokenIndex75 := position, tokenIndex if !_rules[rulews]() { - goto l52 + goto l75 } - goto l51 - l52: - position, tokenIndex = position52, tokenIndex52 + goto l74 + l75: + position, tokenIndex = position75, tokenIndex75 } - l53: + l76: { - position54, tokenIndex54 := position, tokenIndex + position77, tokenIndex77 := position, tokenIndex if !_rules[ruletable_attribute]() { - goto l54 + goto l77 } - l55: + l78: { - position56, tokenIndex56 := position, tokenIndex + position79, tokenIndex79 := position, tokenIndex if !_rules[rulews]() { - goto l56 + goto l79 } - goto l55 - l56: - position, tokenIndex = position56, tokenIndex56 + goto l78 + l79: + position, tokenIndex = position79, tokenIndex79 } { - position57, tokenIndex57 := position, tokenIndex + position80, tokenIndex80 := position, tokenIndex if !_rules[ruleattribute_sep]() { - goto l57 + goto l80 } - goto l58 - l57: - position, tokenIndex = position57, tokenIndex57 + goto l81 + l80: + position, tokenIndex = position80, tokenIndex80 } - l58: - goto l53 - l54: - position, tokenIndex = position54, tokenIndex54 + l81: + goto l76 + l77: + position, tokenIndex = position77, tokenIndex77 } - l59: + l82: { - position60, tokenIndex60 := position, tokenIndex + position83, tokenIndex83 := position, tokenIndex if !_rules[rulews]() { - goto l60 + goto l83 } - goto l59 - l60: - position, tokenIndex = position60, tokenIndex60 + goto l82 + l83: + position, tokenIndex = position83, tokenIndex83 } if buffer[position] != rune('}') { - goto l47 + goto l70 } position++ - l61: + l84: { - position62, tokenIndex62 := position, tokenIndex + position85, tokenIndex85 := position, tokenIndex if !_rules[rulespace]() { - goto l62 + goto l85 } - goto l61 - l62: - position, tokenIndex = position62, tokenIndex62 + goto l84 + l85: + position, tokenIndex = position85, tokenIndex85 } - goto l48 - l47: - position, tokenIndex = position47, tokenIndex47 + goto l71 + l70: + position, tokenIndex = position70, tokenIndex70 } - l48: + l71: if !_rules[rulenewline_or_eot]() { - goto l45 + goto l68 } - l63: + l86: { - position64, tokenIndex64 := position, tokenIndex + position87, tokenIndex87 := position, tokenIndex { - position65, tokenIndex65 := position, tokenIndex + position88, tokenIndex88 := position, tokenIndex if !_rules[ruletable_column]() { - goto l66 + goto l89 } - goto l65 - l66: - position, tokenIndex = position65, tokenIndex65 + goto l88 + l89: + position, tokenIndex = position88, tokenIndex88 if !_rules[ruleempty_line]() { - goto l64 + goto l87 } } - l65: - goto l63 - l64: - position, tokenIndex = position64, tokenIndex64 + l88: + goto l86 + l87: + position, tokenIndex = position87, tokenIndex87 } - add(ruletable_info, position46) + add(ruletable_info, position69) } return true - l45: - position, tokenIndex = position45, tokenIndex45 + l68: + position, tokenIndex = position68, tokenIndex68 return false }, - /* 7 table_title <- <( Action3)> */ + /* 9 table_title <- <( Action4)> */ func() bool { - position67, tokenIndex67 := position, tokenIndex + position90, tokenIndex90 := position, tokenIndex { - position68 := position + position91 := position { - position69 := position + position92 := position if !_rules[rulestring]() { - goto l67 + goto l90 } - add(rulePegText, position69) + add(rulePegText, position92) } - if !_rules[ruleAction3]() { - goto l67 + if !_rules[ruleAction4]() { + goto l90 } - add(ruletable_title, position68) + add(ruletable_title, position91) } return true - l67: - position, tokenIndex = position67, tokenIndex67 + l90: + position, tokenIndex = position90, tokenIndex90 return false }, - /* 8 table_column <- <(space* column_name (space* '{' ws* (column_attribute ws* attribute_sep?)* ws* '}' space*)? newline_or_eot)> */ + /* 10 table_column <- <(space* column_name (space* '{' ws* (column_attribute ws* attribute_sep?)* ws* '}' space*)? newline_or_eot)> */ func() bool { - position70, tokenIndex70 := position, tokenIndex + position93, tokenIndex93 := position, tokenIndex { - position71 := position - l72: + position94 := position + l95: { - position73, tokenIndex73 := position, tokenIndex + position96, tokenIndex96 := position, tokenIndex if !_rules[rulespace]() { - goto l73 + goto l96 } - goto l72 - l73: - position, tokenIndex = position73, tokenIndex73 + goto l95 + l96: + position, tokenIndex = position96, tokenIndex96 } if !_rules[rulecolumn_name]() { - goto l70 + goto l93 } { - position74, tokenIndex74 := position, tokenIndex - l76: + position97, tokenIndex97 := position, tokenIndex + l99: { - position77, tokenIndex77 := position, tokenIndex + position100, tokenIndex100 := position, tokenIndex if !_rules[rulespace]() { - goto l77 + goto l100 } - goto l76 - l77: - position, tokenIndex = position77, tokenIndex77 + goto l99 + l100: + position, tokenIndex = position100, tokenIndex100 } if buffer[position] != rune('{') { - goto l74 + goto l97 } position++ - l78: + l101: { - position79, tokenIndex79 := position, tokenIndex + position102, tokenIndex102 := position, tokenIndex if !_rules[rulews]() { - goto l79 + goto l102 } - goto l78 - l79: - position, tokenIndex = position79, tokenIndex79 + goto l101 + l102: + position, tokenIndex = position102, tokenIndex102 } - l80: + l103: { - position81, tokenIndex81 := position, tokenIndex + position104, tokenIndex104 := position, tokenIndex if !_rules[rulecolumn_attribute]() { - goto l81 + goto l104 } - l82: + l105: { - position83, tokenIndex83 := position, tokenIndex + position106, tokenIndex106 := position, tokenIndex if !_rules[rulews]() { - goto l83 + goto l106 } - goto l82 - l83: - position, tokenIndex = position83, tokenIndex83 + goto l105 + l106: + position, tokenIndex = position106, tokenIndex106 } { - position84, tokenIndex84 := position, tokenIndex + position107, tokenIndex107 := position, tokenIndex if !_rules[ruleattribute_sep]() { - goto l84 + goto l107 } - goto l85 - l84: - position, tokenIndex = position84, tokenIndex84 + goto l108 + l107: + position, tokenIndex = position107, tokenIndex107 } - l85: - goto l80 - l81: - position, tokenIndex = position81, tokenIndex81 + l108: + goto l103 + l104: + position, tokenIndex = position104, tokenIndex104 } - l86: + l109: { - position87, tokenIndex87 := position, tokenIndex + position110, tokenIndex110 := position, tokenIndex if !_rules[rulews]() { - goto l87 + goto l110 } - goto l86 - l87: - position, tokenIndex = position87, tokenIndex87 + goto l109 + l110: + position, tokenIndex = position110, tokenIndex110 } if buffer[position] != rune('}') { - goto l74 + goto l97 } position++ - l88: + l111: { - position89, tokenIndex89 := position, tokenIndex + position112, tokenIndex112 := position, tokenIndex if !_rules[rulespace]() { - goto l89 + goto l112 } - goto l88 - l89: - position, tokenIndex = position89, tokenIndex89 + goto l111 + l112: + position, tokenIndex = position112, tokenIndex112 } - goto l75 - l74: - position, tokenIndex = position74, tokenIndex74 + goto l98 + l97: + position, tokenIndex = position97, tokenIndex97 } - l75: + l98: if !_rules[rulenewline_or_eot]() { - goto l70 + goto l93 } - add(ruletable_column, position71) + add(ruletable_column, position94) } return true - l70: - position, tokenIndex = position70, tokenIndex70 + l93: + position, tokenIndex = position93, tokenIndex93 return false }, - /* 9 column_name <- <( Action4)> */ + /* 11 column_name <- <( Action5)> */ func() bool { - position90, tokenIndex90 := position, tokenIndex + position113, tokenIndex113 := position, tokenIndex { - position91 := position + position114 := position { - position92 := position + position115 := position if !_rules[rulestring]() { - goto l90 + goto l113 } - add(rulePegText, position92) + add(rulePegText, position115) } - if !_rules[ruleAction4]() { - goto l90 + if !_rules[ruleAction5]() { + goto l113 } - add(rulecolumn_name, position91) + add(rulecolumn_name, position114) } return true - l90: - position, tokenIndex = position90, tokenIndex90 + l113: + position, tokenIndex = position113, tokenIndex113 return false }, - /* 10 relation_info <- <(space* relation_left space* cardinality_left ('-' '-') cardinality_right space* relation_right (ws* '{' ws* (relation_attribute ws* attribute_sep? ws*)* ws* '}')? newline_or_eot Action5)> */ + /* 12 relation_info <- <(space* relation_left space* cardinality_left ('-' '-') cardinality_right space* relation_right (ws* '{' ws* (relation_attribute ws* attribute_sep? ws*)* ws* '}')? newline_or_eot Action6)> */ func() bool { - position93, tokenIndex93 := position, tokenIndex + position116, tokenIndex116 := position, tokenIndex { - position94 := position - l95: + position117 := position + l118: { - position96, tokenIndex96 := position, tokenIndex + position119, tokenIndex119 := position, tokenIndex if !_rules[rulespace]() { - goto l96 + goto l119 } - goto l95 - l96: - position, tokenIndex = position96, tokenIndex96 + goto l118 + l119: + position, tokenIndex = position119, tokenIndex119 } if !_rules[rulerelation_left]() { - goto l93 + goto l116 } - l97: + l120: { - position98, tokenIndex98 := position, tokenIndex + position121, tokenIndex121 := position, tokenIndex if !_rules[rulespace]() { - goto l98 + goto l121 } - goto l97 - l98: - position, tokenIndex = position98, tokenIndex98 + goto l120 + l121: + position, tokenIndex = position121, tokenIndex121 } if !_rules[rulecardinality_left]() { - goto l93 + goto l116 } if buffer[position] != rune('-') { - goto l93 + goto l116 } position++ if buffer[position] != rune('-') { - goto l93 + goto l116 } position++ if !_rules[rulecardinality_right]() { - goto l93 + goto l116 } - l99: + l122: { - position100, tokenIndex100 := position, tokenIndex + position123, tokenIndex123 := position, tokenIndex if !_rules[rulespace]() { - goto l100 + goto l123 } - goto l99 - l100: - position, tokenIndex = position100, tokenIndex100 + goto l122 + l123: + position, tokenIndex = position123, tokenIndex123 } if !_rules[rulerelation_right]() { - goto l93 + goto l116 } { - position101, tokenIndex101 := position, tokenIndex - l103: + position124, tokenIndex124 := position, tokenIndex + l126: { - position104, tokenIndex104 := position, tokenIndex + position127, tokenIndex127 := position, tokenIndex if !_rules[rulews]() { - goto l104 + goto l127 } - goto l103 - l104: - position, tokenIndex = position104, tokenIndex104 + goto l126 + l127: + position, tokenIndex = position127, tokenIndex127 } if buffer[position] != rune('{') { - goto l101 + goto l124 } position++ - l105: + l128: { - position106, tokenIndex106 := position, tokenIndex + position129, tokenIndex129 := position, tokenIndex if !_rules[rulews]() { - goto l106 + goto l129 } - goto l105 - l106: - position, tokenIndex = position106, tokenIndex106 + goto l128 + l129: + position, tokenIndex = position129, tokenIndex129 } - l107: + l130: { - position108, tokenIndex108 := position, tokenIndex + position131, tokenIndex131 := position, tokenIndex if !_rules[rulerelation_attribute]() { - goto l108 + goto l131 } - l109: + l132: { - position110, tokenIndex110 := position, tokenIndex + position133, tokenIndex133 := position, tokenIndex if !_rules[rulews]() { - goto l110 + goto l133 } - goto l109 - l110: - position, tokenIndex = position110, tokenIndex110 + goto l132 + l133: + position, tokenIndex = position133, tokenIndex133 } { - position111, tokenIndex111 := position, tokenIndex + position134, tokenIndex134 := position, tokenIndex if !_rules[ruleattribute_sep]() { - goto l111 + goto l134 } - goto l112 - l111: - position, tokenIndex = position111, tokenIndex111 + goto l135 + l134: + position, tokenIndex = position134, tokenIndex134 } - l112: - l113: + l135: + l136: { - position114, tokenIndex114 := position, tokenIndex + position137, tokenIndex137 := position, tokenIndex if !_rules[rulews]() { - goto l114 + goto l137 } - goto l113 - l114: - position, tokenIndex = position114, tokenIndex114 + goto l136 + l137: + position, tokenIndex = position137, tokenIndex137 } - goto l107 - l108: - position, tokenIndex = position108, tokenIndex108 + goto l130 + l131: + position, tokenIndex = position131, tokenIndex131 } - l115: + l138: { - position116, tokenIndex116 := position, tokenIndex + position139, tokenIndex139 := position, tokenIndex if !_rules[rulews]() { - goto l116 + goto l139 } - goto l115 - l116: - position, tokenIndex = position116, tokenIndex116 + goto l138 + l139: + position, tokenIndex = position139, tokenIndex139 } if buffer[position] != rune('}') { - goto l101 + goto l124 } position++ - goto l102 - l101: - position, tokenIndex = position101, tokenIndex101 + goto l125 + l124: + position, tokenIndex = position124, tokenIndex124 } - l102: + l125: if !_rules[rulenewline_or_eot]() { - goto l93 + goto l116 } - if !_rules[ruleAction5]() { - goto l93 + if !_rules[ruleAction6]() { + goto l116 } - add(rulerelation_info, position94) + add(rulerelation_info, position117) } return true - l93: - position, tokenIndex = position93, tokenIndex93 + l116: + position, tokenIndex = position116, tokenIndex116 return false }, - /* 11 relation_left <- <( Action6)> */ + /* 13 relation_left <- <( Action7)> */ func() bool { - position117, tokenIndex117 := position, tokenIndex + position140, tokenIndex140 := position, tokenIndex { - position118 := position + position141 := position { - position119 := position + position142 := position if !_rules[rulestring]() { - goto l117 + goto l140 } - add(rulePegText, position119) + add(rulePegText, position142) } - if !_rules[ruleAction6]() { - goto l117 + if !_rules[ruleAction7]() { + goto l140 } - add(rulerelation_left, position118) + add(rulerelation_left, position141) } return true - l117: - position, tokenIndex = position117, tokenIndex117 + l140: + position, tokenIndex = position140, tokenIndex140 return false }, - /* 12 cardinality_left <- <( Action7)> */ + /* 14 cardinality_left <- <( Action8)> */ func() bool { - position120, tokenIndex120 := position, tokenIndex + position143, tokenIndex143 := position, tokenIndex { - position121 := position + position144 := position { - position122 := position + position145 := position if !_rules[rulecardinality]() { - goto l120 + goto l143 } - add(rulePegText, position122) + add(rulePegText, position145) } - if !_rules[ruleAction7]() { - goto l120 + if !_rules[ruleAction8]() { + goto l143 } - add(rulecardinality_left, position121) + add(rulecardinality_left, position144) } return true - l120: - position, tokenIndex = position120, tokenIndex120 + l143: + position, tokenIndex = position143, tokenIndex143 return false }, - /* 13 relation_right <- <( Action8)> */ + /* 15 relation_right <- <( Action9)> */ func() bool { - position123, tokenIndex123 := position, tokenIndex + position146, tokenIndex146 := position, tokenIndex { - position124 := position + position147 := position { - position125 := position + position148 := position if !_rules[rulestring]() { - goto l123 + goto l146 } - add(rulePegText, position125) + add(rulePegText, position148) } - if !_rules[ruleAction8]() { - goto l123 + if !_rules[ruleAction9]() { + goto l146 } - add(rulerelation_right, position124) + add(rulerelation_right, position147) } return true - l123: - position, tokenIndex = position123, tokenIndex123 + l146: + position, tokenIndex = position146, tokenIndex146 return false }, - /* 14 cardinality_right <- <( Action9)> */ + /* 16 cardinality_right <- <( Action10)> */ func() bool { - position126, tokenIndex126 := position, tokenIndex + position149, tokenIndex149 := position, tokenIndex { - position127 := position + position150 := position { - position128 := position + position151 := position if !_rules[rulecardinality]() { - goto l126 + goto l149 } - add(rulePegText, position128) + add(rulePegText, position151) } - if !_rules[ruleAction9]() { - goto l126 + if !_rules[ruleAction10]() { + goto l149 } - add(rulecardinality_right, position127) + add(rulecardinality_right, position150) } return true - l126: - position, tokenIndex = position126, tokenIndex126 + l149: + position, tokenIndex = position149, tokenIndex149 return false }, - /* 15 title_attribute <- <(attribute_key space* ':' space* attribute_value Action10)> */ + /* 17 title_attribute <- <(attribute_key space* ':' space* attribute_value Action11)> */ func() bool { - position129, tokenIndex129 := position, tokenIndex + position152, tokenIndex152 := position, tokenIndex { - position130 := position + position153 := position if !_rules[ruleattribute_key]() { - goto l129 + goto l152 } - l131: + l154: { - position132, tokenIndex132 := position, tokenIndex + position155, tokenIndex155 := position, tokenIndex if !_rules[rulespace]() { - goto l132 + goto l155 } - goto l131 - l132: - position, tokenIndex = position132, tokenIndex132 + goto l154 + l155: + position, tokenIndex = position155, tokenIndex155 } if buffer[position] != rune(':') { - goto l129 + goto l152 } position++ - l133: + l156: { - position134, tokenIndex134 := position, tokenIndex + position157, tokenIndex157 := position, tokenIndex if !_rules[rulespace]() { - goto l134 + goto l157 } - goto l133 - l134: - position, tokenIndex = position134, tokenIndex134 + goto l156 + l157: + position, tokenIndex = position157, tokenIndex157 } if !_rules[ruleattribute_value]() { - goto l129 + goto l152 } - if !_rules[ruleAction10]() { - goto l129 + if !_rules[ruleAction11]() { + goto l152 } - add(ruletitle_attribute, position130) + add(ruletitle_attribute, position153) } return true - l129: - position, tokenIndex = position129, tokenIndex129 + l152: + position, tokenIndex = position152, tokenIndex152 return false }, - /* 16 table_attribute <- <(attribute_key space* ':' space* attribute_value Action11)> */ + /* 18 table_attribute <- <(attribute_key space* ':' space* attribute_value Action12)> */ func() bool { - position135, tokenIndex135 := position, tokenIndex + position158, tokenIndex158 := position, tokenIndex { - position136 := position + position159 := position if !_rules[ruleattribute_key]() { - goto l135 + goto l158 } - l137: + l160: { - position138, tokenIndex138 := position, tokenIndex + position161, tokenIndex161 := position, tokenIndex if !_rules[rulespace]() { - goto l138 + goto l161 } - goto l137 - l138: - position, tokenIndex = position138, tokenIndex138 + goto l160 + l161: + position, tokenIndex = position161, tokenIndex161 } if buffer[position] != rune(':') { - goto l135 + goto l158 } position++ - l139: + l162: { - position140, tokenIndex140 := position, tokenIndex + position163, tokenIndex163 := position, tokenIndex if !_rules[rulespace]() { - goto l140 + goto l163 } - goto l139 - l140: - position, tokenIndex = position140, tokenIndex140 + goto l162 + l163: + position, tokenIndex = position163, tokenIndex163 } if !_rules[ruleattribute_value]() { - goto l135 + goto l158 } - if !_rules[ruleAction11]() { - goto l135 + if !_rules[ruleAction12]() { + goto l158 } - add(ruletable_attribute, position136) + add(ruletable_attribute, position159) } return true - l135: - position, tokenIndex = position135, tokenIndex135 + l158: + position, tokenIndex = position158, tokenIndex158 return false }, - /* 17 column_attribute <- <(attribute_key space* ':' space* attribute_value Action12)> */ + /* 19 column_attribute <- <(attribute_key space* ':' space* attribute_value Action13)> */ func() bool { - position141, tokenIndex141 := position, tokenIndex + position164, tokenIndex164 := position, tokenIndex { - position142 := position + position165 := position if !_rules[ruleattribute_key]() { - goto l141 + goto l164 } - l143: + l166: { - position144, tokenIndex144 := position, tokenIndex + position167, tokenIndex167 := position, tokenIndex if !_rules[rulespace]() { - goto l144 + goto l167 } - goto l143 - l144: - position, tokenIndex = position144, tokenIndex144 + goto l166 + l167: + position, tokenIndex = position167, tokenIndex167 } if buffer[position] != rune(':') { - goto l141 + goto l164 } position++ - l145: + l168: { - position146, tokenIndex146 := position, tokenIndex + position169, tokenIndex169 := position, tokenIndex if !_rules[rulespace]() { - goto l146 + goto l169 } - goto l145 - l146: - position, tokenIndex = position146, tokenIndex146 + goto l168 + l169: + position, tokenIndex = position169, tokenIndex169 } if !_rules[ruleattribute_value]() { - goto l141 + goto l164 } - if !_rules[ruleAction12]() { - goto l141 + if !_rules[ruleAction13]() { + goto l164 } - add(rulecolumn_attribute, position142) + add(rulecolumn_attribute, position165) } return true - l141: - position, tokenIndex = position141, tokenIndex141 + l164: + position, tokenIndex = position164, tokenIndex164 return false }, - /* 18 relation_attribute <- <(attribute_key space* ':' space* attribute_value Action13)> */ + /* 20 relation_attribute <- <(attribute_key space* ':' space* attribute_value Action14)> */ func() bool { - position147, tokenIndex147 := position, tokenIndex + position170, tokenIndex170 := position, tokenIndex { - position148 := position + position171 := position if !_rules[ruleattribute_key]() { - goto l147 + goto l170 } - l149: + l172: { - position150, tokenIndex150 := position, tokenIndex + position173, tokenIndex173 := position, tokenIndex if !_rules[rulespace]() { - goto l150 + goto l173 } - goto l149 - l150: - position, tokenIndex = position150, tokenIndex150 + goto l172 + l173: + position, tokenIndex = position173, tokenIndex173 } if buffer[position] != rune(':') { - goto l147 + goto l170 } position++ - l151: + l174: { - position152, tokenIndex152 := position, tokenIndex + position175, tokenIndex175 := position, tokenIndex if !_rules[rulespace]() { - goto l152 + goto l175 } - goto l151 - l152: - position, tokenIndex = position152, tokenIndex152 + goto l174 + l175: + position, tokenIndex = position175, tokenIndex175 } if !_rules[ruleattribute_value]() { - goto l147 + goto l170 } - if !_rules[ruleAction13]() { - goto l147 + if !_rules[ruleAction14]() { + goto l170 } - add(rulerelation_attribute, position148) + add(rulerelation_attribute, position171) } return true - l147: - position, tokenIndex = position147, tokenIndex147 + l170: + position, tokenIndex = position170, tokenIndex170 return false }, - /* 19 attribute_key <- <( Action14)> */ + /* 21 attribute_key <- <( Action15)> */ func() bool { - position153, tokenIndex153 := position, tokenIndex + position176, tokenIndex176 := position, tokenIndex { - position154 := position + position177 := position { - position155 := position + position178 := position if !_rules[rulestring]() { - goto l153 + goto l176 } - add(rulePegText, position155) + add(rulePegText, position178) } - if !_rules[ruleAction14]() { - goto l153 + if !_rules[ruleAction15]() { + goto l176 } - add(ruleattribute_key, position154) + add(ruleattribute_key, position177) } return true - l153: - position, tokenIndex = position153, tokenIndex153 + l176: + position, tokenIndex = position176, tokenIndex176 return false }, - /* 20 attribute_value <- <(bare_value / quoted_value)> */ + /* 22 attribute_value <- <(bare_value / quoted_value)> */ func() bool { - position156, tokenIndex156 := position, tokenIndex + position179, tokenIndex179 := position, tokenIndex { - position157 := position + position180 := position { - position158, tokenIndex158 := position, tokenIndex + position181, tokenIndex181 := position, tokenIndex if !_rules[rulebare_value]() { - goto l159 + goto l182 } - goto l158 - l159: - position, tokenIndex = position158, tokenIndex158 + goto l181 + l182: + position, tokenIndex = position181, tokenIndex181 if !_rules[rulequoted_value]() { - goto l156 + goto l179 } } - l158: - add(ruleattribute_value, position157) + l181: + add(ruleattribute_value, position180) } return true - l156: - position, tokenIndex = position156, tokenIndex156 + l179: + position, tokenIndex = position179, tokenIndex179 return false }, - /* 21 bare_value <- <( Action15)> */ + /* 23 bare_value <- <( Action16)> */ func() bool { - position160, tokenIndex160 := position, tokenIndex + position183, tokenIndex183 := position, tokenIndex { - position161 := position + position184 := position { - position162 := position + position185 := position if !_rules[rulestring]() { - goto l160 + goto l183 } - add(rulePegText, position162) + add(rulePegText, position185) } - if !_rules[ruleAction15]() { - goto l160 + if !_rules[ruleAction16]() { + goto l183 } - add(rulebare_value, position161) + add(rulebare_value, position184) } return true - l160: - position, tokenIndex = position160, tokenIndex160 + l183: + position, tokenIndex = position183, tokenIndex183 return false }, - /* 22 quoted_value <- <(<('"' string_in_quote '"')> Action16)> */ + /* 24 quoted_value <- <(<('"' string_in_quote '"')> Action17)> */ func() bool { - position163, tokenIndex163 := position, tokenIndex + position186, tokenIndex186 := position, tokenIndex { - position164 := position + position187 := position { - position165 := position + position188 := position if buffer[position] != rune('"') { - goto l163 + goto l186 } position++ if !_rules[rulestring_in_quote]() { - goto l163 + goto l186 } if buffer[position] != rune('"') { - goto l163 + goto l186 } position++ - add(rulePegText, position165) + add(rulePegText, position188) } - if !_rules[ruleAction16]() { - goto l163 + if !_rules[ruleAction17]() { + goto l186 } - add(rulequoted_value, position164) + add(rulequoted_value, position187) } return true - l163: - position, tokenIndex = position163, tokenIndex163 + l186: + position, tokenIndex = position186, tokenIndex186 return false }, - /* 23 attribute_sep <- <(space* ',' space*)> */ + /* 25 attribute_sep <- <(space* ',' space*)> */ func() bool { - position166, tokenIndex166 := position, tokenIndex + position189, tokenIndex189 := position, tokenIndex { - position167 := position - l168: + position190 := position + l191: { - position169, tokenIndex169 := position, tokenIndex + position192, tokenIndex192 := position, tokenIndex if !_rules[rulespace]() { - goto l169 + goto l192 } - goto l168 - l169: - position, tokenIndex = position169, tokenIndex169 + goto l191 + l192: + position, tokenIndex = position192, tokenIndex192 } if buffer[position] != rune(',') { - goto l166 + goto l189 } position++ - l170: + l193: { - position171, tokenIndex171 := position, tokenIndex + position194, tokenIndex194 := position, tokenIndex if !_rules[rulespace]() { - goto l171 + goto l194 } - goto l170 - l171: - position, tokenIndex = position171, tokenIndex171 + goto l193 + l194: + position, tokenIndex = position194, tokenIndex194 } - add(ruleattribute_sep, position167) + add(ruleattribute_sep, position190) } return true - l166: - position, tokenIndex = position166, tokenIndex166 + l189: + position, tokenIndex = position189, tokenIndex189 return false }, - /* 24 comment_string <- <(!('\r' / '\n') .)*> */ + /* 26 comment_string <- <(!('\r' / '\n') .)*> */ func() bool { { - position173 := position - l174: + position196 := position + l197: { - position175, tokenIndex175 := position, tokenIndex + position198, tokenIndex198 := position, tokenIndex { - position176, tokenIndex176 := position, tokenIndex + position199, tokenIndex199 := position, tokenIndex { - position177, tokenIndex177 := position, tokenIndex + position200, tokenIndex200 := position, tokenIndex if buffer[position] != rune('\r') { - goto l178 + goto l201 } position++ - goto l177 - l178: - position, tokenIndex = position177, tokenIndex177 + goto l200 + l201: + position, tokenIndex = position200, tokenIndex200 if buffer[position] != rune('\n') { - goto l176 + goto l199 } position++ } - l177: - goto l175 - l176: - position, tokenIndex = position176, tokenIndex176 + l200: + goto l198 + l199: + position, tokenIndex = position199, tokenIndex199 } if !matchDot() { - goto l175 + goto l198 } - goto l174 - l175: - position, tokenIndex = position175, tokenIndex175 + goto l197 + l198: + position, tokenIndex = position198, tokenIndex198 } - add(rulecomment_string, position173) + add(rulecomment_string, position196) } return true }, - /* 25 ws <- <(' ' / '\t' / '\r' / '\n')+> */ + /* 27 ws <- <(' ' / '\t' / '\r' / '\n')+> */ func() bool { - position179, tokenIndex179 := position, tokenIndex + position202, tokenIndex202 := position, tokenIndex { - position180 := position + position203 := position { - position183, tokenIndex183 := position, tokenIndex + position206, tokenIndex206 := position, tokenIndex if buffer[position] != rune(' ') { - goto l184 + goto l207 } position++ - goto l183 - l184: - position, tokenIndex = position183, tokenIndex183 + goto l206 + l207: + position, tokenIndex = position206, tokenIndex206 if buffer[position] != rune('\t') { - goto l185 + goto l208 } position++ - goto l183 - l185: - position, tokenIndex = position183, tokenIndex183 + goto l206 + l208: + position, tokenIndex = position206, tokenIndex206 if buffer[position] != rune('\r') { - goto l186 + goto l209 } position++ - goto l183 - l186: - position, tokenIndex = position183, tokenIndex183 + goto l206 + l209: + position, tokenIndex = position206, tokenIndex206 if buffer[position] != rune('\n') { - goto l179 + goto l202 } position++ } - l183: - l181: + l206: + l204: { - position182, tokenIndex182 := position, tokenIndex + position205, tokenIndex205 := position, tokenIndex { - position187, tokenIndex187 := position, tokenIndex + position210, tokenIndex210 := position, tokenIndex if buffer[position] != rune(' ') { - goto l188 + goto l211 } position++ - goto l187 - l188: - position, tokenIndex = position187, tokenIndex187 + goto l210 + l211: + position, tokenIndex = position210, tokenIndex210 if buffer[position] != rune('\t') { - goto l189 + goto l212 } position++ - goto l187 - l189: - position, tokenIndex = position187, tokenIndex187 + goto l210 + l212: + position, tokenIndex = position210, tokenIndex210 if buffer[position] != rune('\r') { - goto l190 + goto l213 } position++ - goto l187 - l190: - position, tokenIndex = position187, tokenIndex187 + goto l210 + l213: + position, tokenIndex = position210, tokenIndex210 if buffer[position] != rune('\n') { - goto l182 + goto l205 } position++ } - l187: - goto l181 - l182: - position, tokenIndex = position182, tokenIndex182 + l210: + goto l204 + l205: + position, tokenIndex = position205, tokenIndex205 } - add(rulews, position180) + add(rulews, position203) } return true - l179: - position, tokenIndex = position179, tokenIndex179 + l202: + position, tokenIndex = position202, tokenIndex202 return false }, - /* 26 newline <- <(('\r' '\n') / '\n' / '\r')> */ + /* 28 newline <- <(('\r' '\n') / '\n' / '\r')> */ func() bool { - position191, tokenIndex191 := position, tokenIndex + position214, tokenIndex214 := position, tokenIndex { - position192 := position + position215 := position { - position193, tokenIndex193 := position, tokenIndex + position216, tokenIndex216 := position, tokenIndex if buffer[position] != rune('\r') { - goto l194 + goto l217 } position++ if buffer[position] != rune('\n') { - goto l194 + goto l217 } position++ - goto l193 - l194: - position, tokenIndex = position193, tokenIndex193 + goto l216 + l217: + position, tokenIndex = position216, tokenIndex216 if buffer[position] != rune('\n') { - goto l195 + goto l218 } position++ - goto l193 - l195: - position, tokenIndex = position193, tokenIndex193 + goto l216 + l218: + position, tokenIndex = position216, tokenIndex216 if buffer[position] != rune('\r') { - goto l191 + goto l214 } position++ } - l193: - add(rulenewline, position192) + l216: + add(rulenewline, position215) } return true - l191: - position, tokenIndex = position191, tokenIndex191 + l214: + position, tokenIndex = position214, tokenIndex214 return false }, - /* 27 newline_or_eot <- <(newline / EOT)> */ + /* 29 newline_or_eot <- <(newline / EOT)> */ func() bool { - position196, tokenIndex196 := position, tokenIndex + position219, tokenIndex219 := position, tokenIndex { - position197 := position + position220 := position { - position198, tokenIndex198 := position, tokenIndex + position221, tokenIndex221 := position, tokenIndex if !_rules[rulenewline]() { - goto l199 + goto l222 } - goto l198 - l199: - position, tokenIndex = position198, tokenIndex198 + goto l221 + l222: + position, tokenIndex = position221, tokenIndex221 if !_rules[ruleEOT]() { - goto l196 + goto l219 } } - l198: - add(rulenewline_or_eot, position197) + l221: + add(rulenewline_or_eot, position220) } return true - l196: - position, tokenIndex = position196, tokenIndex196 + l219: + position, tokenIndex = position219, tokenIndex219 return false }, - /* 28 space <- <(' ' / '\t')+> */ + /* 30 space <- <(' ' / '\t')+> */ func() bool { - position200, tokenIndex200 := position, tokenIndex + position223, tokenIndex223 := position, tokenIndex { - position201 := position + position224 := position { - position204, tokenIndex204 := position, tokenIndex + position227, tokenIndex227 := position, tokenIndex if buffer[position] != rune(' ') { - goto l205 + goto l228 } position++ - goto l204 - l205: - position, tokenIndex = position204, tokenIndex204 + goto l227 + l228: + position, tokenIndex = position227, tokenIndex227 if buffer[position] != rune('\t') { - goto l200 + goto l223 } position++ } - l204: - l202: + l227: + l225: { - position203, tokenIndex203 := position, tokenIndex + position226, tokenIndex226 := position, tokenIndex { - position206, tokenIndex206 := position, tokenIndex + position229, tokenIndex229 := position, tokenIndex if buffer[position] != rune(' ') { - goto l207 + goto l230 } position++ - goto l206 - l207: - position, tokenIndex = position206, tokenIndex206 + goto l229 + l230: + position, tokenIndex = position229, tokenIndex229 if buffer[position] != rune('\t') { - goto l203 + goto l226 } position++ } - l206: - goto l202 - l203: - position, tokenIndex = position203, tokenIndex203 + l229: + goto l225 + l226: + position, tokenIndex = position226, tokenIndex226 } - add(rulespace, position201) + add(rulespace, position224) } return true - l200: - position, tokenIndex = position200, tokenIndex200 + l223: + position, tokenIndex = position223, tokenIndex223 return false }, - /* 29 string <- <(!('"' / '\t' / '\r' / '\n' / '/' / ':' / ',' / '[' / ']' / '{' / '}' / ' ') .)+> */ + /* 31 string <- <(!('"' / '\t' / '\r' / '\n' / '/' / ':' / ',' / '[' / ']' / '{' / '}' / ' ') .)+> */ func() bool { - position208, tokenIndex208 := position, tokenIndex + position231, tokenIndex231 := position, tokenIndex { - position209 := position + position232 := position { - position212, tokenIndex212 := position, tokenIndex + position235, tokenIndex235 := position, tokenIndex { - position213, tokenIndex213 := position, tokenIndex + position236, tokenIndex236 := position, tokenIndex if buffer[position] != rune('"') { - goto l214 + goto l237 } position++ - goto l213 - l214: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l237: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('\t') { - goto l215 + goto l238 } position++ - goto l213 - l215: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l238: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('\r') { - goto l216 + goto l239 } position++ - goto l213 - l216: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l239: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('\n') { - goto l217 + goto l240 } position++ - goto l213 - l217: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l240: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('/') { - goto l218 + goto l241 } position++ - goto l213 - l218: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l241: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune(':') { - goto l219 + goto l242 } position++ - goto l213 - l219: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l242: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune(',') { - goto l220 + goto l243 } position++ - goto l213 - l220: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l243: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('[') { - goto l221 + goto l244 } position++ - goto l213 - l221: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l244: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune(']') { - goto l222 + goto l245 } position++ - goto l213 - l222: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l245: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('{') { - goto l223 + goto l246 } position++ - goto l213 - l223: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l246: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune('}') { - goto l224 + goto l247 } position++ - goto l213 - l224: - position, tokenIndex = position213, tokenIndex213 + goto l236 + l247: + position, tokenIndex = position236, tokenIndex236 if buffer[position] != rune(' ') { - goto l212 + goto l235 } position++ } - l213: - goto l208 - l212: - position, tokenIndex = position212, tokenIndex212 + l236: + goto l231 + l235: + position, tokenIndex = position235, tokenIndex235 } if !matchDot() { - goto l208 + goto l231 } - l210: + l233: { - position211, tokenIndex211 := position, tokenIndex + position234, tokenIndex234 := position, tokenIndex { - position225, tokenIndex225 := position, tokenIndex + position248, tokenIndex248 := position, tokenIndex { - position226, tokenIndex226 := position, tokenIndex + position249, tokenIndex249 := position, tokenIndex if buffer[position] != rune('"') { - goto l227 + goto l250 } position++ - goto l226 - l227: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l250: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('\t') { - goto l228 + goto l251 } position++ - goto l226 - l228: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l251: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('\r') { - goto l229 + goto l252 } position++ - goto l226 - l229: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l252: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('\n') { - goto l230 + goto l253 } position++ - goto l226 - l230: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l253: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('/') { - goto l231 + goto l254 } position++ - goto l226 - l231: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l254: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune(':') { - goto l232 + goto l255 } position++ - goto l226 - l232: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l255: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune(',') { - goto l233 + goto l256 } position++ - goto l226 - l233: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l256: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('[') { - goto l234 + goto l257 } position++ - goto l226 - l234: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l257: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune(']') { - goto l235 + goto l258 } position++ - goto l226 - l235: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l258: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('{') { - goto l236 + goto l259 } position++ - goto l226 - l236: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l259: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune('}') { - goto l237 + goto l260 } position++ - goto l226 - l237: - position, tokenIndex = position226, tokenIndex226 + goto l249 + l260: + position, tokenIndex = position249, tokenIndex249 if buffer[position] != rune(' ') { - goto l225 + goto l248 } position++ } - l226: - goto l211 - l225: - position, tokenIndex = position225, tokenIndex225 + l249: + goto l234 + l248: + position, tokenIndex = position248, tokenIndex248 } if !matchDot() { - goto l211 + goto l234 } - goto l210 - l211: - position, tokenIndex = position211, tokenIndex211 + goto l233 + l234: + position, tokenIndex = position234, tokenIndex234 } - add(rulestring, position209) + add(rulestring, position232) } return true - l208: - position, tokenIndex = position208, tokenIndex208 + l231: + position, tokenIndex = position231, tokenIndex231 return false }, - /* 30 string_in_quote <- <(!('"' / '\t' / '\r' / '\n') .)+> */ + /* 32 string_in_quote <- <(!('"' / '\t' / '\r' / '\n') .)+> */ func() bool { - position238, tokenIndex238 := position, tokenIndex + position261, tokenIndex261 := position, tokenIndex { - position239 := position + position262 := position { - position242, tokenIndex242 := position, tokenIndex + position265, tokenIndex265 := position, tokenIndex { - position243, tokenIndex243 := position, tokenIndex + position266, tokenIndex266 := position, tokenIndex if buffer[position] != rune('"') { - goto l244 + goto l267 } position++ - goto l243 - l244: - position, tokenIndex = position243, tokenIndex243 + goto l266 + l267: + position, tokenIndex = position266, tokenIndex266 if buffer[position] != rune('\t') { - goto l245 + goto l268 } position++ - goto l243 - l245: - position, tokenIndex = position243, tokenIndex243 + goto l266 + l268: + position, tokenIndex = position266, tokenIndex266 if buffer[position] != rune('\r') { - goto l246 + goto l269 } position++ - goto l243 - l246: - position, tokenIndex = position243, tokenIndex243 + goto l266 + l269: + position, tokenIndex = position266, tokenIndex266 if buffer[position] != rune('\n') { - goto l242 + goto l265 } position++ } - l243: - goto l238 - l242: - position, tokenIndex = position242, tokenIndex242 + l266: + goto l261 + l265: + position, tokenIndex = position265, tokenIndex265 } if !matchDot() { - goto l238 + goto l261 } - l240: + l263: { - position241, tokenIndex241 := position, tokenIndex + position264, tokenIndex264 := position, tokenIndex { - position247, tokenIndex247 := position, tokenIndex + position270, tokenIndex270 := position, tokenIndex { - position248, tokenIndex248 := position, tokenIndex + position271, tokenIndex271 := position, tokenIndex if buffer[position] != rune('"') { - goto l249 + goto l272 } position++ - goto l248 - l249: - position, tokenIndex = position248, tokenIndex248 + goto l271 + l272: + position, tokenIndex = position271, tokenIndex271 if buffer[position] != rune('\t') { - goto l250 + goto l273 } position++ - goto l248 - l250: - position, tokenIndex = position248, tokenIndex248 + goto l271 + l273: + position, tokenIndex = position271, tokenIndex271 if buffer[position] != rune('\r') { - goto l251 + goto l274 } position++ - goto l248 - l251: - position, tokenIndex = position248, tokenIndex248 + goto l271 + l274: + position, tokenIndex = position271, tokenIndex271 if buffer[position] != rune('\n') { - goto l247 + goto l270 } position++ } - l248: - goto l241 - l247: - position, tokenIndex = position247, tokenIndex247 + l271: + goto l264 + l270: + position, tokenIndex = position270, tokenIndex270 } if !matchDot() { - goto l241 + goto l264 } - goto l240 - l241: - position, tokenIndex = position241, tokenIndex241 + goto l263 + l264: + position, tokenIndex = position264, tokenIndex264 } - add(rulestring_in_quote, position239) + add(rulestring_in_quote, position262) } return true - l238: - position, tokenIndex = position238, tokenIndex238 + l261: + position, tokenIndex = position261, tokenIndex261 return false }, - /* 31 cardinality <- <('0' / '1' / '*' / '+')> */ + /* 33 cardinality <- <('0' / '1' / '?' / '*' / '+')> */ func() bool { - position252, tokenIndex252 := position, tokenIndex + position275, tokenIndex275 := position, tokenIndex { - position253 := position + position276 := position { - position254, tokenIndex254 := position, tokenIndex + position277, tokenIndex277 := position, tokenIndex if buffer[position] != rune('0') { - goto l255 + goto l278 } position++ - goto l254 - l255: - position, tokenIndex = position254, tokenIndex254 + goto l277 + l278: + position, tokenIndex = position277, tokenIndex277 if buffer[position] != rune('1') { - goto l256 + goto l279 } position++ - goto l254 - l256: - position, tokenIndex = position254, tokenIndex254 + goto l277 + l279: + position, tokenIndex = position277, tokenIndex277 + if buffer[position] != rune('?') { + goto l280 + } + position++ + goto l277 + l280: + position, tokenIndex = position277, tokenIndex277 if buffer[position] != rune('*') { - goto l257 + goto l281 } position++ - goto l254 - l257: - position, tokenIndex = position254, tokenIndex254 + goto l277 + l281: + position, tokenIndex = position277, tokenIndex277 if buffer[position] != rune('+') { - goto l252 + goto l275 } position++ } - l254: - add(rulecardinality, position253) + l277: + add(rulecardinality, position276) } return true - l252: - position, tokenIndex = position252, tokenIndex252 + l275: + position, tokenIndex = position275, tokenIndex275 return false }, nil, - /* 34 Action0 <- <{p.Err(begin, buffer)}> */ + /* 36 Action0 <- <{p.Err(begin, buffer)}> */ func() bool { { add(ruleAction0, position) } return true }, - /* 35 Action1 <- <{p.Err(begin, buffer)}> */ + /* 37 Action1 <- <{p.Err(begin, buffer)}> */ func() bool { { add(ruleAction1, position) } return true }, - /* 36 Action2 <- <{ p.ClearTableAndColumn() }> */ + /* 38 Action2 <- <{ p.ClearTableAndColumn() }> */ func() bool { { add(ruleAction2, position) } return true }, - /* 37 Action3 <- <{ p.AddTable(text) }> */ + /* 39 Action3 <- <{ p.AddColorDefine() }> */ func() bool { { add(ruleAction3, position) } return true }, - /* 38 Action4 <- <{ p.AddColumn(text) }> */ + /* 40 Action4 <- <{ p.AddTable(text) }> */ func() bool { { add(ruleAction4, position) } return true }, - /* 39 Action5 <- <{ p.AddRelation() }> */ + /* 41 Action5 <- <{ p.AddColumn(text) }> */ func() bool { { add(ruleAction5, position) } return true }, - /* 40 Action6 <- <{ p.SetRelationLeft(text) }> */ + /* 42 Action6 <- <{ p.AddRelation() }> */ func() bool { { add(ruleAction6, position) } return true }, - /* 41 Action7 <- <{ p.SetCardinalityLeft(text)}> */ + /* 43 Action7 <- <{ p.SetRelationLeft(text) }> */ func() bool { { add(ruleAction7, position) } return true }, - /* 42 Action8 <- <{ p.SetRelationRight(text) }> */ + /* 44 Action8 <- <{ p.SetCardinalityLeft(text)}> */ func() bool { { add(ruleAction8, position) } return true }, - /* 43 Action9 <- <{ p.SetCardinalityRight(text)}> */ + /* 45 Action9 <- <{ p.SetRelationRight(text) }> */ func() bool { { add(ruleAction9, position) } return true }, - /* 44 Action10 <- <{ p.AddTitleKeyValue() }> */ + /* 46 Action10 <- <{ p.SetCardinalityRight(text)}> */ func() bool { { add(ruleAction10, position) } return true }, - /* 45 Action11 <- <{ p.AddTableKeyValue() }> */ + /* 47 Action11 <- <{ p.AddTitleKeyValue() }> */ func() bool { { add(ruleAction11, position) } return true }, - /* 46 Action12 <- <{ p.AddColumnKeyValue() }> */ + /* 48 Action12 <- <{ p.AddTableKeyValue() }> */ func() bool { { add(ruleAction12, position) } return true }, - /* 47 Action13 <- <{ p.AddRelationKeyValue() }> */ + /* 49 Action13 <- <{ p.AddColumnKeyValue() }> */ func() bool { { add(ruleAction13, position) } return true }, - /* 48 Action14 <- <{ p.SetKey(text) }> */ + /* 50 Action14 <- <{ p.AddRelationKeyValue() }> */ func() bool { { add(ruleAction14, position) } return true }, - /* 49 Action15 <- <{ p.SetValue(text) }> */ + /* 51 Action15 <- <{ p.SetKey(text) }> */ func() bool { { add(ruleAction15, position) } return true }, - /* 50 Action16 <- <{ p.SetValue(text) }> */ + /* 52 Action16 <- <{ p.SetValue(text) }> */ func() bool { { add(ruleAction16, position) } return true }, + /* 53 Action17 <- <{ p.SetValue(text) }> */ + func() bool { + { + add(ruleAction17, position) + } + return true + }, } p.rules = _rules return nil diff --git a/examples/simple.er b/examples/simple.er index b8a32e6..f774817 100644 --- a/examples/simple.er +++ b/examples/simple.er @@ -1,13 +1,22 @@ # Entities are declared in '[' ... ']'. All attributes after the entity header # up until the end of the file (or the next entity declaration) correspond # to this entity. -[Person] + +# red #fcecec +# blue #ececfc + +colors { + person: "#fcecec", + loc: "#ececfc", +} + +[Person] {bgcolor: "person"} *name height weight +birth_location_id -[Location] +[Location] {bgcolor: "loc"} *id city state @@ -18,7 +27,7 @@ country # possible cardinalities: # # Cardinality Syntax -# 0 or 1 0 +# 0 or 1 0/? # exactly 1 1 # 0 or more * # 1 or more + diff --git a/examples/simple.md b/examples/simple.md new file mode 100644 index 0000000..3e91084 --- /dev/null +++ b/examples/simple.md @@ -0,0 +1,23 @@ +# Simple ERD Example + +```erd {cmd=true stdin=true args=["-f", "svg"] output="html"} + +colors { + person: "#fcecec", + loc: "#ececfc", +} + +[User.Person] {bgcolor: "person" label: "comment"} +*name +height +weight ++birth_location_id + +[Location] {bgcolor: "loc"} +*id +city +state +country + +User.Person 1--* Location +``` diff --git a/glide.lock b/glide.lock deleted file mode 100644 index e0b5316..0000000 --- a/glide.lock +++ /dev/null @@ -1,14 +0,0 @@ -hash: e0585344112b97afd83bdd6733cc1162fe82b81d58f637ab489e054cc5c524a5 -updated: 2018-01-16T23:55:25.566568+09:00 -imports: -- name: github.com/jessevdk/go-flags - version: 96dc06278ce32a0e9d957d590bb987c81ee66407 -- name: golang.org/x/crypto - version: bed12803fa9663d7aa2c2346b0c634ad2dcd43b7 - subpackages: - - ssh/terminal -- name: golang.org/x/sys - version: 7a6e5648d140666db5d920909e082ca00a87ba2c - subpackages: - - unix -testImports: [] diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 3f7ed6d..0000000 --- a/glide.yaml +++ /dev/null @@ -1,7 +0,0 @@ -package: github.com/kaishuu0123/erd-go -import: -- package: golang.org/x/crypto - subpackages: - - ssh/terminal -- package: github.com/jessevdk/go-flags - version: ^1.3.0 diff --git a/go.mod b/go.mod index 93171d2..c4a615e 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,10 @@ module github.com/kaishuu0123/erd-go +go 1.15 + require ( github.com/jessevdk/go-flags v1.3.0 github.com/jteeuwen/go-bindata v3.0.7+incompatible // indirect golang.org/x/crypto v0.0.0-20170202201058-bed12803fa96 - golang.org/x/sys v0.0.0-20170201051245-7a6e5648d140 + golang.org/x/sys v0.0.0-20170201051245-7a6e5648d140 // indirect ) diff --git a/go.sum b/go.sum index 6e0e605..3cfad6d 100644 --- a/go.sum +++ b/go.sum @@ -4,4 +4,5 @@ github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+es github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs= golang.org/x/crypto v0.0.0-20170202201058-bed12803fa96 h1:wszq1jlNwkJcdZ05G3gpSdgYKTHwHCorxTZTG88nXN4= golang.org/x/crypto v0.0.0-20170202201058-bed12803fa96/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/sys v0.0.0-20170201051245-7a6e5648d140 h1:wxED/WNVMni7c0XHQ2hO7hXtwxskOTX5+iGd53LdZO0= golang.org/x/sys v0.0.0-20170201051245-7a6e5648d140/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/parse.go b/parse.go index 573f456..17d8c60 100644 --- a/parse.go +++ b/parse.go @@ -3,6 +3,7 @@ package main import ( "errors" "fmt" + "regexp" "strconv" "strings" ) @@ -31,11 +32,13 @@ type Column struct { // Table in a database type Table struct { + Name string Title string TableAttributes map[string]string Columns []Column CurrentColumnID int PrimaryKeys []int + Connected bool } // Title ... @@ -50,16 +53,24 @@ type Erd struct { Tables map[string]*Table Relations []Relation CurrentRelation Relation + TableNames []string // for ordering Isolations + Isolations []string key string value string CurrentTableName string IsError bool - line int + Colors map[string]string } -func (e *Erd) addTableTitle(t string) { - t = strings.Trim(t, "\"") - e.Tables[e.CurrentTableName].Title = t +var re = regexp.MustCompile(`[^a-zA-Z0-9\\_]`) + +func replaceAllIllegal(text string) string { + return re.ReplaceAllString(text, "_") +} + +// Connect marks the table is connected to another +func (t *Table) Connect() { + t.Connected = true } // ClearTableAndColumn clears the current table @@ -80,8 +91,10 @@ func (e *Erd) AddTable(text string) { if e.Tables == nil { e.Tables = map[string]*Table{} } - e.Tables[text] = &Table{Title: text, TableAttributes: map[string]string{}} - e.CurrentTableName = text + name := replaceAllIllegal(text) + e.Tables[name] = &Table{Name: name, Title: text, TableAttributes: map[string]string{}} + e.TableNames = append(e.TableNames, name) + e.CurrentTableName = name } // AddTableKeyValue add a key value pair to the table attributes @@ -90,7 +103,23 @@ func (e *Erd) AddTableKeyValue() { if table.TableAttributes == nil { table.TableAttributes = map[string]string{} } - table.TableAttributes[e.key] = e.value + + val := e.value + if strings.Contains(e.key, "color") { + v, ok := e.Colors[e.value] + if ok { + val = v + } + } + table.TableAttributes[e.key] = val +} + +// AddColorDefine stores the named color palette +func (e *Erd) AddColorDefine() { + if e.Colors == nil { + e.Colors = map[string]string{} + } + e.Colors[e.key] = e.value } // AddColumn adds a column to the EDR @@ -132,6 +161,13 @@ func (e *Erd) SetValue(text string) { } } +// Connect set the table status as connected, for rendering horizontal isolated nodes later +func (e *Erd) Connect(name string) { + if table, ok := e.Tables[name]; ok { + table.Connect() + } +} + // AddRelation adds the current relation to the EDR func (e *Erd) AddRelation() { e.Relations = append(e.Relations, e.CurrentRelation) @@ -148,7 +184,9 @@ func (e *Erd) AddRelationKeyValue() { // SetRelationLeft sets the left side of the current relation func (e *Erd) SetRelationLeft(text string) { - e.CurrentRelation.LeftTableName = text + name := replaceAllIllegal(text) + e.CurrentRelation.LeftTableName = name + e.Connect(name) } // SetCardinalityLeft sets the left cardinality of the current relation @@ -158,7 +196,19 @@ func (e *Erd) SetCardinalityLeft(text string) { // SetRelationRight sets the right side of the current relation func (e *Erd) SetRelationRight(text string) { - e.CurrentRelation.RightTableName = text + name := replaceAllIllegal(text) + e.CurrentRelation.RightTableName = name + e.Connect(name) +} + +func (e *Erd) CalcIsolated() { + for _, name := range e.TableNames { + if table, ok := e.Tables[name]; ok { + if !table.Connected { + e.Isolations = append(e.Isolations, name) + } + } + } } // SetCardinalityRight sets the right cardinality of the current relation diff --git a/parse_test.go b/parse_test.go index d468ee8..8c7d686 100644 --- a/parse_test.go +++ b/parse_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "strings" "testing" "text/template" ) @@ -31,8 +32,11 @@ country Person *--1 Location ` parser := &Parser{Buffer: contents} - parser.Init() - err := parser.Parse() + err := parser.Init() + if err != nil { + t.Fatal(err) + } + err = parser.Parse() if err != nil { t.Fatal(err) } @@ -46,7 +50,7 @@ Person *--1 Location dot, _ := Asset("templates/dot.tmpl") tables, _ := Asset("templates/dot_tables.tmpl") relations, _ := Asset("templates/dot_relations.tmpl") - templates := template.Must(template.New("").Parse(string(dot) + string(tables) + string(relations))) + templates := template.Must(template.New("").Funcs(template.FuncMap{"StringsJoin": strings.Join}).Parse(string(dot) + string(tables) + string(relations))) fd := bytes.NewBufferString("") if err := templates.ExecuteTemplate(fd, "dot", parser.Erd); err != nil { diff --git a/templates/dot_relations.tmpl b/templates/dot_relations.tmpl index 3fa1979..ac1bd6a 100644 --- a/templates/dot_relations.tmpl +++ b/templates/dot_relations.tmpl @@ -5,6 +5,8 @@ arrowhead=ocrow,headlabel=<0..N>, {{- else if (eq .RightCardinality "+")}} arrowhead=ocrowtee,headlabel=<1..N>, + {{- else if (eq .RightCardinality "?")}} + arrowhead=ocrowtee,headlabel=<{0,1}>, {{- else -}} arrowhead=noneotee,headlabel=<{{.RightCardinality}}>, {{- end -}} @@ -15,9 +17,14 @@ arrowtail=ocrow,taillabel=<0..N> {{- else if (eq .LeftCardinality "+")}} arrowtail=ocrowtee,taillabel=<1..N> + {{- else if (eq .LeftCardinality "?")}} + arrowtail=ocrowtee,taillabel=<{0,1}> {{- else -}} arrowtail=noneotee,taillabel=<{{.LeftCardinality}}> {{- end -}} ]; {{- end -}} -{{- end -}} \ No newline at end of file +{{ if gt (len .Isolations) 1 }} + {{ StringsJoin .Isolations " -- "}} [style=invis] +{{- end -}} +{{- end -}} diff --git a/templates/dot_tables.tmpl b/templates/dot_tables.tmpl index fc13650..c69f323 100644 --- a/templates/dot_tables.tmpl +++ b/templates/dot_tables.tmpl @@ -1,6 +1,6 @@ {{define "dot_tables"}} {{range $tk, $t := .Tables}} - {{.Title}} [label=< - +
{{.Title}} + {{.Title}} + {{- if .TableAttributes.label -}} +  {{.TableAttributes.label}} + {{- end -}} +
{{- if .Columns -}} diff --git a/templates_bindata.go b/templates_bindata.go index 12c3e6a..004f451 100644 --- a/templates_bindata.go +++ b/templates_bindata.go @@ -1,8 +1,8 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: -// templates/dot.tmpl (752B) -// templates/dot_relations.tmpl (821B) -// templates/dot_tables.tmpl (1.001kB) +// templates/dot.tmpl +// templates/dot_relations.tmpl +// templates/dot_tables.tmpl package main @@ -22,7 +22,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer @@ -30,7 +30,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("read %q: %v", name, err) + return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err @@ -86,12 +86,12 @@ func templatesDotTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "templates/dot.tmpl", size: 752, mode: os.FileMode(0644), modTime: time.Unix(1541039245, 0)} + info := bindataFileInfo{name: "templates/dot.tmpl", size: 752, mode: os.FileMode(436), modTime: time.Unix(1571059917, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x82, 0x6f, 0x6d, 0x33, 0xa, 0x4f, 0x57, 0xe4, 0x65, 0xb4, 0xbb, 0xf4, 0xd9, 0xc1, 0x34, 0x16, 0xdc, 0x69, 0x7d, 0x32, 0x9, 0x7d, 0x46, 0xe9, 0x11, 0x7b, 0x46, 0x5a, 0x90, 0xd3, 0x7e, 0x63}} return a, nil } -var _templatesDot_relationsTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x92\x51\x4b\xfb\x30\x14\xc5\xdf\xfb\x29\x2e\x7d\xfa\xef\xef\x1a\xdd\xb3\xdd\x40\x04\x9f\xa4\xc2\xd8\x9b\x88\xdc\x9a\xdb\x2d\x10\x13\x4c\x23\x43\x42\xbe\xbb\xa4\x76\xb1\x9a\x74\xf8\x76\x39\xdc\xfc\xce\xe5\x9c\x38\xc7\xa9\x13\x8a\xa0\xe4\xda\x3e\x1b\x92\x68\x85\x56\x7d\xe9\x7d\xe1\x9c\x41\xb5\x27\x60\xdb\x93\xea\x7d\x01\xe0\x1c\xbb\xa7\xce\xee\xb0\x95\xd4\xe0\x2b\x79\x0f\x55\x15\xd4\xad\xd8\x1f\x7e\xc8\x8f\x05\x40\xd8\xaf\x40\x74\xf0\x8f\xde\xe0\x6b\xe5\x16\x0d\x17\x0a\xa5\xb0\x1f\x50\xfe\x2f\x17\x50\x0d\x5c\x00\x34\x46\x1f\x0f\x84\x7c\xad\x5f\x8c\x3e\x2e\xc3\x28\xb1\x25\xb9\xae\xeb\xbb\x87\x66\xb7\xb9\x62\xac\xa9\x2f\x87\x71\xb3\x8c\x70\x92\x3d\x9d\x71\xb8\x28\x17\x79\xbe\x25\x4a\x2d\x56\xf3\x16\xe9\x99\x4a\x2b\xd2\x59\xcc\x29\x8e\xc9\x25\xde\x67\xb8\x8a\x47\xec\x98\x53\x4c\xfb\xc6\x5a\x23\xda\x77\x4b\x3d\x1b\xd0\x71\x31\x31\x9a\x79\xf0\x47\xc3\x21\xb6\xd0\xe8\xf9\x5e\x2c\x0a\x39\xf6\x12\xc6\xd9\x5e\xf2\xb5\x24\xfc\x5f\xad\x7c\xd3\x43\x9c\x89\xc1\x6a\xd6\x20\xbd\x31\x96\x92\x50\xc6\x9f\x9b\xed\x24\x93\xd0\xd3\x75\x31\x15\x26\xf3\x67\x00\x00\x00\xff\xff\x93\x21\x06\x17\x35\x03\x00\x00") +var _templatesDot_relationsTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x93\x4f\x4b\x33\x31\x10\x87\xef\xfb\x29\x86\x9c\xda\xf7\xed\xae\xdd\xb3\xfd\x83\x08\x82\x22\x15\x6a\x6f\x52\x24\x75\xa7\xdb\x40\x4c\x30\x19\x2d\x25\xe4\xbb\x4b\xd6\x75\x6b\x9b\x6d\x71\xbd\x0d\xc3\xf4\xf9\xa5\xf3\xec\x38\x57\xe0\x5a\x28\x04\x56\x68\x7a\x36\x28\x39\x09\xad\x2c\xf3\x3e\x71\xce\x70\x55\x22\x64\xf3\xef\xae\xf7\x09\x80\x73\xd9\x3d\xae\x69\xc1\x57\x12\x67\xfc\x15\xbd\x87\x34\x0d\xdd\xb9\x28\x37\x07\xed\xa7\x04\x20\xcc\xa7\x20\xd6\xd0\xc3\x37\xf8\x1a\xb9\xe6\xa6\x10\x8a\x4b\x41\x3b\x60\xff\x58\x1f\xd2\x8a\x0b\xc0\x8d\xd1\xdb\x0d\xf2\x62\xac\x5f\x8c\xde\x0e\x42\x29\xf9\x0a\xe5\x78\x34\xba\x79\x98\x2d\x26\xc3\x2c\x9b\x8d\x2e\xaa\x72\x32\x68\xe0\x28\x2d\x9e\x49\xf8\xcf\xfa\xed\x7c\x42\x8c\x23\xf2\xbf\x44\x4c\x3b\x45\xb8\xe1\x20\xf7\x27\x32\xe2\x55\x28\xad\x50\xb7\x73\x5c\xf4\x14\xdf\xc6\x55\x45\x83\xad\x5d\x34\x46\xaf\x88\x8c\x58\xbd\x13\xda\xac\x42\x37\x83\x51\xd0\x89\x1f\xfc\x32\xb0\xda\x5b\xf8\x6a\xce\xbb\x27\x2e\x64\xed\x3e\x94\x27\xdd\xb7\x7b\x89\xf8\x47\xe6\xf7\xf4\xb0\xce\x28\x20\xef\x1e\x30\xed\x14\x70\xe0\xfd\x8c\xf6\x0a\xd3\x68\x8f\x31\xee\xf8\x21\xbe\x85\xda\x38\x58\x5e\x26\x3f\x1b\xce\x85\xbf\x53\x12\xf4\x24\x2a\xc8\x6e\xad\xae\x6f\xbb\x0f\x39\xd4\xf7\x0d\x8f\x64\x84\x2a\xed\x9d\x16\x07\x23\xc0\xc2\xa5\xb3\x70\xd9\x96\x76\x12\xc7\x42\x7d\x08\xbb\x3c\xe2\xef\xeb\xcf\x00\x00\x00\xff\xff\x72\x2f\x28\xd9\x5c\x04\x00\x00") func templatesDot_relationsTmplBytes() ([]byte, error) { return bindataRead( @@ -106,12 +106,12 @@ func templatesDot_relationsTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "templates/dot_relations.tmpl", size: 821, mode: os.FileMode(0644), modTime: time.Unix(1541039245, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x42, 0xae, 0xa7, 0x5e, 0xa6, 0x52, 0x9f, 0x68, 0xdb, 0x69, 0x98, 0x6e, 0x2b, 0xfb, 0x2a, 0x4a, 0x14, 0x1a, 0xdb, 0x2c, 0xd9, 0x65, 0xe5, 0x8a, 0x3a, 0xb3, 0xfa, 0xba, 0xdb, 0x80, 0x84, 0x96}} + info := bindataFileInfo{name: "templates/dot_relations.tmpl", size: 1116, mode: os.FileMode(436), modTime: time.Unix(1612438160, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6, 0xa9, 0xdd, 0x7c, 0xd2, 0x28, 0xd5, 0x41, 0x2a, 0xd9, 0x29, 0x8c, 0xb3, 0xe5, 0xe8, 0xf7, 0x65, 0xca, 0x26, 0x9d, 0x1b, 0xcc, 0xe5, 0xc0, 0x70, 0xa4, 0x4f, 0xf9, 0xf4, 0xf6, 0x78, 0xd2}} return a, nil } -var _templatesDot_tablesTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x93\x5f\x8b\x9b\x40\x14\xc5\xdf\xf3\x29\x2e\x97\xa5\x4f\x89\x66\xdb\xb4\x0f\xdd\x19\xc1\x7f\xd9\x15\xac\x06\x77\x68\xa1\xa5\x14\x8d\x93\x20\x9d\x6a\xd1\xd9\xc2\x32\xf5\xbb\x17\x27\x63\x1a\xd3\xa4\xb0\x79\xc9\xdc\x93\x3b\xf7\x9e\xfc\x8e\x2a\x55\xf2\x5d\x55\x73\xc0\xb2\x91\xdf\x64\x5e\x08\xde\x61\xdf\xcf\x94\x6a\xf3\x7a\xcf\xe1\x46\x7e\x9f\xc3\x8d\x84\xf7\x14\x2c\xa6\x7f\xed\xfb\x19\x80\x52\x16\xab\xa4\xe0\x7d\x0f\x5f\x44\x5e\x70\x41\x09\x61\xae\x17\x87\x33\xd0\x1f\x2f\xcd\x82\x30\xa3\xb8\x44\x23\xf8\x61\x1c\x6f\xdc\x20\x88\x92\xfb\x33\xf5\x71\xe3\xfa\x07\xd5\x7a\x3b\xea\x9f\xa2\x80\x3d\x50\xbc\x7d\xb3\x1a\x15\x37\x8e\xee\x13\x8a\x7e\x98\xb0\x30\x1b\x45\xc7\x7c\x13\x96\x8d\xc7\xa1\x08\xce\xba\xe1\xa3\xa9\xbd\x94\xb1\xf4\x03\x9e\x8e\x77\xc8\x3a\x4d\x18\x6c\xd2\x28\x61\x8b\xc7\xe8\x73\x48\xf1\x76\x85\xb0\x76\xfd\x90\xe2\x03\x17\xbf\xb8\xac\xb6\x39\x14\x8d\x28\xd1\x21\x9e\xf3\xf7\x8f\x13\xdb\x73\x88\x3d\xdc\x76\x88\xcd\x82\xa3\x17\x7b\x34\x43\x6c\x4d\xe4\x50\x28\xb5\x80\x6a\x07\x96\xdf\x88\xa7\x1f\x75\x07\x0b\x8d\x11\xe0\xf7\xa1\xf5\xbf\xec\x8c\xfb\x38\x5c\xb3\x17\xe0\x5c\x5d\x80\x39\x9a\x1c\xdc\x98\x7c\x87\x78\xb7\x3a\x5e\x63\xcd\x18\xbb\x4e\x55\xfb\xb8\xc4\xed\x35\x4e\xf0\x68\x34\xc7\x01\x53\x00\xae\x94\x6d\x55\x3c\x49\xde\x59\xfa\xf1\x39\xf2\x30\xdb\xf4\xf0\x43\x08\x6e\x5b\xe5\x02\x22\x99\x8b\x6a\x8b\xd3\x85\x4b\x04\x3f\x8d\xd3\x8c\xe2\xbe\xe5\xcf\xef\x96\xe8\xbc\xaa\x8b\xee\xe7\x9d\x52\x57\xd6\x5c\xb6\xc5\xeb\x72\xb2\xff\x72\x9c\xc7\x5e\xd3\xf9\x4f\xbc\x66\xcc\x34\x6f\xfd\xce\x9c\xd8\x28\xf6\xdb\x46\x34\xad\x99\x31\xdf\x55\x42\x68\x81\xe2\x80\xee\x5a\x33\xce\x75\x7b\x27\x9f\x05\xa7\xc3\x1d\x5e\x9e\xaf\xd5\xf5\xd7\xbb\xd9\xa9\x74\x7a\xfe\x13\x00\x00\xff\xff\xa8\x98\x28\xae\xe9\x03\x00\x00") +var _templatesDot_tablesTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x52\x5d\x8f\x93\x40\x14\x7d\xef\xaf\xb8\xb9\xd9\xf8\xd4\x96\xae\x56\x1f\x5c\x86\x84\xaf\xee\x92\x20\x34\xec\x44\x13\x8d\x31\x50\xa6\x0d\x71\x16\x0c\xcc\x9a\x6c\x46\xfe\xbb\x61\x3a\x60\x41\xfc\x8a\x7d\x29\xf7\x70\x3f\x0e\xe7\x1c\x29\x73\x76\x2c\x4a\x06\x98\x57\xe2\x93\x48\x33\xce\x1a\x6c\xdb\x85\x94\x75\x5a\x9e\x18\x5c\x89\xcf\x4b\xb8\x12\xf0\x9a\xc0\x9a\xaa\xb7\x6d\xbb\x00\x90\x72\x1d\xa5\x0f\xac\x6d\xe1\x03\x4f\x33\xc6\x89\x69\x52\xdb\x09\xfd\x05\xa8\x9f\x13\x27\x9e\x9f\x10\xdc\xa0\x06\x5c\x3f\x0c\xf7\xb6\xe7\x05\xd1\xed\x04\xbd\xdf\xdb\xee\x19\x5d\xbf\xec\xf1\x77\x81\x47\xef\x08\x5e\xbf\xd8\xf6\x88\x1d\x06\xb7\x11\x41\xd7\x8f\xa8\x9f\xf4\xa0\xa5\xff\x4d\x9a\xf4\x8f\x5d\xe1\x4d\xba\xe1\xad\xae\x9d\x98\xd2\xf8\x0d\x5e\xae\xff\x31\x07\x60\xee\xe2\x88\xc2\x3e\x0e\x22\xba\xba\x0f\xde\xfb\x04\xaf\xb7\x08\x3b\xdb\xf5\x09\xde\x31\xfe\x95\x89\xe2\x90\x42\x56\xf1\x1c\x2d\xd3\xb1\xa4\x5c\xd3\x42\x70\xd6\xb6\xa6\xe1\x58\xa6\xd1\x4d\x5f\xae\x93\x72\x05\xc5\x51\xab\x66\x0b\x51\x17\xd9\xa3\x60\xcd\x5a\xe9\x05\x2b\x25\xe3\xf4\xf8\xf9\x98\x5d\x17\x29\x87\x40\xa4\xbc\x38\xe0\x98\xd0\x06\xc1\x8d\xc3\x38\x21\x78\xaa\xd9\xd3\xab\x0d\x5a\xcf\xca\xac\xf9\x72\xd3\x91\x99\xbb\xd3\x91\x9b\x23\xc6\xca\x7c\x44\xc1\x34\xa8\x37\xc8\x69\xf4\x7a\x9a\x86\x32\xf5\x5c\xf4\xdf\xe3\x56\xfc\xf1\xa1\x6c\x86\xf1\x6f\xe7\xd6\xdf\xda\xaf\x0d\x08\xfd\x1d\xfd\x87\x44\x6c\x67\xf2\xd0\x93\xec\xd8\xe8\x84\x76\x01\x3d\xa8\x80\x6a\x6a\xc3\x77\xfd\x2a\x18\x8a\x87\x35\xe3\xf7\x73\x1c\xd9\x3a\x56\x6e\x2c\xc0\x1f\x1c\xfd\x7f\x3f\xe7\xcf\xcc\xd3\xfa\x3b\x3b\x87\x5e\xdd\xf9\x93\xbd\x7a\xcd\xd8\xef\x69\xae\xb2\xd3\xa1\xe2\x55\xad\x77\x2c\x8f\x05\xe7\x0a\x20\x38\x13\xc2\xa1\x19\x97\xaa\xbd\x11\x4f\x9c\x91\x6e\x86\xe5\xd3\xb3\xaa\xfe\x78\xb3\xb8\x84\x2e\x9f\xbf\x07\x00\x00\xff\xff\x3c\x8a\xab\x86\xab\x04\x00\x00") func templatesDot_tablesTmplBytes() ([]byte, error) { return bindataRead( @@ -126,8 +126,8 @@ func templatesDot_tablesTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "templates/dot_tables.tmpl", size: 1001, mode: os.FileMode(0644), modTime: time.Unix(1541039245, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2b, 0x48, 0x1e, 0x19, 0x73, 0x71, 0x38, 0x82, 0xb7, 0x10, 0xf8, 0xe4, 0xa5, 0xd0, 0xef, 0x15, 0x3d, 0xc8, 0x92, 0xe6, 0x8e, 0x8, 0xe9, 0x3e, 0x74, 0xf3, 0xb8, 0x46, 0x8f, 0x5b, 0x31, 0xa3}} + info := bindataFileInfo{name: "templates/dot_tables.tmpl", size: 1195, mode: os.FileMode(436), modTime: time.Unix(1612404317, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0xfb, 0x63, 0x46, 0x83, 0x6b, 0x2c, 0xfe, 0x10, 0x5, 0xa0, 0xcc, 0xe2, 0x41, 0xe7, 0xcc, 0x43, 0x75, 0xcd, 0xeb, 0x89, 0xd3, 0x5e, 0x1, 0xdc, 0xd8, 0xe0, 0x4b, 0x60, 0x74, 0x3c, 0xc4}} return a, nil }