sassc4 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +97 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +51 -0
- data/ext/depend +4 -0
- data/ext/extconf.rb +92 -0
- data/ext/libsass/VERSION +1 -0
- data/ext/libsass/contrib/plugin.cpp +60 -0
- data/ext/libsass/include/sass/base.h +97 -0
- data/ext/libsass/include/sass/context.h +174 -0
- data/ext/libsass/include/sass/functions.h +139 -0
- data/ext/libsass/include/sass/values.h +145 -0
- data/ext/libsass/include/sass/version.h +12 -0
- data/ext/libsass/include/sass.h +15 -0
- data/ext/libsass/include/sass2scss.h +120 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +953 -0
- data/ext/libsass/src/ast.hpp +1064 -0
- data/ext/libsass/src/ast2c.cpp +80 -0
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +140 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
- data/ext/libsass/src/ast_helpers.hpp +316 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +275 -0
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +1070 -0
- data/ext/libsass/src/ast_selectors.hpp +523 -0
- data/ext/libsass/src/ast_supports.cpp +114 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +1154 -0
- data/ext/libsass/src/ast_values.hpp +498 -0
- data/ext/libsass/src/b64/cencode.h +32 -0
- data/ext/libsass/src/b64/encode.h +79 -0
- data/ext/libsass/src/backtrace.cpp +50 -0
- data/ext/libsass/src/backtrace.hpp +29 -0
- data/ext/libsass/src/base64vlq.cpp +47 -0
- data/ext/libsass/src/base64vlq.hpp +30 -0
- data/ext/libsass/src/bind.cpp +312 -0
- data/ext/libsass/src/bind.hpp +15 -0
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/c99func.c +54 -0
- data/ext/libsass/src/cencode.c +106 -0
- data/ext/libsass/src/check_nesting.cpp +393 -0
- data/ext/libsass/src/check_nesting.hpp +70 -0
- data/ext/libsass/src/color_maps.cpp +652 -0
- data/ext/libsass/src/color_maps.hpp +323 -0
- data/ext/libsass/src/color_spaces.cpp +241 -0
- data/ext/libsass/src/color_spaces.hpp +227 -0
- data/ext/libsass/src/constants.cpp +199 -0
- data/ext/libsass/src/constants.hpp +200 -0
- data/ext/libsass/src/context.cpp +870 -0
- data/ext/libsass/src/context.hpp +140 -0
- data/ext/libsass/src/cssize.cpp +521 -0
- data/ext/libsass/src/cssize.hpp +71 -0
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debug.hpp +43 -0
- data/ext/libsass/src/debugger.hpp +964 -0
- data/ext/libsass/src/emitter.cpp +297 -0
- data/ext/libsass/src/emitter.hpp +101 -0
- data/ext/libsass/src/environment.cpp +260 -0
- data/ext/libsass/src/environment.hpp +124 -0
- data/ext/libsass/src/error_handling.cpp +239 -0
- data/ext/libsass/src/error_handling.hpp +248 -0
- data/ext/libsass/src/eval.cpp +1543 -0
- data/ext/libsass/src/eval.hpp +110 -0
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +875 -0
- data/ext/libsass/src/expand.hpp +98 -0
- data/ext/libsass/src/extender.cpp +1226 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +531 -0
- data/ext/libsass/src/file.hpp +124 -0
- data/ext/libsass/src/fn_colors.cpp +836 -0
- data/ext/libsass/src/fn_colors.hpp +99 -0
- data/ext/libsass/src/fn_lists.cpp +285 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +248 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +246 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +205 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +268 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +159 -0
- data/ext/libsass/src/fn_utils.hpp +62 -0
- data/ext/libsass/src/inspect.cpp +1126 -0
- data/ext/libsass/src/inspect.hpp +101 -0
- data/ext/libsass/src/json.cpp +1436 -0
- data/ext/libsass/src/json.hpp +117 -0
- data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
- data/ext/libsass/src/lexer.cpp +122 -0
- data/ext/libsass/src/lexer.hpp +304 -0
- data/ext/libsass/src/listize.cpp +70 -0
- data/ext/libsass/src/listize.hpp +37 -0
- data/ext/libsass/src/mapping.hpp +19 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
- data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +223 -0
- data/ext/libsass/src/operators.cpp +267 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +320 -0
- data/ext/libsass/src/output.hpp +47 -0
- data/ext/libsass/src/parser.cpp +3059 -0
- data/ext/libsass/src/parser.hpp +395 -0
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +188 -0
- data/ext/libsass/src/plugins.hpp +57 -0
- data/ext/libsass/src/position.cpp +163 -0
- data/ext/libsass/src/position.hpp +147 -0
- data/ext/libsass/src/prelexer.cpp +1780 -0
- data/ext/libsass/src/prelexer.hpp +484 -0
- data/ext/libsass/src/remove_placeholders.cpp +86 -0
- data/ext/libsass/src/remove_placeholders.hpp +37 -0
- data/ext/libsass/src/sass.cpp +156 -0
- data/ext/libsass/src/sass.hpp +147 -0
- data/ext/libsass/src/sass2scss.cpp +895 -0
- data/ext/libsass/src/sass_context.cpp +742 -0
- data/ext/libsass/src/sass_context.hpp +129 -0
- data/ext/libsass/src/sass_functions.cpp +210 -0
- data/ext/libsass/src/sass_functions.hpp +50 -0
- data/ext/libsass/src/sass_values.cpp +362 -0
- data/ext/libsass/src/sass_values.hpp +82 -0
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +202 -0
- data/ext/libsass/src/source_map.hpp +65 -0
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +114 -0
- data/ext/libsass/src/to_value.hpp +46 -0
- data/ext/libsass/src/units.cpp +507 -0
- data/ext/libsass/src/units.hpp +110 -0
- data/ext/libsass/src/utf8/checked.h +336 -0
- data/ext/libsass/src/utf8/core.h +332 -0
- data/ext/libsass/src/utf8/unchecked.h +235 -0
- data/ext/libsass/src/utf8.h +34 -0
- data/ext/libsass/src/utf8_string.cpp +104 -0
- data/ext/libsass/src/utf8_string.hpp +38 -0
- data/ext/libsass/src/util.cpp +723 -0
- data/ext/libsass/src/util.hpp +105 -0
- data/ext/libsass/src/util_string.cpp +125 -0
- data/ext/libsass/src/util_string.hpp +73 -0
- data/ext/libsass/src/values.cpp +140 -0
- data/ext/libsass/src/values.hpp +12 -0
- data/lib/sassc/dependency.rb +17 -0
- data/lib/sassc/engine.rb +141 -0
- data/lib/sassc/error.rb +37 -0
- data/lib/sassc/functions_handler.rb +73 -0
- data/lib/sassc/import_handler.rb +50 -0
- data/lib/sassc/importer.rb +31 -0
- data/lib/sassc/native/native_context_api.rb +147 -0
- data/lib/sassc/native/native_functions_api.rb +159 -0
- data/lib/sassc/native/sass2scss_api.rb +10 -0
- data/lib/sassc/native/sass_input_style.rb +13 -0
- data/lib/sassc/native/sass_output_style.rb +12 -0
- data/lib/sassc/native/sass_value.rb +97 -0
- data/lib/sassc/native/string_list.rb +10 -0
- data/lib/sassc/native.rb +64 -0
- data/lib/sassc/sass_2_scss.rb +9 -0
- data/lib/sassc/script/functions.rb +8 -0
- data/lib/sassc/script/value/bool.rb +32 -0
- data/lib/sassc/script/value/color.rb +95 -0
- data/lib/sassc/script/value/list.rb +136 -0
- data/lib/sassc/script/value/map.rb +69 -0
- data/lib/sassc/script/value/number.rb +389 -0
- data/lib/sassc/script/value/string.rb +96 -0
- data/lib/sassc/script/value.rb +137 -0
- data/lib/sassc/script/value_conversion/base.rb +13 -0
- data/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/lib/sassc/script/value_conversion/color.rb +18 -0
- data/lib/sassc/script/value_conversion/list.rb +25 -0
- data/lib/sassc/script/value_conversion/map.rb +21 -0
- data/lib/sassc/script/value_conversion/number.rb +13 -0
- data/lib/sassc/script/value_conversion/string.rb +17 -0
- data/lib/sassc/script/value_conversion.rb +69 -0
- data/lib/sassc/script.rb +17 -0
- data/lib/sassc/util/normalized_map.rb +117 -0
- data/lib/sassc/util.rb +231 -0
- data/lib/sassc/version.rb +5 -0
- data/lib/sassc.rb +57 -0
- data/sassc.gemspec +69 -0
- data/test/css_color_level4_test.rb +168 -0
- data/test/custom_importer_test.rb +127 -0
- data/test/engine_test.rb +314 -0
- data/test/error_test.rb +29 -0
- data/test/fixtures/paths.scss +10 -0
- data/test/functions_test.rb +340 -0
- data/test/native_test.rb +213 -0
- data/test/output_style_test.rb +107 -0
- data/test/sass_2_scss_test.rb +14 -0
- data/test/test_helper.rb +45 -0
- metadata +396 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
#ifndef SASS_PARSER_H
|
|
2
|
+
#define SASS_PARSER_H
|
|
3
|
+
|
|
4
|
+
// sass.hpp must go before all system headers to get the
|
|
5
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
6
|
+
#include "sass.hpp"
|
|
7
|
+
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
#include "ast.hpp"
|
|
12
|
+
#include "position.hpp"
|
|
13
|
+
#include "context.hpp"
|
|
14
|
+
#include "position.hpp"
|
|
15
|
+
#include "prelexer.hpp"
|
|
16
|
+
#include "source.hpp"
|
|
17
|
+
|
|
18
|
+
#ifndef MAX_NESTING
|
|
19
|
+
// Note that this limit is not an exact science
|
|
20
|
+
// it depends on various factors, which some are
|
|
21
|
+
// not under our control (compile time or even OS
|
|
22
|
+
// dependent settings on the available stack size)
|
|
23
|
+
// It should fix most common segfault cases though.
|
|
24
|
+
#define MAX_NESTING 512
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
struct Lookahead {
|
|
28
|
+
const char* found;
|
|
29
|
+
const char* error;
|
|
30
|
+
const char* position;
|
|
31
|
+
bool parsable;
|
|
32
|
+
bool has_interpolants;
|
|
33
|
+
bool is_custom_property;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
namespace Sass {
|
|
37
|
+
|
|
38
|
+
class Parser : public SourceSpan {
|
|
39
|
+
public:
|
|
40
|
+
|
|
41
|
+
enum Scope { Root, Mixin, Function, Media, Control, Properties, Rules, AtRoot };
|
|
42
|
+
|
|
43
|
+
Context& ctx;
|
|
44
|
+
sass::vector<Block_Obj> block_stack;
|
|
45
|
+
sass::vector<Scope> stack;
|
|
46
|
+
SourceDataObj source;
|
|
47
|
+
const char* begin;
|
|
48
|
+
const char* position;
|
|
49
|
+
const char* end;
|
|
50
|
+
Offset before_token;
|
|
51
|
+
Offset after_token;
|
|
52
|
+
SourceSpan pstate;
|
|
53
|
+
Backtraces traces;
|
|
54
|
+
size_t indentation;
|
|
55
|
+
size_t nestings;
|
|
56
|
+
bool allow_parent;
|
|
57
|
+
Token lexed;
|
|
58
|
+
|
|
59
|
+
Parser(SourceData* source, Context& ctx, Backtraces, bool allow_parent = true);
|
|
60
|
+
|
|
61
|
+
// special static parsers to convert strings into certain selectors
|
|
62
|
+
static SelectorListObj parse_selector(SourceData* source, Context& ctx, Backtraces, bool allow_parent = true);
|
|
63
|
+
|
|
64
|
+
#ifdef __clang__
|
|
65
|
+
|
|
66
|
+
// lex and peak uses the template parameter to branch on the action, which
|
|
67
|
+
// triggers clangs tautological comparison on the single-comparison
|
|
68
|
+
// branches. This is not a bug, just a merging of behaviour into
|
|
69
|
+
// one function
|
|
70
|
+
|
|
71
|
+
#pragma clang diagnostic push
|
|
72
|
+
#pragma clang diagnostic ignored "-Wtautological-compare"
|
|
73
|
+
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
// skip current token and next whitespace
|
|
78
|
+
// moves SourceSpan right before next token
|
|
79
|
+
void advanceToNextToken();
|
|
80
|
+
|
|
81
|
+
bool peek_newline(const char* start = 0);
|
|
82
|
+
|
|
83
|
+
// skip over spaces, tabs and line comments
|
|
84
|
+
template <Prelexer::prelexer mx>
|
|
85
|
+
const char* sneak(const char* start = 0)
|
|
86
|
+
{
|
|
87
|
+
using namespace Prelexer;
|
|
88
|
+
|
|
89
|
+
// maybe use optional start position from arguments?
|
|
90
|
+
const char* it_position = start ? start : position;
|
|
91
|
+
|
|
92
|
+
// skip white-space?
|
|
93
|
+
if (mx == spaces ||
|
|
94
|
+
mx == no_spaces ||
|
|
95
|
+
mx == css_comments ||
|
|
96
|
+
mx == css_whitespace ||
|
|
97
|
+
mx == optional_spaces ||
|
|
98
|
+
mx == optional_css_comments ||
|
|
99
|
+
mx == optional_css_whitespace
|
|
100
|
+
) {
|
|
101
|
+
return it_position;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// skip over spaces, tabs and sass line comments
|
|
105
|
+
const char* pos = optional_css_whitespace(it_position);
|
|
106
|
+
// always return a valid position
|
|
107
|
+
return pos ? pos : it_position;
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// match will not skip over space, tabs and line comment
|
|
112
|
+
// return the position where the lexer match will occur
|
|
113
|
+
template <Prelexer::prelexer mx>
|
|
114
|
+
const char* match(const char* start = 0)
|
|
115
|
+
{
|
|
116
|
+
// match the given prelexer
|
|
117
|
+
return mx(position);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// peek will only skip over space, tabs and line comment
|
|
121
|
+
// return the position where the lexer match will occur
|
|
122
|
+
template <Prelexer::prelexer mx>
|
|
123
|
+
const char* peek(const char* start = 0)
|
|
124
|
+
{
|
|
125
|
+
|
|
126
|
+
// sneak up to the actual token we want to lex
|
|
127
|
+
// this should skip over white-space if desired
|
|
128
|
+
const char* it_before_token = sneak < mx >(start);
|
|
129
|
+
|
|
130
|
+
// match the given prelexer
|
|
131
|
+
const char* match = mx(it_before_token);
|
|
132
|
+
|
|
133
|
+
// check if match is in valid range
|
|
134
|
+
return match <= end ? match : 0;
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// white-space handling is built into the lexer
|
|
139
|
+
// this way you do not need to parse it yourself
|
|
140
|
+
// some matchers don't accept certain white-space
|
|
141
|
+
// we do not support start arg, since we manipulate
|
|
142
|
+
// sourcemap offset and we modify the position pointer!
|
|
143
|
+
// lex will only skip over space, tabs and line comment
|
|
144
|
+
template <Prelexer::prelexer mx>
|
|
145
|
+
const char* lex(bool lazy = true, bool force = false)
|
|
146
|
+
{
|
|
147
|
+
|
|
148
|
+
if (*position == 0) return 0;
|
|
149
|
+
|
|
150
|
+
// position considered before lexed token
|
|
151
|
+
// we can skip whitespace or comments for
|
|
152
|
+
// lazy developers (but we need control)
|
|
153
|
+
const char* it_before_token = position;
|
|
154
|
+
|
|
155
|
+
// sneak up to the actual token we want to lex
|
|
156
|
+
// this should skip over white-space if desired
|
|
157
|
+
if (lazy) it_before_token = sneak < mx >(position);
|
|
158
|
+
|
|
159
|
+
// now call matcher to get position after token
|
|
160
|
+
const char* it_after_token = mx(it_before_token);
|
|
161
|
+
|
|
162
|
+
// check if match is in valid range
|
|
163
|
+
if (it_after_token > end) return 0;
|
|
164
|
+
|
|
165
|
+
// maybe we want to update the parser state anyway?
|
|
166
|
+
if (force == false) {
|
|
167
|
+
// assertion that we got a valid match
|
|
168
|
+
if (it_after_token == 0) return 0;
|
|
169
|
+
// assertion that we actually lexed something
|
|
170
|
+
if (it_after_token == it_before_token) return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// create new lexed token object (holds the parse results)
|
|
174
|
+
lexed = Token(position, it_before_token, it_after_token);
|
|
175
|
+
|
|
176
|
+
// advance position (add whitespace before current token)
|
|
177
|
+
before_token = after_token.add(position, it_before_token);
|
|
178
|
+
|
|
179
|
+
// update after_token position for current token
|
|
180
|
+
after_token.add(it_before_token, it_after_token);
|
|
181
|
+
|
|
182
|
+
// ToDo: could probably do this incremental on original object (API wants offset?)
|
|
183
|
+
pstate = SourceSpan(source, before_token, after_token - before_token);
|
|
184
|
+
|
|
185
|
+
// advance internal char iterator
|
|
186
|
+
return position = it_after_token;
|
|
187
|
+
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// lex_css skips over space, tabs, line and block comment
|
|
191
|
+
// all block comments will be consumed and thrown away
|
|
192
|
+
// source-map position will point to token after the comment
|
|
193
|
+
template <Prelexer::prelexer mx>
|
|
194
|
+
const char* lex_css()
|
|
195
|
+
{
|
|
196
|
+
// copy old token
|
|
197
|
+
Token prev = lexed;
|
|
198
|
+
// store previous pointer
|
|
199
|
+
const char* oldpos = position;
|
|
200
|
+
Offset bt = before_token;
|
|
201
|
+
Offset at = after_token;
|
|
202
|
+
SourceSpan op = pstate;
|
|
203
|
+
// throw away comments
|
|
204
|
+
// update srcmap position
|
|
205
|
+
lex < Prelexer::css_comments >();
|
|
206
|
+
// now lex a new token
|
|
207
|
+
const char* pos = lex< mx >();
|
|
208
|
+
// maybe restore prev state
|
|
209
|
+
if (pos == 0) {
|
|
210
|
+
pstate = op;
|
|
211
|
+
lexed = prev;
|
|
212
|
+
position = oldpos;
|
|
213
|
+
after_token = at;
|
|
214
|
+
before_token = bt;
|
|
215
|
+
}
|
|
216
|
+
// return match
|
|
217
|
+
return pos;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// all block comments will be skipped and thrown away
|
|
221
|
+
template <Prelexer::prelexer mx>
|
|
222
|
+
const char* peek_css(const char* start = 0)
|
|
223
|
+
{
|
|
224
|
+
// now peek a token (skip comments first)
|
|
225
|
+
return peek< mx >(peek < Prelexer::css_comments >(start));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#ifdef __clang__
|
|
229
|
+
|
|
230
|
+
#pragma clang diagnostic pop
|
|
231
|
+
|
|
232
|
+
#endif
|
|
233
|
+
|
|
234
|
+
void error(sass::string msg);
|
|
235
|
+
// generate message with given and expected sample
|
|
236
|
+
// text before and in the middle are configurable
|
|
237
|
+
void css_error(const sass::string& msg,
|
|
238
|
+
const sass::string& prefix = " after ",
|
|
239
|
+
const sass::string& middle = ", was: ",
|
|
240
|
+
const bool trim = true);
|
|
241
|
+
void read_bom();
|
|
242
|
+
|
|
243
|
+
Block_Obj parse();
|
|
244
|
+
Import_Obj parse_import();
|
|
245
|
+
Definition_Obj parse_definition(Definition::Type which_type);
|
|
246
|
+
Parameters_Obj parse_parameters();
|
|
247
|
+
Parameter_Obj parse_parameter();
|
|
248
|
+
Mixin_Call_Obj parse_include_directive();
|
|
249
|
+
Arguments_Obj parse_arguments();
|
|
250
|
+
Arguments_Obj parse_color_arguments();
|
|
251
|
+
Argument_Obj parse_argument();
|
|
252
|
+
Assignment_Obj parse_assignment();
|
|
253
|
+
StyleRuleObj parse_ruleset(Lookahead lookahead);
|
|
254
|
+
SelectorListObj parseSelectorList(bool chroot);
|
|
255
|
+
ComplexSelectorObj parseComplexSelector(bool chroot);
|
|
256
|
+
Selector_Schema_Obj parse_selector_schema(const char* end_of_selector, bool chroot);
|
|
257
|
+
CompoundSelectorObj parseCompoundSelector();
|
|
258
|
+
SimpleSelectorObj parse_simple_selector();
|
|
259
|
+
PseudoSelectorObj parse_negated_selector2();
|
|
260
|
+
Expression* parse_binominal();
|
|
261
|
+
SimpleSelectorObj parse_pseudo_selector();
|
|
262
|
+
AttributeSelectorObj parse_attribute_selector();
|
|
263
|
+
Block_Obj parse_block(bool is_root = false);
|
|
264
|
+
Block_Obj parse_css_block(bool is_root = false);
|
|
265
|
+
bool parse_block_nodes(bool is_root = false);
|
|
266
|
+
bool parse_block_node(bool is_root = false);
|
|
267
|
+
|
|
268
|
+
Declaration_Obj parse_declaration();
|
|
269
|
+
ExpressionObj parse_map();
|
|
270
|
+
ExpressionObj parse_bracket_list();
|
|
271
|
+
ExpressionObj parse_list(bool delayed = false);
|
|
272
|
+
ExpressionObj parse_comma_list(bool delayed = false);
|
|
273
|
+
ExpressionObj parse_space_list();
|
|
274
|
+
ExpressionObj parse_disjunction();
|
|
275
|
+
ExpressionObj parse_conjunction();
|
|
276
|
+
ExpressionObj parse_relation();
|
|
277
|
+
ExpressionObj parse_expression();
|
|
278
|
+
ExpressionObj parse_operators();
|
|
279
|
+
ExpressionObj parse_factor();
|
|
280
|
+
ExpressionObj parse_value();
|
|
281
|
+
Function_Call_Obj parse_calc_function();
|
|
282
|
+
Function_Call_Obj parse_function_call();
|
|
283
|
+
Function_Call_Obj parse_function_call_schema();
|
|
284
|
+
String_Obj parse_url_function_string();
|
|
285
|
+
String_Obj parse_url_function_argument();
|
|
286
|
+
String_Obj parse_interpolated_chunk(Token, bool constant = false, bool css = true);
|
|
287
|
+
String_Obj parse_string();
|
|
288
|
+
ValueObj parse_static_value();
|
|
289
|
+
String_Schema_Obj parse_css_variable_value();
|
|
290
|
+
String_Obj parse_ie_property();
|
|
291
|
+
String_Obj parse_ie_keyword_arg();
|
|
292
|
+
String_Schema_Obj parse_value_schema(const char* stop);
|
|
293
|
+
String_Obj parse_identifier_schema();
|
|
294
|
+
If_Obj parse_if_directive(bool else_if = false);
|
|
295
|
+
ForRuleObj parse_for_directive();
|
|
296
|
+
EachRuleObj parse_each_directive();
|
|
297
|
+
WhileRuleObj parse_while_directive();
|
|
298
|
+
MediaRule_Obj parseMediaRule();
|
|
299
|
+
sass::vector<CssMediaQuery_Obj> parseCssMediaQueries();
|
|
300
|
+
sass::string parseIdentifier();
|
|
301
|
+
CssMediaQuery_Obj parseCssMediaQuery();
|
|
302
|
+
Return_Obj parse_return_directive();
|
|
303
|
+
Content_Obj parse_content_directive();
|
|
304
|
+
void parse_charset_directive();
|
|
305
|
+
List_Obj parse_media_queries();
|
|
306
|
+
Media_Query_Obj parse_media_query();
|
|
307
|
+
Media_Query_ExpressionObj parse_media_expression();
|
|
308
|
+
SupportsRuleObj parse_supports_directive();
|
|
309
|
+
SupportsConditionObj parse_supports_condition(bool top_level);
|
|
310
|
+
SupportsConditionObj parse_supports_negation();
|
|
311
|
+
SupportsConditionObj parse_supports_operator(bool top_level);
|
|
312
|
+
SupportsConditionObj parse_supports_interpolation();
|
|
313
|
+
SupportsConditionObj parse_supports_declaration();
|
|
314
|
+
SupportsConditionObj parse_supports_condition_in_parens(bool parens_required);
|
|
315
|
+
AtRootRuleObj parse_at_root_block();
|
|
316
|
+
At_Root_Query_Obj parse_at_root_query();
|
|
317
|
+
String_Schema_Obj parse_almost_any_value();
|
|
318
|
+
AtRuleObj parse_directive();
|
|
319
|
+
WarningRuleObj parse_warning();
|
|
320
|
+
ErrorRuleObj parse_error();
|
|
321
|
+
DebugRuleObj parse_debug();
|
|
322
|
+
|
|
323
|
+
Value* color_or_string(const sass::string& lexed) const;
|
|
324
|
+
|
|
325
|
+
// be more like ruby sass
|
|
326
|
+
ExpressionObj lex_almost_any_value_token();
|
|
327
|
+
ExpressionObj lex_almost_any_value_chars();
|
|
328
|
+
ExpressionObj lex_interp_string();
|
|
329
|
+
ExpressionObj lex_interp_uri();
|
|
330
|
+
ExpressionObj lex_interpolation();
|
|
331
|
+
|
|
332
|
+
// these will throw errors
|
|
333
|
+
Token lex_variable();
|
|
334
|
+
Token lex_identifier();
|
|
335
|
+
|
|
336
|
+
void parse_block_comments(bool store = true);
|
|
337
|
+
|
|
338
|
+
Lookahead lookahead_for_value(const char* start = 0);
|
|
339
|
+
Lookahead lookahead_for_selector(const char* start = 0);
|
|
340
|
+
Lookahead lookahead_for_include(const char* start = 0);
|
|
341
|
+
|
|
342
|
+
ExpressionObj fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, Operand op);
|
|
343
|
+
ExpressionObj fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, sass::vector<Operand>& ops, size_t i = 0);
|
|
344
|
+
|
|
345
|
+
void throw_syntax_error(sass::string message, size_t ln = 0);
|
|
346
|
+
void throw_read_error(sass::string message, size_t ln = 0);
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
template <Prelexer::prelexer open, Prelexer::prelexer close>
|
|
350
|
+
ExpressionObj lex_interp()
|
|
351
|
+
{
|
|
352
|
+
if (lex < open >(false)) {
|
|
353
|
+
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
|
354
|
+
// std::cerr << "LEX [[" << sass::string(lexed) << "]]\n";
|
|
355
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
|
356
|
+
if (position[0] == '#' && position[1] == '{') {
|
|
357
|
+
ExpressionObj itpl = lex_interpolation();
|
|
358
|
+
if (!itpl.isNull()) schema->append(itpl);
|
|
359
|
+
while (lex < close >(false)) {
|
|
360
|
+
// std::cerr << "LEX [[" << sass::string(lexed) << "]]\n";
|
|
361
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
|
362
|
+
if (position[0] == '#' && position[1] == '{') {
|
|
363
|
+
ExpressionObj itpl = lex_interpolation();
|
|
364
|
+
if (!itpl.isNull()) schema->append(itpl);
|
|
365
|
+
} else {
|
|
366
|
+
return schema;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
} else {
|
|
370
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return {};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
public:
|
|
377
|
+
static Number* lexed_number(const SourceSpan& pstate, const sass::string& parsed);
|
|
378
|
+
static Number* lexed_dimension(const SourceSpan& pstate, const sass::string& parsed);
|
|
379
|
+
static Number* lexed_percentage(const SourceSpan& pstate, const sass::string& parsed);
|
|
380
|
+
static Value* lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed);
|
|
381
|
+
private:
|
|
382
|
+
Number* lexed_number(const sass::string& parsed) { return lexed_number(pstate, parsed); };
|
|
383
|
+
Number* lexed_dimension(const sass::string& parsed) { return lexed_dimension(pstate, parsed); };
|
|
384
|
+
Number* lexed_percentage(const sass::string& parsed) { return lexed_percentage(pstate, parsed); };
|
|
385
|
+
Value* lexed_hex_color(const sass::string& parsed) { return lexed_hex_color(pstate, parsed); };
|
|
386
|
+
|
|
387
|
+
static const char* re_attr_sensitive_close(const char* src);
|
|
388
|
+
static const char* re_attr_insensitive_close(const char* src);
|
|
389
|
+
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
#endif
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
|
|
5
|
+
#include "parser.hpp"
|
|
6
|
+
|
|
7
|
+
namespace Sass {
|
|
8
|
+
|
|
9
|
+
using namespace Prelexer;
|
|
10
|
+
using namespace Constants;
|
|
11
|
+
|
|
12
|
+
ComplexSelectorObj Parser::parseComplexSelector(bool chroot)
|
|
13
|
+
{
|
|
14
|
+
|
|
15
|
+
NESTING_GUARD(nestings);
|
|
16
|
+
|
|
17
|
+
lex < block_comment >();
|
|
18
|
+
advanceToNextToken();
|
|
19
|
+
|
|
20
|
+
ComplexSelectorObj sel = SASS_MEMORY_NEW(ComplexSelector, pstate);
|
|
21
|
+
|
|
22
|
+
if (peek < end_of_file >()) return sel;
|
|
23
|
+
|
|
24
|
+
while (true) {
|
|
25
|
+
|
|
26
|
+
lex < block_comment >();
|
|
27
|
+
advanceToNextToken();
|
|
28
|
+
|
|
29
|
+
// check for child (+) combinator
|
|
30
|
+
if (lex < exactly < selector_combinator_child > >()) {
|
|
31
|
+
sel->append(SASS_MEMORY_NEW(SelectorCombinator, pstate, SelectorCombinator::CHILD, peek_newline()));
|
|
32
|
+
}
|
|
33
|
+
// check for general sibling (~) combinator
|
|
34
|
+
else if (lex < exactly < selector_combinator_general > >()) {
|
|
35
|
+
sel->append(SASS_MEMORY_NEW(SelectorCombinator, pstate, SelectorCombinator::GENERAL, peek_newline()));
|
|
36
|
+
}
|
|
37
|
+
// check for adjecant sibling (+) combinator
|
|
38
|
+
else if (lex < exactly < selector_combinator_adjacent > >()) {
|
|
39
|
+
sel->append(SASS_MEMORY_NEW(SelectorCombinator, pstate, SelectorCombinator::ADJACENT, peek_newline()));
|
|
40
|
+
}
|
|
41
|
+
// check if we can parse a compound selector
|
|
42
|
+
else if (CompoundSelectorObj compound = parseCompoundSelector()) {
|
|
43
|
+
sel->append(compound);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (sel->empty()) return {};
|
|
51
|
+
|
|
52
|
+
// check if we parsed any parent references
|
|
53
|
+
sel->chroots(sel->has_real_parent_ref() || chroot);
|
|
54
|
+
|
|
55
|
+
sel->update_pstate(pstate);
|
|
56
|
+
|
|
57
|
+
return sel;
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
SelectorListObj Parser::parseSelectorList(bool chroot)
|
|
62
|
+
{
|
|
63
|
+
|
|
64
|
+
bool reloop;
|
|
65
|
+
bool had_linefeed = false;
|
|
66
|
+
NESTING_GUARD(nestings);
|
|
67
|
+
SelectorListObj list = SASS_MEMORY_NEW(SelectorList, pstate);
|
|
68
|
+
|
|
69
|
+
if (peek_css< alternatives < end_of_file, exactly <'{'>, exactly <','> > >()) {
|
|
70
|
+
css_error("Invalid CSS", " after ", ": expected selector, was ");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
do {
|
|
74
|
+
reloop = false;
|
|
75
|
+
|
|
76
|
+
had_linefeed = had_linefeed || peek_newline();
|
|
77
|
+
|
|
78
|
+
if (peek_css< alternatives < class_char < selector_list_delims > > >())
|
|
79
|
+
break; // in case there are superfluous commas at the end
|
|
80
|
+
|
|
81
|
+
// now parse the complex selector
|
|
82
|
+
ComplexSelectorObj complex = parseComplexSelector(chroot);
|
|
83
|
+
if (complex.isNull()) return list.detach();
|
|
84
|
+
complex->hasPreLineFeed(had_linefeed);
|
|
85
|
+
|
|
86
|
+
had_linefeed = false;
|
|
87
|
+
|
|
88
|
+
while (peek_css< exactly<','> >())
|
|
89
|
+
{
|
|
90
|
+
lex< css_comments >(false);
|
|
91
|
+
// consume everything up and including the comma separator
|
|
92
|
+
reloop = lex< exactly<','> >() != 0;
|
|
93
|
+
// remember line break (also between some commas)
|
|
94
|
+
had_linefeed = had_linefeed || peek_newline();
|
|
95
|
+
// remember line break (also between some commas)
|
|
96
|
+
}
|
|
97
|
+
list->append(complex);
|
|
98
|
+
|
|
99
|
+
} while (reloop);
|
|
100
|
+
|
|
101
|
+
while (lex_css< kwd_optional >()) {
|
|
102
|
+
list->is_optional(true);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// update for end position
|
|
106
|
+
list->update_pstate(pstate);
|
|
107
|
+
|
|
108
|
+
return list.detach();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// parse one compound selector, which is basically
|
|
112
|
+
// a list of simple selectors (directly adjacent)
|
|
113
|
+
// lex them exactly (without skipping white-space)
|
|
114
|
+
CompoundSelectorObj Parser::parseCompoundSelector()
|
|
115
|
+
{
|
|
116
|
+
// init an empty compound selector wrapper
|
|
117
|
+
CompoundSelectorObj seq = SASS_MEMORY_NEW(CompoundSelector, pstate);
|
|
118
|
+
|
|
119
|
+
// skip initial white-space
|
|
120
|
+
lex < block_comment >();
|
|
121
|
+
advanceToNextToken();
|
|
122
|
+
|
|
123
|
+
if (lex< exactly<'&'> >(false))
|
|
124
|
+
{
|
|
125
|
+
// ToDo: check the conditions and try to simplify flag passing
|
|
126
|
+
if (!allow_parent) error("Parent selectors aren't allowed here.");
|
|
127
|
+
// Create and append a new parent selector object
|
|
128
|
+
seq->hasRealParent(true);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// parse list
|
|
132
|
+
while (true)
|
|
133
|
+
{
|
|
134
|
+
// remove all block comments
|
|
135
|
+
// leaves trailing white-space
|
|
136
|
+
lex < block_comment >();
|
|
137
|
+
// parse parent selector
|
|
138
|
+
if (lex< exactly<'&'> >(false))
|
|
139
|
+
{
|
|
140
|
+
// parent selector only allowed at start
|
|
141
|
+
// upcoming Sass may allow also trailing
|
|
142
|
+
SourceSpan state(pstate);
|
|
143
|
+
sass::string found("&");
|
|
144
|
+
if (lex < identifier >()) {
|
|
145
|
+
found += sass::string(lexed);
|
|
146
|
+
}
|
|
147
|
+
sass::string sel(seq->hasRealParent() ? "&" : "");
|
|
148
|
+
if (!seq->empty()) { sel = seq->last()->to_string({ NESTED, 5 }); }
|
|
149
|
+
// ToDo: parser should throw parser exceptions
|
|
150
|
+
error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n"
|
|
151
|
+
"\"" + found + "\" may only be used at the beginning of a compound selector.");
|
|
152
|
+
}
|
|
153
|
+
// parse functional
|
|
154
|
+
else if (match < re_functional >())
|
|
155
|
+
{
|
|
156
|
+
seq->append(parse_simple_selector());
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// parse type selector
|
|
160
|
+
else if (lex< re_type_selector >(false))
|
|
161
|
+
{
|
|
162
|
+
seq->append(SASS_MEMORY_NEW(TypeSelector, pstate, lexed));
|
|
163
|
+
}
|
|
164
|
+
// peek for abort conditions
|
|
165
|
+
else if (peek< spaces >()) break;
|
|
166
|
+
else if (peek< end_of_file >()) { break; }
|
|
167
|
+
else if (peek_css < class_char < selector_combinator_ops > >()) break;
|
|
168
|
+
else if (peek_css < class_char < complex_selector_delims > >()) break;
|
|
169
|
+
// otherwise parse another simple selector
|
|
170
|
+
else {
|
|
171
|
+
SimpleSelectorObj sel = parse_simple_selector();
|
|
172
|
+
if (!sel) return {};
|
|
173
|
+
seq->append(sel);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// EO while true
|
|
177
|
+
|
|
178
|
+
if (seq && !peek_css<alternatives<end_of_file,exactly<'{'>>>()) {
|
|
179
|
+
seq->hasPostLineBreak(peek_newline());
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// We may have set hasRealParent
|
|
183
|
+
if (seq && seq->empty() && !seq->hasRealParent()) return {};
|
|
184
|
+
|
|
185
|
+
return seq;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
}
|