Skip to content

Commit 4271329

Browse files
committed
Refactoring: flattenning parsed magic class structures
this gives us a better simpler model of parsed magics
1 parent 48da1c1 commit 4271329

File tree

7 files changed

+99
-122
lines changed

7 files changed

+99
-122
lines changed

jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/magic/CellMagicArgs.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/magic/LineMagicArgs.java

Lines changed: 0 additions & 14 deletions
This file was deleted.

jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/magic/MagicParser.java

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,73 @@
1111
*/
1212
public class MagicParser {
1313

14+
private final Pattern lineMagicPattern;
15+
private final Pattern cellMagicPattern;
16+
private final MagicTranspiler transpiler;
17+
18+
public MagicParser(String lineMagicStart, String cellMagicStart, MagicTranspiler transpiler) {
19+
this.lineMagicPattern = Pattern.compile(lineMagicStart + "(?<args>\\w.*?)$", Pattern.MULTILINE);
20+
this.cellMagicPattern = Pattern.compile("^(?<argsLine>" + cellMagicStart + "(?<args>\\w.*?))\\R(?<body>(?sU).+?)$");
21+
this.transpiler = transpiler;
22+
}
23+
24+
/**
25+
* Replaces cell and line magics in the source with native kernel code.
26+
*/
27+
public String resolveMagics(String cellSource) {
28+
return transpileCellMagic(cellSource).orElse(transpileLineMagics(cellSource));
29+
}
30+
31+
private Optional<String> transpileCellMagic(String cellSource) {
32+
ParsedCellMagic parsedCell = parseCellMagic(cellSource);
33+
return Optional.ofNullable(parsedCell).map(transpiler::transpileCell);
34+
}
35+
36+
String transpileLineMagics(String cellSource) {
37+
38+
StringBuffer out = new StringBuffer();
39+
Matcher m = lineMagicPattern.matcher(cellSource);
40+
41+
while (m.find()) {
42+
ParsedLineMagic parsed = parseLineMagic(cellSource, m);
43+
String transformed = transpiler.transpileLine(parsed);
44+
m.appendReplacement(out, Matcher.quoteReplacement(transformed));
45+
}
46+
47+
m.appendTail(out);
48+
return out.toString();
49+
}
50+
51+
ParsedCellMagic parseCellMagic(String cellSource) {
52+
Matcher m = cellMagicPattern.matcher(cellSource);
53+
54+
if (!m.matches()) {
55+
return null;
56+
}
57+
58+
List<String> split = split(m.group("args"));
59+
String body = m.group("body");
60+
61+
return new ParsedCellMagic(
62+
split.get(0),
63+
split.subList(1, split.size()),
64+
body);
65+
}
66+
67+
private ParsedLineMagic parseLineMagic(String cellSource, Matcher matchedLine) {
68+
List<String> split = split(matchedLine.group("args"));
69+
70+
String rawLinePrefix = cellSource.substring(0, matchedLine.start());
71+
String linePrefix = rawLinePrefix.substring(rawLinePrefix.lastIndexOf('\n') + 1);
72+
73+
return new ParsedLineMagic(
74+
split.get(0),
75+
split.subList(1, split.size()),
76+
linePrefix,
77+
matchedLine.group()
78+
);
79+
}
80+
1481
static List<String> split(String args) {
1582
args = args.trim();
1683

@@ -64,69 +131,4 @@ static List<String> split(String args) {
64131

65132
return split;
66133
}
67-
68-
private final Pattern lineMagicPattern;
69-
private final Pattern cellMagicPattern;
70-
private final MagicTranspiler transpiler;
71-
72-
public MagicParser(String lineMagicStart, String cellMagicStart, MagicTranspiler transpiler) {
73-
this.lineMagicPattern = Pattern.compile(lineMagicStart + "(?<args>\\w.*?)$", Pattern.MULTILINE);
74-
this.cellMagicPattern = Pattern.compile("^(?<argsLine>" + cellMagicStart + "(?<args>\\w.*?))\\R(?<body>(?sU).+?)$");
75-
this.transpiler = transpiler;
76-
}
77-
78-
/**
79-
* Replaces cell and line magics in the source with native kernel code.
80-
*/
81-
public String resolveMagics(String cellSource) {
82-
return transpileCellMagic(cellSource).orElse(transpileLineMagics(cellSource));
83-
}
84-
85-
private Optional<String> transpileCellMagic(String cellSource) {
86-
ParsedCellMagic parsedCell = parseCellMagic(cellSource);
87-
return Optional.ofNullable(parsedCell).map(transpiler::transpileCell);
88-
}
89-
90-
String transpileLineMagics(String cellSource) {
91-
92-
StringBuffer out = new StringBuffer();
93-
Matcher m = lineMagicPattern.matcher(cellSource);
94-
95-
while (m.find()) {
96-
ParsedLineMagic parsed = parseLineMagic(cellSource, m);
97-
String transformed = transpiler.transpileLine(parsed);
98-
m.appendReplacement(out, Matcher.quoteReplacement(transformed));
99-
}
100-
101-
m.appendTail(out);
102-
return out.toString();
103-
}
104-
105-
ParsedCellMagic parseCellMagic(String cellSource) {
106-
Matcher m = this.cellMagicPattern.matcher(cellSource);
107-
108-
if (!m.matches()) {
109-
return null;
110-
}
111-
112-
String rawArgsLine = m.group("argsLine");
113-
String rawArgs = m.group("args");
114-
String body = m.group("body");
115-
List<String> split = split(rawArgs);
116-
117-
CellMagicArgs args = new CellMagicArgs(split.get(0), split.subList(1, split.size()), body);
118-
return new ParsedCellMagic(args, rawArgsLine, cellSource);
119-
}
120-
121-
private ParsedLineMagic parseLineMagic(String cellSource, Matcher matchedLine) {
122-
String raw = matchedLine.group();
123-
String rawArgs = matchedLine.group("args");
124-
List<String> split = split(rawArgs);
125-
126-
LineMagicArgs args = new LineMagicArgs(split.get(0), split.subList(1, split.size()));
127-
128-
String rawLinePrefix = cellSource.substring(0, matchedLine.start());
129-
String linePrefix = rawLinePrefix.substring(rawLinePrefix.lastIndexOf('\n') + 1);
130-
return new ParsedLineMagic(args, raw, cellSource, linePrefix);
131-
}
132134
}

jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/magic/MagicTranspiler.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,29 @@ public class MagicTranspiler {
2121

2222
public String transpileCell(ParsedCellMagic magic) {
2323
return String.format(CELL_CALL_TEMPLATE,
24-
argWithEscapingToJava(magic.magicCall.name),
25-
magic.magicCall.args.stream()
24+
argWithEscapingToJava(magic.name),
25+
magic.args.stream()
2626
.map(this::argWithEscapingToJava)
2727
.collect(Collectors.joining(",")),
28-
argWithEscapingToJava(magic.magicCall.body)
28+
argWithEscapingToJava(magic.cellBodyAfterMagic)
2929
);
3030
}
3131

3232
public String transpileLine(ParsedLineMagic magic) {
3333
boolean inString = false;
34-
Matcher m = UNESCAPED_QUOTE.matcher(magic.linePrefix);
34+
Matcher m = UNESCAPED_QUOTE.matcher(magic.magicLinePrefix);
3535
while (m.find()) {
3636
inString = !inString;
3737
}
3838

3939
// If in a string literal, don't apply the magic, just use the original
4040
if (inString) {
41-
return magic.raw;
41+
return magic.unparsedMagic;
4242
}
4343

4444
return String.format(LINE_CALL_TEMPLATE,
45-
argWithEscapingToJava(magic.magicCall.name),
46-
magic.magicCall.args.stream()
45+
argWithEscapingToJava(magic.name),
46+
magic.args.stream()
4747
.map(this::argWithEscapingToJava)
4848
.collect(Collectors.joining(","))
4949
);
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package org.dflib.jjava.jupyter.kernel.magic;
22

3+
import java.util.List;
4+
35
public class ParsedCellMagic {
46

5-
public final CellMagicArgs magicCall;
6-
public final String rawArgsLine;
7-
public final String rawCell;
7+
public final String name;
8+
public final List<String> args;
9+
public final String cellBodyAfterMagic;
810

9-
public ParsedCellMagic(CellMagicArgs magicCall, String rawArgsLine, String rawCell) {
10-
this.magicCall = magicCall;
11-
this.rawArgsLine = rawArgsLine;
12-
this.rawCell = rawCell;
11+
public ParsedCellMagic(String name, List<String> args, String cellBodyAfterMagic) {
12+
this.name = name;
13+
this.args = args;
14+
this.cellBodyAfterMagic = cellBodyAfterMagic;
1315
}
1416
}
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package org.dflib.jjava.jupyter.kernel.magic;
22

3+
import java.util.List;
4+
35
public class ParsedLineMagic {
46

5-
public final LineMagicArgs magicCall;
6-
public final String raw;
7-
public final String rawCell;
8-
public final String linePrefix;
7+
public final String name;
8+
public final List<String> args;
9+
public final String magicLinePrefix;
10+
public final String unparsedMagic;
911

10-
public ParsedLineMagic(LineMagicArgs magicCall, String raw, String rawCell, String linePrefix) {
11-
this.magicCall = magicCall;
12-
this.raw = raw;
13-
this.rawCell = rawCell;
14-
this.linePrefix = linePrefix;
12+
public ParsedLineMagic(String name, List<String> args, String magicLinePrefix, String unparsedMagic) {
13+
this.name = name;
14+
this.args = args;
15+
this.magicLinePrefix = magicLinePrefix;
16+
this.unparsedMagic = unparsedMagic;
1517
}
1618
}

jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/magic/MagicParserTest.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ public void parseCellMagic() {
1818
ParsedCellMagic parsed = inlineParser(emptyTranspiler).parseCellMagic(cell);
1919

2020
assertNotNull(parsed);
21-
assertEquals("cellMagicName", parsed.magicCall.name);
22-
assertEquals(Arrays.asList("arg1", "arg2 arg2", "arg3"), parsed.magicCall.args);
23-
assertEquals("This is the body\nwith multiple lines", parsed.magicCall.body);
24-
assertEquals("//%%cellMagicName arg1 \"arg2 arg2\" arg3 ", parsed.rawArgsLine);
25-
assertEquals(cell, parsed.rawCell);
21+
assertEquals("cellMagicName", parsed.name);
22+
assertEquals(Arrays.asList("arg1", "arg2 arg2", "arg3"), parsed.args);
23+
assertEquals("This is the body\nwith multiple lines", parsed.cellBodyAfterMagic);
2624
}
2725

2826
@Test
@@ -118,7 +116,7 @@ public String transpileCell(ParsedCellMagic magic) {
118116

119117
@Override
120118
public String transpileLine(ParsedLineMagic magic) {
121-
return "**" + magic.magicCall.name + "-" + String.join(",", magic.magicCall.args);
119+
return "**" + magic.name + "-" + String.join(",", magic.args);
122120
}
123121
};
124122

@@ -131,7 +129,7 @@ public String transpileCell(ParsedCellMagic magic) {
131129

132130
@Override
133131
public String transpileLine(ParsedLineMagic magic) {
134-
return magic.magicCall.name;
132+
return magic.name;
135133
}
136134
};
137135
}

0 commit comments

Comments
 (0)