about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-03-18 17:09:47 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-03-18 17:09:47 -0700
commit06615231aefacc536362667d571800eb2b08c048 (patch)
tree69d1012d4f8d46112c3bf7ef1b16b218ae8791b6
parent7dc0928f52eb5ab795292d300808aac06b4564b5 (diff)
downloadteliva-06615231aefacc536362667d571800eb2b08c048.tar.gz
graphviz: done parsing directed graphs
This is mostly what I want since I'm interested in parsing the output of
debtree.
-rw-r--r--graphviz.tlv84
1 files changed, 83 insertions, 1 deletions
diff --git a/graphviz.tlv b/graphviz.tlv
index 54a6404..e79b592 100644
--- a/graphviz.tlv
+++ b/graphviz.tlv
@@ -564,10 +564,18 @@
     >        return self:string()
     >      elseif c == '<' then
     >        error('html strings are not implemented yet')
-    >      elseif string.pos('-.0123456789', c) then
+    >      elseif c == '-' then
+    >        if self.chars.peek2 == '-' or self.chars.peek2 == '>' then
+    >          return self:edgeop()
+    >        else
+    >          return self:numeral()
+    >        end
+    >      elseif string.pos('.0123456789', c) then
     >        return self:numeral()
     >      elseif string.match(c, '[%a_]') then
     >        return self:identifier()
+    >      else
+    >        error('unexpected character '..str(c))
     >      end
     >    end,
     >    skip_whitespace_and_comments = function(self)
@@ -654,6 +662,9 @@
     >      end
     >      return result
     >    end,
+    >    edgeop = function(self)
+    >      return self.chars:read()..self.chars:read()
+    >    end,
     >  }
     >end
     >
@@ -673,3 +684,74 @@
     >  check_tokenizer('"abc def" 124', '"abc def"', 'tokenizer: string')
     >  check_tokenizer('',              nil,         'tokenizer: eof')
     >end
+- __teliva_timestamp: original
+  parse_graph:
+    >-- https://graphviz.org/doc/info/lang.html
+    >function parse_graph(tokens, graph)
+    >  local t = tokens:read()
+    >  if t == 'strict' then
+    >    t = tokens:read()
+    >  end
+    >  if t == 'graph' then
+    >    error('undirected graphs not supported just yet')
+    >  elseif t == 'digraph' then
+    >    return parse_directed_graph(tokens, graph)
+    >  else
+    >    error('parse_graph: unexpected token '..t)
+    >  end
+    >end
+- __teliva_timestamp:
+    >Fri Mar 18 16:52:39 2022
+  skip_attr_list:
+    >function skip_attr_list(tokens)
+    >  while true do
+    >    local tok = tokens:read()
+    >    if tok == nil then
+    >      error('unterminated attr list; looked for "]" in vain')
+    >    end
+    >    if tok == ']' then break end
+    >  end
+    >end
+- __teliva_timestamp:
+    >Fri Mar 18 17:01:49 2022
+  parse_directed_graph:
+    >function parse_directed_graph(tokens, graph)
+    >  tokens:read()  -- skip name
+    >  assert(tokens:read() == '{')
+    >  while true do
+    >    if tokens:peek() == nil then
+    >      error('file not terminated with "}"')
+    >    end
+    >    if tokens:peek() == '}' then break end
+    >    local tok1 = tokens:read()
+    >    if tok1 == '[' then
+    >      skip_attr_list(tokens)
+    >    else
+    >      local tok2 = tokens:read()
+    >      if tok2 == '[' then
+    >        -- node_stmt
+    >        skip_attr_list(tokens)
+    >        -- otherwise ignore node declarations;
+    >        -- we'll assume the graph is fully connected
+    >        -- and we can focus on just edges
+    >      elseif tok2 == '->' then
+    >        -- edge_stmt
+    >        local tok3 = tokens:read()
+    >        if graph[tok1] == nil then
+    >          graph[tok1] = {tok3}
+    >        else
+    >          append(graph[tok1], {tok3})
+    >        end
+    >      elseif tok2 == '--' then
+    >        error('unexpected token "--" in digraph; edges should be directed using "->"')
+    >      elseif tok2 == '=' then
+    >        -- id '=' id
+    >        -- skip
+    >        tokens:read()
+    >      else
+    >        error('unexpected token '..tok2)
+    >      end
+    >    end
+    >  end
+    >  assert(tokens:read() == '}')
+    >end