Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/core/adot/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export class NumberLiteral extends Expression {
}
}

export class StringLiteral extends Expression {
constructor(public readonly token: Token, public value: string) {
super();
}
}

export class Identifier extends Expression {
constructor(public readonly token: Token, public value: string) {
super();
Expand Down
3 changes: 3 additions & 0 deletions src/core/adot/evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ export class Evaluator {
attributesList["cost"] && typeof attributesList["cost"] === "number"
? attributesList["cost"]
: null,
attributesList["name"] && typeof attributesList["name"] === "string"
? attributesList["name"]
: null,
isDirected
);

Expand Down
12 changes: 12 additions & 0 deletions src/core/adot/lexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ describe("Lexer next token", () => {
a -- b;
c [cost=10.23]
c -- d0 [cost=10]

x -- y [name="test"]
}

test {}
Expand Down Expand Up @@ -54,6 +56,16 @@ subgraph
[TOKEN_TYPE.Number, "10"],
[TOKEN_TYPE.RBracket, "]"],

// x -- y [name="test"]
[TOKEN_TYPE.Id, "x"],
[TOKEN_TYPE.Edge, "--"],
[TOKEN_TYPE.Id, "y"],
[TOKEN_TYPE.LBracket, "["],
[TOKEN_TYPE.Id, "name"],
[TOKEN_TYPE.Eq, "="],
[TOKEN_TYPE.String, "test"],
[TOKEN_TYPE.RBracket, "]"],

// }
[TOKEN_TYPE.RBrace, "}"],

Expand Down
30 changes: 30 additions & 0 deletions src/core/adot/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ export class Lexer {
token = this.newToken(TOKEN_TYPE.Illegal, this.char + this.peekChar());
}
break;
case '"':
const string = this.readString();
if (string === null) {
token = this.newToken(TOKEN_TYPE.Illegal, this.char);
} else {
token = this.newToken(TOKEN_TYPE.String, string);
}
break;
case "=":
token = this.newToken(TOKEN_TYPE.Eq, this.char);
break;
Expand Down Expand Up @@ -67,6 +75,28 @@ export class Lexer {
return token;
}

private readString(): string | null {
let output = "";
this.readChar(); // Skip the initial quote
let escape = false;
while (this.char != '"' || escape) {
if (this.char == "\n") return null; // Early EoL
if (escape) {
output += this.char;
escape = false;
} else {
if (this.char == "\\") {
escape = true;
} else {
output += this.char;
}
}
this.readChar();
}

return output;
}

private readNumber(): string {
const position = this.pos;

Expand Down
6 changes: 6 additions & 0 deletions src/core/adot/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ export class Parser {
return this.parseIdentifier();
case TOKEN_TYPE.Number:
return this.parseNumberLiteral();
case TOKEN_TYPE.String:
return this.parseStringLiteral();
default:
throw this.error(errorFmtAt(this.currToken, "Expected an expression."));
}
Expand All @@ -214,6 +216,10 @@ export class Parser {
return new ast.NumberLiteral(this.currToken, parseFloat(this.currToken.literal));
}

private parseStringLiteral(): ast.StringLiteral {
return new ast.StringLiteral(this.currToken, this.currToken.literal);
}

private parseIdentifier(): ast.Identifier {
return new ast.Identifier(this.currToken, this.currToken.literal);
}
Expand Down
1 change: 1 addition & 0 deletions src/core/adot/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const TOKEN_TYPE = {
Eq: "EQ",
Illegal: "ILLEGAL",
EOF: "EOF",
String: "STRING",
} as const;

export type TokenType = (typeof TOKEN_TYPE)[keyof typeof TOKEN_TYPE];
Expand Down
1 change: 1 addition & 0 deletions src/core/simulator/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class Edge {
public readonly from: string,
public readonly to: string,
public weight: number | null,
public name: string | null,
public readonly directed: boolean
) {}

Expand Down
10 changes: 5 additions & 5 deletions src/features/graph-view/components/Edge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type EdgeProps = {
position?: number;
circular?: boolean;
thicken?: boolean;
weight?: number;
name?: string;
};

export function Edge(props: EdgeProps) {
Expand All @@ -34,7 +34,7 @@ function StraightEdge({
color = "slate",
thicken = false,
position = 0,
weight,
name,
}: EdgeProps) {
const edgePathRef = useRef<SVGPathElement>(null);

Expand Down Expand Up @@ -69,7 +69,7 @@ function StraightEdge({
d={path}
stroke={stroke}
/>
{weight && <EdgeLabel text={weight.toString()} position={edgeLabelPosition} angle={-deg} />}
{name && <EdgeLabel text={name} position={edgeLabelPosition} angle={-deg} />}
{directed && <Arrow position={end} angle={-angle} color={color} />}
</g>
);
Expand All @@ -81,7 +81,7 @@ const getPathCenter = (path: SVGPathElement) => {
return new Vec2(centerPoint.x, centerPoint.y);
};

const CircularEdge = ({ x, y, directed, position = 0, color = "slate", weight }: EdgeProps) => {
const CircularEdge = ({ x, y, directed, position = 0, color = "slate", name }: EdgeProps) => {
const radius = 6 * position + 16;
const cx = radius + vertexRadius / 1.61;
const transform = `translate(${x} ${y}) rotate(65)`;
Expand All @@ -103,7 +103,7 @@ const CircularEdge = ({ x, y, directed, position = 0, color = "slate", weight }:
r={radius}
stroke={stroke}
/>
{weight && <EdgeLabel text={weight.toString()} position={edgeLabelPosition} angle={-90} />}
{name && <EdgeLabel text={name} position={edgeLabelPosition} angle={-90} />}
{directed && <Arrow position={arrowPosition} angle={arrowAngle} color={color} />}
</g>
);
Expand Down
11 changes: 10 additions & 1 deletion src/features/graph-view/components/Edges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export function Edges({ positionedEdges, arrangement, highlights }: EdgesProps)
const { x: toX, y: toY } = arrangement[edge.to] ?? centerPosition;
const isCircular = edge.from === edge.to;

let name = edge.name ?? undefined;
if (edge.weight !== null) {
if (name) {
name += `: ${edge.weight}`;
} else {
name = edge.weight.toString();
}
}

return (
<Edge
key={edge.id}
Expand All @@ -34,7 +43,7 @@ export function Edges({ positionedEdges, arrangement, highlights }: EdgesProps)
circular={isCircular}
color={color}
thicken={!!color}
weight={edge.weight ?? undefined}
name={name}
/>
);
});
Expand Down
4 changes: 4 additions & 0 deletions src/pages/editor/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const initialCode = `graph {
c -- c0 [cost=0.3];
d -- d0 [cost=0.3];
e -- e0 [cost=0.8];

# You can also give edges explicit names

x -- z [name="Connection"]
}
`;

Expand Down