Browse code
initial commit
fiddlerwoaroof authored on 28/06/2016 16:49:44
Showing 4 changed files
Showing 4 changed files
0 | 6 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,13 @@ |
1 |
+;;;; phpgen.asd |
|
2 |
+ |
|
3 |
+(asdf:defsystem #:phpgen |
|
4 |
+ :description "Describe phpgen here" |
|
5 |
+ :author "Your Name <your.name@example.com>" |
|
6 |
+ :license "Specify license here" |
|
7 |
+ :depends-on (#:fwoar.lisputils |
|
8 |
+ #:alexandria |
|
9 |
+ #:serapeum) |
|
10 |
+ :serial t |
|
11 |
+ :components ((:file "package") |
|
12 |
+ (:file "phpgen"))) |
|
13 |
+ |
0 | 14 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,120 @@ |
1 |
+;;;; phpgen.lisp |
|
2 |
+ |
|
3 |
+(in-package #:phpgen) |
|
4 |
+ |
|
5 |
+;;; "phpgen" goes here. Hacks and glory await! |
|
6 |
+ |
|
7 |
+(defgeneric generate-php (ast &optional level)) |
|
8 |
+ |
|
9 |
+(defclass ast () |
|
10 |
+ ((%children :initarg :children :accessor children :initform '()))) |
|
11 |
+ |
|
12 |
+(defclass statement (ast) |
|
13 |
+ ((%statement-control :initarg :statement-control :accessor statement-control :initform nil)) |
|
14 |
+ (:documentation "A linguistic construct without a return value")) |
|
15 |
+ |
|
16 |
+(defclass expression (ast) |
|
17 |
+ () |
|
18 |
+ (:documentation "A linguistic construct with a return value")) |
|
19 |
+ |
|
20 |
+(defmethod generate-php ((ast string) &optional level) |
|
21 |
+ (declare (ignore level)) |
|
22 |
+ (when (ends-with #\; ast) |
|
23 |
+ (setf ast (subseq ast (length ast)))) |
|
24 |
+ (trim-whitespace ast)) |
|
25 |
+ |
|
26 |
+(defmethod separate-children ((ast ast)) |
|
27 |
+ " ") |
|
28 |
+ |
|
29 |
+(defmethod separate-children ((ast statement)) |
|
30 |
+ (format nil ";~%")) |
|
31 |
+ |
|
32 |
+ |
|
33 |
+(defmethod generate-php ((ast ast) &optional (level 0)) |
|
34 |
+ (apply #'concatenate 'string |
|
35 |
+ (loop for child in (children ast) |
|
36 |
+ collect (format nil "~vt~a~a" |
|
37 |
+ (* 4 (1+ level)) |
|
38 |
+ (generate-php child (1+ level)) |
|
39 |
+ (separate-children ast))))) |
|
40 |
+ |
|
41 |
+(defmethod generate-php :around ((ast statement) &optional (level 0)) |
|
42 |
+ (declare (ignore level)) |
|
43 |
+ (format nil "~a{~%~a~&}~a~%" |
|
44 |
+ (format-preamble ast (statement-control ast)) |
|
45 |
+ (call-next-method) |
|
46 |
+ (format-postamble ast (statement-control ast)))) |
|
47 |
+ |
|
48 |
+(defclass conditional-statement (statement) |
|
49 |
+ ()) |
|
50 |
+ |
|
51 |
+(defmethod format-postamble ((ast conditional-statement) value) |
|
52 |
+ (declare (ignore ast)) |
|
53 |
+ (format nil "" value)) |
|
54 |
+ |
|
55 |
+(defmethod format-preamble ((ast conditional-statement) value) |
|
56 |
+ (declare (ignore ast)) |
|
57 |
+ (format nil "(~a)" value)) |
|
58 |
+ |
|
59 |
+(defclass if-statement (conditional-statement) |
|
60 |
+ ()) |
|
61 |
+ |
|
62 |
+(defclass while-statement (conditional-statement) |
|
63 |
+ ()) |
|
64 |
+ |
|
65 |
+(defclass do-while-statement (conditional-statement) |
|
66 |
+ ()) |
|
67 |
+ |
|
68 |
+(defmacro define-conditional-statement (name &optional (keyword (string-downcase name))) |
|
69 |
+ (let ((name (intern (format nil "~a-STATEMENT" name)))) |
|
70 |
+ `(progn |
|
71 |
+ (defclass ,name (conditional-statement) |
|
72 |
+ ()) |
|
73 |
+ |
|
74 |
+ (defmethod generate-php :around ((ast ,name) &optional level) |
|
75 |
+ (declare (ignore level)) |
|
76 |
+ (format nil ,(format nil "~a ~~a" keyword) |
|
77 |
+ (call-next-method)))))) |
|
78 |
+ |
|
79 |
+(define-conditional-statement if) |
|
80 |
+(define-conditional-statement elseif "elseif") |
|
81 |
+(define-conditional-statement while "while") |
|
82 |
+ |
|
83 |
+(defmethod generate-php :around ((ast do-while-statement) &optional level) |
|
84 |
+ (declare (ignore level)) |
|
85 |
+ (format nil "do ~a" |
|
86 |
+ (call-next-method))) |
|
87 |
+ |
|
88 |
+(defmethod format-preamble ((ast do-while-statement) value) |
|
89 |
+ "") |
|
90 |
+ |
|
91 |
+(defmethod format-postamble ((ast do-while-statement) value) |
|
92 |
+ (format nil " while (~a)" value)) |
|
93 |
+ |
|
94 |
+(defclass assignment (expression) |
|
95 |
+ ((place :initarg :place :accessor ast-place :initform nil) |
|
96 |
+ (value :initarg :value :accessor ast-value :initform nil))) |
|
97 |
+ |
|
98 |
+(defclass function-call (expression) |
|
99 |
+ ((name :initarg :name :accessor ast-name :initform nil))) |
|
100 |
+ |
|
101 |
+(defmethod generate-php ((ast function-call) &optional level) |
|
102 |
+ (declare (ignore level)) |
|
103 |
+ (format nil "~a(~{~a~^, ~})" |
|
104 |
+ (ast-name ast) |
|
105 |
+ (mapcar #'generate-php (children ast)))) |
|
106 |
+ |
|
107 |
+(defmethod generate-php ((ast assignment) &optional level) |
|
108 |
+ (declare (ignore level)) |
|
109 |
+ (format nil "~a = ~a" |
|
110 |
+ (generate-php (ast-place ast)) |
|
111 |
+ (generate-php (ast-value ast)))) |
|
112 |
+ |
|
113 |
+(trace generate-php) |
|
114 |
+ |
|
115 |
+(generate-php "bar") |
|
116 |
+(generate-php (make-instance 'ast :children (list "bar" "baz"))) |
|
117 |
+(generate-php (make-instance 'function-call :name "foo" :children (list "bar" "baz"))) |
|
118 |
+(generate-php (make-instance 'do-while-statement :statement-control "foo" |
|
119 |
+ :children (list "bar" |
|
120 |
+ "baz"))) |