Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
node-sass
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
楚学文
node-sass
Commits
3238f08b
Commit
3238f08b
authored
Mar 22, 2012
by
Aaron Leung
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Evaluator is mostly working. Ironing out some intermittent bugs.
parent
53ac5d5f
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
211 additions
and
122 deletions
+211
-122
Makefile
Makefile
+1
-1
document.hpp
document.hpp
+4
-0
document_parser.cpp
document_parser.cpp
+39
-16
evaluator.cpp
evaluator.cpp
+115
-56
lists.scss
lists.scss
+9
-35
node.cpp
node.cpp
+15
-4
node.hpp
node.hpp
+28
-10
No files found.
Makefile
View file @
3238f08b
build
:
sassc.cpp document.cpp node.cpp token.cpp prelexer.cpp
g++
-o
bin/sassc sassc.cpp document.cpp document_parser.cpp document_emitter.cpp node.cpp token.cpp prelexer.cpp
g++
-o
bin/sassc sassc.cpp document.cpp document_parser.cpp
evaluator.cpp
document_emitter.cpp node.cpp token.cpp prelexer.cpp
test
:
build
ruby spec.rb spec/basic/
...
...
document.hpp
View file @
3238f08b
#include <map>
#ifndef SASS_NODE_INCLUDED
#include "node.hpp"
#endif
#include "context.hpp"
namespace
Sass
{
...
...
document_parser.cpp
View file @
3238f08b
#include "document.hpp"
#include "evaluator.hpp"
#include <iostream>
namespace
Sass
{
...
...
@@ -50,8 +51,8 @@ namespace Sass {
val
.
from_variable
=
true
;
val
.
eval_me
=
true
;
//
context.environment[key] = eval(val);
context
.
environment
[
key
]
=
val
;
context
.
environment
[
key
]
=
eval
(
val
);
//
context.environment[key] = val;
}
Node
Document
::
parse_ruleset
()
...
...
@@ -311,17 +312,19 @@ namespace Sass {
peek
<
exactly
<
'}'
>
>
(
position
)
||
peek
<
exactly
<
')'
>
>
(
position
)
||
peek
<
exactly
<
','
>
>
(
position
))
{
return
expr1
;
}
{
return
expr1
.
eval_me
?
eval
(
expr1
)
:
expr1
;
}
Node
space_list
(
line_number
,
Node
::
space_list
,
2
);
space_list
<<
expr1
;
// space_list << expr1;
space_list
<<
(
expr1
.
eval_me
?
eval
(
expr1
)
:
expr1
);
while
(
!
(
peek
<
exactly
<
';'
>
>
(
position
)
||
peek
<
exactly
<
'}'
>
>
(
position
)
||
peek
<
exactly
<
')'
>
>
(
position
)
||
peek
<
exactly
<
','
>
>
(
position
)))
// { space_list << eval(parse_expression());
{
space_list
<<
parse_expression
();
}
{
Node
expr
(
parse_expression
());
space_list
<<
(
expr
.
eval_me
?
eval
(
expr
)
:
expr
);
}
// { space_list << parse_expression(); }
return
space_list
;
}
...
...
@@ -336,6 +339,7 @@ namespace Sass {
Node
expression
(
line_number
,
Node
::
expression
,
3
);
term1
.
eval_me
=
true
;
cerr
<<
"Parsed an initial term: "
<<
term1
.
to_string
(
""
)
<<
endl
;
expression
<<
term1
;
while
(
lex
<
exactly
<
'+'
>
>
()
||
lex
<
exactly
<
'-'
>
>
())
{
...
...
@@ -350,6 +354,8 @@ namespace Sass {
expression
<<
term
;
}
expression
.
eval_me
=
true
;
cerr
<<
"parsed an expression: "
<<
expression
.
to_string
(
""
)
<<
endl
;
return
expression
;
}
...
...
@@ -378,6 +384,11 @@ namespace Sass {
term
<<
fact
;
}
// if (term.eval_me) {
// for (int i = 0; i < term.children->size(); i += 2) {
// term.children->at(i).eval_me = true;
// }
// }
return
term
;
}
...
...
@@ -386,6 +397,9 @@ namespace Sass {
if
(
lex
<
exactly
<
'('
>
>
())
{
Node
value
(
parse_list
());
value
.
eval_me
=
true
;
if
(
value
.
type
==
Node
::
comma_list
||
value
.
type
==
Node
::
space_list
)
{
value
.
children
->
front
().
eval_me
=
true
;
}
lex
<
exactly
<
')'
>
>
();
return
value
;
}
...
...
@@ -396,17 +410,26 @@ namespace Sass {
Node
Document
::
parse_value
()
{
lex
<
identifier
>
()
||
lex
<
dimension
>
()
||
lex
<
percentage
>
()
||
lex
<
number
>
()
||
lex
<
hex
>
()
||
lex
<
string_constant
>
()
||
lex
<
variable
>
();
if
(
lex
<
identifier
>
())
{
return
Node
(
line_number
,
Node
::
identifier
,
lexed
);
}
if
(
lexed
.
begin
[
0
]
==
'$'
)
{
return
context
.
environment
[
lexed
];
}
else
{
return
Node
(
line_number
,
Node
::
value
,
lexed
);
}
if
(
lex
<
percentage
>
())
{
return
Node
(
line_number
,
Node
::
textual_percentage
,
lexed
);
}
if
(
lex
<
dimension
>
())
{
return
Node
(
line_number
,
Node
::
textual_dimension
,
lexed
);
}
if
(
lex
<
number
>
())
{
return
Node
(
line_number
,
Node
::
textual_number
,
lexed
);
}
if
(
lex
<
hex
>
())
{
return
Node
(
line_number
,
Node
::
textual_hex
,
lexed
);
}
if
(
lex
<
string_constant
>
())
{
return
Node
(
line_number
,
Node
::
string_constant
,
lexed
);
}
if
(
lex
<
variable
>
())
{
return
context
.
environment
[
lexed
];
}
}
// const char* Document::look_for_rule(const char* start)
...
...
document_
evaluator.cpp
→
evaluator.cpp
View file @
3238f08b
#include "
document
.hpp"
#include "
evaluator
.hpp"
#include <iostream>
#include <cstdlib>
Node
eval
(
const
Node
&
expr
)
{
switch
(
expr
.
type
)
namespace
Sass
{
using
std
::
cerr
;
using
std
::
endl
;
Node
eval
(
const
Node
&
expr
)
{
case
expression
:
{
Node
acc
(
expr
.
line_number
,
Node
::
expression
,
eval
(
expr
.
children
->
at
(
0
)));
Node
rhs
(
eval
(
expr
.
children
->
at
(
2
)));
accumulate
(
expr
.
children
->
at
(
1
).
type
,
acc
,
rhs
);
for
(
int
i
=
3
;
i
<
expr
.
children
->
size
();
i
+=
2
)
{
Node
rhs
(
eval
(
expr
.
children
->
at
(
i
+
1
)));
accumulate
(
expr
.
children
->
at
(
i
),
acc
,
rhs
);
}
return
acc
;
}
break
;
case
term
:
{
cerr
<<
"evaluating type "
<<
expr
.
type
<<
": "
<<
expr
.
to_string
(
""
)
<<
endl
;
switch
(
expr
.
type
)
{
case
Node
:
:
comma_list
:
case
Node
:
:
space_list
:
{
if
(
expr
.
eval_me
)
{
*
(
expr
.
children
->
begin
())
=
eval
(
expr
.
children
->
front
());
}
return
expr
;
}
break
;
case
Node
:
:
expression
:
{
Node
acc
(
expr
.
line_number
,
Node
::
expression
,
eval
(
expr
.
children
->
at
(
0
)));
Node
rhs
(
eval
(
expr
.
children
->
at
(
2
)));
accumulate
(
expr
.
children
->
at
(
1
).
type
,
acc
,
rhs
);
cerr
<<
"blah"
<<
endl
;
for
(
int
i
=
3
;
i
<
expr
.
children
->
size
();
i
+=
2
)
{
Node
rhs
(
eval
(
expr
.
children
->
at
(
i
+
1
)));
accumulate
(
expr
.
children
->
at
(
i
).
type
,
acc
,
rhs
);
}
return
acc
.
children
->
size
()
==
1
?
acc
.
children
->
front
()
:
acc
;
}
break
;
case
Node
:
:
term
:
{
if
(
expr
.
eval_me
)
{
Node
acc
(
expr
.
line_number
,
Node
::
expression
,
eval
(
expr
.
children
->
at
(
0
)));
Node
rhs
(
eval
(
expr
.
children
->
at
(
2
)));
accumulate
(
expr
.
children
->
at
(
1
).
type
,
acc
,
rhs
);
for
(
int
i
=
3
;
i
<
expr
.
children
->
size
();
i
+=
2
)
{
Node
rhs
(
eval
(
expr
.
children
->
at
(
i
+
1
)));
accumulate
(
expr
.
children
->
at
(
i
).
type
,
acc
,
rhs
);
}
return
acc
.
children
->
size
()
==
1
?
acc
.
children
->
front
()
:
acc
;
}
else
{
return
expr
;
}
}
break
;
case
Node
:
:
textual_percentage
:
case
Node
:
:
textual_dimension
:
{
double
numval
=
std
::
atof
(
expr
.
token
.
begin
);
Token
unit
(
Prelexer
::
number
(
expr
.
token
.
begin
),
expr
.
token
.
end
);
return
Node
(
expr
.
line_number
,
numval
,
unit
);
}
break
;
case
Node
:
:
textual_number
:
{
double
numval
=
std
::
atof
(
expr
.
token
.
begin
);
return
Node
(
expr
.
line_number
,
numval
);
}
break
;
case
Node
:
:
textual_hex
:
{
long
numval
=
std
::
strtol
(
expr
.
token
.
begin
+
1
,
NULL
,
16
);
Node
result
(
expr
.
line_number
,
numval
);
result
.
is_hex
=
true
;
return
result
;
}
break
;
}
break
;
default:
{
return
expr
;
}
}
}
}
Node
accumulate
(
const
Node
::
Type
op
,
Node
&
acc
,
const
Node
&
rhs
)
{
Node
lhs
(
acc
.
children
->
back
());
if
(
lhs
.
type
==
Node
::
number
&&
rhs
.
type
==
Node
::
number
)
{
Node
result
(
acc
.
line_number
,
Node
::
number
,
operate
(
op
,
lhs
,
rhs
));
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
number
&&
rhs
.
type
==
Node
::
numeric_dimension
)
{
Node
result
(
acc
.
line_number
,
Node
::
numeric_dimension
,
operate
(
op
,
lhs
,
rhs
),
rhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
numeric_dimension
&&
rhs
.
type
==
Node
::
number
)
{
Node
result
(
acc
.
line_number
,
Node
::
numeric_dimension
,
operate
(
op
,
lhs
,
rhs
),
lhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
numeric_dimension
&&
rhs
.
type
==
Node
::
numeric_dimension
)
{
// CHECK FOR MISMATCHED UNITS HERE
Node
result
(
acc
.
line_number
,
Node
::
numeric_dimension
,
operate
(
op
,
lhs
,
rhs
),
lhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
{
acc
.
children
->
push_back
(
rhs
);
Node
accumulate
(
const
Node
::
Type
op
,
Node
&
acc
,
Node
&
rhs
)
{
Node
lhs
(
acc
.
children
->
back
());
double
lnum
=
lhs
.
numeric_value
;
double
rnum
=
rhs
.
numeric_value
;
// cerr << "accumulate's args: " << lhs.to_string("") << "\t" << rhs.to_string("") << endl;
// cerr << "accumulate's arg types: " << lhs.type << "\t" << rhs.type << endl;
// cerr << endl;
if
(
lhs
.
type
==
Node
::
number
&&
rhs
.
type
==
Node
::
number
)
{
Node
result
(
acc
.
line_number
,
operate
(
op
,
lnum
,
rnum
));
// cerr << "accumulate just made a node: " << result.to_string("") << "\t" << result.type << endl;
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
number
&&
rhs
.
type
==
Node
::
numeric_dimension
)
{
Node
result
(
acc
.
line_number
,
operate
(
op
,
lnum
,
rnum
),
rhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
numeric_dimension
&&
rhs
.
type
==
Node
::
number
)
{
Node
result
(
acc
.
line_number
,
operate
(
op
,
lnum
,
rnum
),
lhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
if
(
lhs
.
type
==
Node
::
numeric_dimension
&&
rhs
.
type
==
Node
::
numeric_dimension
)
{
// TO DO: CHECK FOR MISMATCHED UNITS HERE
Node
result
(
acc
.
line_number
,
operate
(
op
,
lnum
,
rnum
),
lhs
.
token
);
acc
.
children
->
pop_back
();
acc
.
children
->
push_back
(
result
);
}
else
{
// cerr << "accumulate: didn't do anything" << endl;
acc
.
children
->
push_back
(
rhs
);
}
return
acc
;
}
return
acc
;
}
double
operate
(
const
Node
::
Type
op
,
double
lhs
,
double
rhs
)
{
switch
(
op
)
double
operate
(
const
Node
::
Type
op
,
double
lhs
,
double
rhs
)
{
case
Node
:
:
add
:
return
lhs
+
rhs
;
break
;
case
Node
:
:
sub
:
return
lhs
-
rhs
;
break
;
case
Node
:
:
mul
:
return
lhs
*
rhs
;
break
;
case
Node
:
:
div
:
return
lhs
/
rhs
;
break
;
default:
return
0
;
break
;
switch
(
op
)
{
case
Node
:
:
add
:
return
lhs
+
rhs
;
break
;
case
Node
:
:
sub
:
return
lhs
-
rhs
;
break
;
case
Node
:
:
mul
:
return
lhs
*
rhs
;
break
;
case
Node
:
:
div
:
return
lhs
/
rhs
;
break
;
default:
return
0
;
break
;
}
}
}
\ No newline at end of file
lists.scss
View file @
3238f08b
$x
:
1
2
3
;
$y
:
3
;
$z
:
2
;
$w
:
10
/
2
;
div
{
a
:
b
c
d
;
b
:
a
$x
b
;
c
:
1
(
2
3
)
4
;
d
:
1
,
2
3
,
4
,
(
5
6
,
7
8
)
9
,
10
;
e
:
1
+
(
2
3
)
+
3
+
4
;
f
:
1
+
2
+
(
3
4
)
+
5
+
6
;
g
:
2
/
3
,
(
3
/
4
);
h
:
1
+
2
/
3
;
i
:
2
/
3
+
1
;
j
:
2
/
3
+
1
2
;
k
:
1
2
+
3
/
4
;
l
:
(
1
2
)
+
3
/
4
;
m
:
2
3
/
4
;
n
:
$y
/
2
;
o
:
(
$y
)
/
2
;
p
:
12
/
3
/
$z
;
q
:
12
/
3
/
2
;
r
:
12
/
(
3
/
2
);
s
:
(
12
/
3
)
/
2
;
t
:
5
/
(
1
+
(
3
-
2
)
+
4
/
(
1
*
$z
));
t
:
5
/
(
2
+
3
);
t
:
5
/
(
2
);
t
:
5
/
2
;
u
:
6
/
2
+
4
/
$z
;
v
:
3-2
;
w
:
(
5
/
#{
$w
}
);
x
:
"
#{
$w
}
"
;
// t: 12 (/ 3 / 2);
y
:
5
+
(
4
/
2
4
/
2
4
/
2
);
z
:
2px
+
2px
,
2px
+
2
//,
2px
+
2em
;
/* a: 1 + 2;
b: 3 + 2/3;
c: 1/2 + 1/2;*/
/* shouldn't eval the following "300" */
/* d: 300; */
/* e: 1 + (5/10 2 3);*/
f
:
1
+
((
2
+
(
3
4
)
5
)
6
);
/* f: 1 + ((1+(14/7 8) 9) 6);*/
}
\ No newline at end of file
node.cpp
View file @
3238f08b
...
...
@@ -14,7 +14,7 @@ namespace Sass {
size_t
Node
::
fresh
=
0
;
size_t
Node
::
copied
=
0
;
string
Node
::
to_string
(
const
string
&
prefix
)
string
Node
::
to_string
(
const
string
&
prefix
)
const
{
switch
(
type
)
{
...
...
@@ -109,21 +109,32 @@ namespace Sass {
case
expression
:
case
term
:
{
string
result
(
children
->
at
(
0
).
to_string
(
prefix
));
for
(
int
i
=
2
;
i
<
children
->
size
();
i
+=
2
)
{
// result += " ";
result
+=
children
->
at
(
i
).
to_string
(
prefix
);
// for (int i = 2; i < children->size(); i += 2) {
// // result += " ";
// result += children->at(i).to_string(prefix);
// }
for
(
int
i
=
1
;
i
<
children
->
size
();
++
i
)
{
if
(
!
(
children
->
at
(
i
).
type
==
add
||
children
->
at
(
i
).
type
==
sub
||
children
->
at
(
i
).
type
==
mul
))
{
result
+=
children
->
at
(
i
).
to_string
(
prefix
);
}
}
return
result
;
}
break
;
case
numeric_dimension
:
{
stringstream
ss
;
// ss.setf(std::ios::fixed, std::ios::floatfield);
// ss.precision(3);
ss
<<
numeric_value
<<
string
(
token
);
return
ss
.
str
();
}
break
;
case
number
:
{
stringstream
ss
;
// ss.setf(std::ios::fixed, std::ios::floatfield);
// ss.precision(3);
ss
<<
numeric_value
;
return
ss
.
str
();
}
break
;
...
...
node.hpp
View file @
3238f08b
#define SASS_NODE_INCLUDED
#include <vector>
#include <sstream>
#include "token.hpp"
...
...
@@ -46,10 +48,17 @@ namespace Sass {
factor
,
values
,
value
,
dimension
,
identifier
,
uri
,
textual_percentage
,
textual_dimension
,
textual_number
,
textual_hex
,
string_constant
,
numeric_percentage
,
numeric_dimension
,
number
,
comment
};
...
...
@@ -67,6 +76,7 @@ namespace Sass {
bool
has_backref
;
bool
from_variable
;
bool
eval_me
;
bool
is_hex
;
Node
()
:
type
(
nil
),
children
(
0
)
{
++
fresh
;
}
...
...
@@ -81,7 +91,8 @@ namespace Sass {
has_propsets
(
n
.
has_propsets
),
has_backref
(
n
.
has_backref
),
from_variable
(
n
.
from_variable
),
eval_me
(
n
.
eval_me
)
eval_me
(
n
.
eval_me
),
is_hex
(
n
.
is_hex
)
{
/*n.release();*/
++
copied
;
}
// No joint custody.
Node
(
size_t
line_number
,
Type
type
,
size_t
length
=
0
)
...
...
@@ -95,7 +106,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
children
->
reserve
(
length
);
++
fresh
;
}
Node
(
size_t
line_number
,
Type
type
,
const
Node
&
n
)
...
...
@@ -109,7 +121,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
++
fresh
;
}
Node
(
size_t
line_number
,
Type
type
,
const
Node
&
n
,
const
Node
&
m
)
...
...
@@ -123,7 +136,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
children
->
reserve
(
2
);
children
->
push_back
(
n
);
...
...
@@ -142,7 +156,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
++
fresh
;
}
Node
(
size_t
line_number
,
double
d
)
...
...
@@ -156,7 +171,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
++
fresh
;
}
Node
(
size_t
line_number
,
double
d
,
Token
&
token
)
...
...
@@ -170,7 +186,8 @@ namespace Sass {
has_propsets
(
false
),
has_backref
(
false
),
from_variable
(
false
),
eval_me
(
false
)
eval_me
(
false
),
is_hex
(
false
)
{
++
fresh
;
}
//~Node() { delete children; }
...
...
@@ -189,6 +206,7 @@ namespace Sass {
has_backref
=
n
.
has_backref
;
from_variable
=
n
.
from_variable
;
eval_me
=
n
.
eval_me
;
is_hex
=
n
.
is_hex
;
++
copied
;
return
*
this
;
}
...
...
@@ -207,7 +225,7 @@ namespace Sass {
return
*
this
;
}
string
to_string
(
const
string
&
prefix
);
string
to_string
(
const
string
&
prefix
)
const
;
void
release
()
const
{
children
=
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment