-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
133 lines (127 loc) · 3.56 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env node
const css = require('css')
const fs = require('fs')
const {c} = require('compile-run')
class c_call {
constructor(name, args, type) {
this.name = name
this.args = args
this.type = type
}
generate() {
let genargs = '';
for (let i = 0; i < this.args.length; i++) {
const arg = this.args[i]
if (i > 0) {
genargs += `, ${arg}`
} else {
genargs += arg
}
}
if (this.type === undefined) {
return ` ${this.name}(${genargs});\n`
} else if (this.type == 'var') {
if (parseFloat(this.args)) {
return ` float ${this.name} = ${this.args};\n`
} else if (parseInt(this.args)) {
return ` int ${this.name} = ${this.args};\n`
} else {
return ` char ${this.name}[] = ${this.args};\n`
}
} else if (this.type == 'return') {
return ` return ${genargs};\n`
}
}
}
class c_function {
constructor(name, type) {
this.name = name
this.type = type
this.calls = []
}
generate() {
let gen = ''
gen += `${this.type} ${this.name}() {\n`
for (let i = 0; i < this.calls.length; i++) {
const call = this.calls[i]
gen += call.generate()
}
gen += `}\n`
return gen
}
addCall(call) {
this.calls.push(call)
}
}
const compile = function(generated) {
fs.writeFileSync('out.c', generated)
console.log('Saved transpiled code as out.c')
console.log('Compiling and running out.c')
console.log('\n')
let res = c.runSource(generated)
res.then(result => {
process.stdout.write(result.stdout)
})
.catch(err => {
console.log(err);
})
}
const transpile = function(includes, functions) {
console.log(`Transpiler: Transpiling...`)
let generated = ''
for (const i in includes) {
if (includes.hasOwnProperty(i)) {
const include = includes[i];
generated += `#include ${include}\n`
}
}
for (const f in functions) {
if (functions.hasOwnProperty(f)) {
const func = functions[f];
generated += func.generate()
}
}
return generated
}
const parse = function(path) {
const cssfile = fs.readFileSync(path, 'utf8')
let ast = css.parse(cssfile)
let includes = []
let functions = []
for (const r in ast.stylesheet.rules) {
if (ast.stylesheet.rules.hasOwnProperty(r)) {
const rule = ast.stylesheet.rules[r]
if (rule.type == 'import') {
includes.push(rule.import.replace(/["']/g, ''))
} else if (rule.type == 'rule') {
const selectorsplit = rule.selectors[0].split(":")
let type = selectorsplit[1]
let funcname = selectorsplit[0].replace('.', '')
const c_func = new c_function(funcname, type)
console.log(`Parser: Created new function ${funcname}`)
for (const d in rule.declarations) {
if (rule.declarations.hasOwnProperty(d)) {
const decl = rule.declarations[d]
if (/[a-zA-Z]+\([^\)]*\)(\.[^\)]*\))?/.test(decl.value) && decl.value.startsWith('var')) {
let value = decl.value.match(new RegExp('var('+"(.*)"+')'))[1].replace(/[()]/g,'')
let call = new c_call(decl.property, value, 'var')
c_func.addCall(call)
} else if (decl.property === 'return') {
let args = decl.value.split(/("[^"]*"|'[^']*'|[\S]+)+/).filter(function(e) { return /\S/.test(e); })
let call = new c_call(decl.property, args, 'return')
c_func.addCall(call)
} else {
let args = decl.value.split(/("[^"]*"|'[^']*'|[\S]+)+/).filter(function(e) { return /\S/.test(e); })
let call = new c_call(decl.property, args)
c_func.addCall(call)
}
}
}
console.log(`Parser: ${funcname} contains ${c_func.calls.length} call(s)`)
functions.push(c_func)
}
}
}
return transpile(includes, functions)
}
compile(parse("helloworld.css"))