Skip to content

Commit

Permalink
maintained dot syntax and dot pretty printer
Browse files Browse the repository at this point in the history
  • Loading branch information
jurgenvinju committed Jul 7, 2023
1 parent 1679a10 commit fc35a33
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 165 deletions.
137 changes: 45 additions & 92 deletions src/org/rascalmpl/library/lang/dot/Dot.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -7,112 +7,65 @@
}
@contributor{Bert Lisser - [email protected]}

@synopsis{AST and pretty printer for the Dot language.}
@description{
This model of the DOT language is for generative purposes.
If you need to parse DOT files, have a look at ((lang::dot::syntax::Dot)) instead.
}
module lang::dot::Dot
import String;
import Set;
import Map;

public alias Id = str;

@synopsis{Abstract Data Type of Dot language}

public data DotGraph = graph(Id id, Stms stmts) | digraph(Id id, Stms stmts);

public alias Stms = list[Stm];

public alias NodeId = tuple[Id, PortId];

public alias PortId = tuple[Id, CompassPt];
@synopsis{Abstract Syntax for the Dot language}
data DotGraph = graph(str id, list[Stm] stmts) | digraph(str id, list[Stm] stmts);

public data CompassPt = N()|NE()|E()|SE()|S()|SW()|W()|NW()|C()|_();
alias NodeId = tuple[str, PortId];

alias PortId = tuple[str, CompassPt];

data CompassPt = N() | NE() | E() | SE() | S() | SW() | W() | NW() | C() | \_();

public data Stm
= N(Id id, Attrs attrs)
| N(Id id)
data Stm
= N(str id, Attrs attrs)
| N(str id)
| N(NodeId nid, Attrs attrs)
| N(NodeId nid)
| E(Id from, Id to, Attrs attrs)
| E(Id from, Id to)
| E(str from, str to, Attrs attrs)
| E(str from, str to)
| E(NodeId nfrom, Id to, Attrs attrs)
| E(NodeId nfrom, Id to)
| E(Stm sfrom, Id to, Attrs attrs)
| E(Stm sfrom, Id to)
| E(Id from, NodeId nto, Attrs attrs)
| E(NodeId nfrom, str to)
| E(Stm sfrom, str to, Attrs attrs)
| E(Stm sfrom, str to)
| E(str from, NodeId nto, Attrs attrs)
| E(Id from, NodeId nto)
| E(NodeId nfrom, NodeId nto, Attrs attrs)
| E(NodeId nfrom, NodeId nto)
| E(Stm sfrom, NodeId nto, Attrs attrs)
| E(Stm sfrom, NodeId nto)
| E(Id from, Stm sto, Attrs attrs)
| E(Id from, Stm sto)
| E(str from, Stm sto, Attrs attrs)
| E(str from, Stm sto)
| E(NodeId nfrom, Stm sto, Attrs attrs)
| E(NodeId nfrom, Stm sto)
| E(Stm sfrom, Stm sto, Attrs attrs)
| E(Stm sfrom, Stm sto)
| S(Id id, Stms stms)
| S(Stms stms)
| A(Id prop, Id val)
| S(str id, list[Stm] stms)
| S(list[Stm] stms)
| A(str prop, str val)
| GRAPH(Attrs attrs)
| NODE(Attrs attrs)
| EDGE(Attrs attrs)
;

public alias Attr = tuple[str prop, Id val];

public alias Attrs = list[Attr];

public alias Outline = map[int key, list[str] args];

public alias Dotline = tuple[DotGraph graph, Outline outline];


@synopsis{Dummy function call needed to tag initialized global variables of type DotGraph.
It is possible to select that variable on the outline menu of the Rascal Editor.
An application is for example to display dotgraphs.}

public DotGraph export(DotGraph g) {return g;}

public Dotline export(Dotline g) {return g;}

public bool hasOutline(Dotline _) {return true;}

public bool hasOutline(DotGraph _) {return false;}

public Outline currentOutline;

public void setCurrentOutline(Dotline current) {
currentOutline = current.outline;
}
alias Attrs = lrel[str prop, str val];

@synopsis{Translates DotGraph to String input for dot}
str toString(digraph(Id id,Stms stms))
str toString(digraph(str id,list[Stm] stms))
= "digraph <id> {<for (x<-stms) {>
'<oStm(x)>;<}>
'}
'";

str toString(Dotline g) = toString(g.graph);

list[value] getChildren(value key) {
if (int k:=key) {
if (k==-1)
return toList(domain(currentOutline));
return currentOutline[k];
}
return [];
}

private str reLabel(str prop, str val) {
if (prop=="label") {
return "\"<replaceAll(val,"\"","\\\"")>\"";
}

return val;
}

private str oAttrs(Attrs attrs) = "[<for (y<-attrs) {> <y.prop>=<reLabel(y.prop, y.val)>,<}>]";
private str oAttrs(lrel[str prop, str val] attrs) = "[<for (<prop,val> <- attrs) {> <prop>=<reLabel(prop, val)>,<}>]";

