2
2
3
3
import java .io .File ;
4
4
import java .io .PrintWriter ;
5
+ import java .util .Set ;
5
6
import java .util .regex .Matcher ;
6
7
import java .util .regex .Pattern ;
7
8
10
11
import processing .app .Sketch ;
11
12
import processing .app .SketchCode ;
12
13
14
+ import info .sansgills .mode .python .preproc .*;
15
+
16
+ import org .antlr .v4 .runtime .ANTLRInputStream ;
17
+ import org .antlr .v4 .runtime .CommonTokenStream ;
18
+ import org .antlr .v4 .runtime .tree .ParseTree ;
19
+ import org .antlr .v4 .runtime .tree .ParseTreeWalker ;
20
+
21
+
13
22
14
23
/**
15
24
*
16
25
* Class to handle the building of python files.
17
- * Given that python runs as an interpreter, all this does is handle preprocessing.
26
+ * Given that python runs as an interpreter, all this does is handle preprocessing
27
+ * and write to an output file.
18
28
*
19
29
* See BUILD.md for notes.
20
30
*
21
31
*/
22
32
23
33
public class PythonBuild {
24
-
25
34
Sketch sketch ;
26
35
String resultProgram ;
27
36
@@ -30,6 +39,8 @@ public class PythonBuild {
30
39
File binFolder ;
31
40
File outFile ;
32
41
42
+ String classPath , pythonLibs , javaLibs ;
43
+
33
44
//build tracking
34
45
private int buildnumber ;
35
46
private static int buildstotal = 0 ;
@@ -69,62 +80,60 @@ public void build() throws Exception{
69
80
+ sketch .getName ().toLowerCase ()
70
81
+ ".py" );
71
82
outFile .createNewFile ();
72
-
83
+
73
84
74
85
PrintWriter writer = new PrintWriter (outFile );
75
86
writer .print (resultProgram );
76
87
writer .close ();
77
88
}
78
89
79
90
80
-
81
- //Things we don't need to reload every build
82
- //Some regexes
83
- //A hack, but much less work than a full parser, and we don't need to do very much
84
- private static Pattern getSpecial ; //replace mousePressed / keyPressed /frameRate with getmousePressed, etc.
85
- private static Pattern instanceVars ; //replace 'mouseX' with __applet__.mouseX, etc.
86
- private static Pattern findSetup , indent ; //for static-mode sketches
87
-
88
- static {
89
- getSpecial = Pattern .compile ("(?<!def\\ s{1,1000})(mousePressed|keyPressed|frameRate)(?![0-9a-zA-Z_])(?!\\ s{0,1000}\\ ()" );
90
- instanceVars = Pattern .compile ("(mouseX|mouseY|pmouseX|pmouseY|mouseButton|"
91
- +"keyCode|key|pixels|width|height|displayWidth|displayHeight|focused|frameCount)(?![0-9a-zA-Z_])" );
92
- findSetup = Pattern .compile ("^def\\ s+setup\\ s*\\ (\\ s*\\ )\\ s*:" , Pattern .MULTILINE );
93
- indent = Pattern .compile ("\r ?\n " );
94
- }
95
-
96
-
97
-
98
91
/*
99
92
* Turn .pde into valid python
93
+ *
94
+ * Now with antlr!
100
95
*/
101
96
private String preprocess (StringBuilder program ){
97
+ if (Pattern .matches ("\\ s*" , program )){
98
+ return "def setup():\n \t pass\n \n " ; //empty sketch; TODO fix hack
99
+ }
102
100
try {
103
- String temp ;
101
+ PyPdeLexer lexer = new PyPdeLexer (new ANTLRInputStream (program .toString ()));
102
+ CommonTokenStream tokens = new CommonTokenStream (lexer );
103
+ PyPdeParser parser = new PyPdeParser (tokens );
104
+ ParseTree tree = parser .script ();
105
+ PyPdeConverter converter = new PyPdeConverter (tokens );
106
+ ParseTreeWalker walker = new ParseTreeWalker ();
107
+ walker .walk (converter , tree );
104
108
105
- Matcher regex = getSpecial . matcher ( program );
109
+ String result = converter . getText ( );
106
110
107
- temp = regex . replaceAll ( "get$1()" );
111
+ String [] libraries = converter . getLibraries ( );
108
112
109
- regex = instanceVars . matcher ( temp );
113
+ Set < String > knownPythonLibraries = PythonMode . getPythonLibraries ( );
110
114
111
- temp = regex .replaceAll ("__applet__.$1" );
115
+ pythonLibs = "" ;
116
+ javaLibs = "" ;
112
117
113
- regex = findSetup .matcher (temp );
114
-
115
- if (!regex .find ()){
116
- //no setup function; static mode sketch
117
- //TODO handle bad indentation
118
- program = new StringBuilder (temp );
119
- program .append ("\n noLoop()\n " ); //no need to call draw()
120
- program .insert (0 , "def setup():\n " ); //put the whole function in setup()
121
-
122
- regex = indent .matcher (program );
123
-
124
- temp = regex .replaceAll ("\n \t " ); //indent everything a level! (except the first line)
118
+ for (String lib : libraries ){
119
+ if (knownPythonLibraries .contains (lib )){
120
+ //it's a python library; for now, I'm only handling ones built into jython, so no need to do anything
121
+ }else {
122
+ //normal java library; we can use the normal library infrastructure
123
+ int dot = lib .lastIndexOf ('.' );
124
+ String entry = (dot == -1 ) ? lib : lib .substring (0 , dot );
125
+ Library library = mode .getLibrary (entry );
126
+ javaLibs += library .getJarPath () + System .getProperty ("path.separator" );
127
+ }
125
128
}
126
129
127
- return temp ;
130
+ if (pythonLibs .equals ("" )){
131
+ pythonLibs = null ;
132
+ }
133
+ if (javaLibs .equals ("" )){
134
+ javaLibs = null ;
135
+ }
136
+ return result ;
128
137
129
138
}catch (Exception e ){
130
139
System .err .println ("Preprocessing failed." );
@@ -133,13 +142,20 @@ private String preprocess(StringBuilder program){
133
142
}
134
143
}
135
144
145
+ public String getJavaLibraries (){
146
+ return javaLibs ;
147
+ }
148
+ public boolean hasJavaLibraries (){
149
+ return javaLibs != null ;
150
+ }
136
151
137
152
138
-
139
-
140
-
141
-
142
-
153
+ public String getPythonLibraries (){
154
+ return pythonLibs ;
155
+ }
156
+ public boolean hasPythonLibraries (){
157
+ return pythonLibs != null ;
158
+ }
143
159
144
160
/*
145
161
* The output code string
@@ -164,35 +180,13 @@ public int getBuildNumber(){
164
180
165
181
/*
166
182
* Classes used to run the build.
167
- *
168
- * TODO build during preprocess
169
183
*/
170
184
public String getClassPath () {
171
- //the Processing classpath
172
- String cp = mode .getCoreLibrary ().getClassPath ();
173
-
174
- // From JavaMode.java:
175
- // Finally, add the regular Java CLASSPATH. This contains everything
176
- // imported by the PDE itself (core.jar, pde.jar, quaqua.jar) which may
177
- // in fact be more of a problem.
178
- String javaClassPath = System .getProperty ("java.class.path" );
179
- // Remove quotes if any.. A messy (and frequent) Windows problem
180
- if (javaClassPath .startsWith ("\" " ) && javaClassPath .endsWith ("\" " )) {
181
- javaClassPath = javaClassPath .substring (1 ,
182
- javaClassPath .length () - 1 );
183
- }
184
- cp += File .pathSeparator + javaClassPath ;
185
-
186
- //The .jars for this mode; Jython and wrapper, primarily
187
- String jythonModeLib = Base .getSketchbookModesFolder ().getAbsolutePath ()
188
- + File .separator
189
- + "PythonMode"
190
- + File .separator
191
- + "mode" ;
192
- cp += Base .contentsToClassPath (new File (jythonModeLib ));
193
-
194
-
195
- return cp ; // TODO libraries?
185
+ return classPath ; //computed during preprocessing
186
+ }
187
+
188
+ public String getName () {
189
+ return sketch .getName ();
196
190
}
197
191
198
192
/*
@@ -201,18 +195,4 @@ public String getClassPath() {
201
195
public String getJavaLibraryPath (){
202
196
return "" ;
203
197
}
204
-
205
- /*
206
- * The PApplet subclass to extract from the code
207
- */
208
- public String getClassName (){
209
- return "Placeholder" ; //TODO implement naming scheme
210
- }
211
-
212
- /*
213
- * The name of the output object
214
- */
215
- public String getObjName (){
216
- return "applet" ; // TODO
217
- }
218
198
}
0 commit comments