-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminify.pl
122 lines (106 loc) · 3.71 KB
/
minify.pl
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
# Copyright 2012-2019 Richard Copley
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Minifies Polymorph's GLSL shader sources.
# Not meant for general use.
# Doesn't handle multiline statements.
# Identifiers aren't safe from collisions.
use strict;
my ($infile, $outfile) = @ARGV;
open my $in, "<", $infile or die "Can't open input file \"$infile\": $!";
open my $out, ">", $outfile or die "Can't open output file \"$outfile\": $!";
binmode $out;
my %abbrevs = (
project => "I", # (vec3 x) -> vec4
pdivide => "I", # (vec4 s) -> vec2
raster => "J", # (vec3 x) -> vec2
perp => "I", # (vec2 a, vec2 b) -> vec2
dist => "I", # (vec2 x, vec2 a, vec2 b) -> float
vertex => "I", # (vec3 x, vec4 p, float e [5]) -> void
triangle => "I", # (vec3 A, vec3 B, vec3 C, vec4 x, vec4 y, vec4 z, float e [5], float f [5], float g [5]) -> void
nondegenerate => "J", # (vec2 a, vec2 b, vec2 c) -> bool
snub_segment => "I", # (vec3 Q, vec3 U, vec3 V, vec4 y, vec4 z) -> void
aspect => "I", # (vec3 Q, vec3 V, vec3 W, vec3 X, vec4 h, vec4 i, vec4 j, vec2 v, vec2 w, vec2 x) -> void
);
%abbrevs = map { qr/\b$_\b/ => $abbrevs {$_} } keys %abbrevs;
my $limit = 900;
sub minify
{
my ($buffer, $bol) = @_;
# Abbreviate the specified words.
$buffer =~ s/$_/$abbrevs{$_}/g for keys %abbrevs;
# Keep space only if it separates two words.
$buffer =~ s{\B }{}g; # strip space not after a word
$buffer =~ s{ \B}{}g; # strip space not before a word
$buffer =~ m{ \B} and die "That didn't do what I expected";
# Delete unnecessary zeros from floating-point literals.
$buffer =~ s{(\d\.\d*)0+\b}{$1}g;
$buffer =~ s{\b0\.(\d)}{.$1}g;
while ($limit and $buffer ne "") {
# Zero or more declarations.
# Coalesce consecutive declarations that share a common type into one declaration.
my $oldtype;
my $oldvars;
my $v = qr/\w+(?:\[\w+\])?(?:=[^;]+)?/;
while ($limit and $buffer =~ s/^((?:\w+ )+)($v(?:,$v)*);//) {
my ($type, $vars) = ($1, $2);
-- $limit if $limit;
if ((defined $oldtype) && ($type eq $oldtype)) {
$oldvars .= ",$vars";
}
else {
if (defined $oldtype) {
print $out "$oldtype$oldvars;";
$bol = 0;
}
$oldtype = $type;
$oldvars = $vars;
}
}
if (defined $oldtype) {
print $out "$oldtype$oldvars;";
undef $oldtype;
$bol = 0;
}
# A statement that isn't a declaration.
if ($buffer =~ s/^([^;{}]*(?:[;{}]+|$))//) {
my $statement = $1;
print $out $statement;
$bol = 0;
}
-- $limit if $limit;
}
return $bol;
}
my $buffer = "";
my $bol = 1;
while (defined (my $line = <$in>)) {
$line =~ s{^\s+}{}; # trim leading space
$line =~ s{//.*$}{}; # strip comment
$line =~ s{\s+$}{}; # trim trailing space
$line =~ s{\s+}{ }; # squeeze repeated space
next if $line eq ""; # skip blank line
# Print directive on a separate line.
if ($line =~ m/^#/) {
$bol = minify $buffer, $bol;
$buffer = "";
print $out "\n" unless $bol;
print $out "$line\n";
$bol = 1;
}
else {
$buffer = "$buffer $line";
}
}
$bol = minify $buffer, $bol;
#print $out "\n" unless $bol;