private str oCompassPt(N()) = "n";
private str oCompassPt(NE()) = "ne";
Expand All @@ -131,41 +84,41 @@ str oPortId(PortId id) {

str oNodeId(NodeId id) = "<id[0]><oPortId(id[1])>";

str oStms(Stms stms, str sep) = "<for (y <- stms) {> <oStm(y)><sep><}>";
str oStms(list[Stm] stms, str sep) = "<for (y <- stms) {> <oStm(y)><sep><}>";

str oStm( N(Id id)) = "<id>";
str oStm( N(Id id, Attrs attrs)) = "<id><oAttrs(attrs)>";
str oStm( N(str id)) = "<id>";
str oStm( N(str id, Attrs attrs)) = "<id><oAttrs(attrs)>";

str oStm( E(Id from, Id to)) = "<from>-\><to>";
str oStm( E(Id from, Id to, Attrs attrs)) = "<from>-\><to><oAttrs(attrs)>";
str oStm( E(str from, str to)) = "<from>-\><to>";
str oStm( E(str from, str to, Attrs attrs)) = "<from>-\><to><oAttrs(attrs)>";

str oStm( E(NodeId from, Id to)) = "<oNodeId(from)>-\><to>";
str oStm( E(Id from, Id to, Attrs attrs)) = "<from>-\><to><oAttrs(attrs)>";
str oStm( E(NodeId from, str to)) = "<oNodeId(from)>-\><to>";
str oStm( E(str from, str to, Attrs attrs)) = "<from>-\><to><oAttrs(attrs)>";

str oStm( E(Stm from, Id to)) = "<oStm(from)>-\><to>";
str oStm( E(Stm from, Id to, Attrs attrs)) = "<oStm(from)>-\><to><oAttrs(attrs)>";
str oStm( E(Stm from, str to)) = "<oStm(from)>-\><to>";
str oStm( E(Stm from, str to, Attrs attrs)) = "<oStm(from)>-\><to><oAttrs(attrs)>";

str oStm( E(Id from, NodeId to)) = "<from>-\><oNodeId(to)>";
str oStm( E(Id from, NodeId to, Attrs attrs)) = "<from>-\><oNodeId(to)><oAttrs(attrs)>";
str oStm( E(str from, NodeId to)) = "<from>-\><oNodeId(to)>";
str oStm( E(str from, NodeId to, Attrs attrs)) = "<from>-\><oNodeId(to)><oAttrs(attrs)>";

str oStm( E(NodeId from, NodeId to)) = "<oNodeId(from)>-\><oNodeId(to)>";
str oStm( E(Id from, NodeId to, Attrs attrs)) = "<from>-\><oNodeId(to)><oAttrs(attrs)>";
str oStm( E(str from, NodeId to, Attrs attrs)) = "<from>-\><oNodeId(to)><oAttrs(attrs)>";

str oStm( E(Stm from, NodeId to)) = "<oStm(from)>-\><oNodeId(to)>";
str oStm( E(Stm from, NodeId to, Attrs attrs)) = "<oStm(from)>-\><oNodeId(to)><oAttrs(attrs)>";

str oStm( E(Id from, Stm to)) = "<from>-\><oStm(to)>";
str oStm( E(Id from, Stm to, Attrs attrs)) = "<from>-\><oStm(to)><oAttrs(attrs)>";
str oStm( E(str from, Stm to)) = "<from>-\><oStm(to)>";
str oStm( E(str from, Stm to, Attrs attrs)) = "<from>-\><oStm(to)><oAttrs(attrs)>";

str oStm( E(NodeId from, Stm to)) = "<oNodeId(from)>-\><oStm(to)>";
str oStm( E(Id from, Stm to, Attrs attrs)) = "<from>-\><oStm(to)><oAttrs(attrs)>";
str oStm( E(str from, Stm to, Attrs attrs)) = "<from>-\><oStm(to)><oAttrs(attrs)>";

str oStm( E(Stm from, Stm to)) = "<oStm(from)>-\><oStm(to)>";
str oStm( E(Stm from, Stm to, Attrs attrs)) = "<oStm(from)>-\><oStm(to)><oAttrs(attrs)>";

str oStm( S(Stms stms)) = "subgraph {<oStms(stms,";")>} ";
str oStm( S(Id id, Stms stms)) = "subgraph <id> {<oStms(stms,";")>} ";
str oStm( A(Id prop, Id val)) = "<prop> = <val>";
str oStm( S(list[Stm] stms)) = "subgraph {<oStms(stms,";")>} ";
str oStm( S(str id, list[Stm] stms)) = "subgraph <id> {<oStms(stms,";")>} ";
str oStm( A(str prop, str val)) = "<prop> = <val>";
str oStm( GRAPH(Attrs attrs)) = "graph <oAttrs(attrs)>";
str oStm( EDGE(Attrs attrs)) = "edge <oAttrs(attrs)>";
str oStm( NODE(Attrs attrs)) = "node <oAttrs(attrs)>";
Expand Down
130 changes: 57 additions & 73 deletions src/org/rascalmpl/library/lang/dot/syntax/Dot.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,48 @@
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
}
@synopsis{Grammar for AT&T's Graphviz DOT language.}
@contributor{Bert Lisser - [email protected]}

module lang::dot::\syntax::Dot

start syntax DOT = LAYOUT* Graph Id "{" StatementList "}" "\n"?;

keyword Reserved = "graph"|"digraph"|"node"|"edge"|"subgraph";

syntax Graph = "graph"|"digraph"|AttrTag;

syntax AttrTag = "node"|"edge"|"graph";

syntax Nod = NodeId|Subgraph;

lexical Id = ([A-Z a-z 0-9 _] !<< [A-Z a-z 0-9 _]+ !<< [a-z A-Z 0-9 _][a-z A-Z 0-9 _]* !>> [0-9 A-Z _ a-z]) \ Reserved
| [\"] (![\"] | "\\\"")* [\"]
| [\-]? "." [0-9]+
| [\-]? [0-9]+ "." [0-9]*
;

syntax StatementList = StatementOptional*;

syntax Statement = NodeStatement
|EdgeStatement
|AttrStatement
>Id "=" Id
;

syntax StatementOptional = Statement ";"?;
start syntax DOT = Graph Id "{" {Statement ";"?}* statements ";"? "}";

keyword Reserved
= "graph"
| "digraph"
| "node"
| "edge"
| "subgraph"
;
syntax Graph
= "graph"
| "digraph"
;

syntax AttrTag
= "node"
| "edge"
| "graph"
;

syntax Nod
= NodeId
| Subgraph;

lexical Id
= ([A-Z a-z 0-9 _] !<< [a-z A-Z 0-9 _][a-z A-Z 0-9 _]* !>> [0-9 A-Z _ a-z]) \ Reserved
| [\"] (![\"] | "\\\"")* [\"]
| [\-]? "." [0-9]+
| [\-]? [0-9]+ "." [0-9]*
;

syntax Statement
= NodeStatement
| EdgeStatement
| AttrStatement
| Id "=" Id
;

syntax NodeStatement = Nod AttrList;

Expand All @@ -45,61 +58,32 @@ syntax EdgeOp = "-\>" | "--";

syntax EdgeRhs = Edg+;

syntax NodeId = Id
| Id Port
;
syntax NodeId
= Id
| Id Port
;

syntax Port = ":" Id Id?
// | ":" Id
// | ":" CompassPt
;
syntax Port = ":" Id Id?;

// syntax CompassPt = "n" | "ne" | "e" | "se" | "s" | "sw" | "w"| "nw" | "c" |"_";
syntax CompassPt = "n" | "ne" | "e" | "se" | "s" | "sw" | "w"| "nw" | "c" | "_";

syntax AttrList = AttrList0*;
syntax AttrList = AttrList0*;

syntax AttrList0 = "[" DotAttr* "]";

syntax DotAttr = Id "=" Id | Id "=" Id "," ;

syntax AttrStatement = AttrTag AttrList;

syntax Subgraph = ("subgraph" Id? )? "{" StatementList "}";

lexical Comment = "/*" (![*] | [*] !>> "/")* "*/"
| "//" ![\n]* $
;

layout LAYOUTLIST = LAYOUT* !>> [\ \t\n\r] !>> "//" !>> "/*"
;


lexical LAYOUT = Whitespace: [\ \t\n\r]
| @category="Comment" Comment
;


/*
graph : [ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
stmt_list : [ stmt [ ';' ] [ stmt_list ] ]
stmt : node_stmt
| edge_stmt
| attr_stmt
| ID '=' ID
| subgraph
attr_stmt : (graph | node | edge) attr_list
attr_list : '[' [ a_list ] ']' [ attr_list ]
a_list : ID [ '=' ID ] [ ',' ] [ a_list ]
edge_stmt : (node_id | subgraph) edgeRHS [ attr_list ]
edgeRHS : edgeop (node_id | subgraph) [ edgeRHS ]
node_stmt : node_id [ attr_list ]
node_id : ID [ port ]
port : ':' ID [ ':' compass_pt ]
| ':' compass_pt
subgraph : [ subgraph [ ID ] ] '{' stmt_list '}'
compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)
*/
syntax Subgraph = ("subgraph" Id? )? "{" {Statement ";"?}* statements ";"? "}";

lexical Comment
= "/*" (![*] | [*] !>> "/")* "*/"
| "//" ![\n]* $
;

layout LAYOUTLIST = LAYOUT* !>> [\ \t\n\r] !>> "//" !>> "/*";
lexical LAYOUT
= Whitespace: [\ \t\n\r]
| @category="Comment" Comment
;

0 comments on commit fc35a33

Please sign in to comment.