diff --git a/Bindings/Libsass/Context.hs b/Bindings/Libsass/Context.hs
--- a/Bindings/Libsass/Context.hs
+++ b/Bindings/Libsass/Context.hs
@@ -307,6 +307,15 @@
     -> CSize
     -> IO CString
 
+foreign import ccall unsafe "sass/context.h" sass_option_get_plugin_path_size
+    :: Ptr SassOptions
+    -> IO CSize
+
+foreign import ccall unsafe "sass/context.h" sass_option_get_plugin_path
+    :: Ptr SassOptions
+    -> CSize
+    -> IO CString
+
 foreign import ccall unsafe "sass/context.h" sass_context_get_included_files_size
     :: Ptr SassContext
     -> IO CSize
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 # Change Log
 All notable changes to this project will be documented in this file.
 
+## [0.1.10.0] - 2020-03-26
+### 
+- Update to LibSass 3.6.4
+- Simplify build on Windows
+
 ## [0.1.9.0] - 2020-03-26
 ### Changed
 - Update to LibSass 3.6.3
@@ -91,6 +96,7 @@
 - Bindings to Libsass C API
 - Basic tests
 
+[0.1.10.0]: https://github.com/jakubfijalkowski/hlibsass/compare/v0.1.9.0...v0.1.10.0
 [0.1.9.0]: https://github.com/jakubfijalkowski/hlibsass/compare/v0.1.8.1...v0.1.9.0
 [0.1.8.1]: https://github.com/jakubfijalkowski/hlibsass/compare/v0.1.8.0...v0.1.8.1
 [0.1.8.0]: https://github.com/jakubfijalkowski/hlibsass/compare/v0.1.7.0...v0.1.8.0
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 import           Control.Monad                      (unless, when)
+import           Control.Applicative                ((<|>))
 import           Data.Char                          (toLower)
 import           Data.Maybe                         (fromJust, fromMaybe)
 import           Distribution.PackageDescription
@@ -49,28 +50,28 @@
 execMake :: Verbosity.Verbosity -> String -> String -> IO ()
 execMake verbosity build_target target = do
     gmakePath <- findProgramOnSearchPath Verbosity.silent defaultProgramSearchPath "gmake"
-    let makeExec = case gmakePath of
+    makePath <- findProgramOnSearchPath Verbosity.silent defaultProgramSearchPath "make"
+    mingwMakePath <- findProgramOnSearchPath Verbosity.silent defaultProgramSearchPath "mingw32-make"
+    let makeExec = case (gmakePath <|> makePath <|> mingwMakePath) of
 #if MIN_VERSION_Cabal(1, 24, 0)
                      Just (p, _) -> p
 #else
                      Just p      -> p
 #endif
                      Nothing     -> "make"
-        baseArgs = if null build_target
-                      then [makeExec, "--directory=libsass"]
-                      else ["BUILD=" ++ build_target, makeExec, "--directory=libsass"]
-        makeArgs = if null target
+        baseArgs = ["--directory=libsass", if null target then "all" else target]
+        makeArgs = if null build_target
                       then baseArgs
-                      else baseArgs ++ [target]
-    rawSystemExit verbosity "env" makeArgs
+                      else baseArgs ++ ["BUILD=" ++ build_target]
+    rawSystemExit verbosity makeExec makeArgs
 
 updateLibsassVersion :: ConfigFlags -> IO ()
 updateLibsassVersion flags = do
     let verbosity = fromFlag $ configVerbosity flags
     exists <- doesFileExist "libsass/VERSION"
     unless exists $ do
-        ver <- rawSystemStdout verbosity "env" [ "git", "-C", "libsass", "describe",
-            "--abbrev=4", "--dirty", "--always", "--tags" ]
+        ver <- rawSystemStdout verbosity "git" ["-C", "libsass", "describe",
+            "--abbrev=4", "--dirty", "--always", "--tags"]
         writeFile "libsass/VERSION" ver
 
 
diff --git a/hlibsass.cabal b/hlibsass.cabal
--- a/hlibsass.cabal
+++ b/hlibsass.cabal
@@ -1,5 +1,5 @@
 name:                hlibsass
-version:             0.1.9.0
+version:             0.1.10.0
 license:             MIT
 license-file:        LICENSE
 author:              Jakub Fijałkowski <kuba@codinginfinity.me>
diff --git a/libsass/Makefile b/libsass/Makefile
--- a/libsass/Makefile
+++ b/libsass/Makefile
@@ -143,6 +143,8 @@
 SASS_SASSC_PATH ?= sassc
 SASS_SPEC_PATH ?= sass-spec
 SASS_SPEC_SPEC_DIR ?= spec
+LIBSASS_SPEC_PATH ?= libsass-spec
+LIBSASS_SPEC_SPEC_DIR ?= spec
 SASSC_BIN = $(SASS_SASSC_PATH)/bin/sassc
 RUBY_BIN = ruby
 
@@ -289,25 +291,67 @@
 
 test: test_build
 
-test_build: $(SASSC_BIN)
+$(SASS_SPEC_PATH):
+	git clone https://github.com/sass/sass-spec $(SASS_SPEC_PATH)
+
+$(LIBSASS_SPEC_PATH):
+	git clone https://github.com/mgreter/libsass-spec $(LIBSASS_SPEC_PATH)
+
+test_build: $(SASSC_BIN) $(SASS_SPEC_PATH) $(LIBSASS_SPEC_PATH)
 	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
 	--cmd-args "-I $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)" \
 	$(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)" \
+	$(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/compressed -t compressed" \
+	$(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/compressed
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/nested -t nested" \
+	$(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/nested
 
-test_full: $(SASSC_BIN)
+test_full: $(SASSC_BIN) $(SASS_SPEC_PATH) $(LIBSASS_SPEC_PATH)
 	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
 	--cmd-args "-I $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)" \
 	--run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)" \
+	--run-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/compressed -t compressed" \
+	--run-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/compressed
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/nested -t nested" \
+	--run-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/nested
 
-test_probe: $(SASSC_BIN)
+test_probe: $(SASSC_BIN) $(SASS_SPEC_PATH) $(LIBSASS_SPEC_PATH)
 	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
 	--cmd-args "-I $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)" \
 	--probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)" \
+	--probe-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/compressed -t compressed" \
+	--probe-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/compressed
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/nested -t nested" \
+	--probe-todo $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/nested
 
-test_interactive: $(SASSC_BIN)
+test_interactive: $(SASSC_BIN) $(SASS_SPEC_PATH) $(LIBSASS_SPEC_PATH)
 	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
 	--cmd-args "-I $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)" \
 	--interactive $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)" \
+	--interactive $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/$(LIBSASS_SPEC_SPEC_DIR)
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/compressed -t compressed" \
+	--interactive $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/compressed
+	$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass \
+	--cmd-args "-I $(LIBSASS_SPEC_PATH)/styles/nested -t nested" \
+	--interactive $(LOG_FLAGS) $(LIBSASS_SPEC_PATH)/styles/nested
 
 clean-objects: | lib
 	-$(RM) lib/*.a lib/*.so lib/*.dll lib/*.dylib lib/*.la
diff --git a/libsass/Makefile.conf b/libsass/Makefile.conf
--- a/libsass/Makefile.conf
+++ b/libsass/Makefile.conf
@@ -35,6 +35,7 @@
 	units.cpp \
 	values.cpp \
 	plugins.cpp \
+	source.cpp \
 	position.cpp \
 	lexer.cpp \
 	parser.cpp \
@@ -65,7 +66,8 @@
 	to_value.cpp \
 	source_map.cpp \
 	error_handling.cpp \
-	memory/SharedPtr.cpp \
+	memory/allocator.cpp \
+	memory/shared_ptr.cpp \
 	utf8_string.cpp \
 	base64vlq.cpp
 
diff --git a/libsass/include/sass/context.h b/libsass/include/sass/context.h
--- a/libsass/include/sass/context.h
+++ b/libsass/include/sass/context.h
@@ -125,6 +125,9 @@
 // Getters for options include path array
 ADDAPI size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options);
 ADDAPI const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i);
+// Plugin paths to load dynamic libraries work the same
+ADDAPI size_t ADDCALL sass_option_get_plugin_path_size(struct Sass_Options* options);
+ADDAPI const char* ADDCALL sass_option_get_plugin_path(struct Sass_Options* options, size_t i);
 
 // Calculate the size of the stored null terminated array
 ADDAPI size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx);
diff --git a/libsass/src/MurmurHash2.hpp b/libsass/src/MurmurHash2.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/MurmurHash2.hpp
@@ -0,0 +1,91 @@
+//-----------------------------------------------------------------------------
+// MurmurHash2 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+//-----------------------------------------------------------------------------
+// LibSass only needs MurmurHash2, so we made this header only
+//-----------------------------------------------------------------------------
+
+#ifndef _MURMURHASH2_H_
+#define _MURMURHASH2_H_
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// Other compilers
+
+#else	// defined(_MSC_VER)
+
+#include <stdint.h>
+
+#endif // !defined(_MSC_VER)
+
+//-----------------------------------------------------------------------------
+
+inline uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
+{
+  // 'm' and 'r' are mixing constants generated offline.
+  // They're not really 'magic', they just happen to work well.
+
+  const uint32_t m = 0x5bd1e995;
+  const int r = 24;
+
+  // Initialize the hash to a 'random' value
+
+  uint32_t h = seed ^ len;
+
+  // Mix 4 bytes at a time into the hash
+
+  const unsigned char * data = (const unsigned char *)key;
+
+  while(len >= 4)
+  {
+    uint32_t k = *(uint32_t*)data;
+
+    k *= m;
+    k ^= k >> r;
+    k *= m;
+
+    h *= m;
+    h ^= k;
+
+    data += 4;
+    len -= 4;
+  }
+
+  // Handle the last few bytes of the input array
+
+  switch(len)
+  {
+  case 3:
+    h ^= data[2] << 16;
+    /* fall through */
+  case 2:
+    h ^= data[1] << 8;
+    /* fall through */
+  case 1:
+    h ^= data[0];
+    h *= m;
+  };
+
+  // Do a few final mixes of the hash to ensure the last few
+  // bytes are well-incorporated.
+
+  h ^= h >> 13;
+  h *= m;
+  h ^= h >> 15;
+
+  return h;
+} 
+
+//-----------------------------------------------------------------------------
+
+#endif // _MURMURHASH2_H_
+
diff --git a/libsass/src/ast.cpp b/libsass/src/ast.cpp
--- a/libsass/src/ast.cpp
+++ b/libsass/src/ast.cpp
@@ -6,7 +6,7 @@
 
 namespace Sass {
 
-  static Null sass_null(ParserState("null"));
+  static Null sass_null(SourceSpan("null"));
 
   const char* sass_op_to_name(enum Sass_OP op) {
     switch (op) {
@@ -53,12 +53,12 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  void AST_Node::update_pstate(const ParserState& pstate)
+  void AST_Node::update_pstate(const SourceSpan& pstate)
   {
-    pstate_.offset += pstate - pstate_ + pstate.offset;
+    pstate_.offset += pstate.position - pstate_.position + pstate.offset;
   }
 
-  std::string AST_Node::to_string(Sass_Inspect_Options opt) const
+  sass::string AST_Node::to_string(Sass_Inspect_Options opt) const
   {
     Sass_Output_Options out(opt);
     Emitter emitter(out);
@@ -69,7 +69,7 @@
     return i.get_buffer();
   }
 
-  std::string AST_Node::to_css(Sass_Inspect_Options opt) const
+  sass::string AST_Node::to_css(Sass_Inspect_Options opt) const
   {
     opt.output_style = TO_CSS;
     Sass_Output_Options out(opt);
@@ -81,7 +81,7 @@
     return i.get_buffer();
   }
 
-  std::string AST_Node::to_string() const
+  sass::string AST_Node::to_string() const
   {
     return to_string({ NESTED, 5 });
   }
@@ -89,7 +89,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Statement::Statement(ParserState pstate, Type st, size_t t)
+  Statement::Statement(SourceSpan pstate, Type st, size_t t)
   : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false)
   { }
   Statement::Statement(const Statement* ptr)
@@ -117,7 +117,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Block::Block(ParserState pstate, size_t s, bool r)
+  Block::Block(SourceSpan pstate, size_t s, bool r)
   : Statement(pstate),
     Vectorized<Statement_Obj>(s),
     is_root_(r)
@@ -147,14 +147,14 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Has_Block::Has_Block(ParserState pstate, Block_Obj b)
+  ParentStatement::ParentStatement(SourceSpan pstate, Block_Obj b)
   : Statement(pstate), block_(b)
   { }
-  Has_Block::Has_Block(const Has_Block* ptr)
+  ParentStatement::ParentStatement(const ParentStatement* ptr)
   : Statement(ptr), block_(ptr->block_)
   { }
 
-  bool Has_Block::has_content()
+  bool ParentStatement::has_content()
   {
     return (block_ && block_->has_content()) || Statement::has_content();
   }
@@ -162,17 +162,17 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Ruleset::Ruleset(ParserState pstate, SelectorListObj s, Block_Obj b)
-  : Has_Block(pstate, b), selector_(s), schema_(), is_root_(false)
+  StyleRule::StyleRule(SourceSpan pstate, SelectorListObj s, Block_Obj b)
+  : ParentStatement(pstate, b), selector_(s), schema_(), is_root_(false)
   { statement_type(RULESET); }
-  Ruleset::Ruleset(const Ruleset* ptr)
-  : Has_Block(ptr),
+  StyleRule::StyleRule(const StyleRule* ptr)
+  : ParentStatement(ptr),
     selector_(ptr->selector_),
     schema_(ptr->schema_),
     is_root_(ptr->is_root_)
   { statement_type(RULESET); }
 
-  bool Ruleset::is_invisible() const {
+  bool StyleRule::is_invisible() const {
     if (const SelectorList * sl = Cast<SelectorList>(selector())) {
       for (size_t i = 0, L = sl->length(); i < L; i += 1)
         if (!(*sl)[i]->isInvisible()) return false;
@@ -183,7 +183,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Bubble::Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g, size_t t)
+  Bubble::Bubble(SourceSpan pstate, Statement_Obj n, Statement_Obj g, size_t t)
   : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == nullptr)
   { }
   Bubble::Bubble(const Bubble* ptr)
@@ -200,11 +200,11 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Trace::Trace(ParserState pstate, std::string n, Block_Obj b, char type)
-  : Has_Block(pstate, b), type_(type), name_(n)
+  Trace::Trace(SourceSpan pstate, sass::string n, Block_Obj b, char type)
+  : ParentStatement(pstate, b), type_(type), name_(n)
   { }
   Trace::Trace(const Trace* ptr)
-  : Has_Block(ptr),
+  : ParentStatement(ptr),
     type_(ptr->type_),
     name_(ptr->name_)
   { }
@@ -212,25 +212,25 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Directive::Directive(ParserState pstate, std::string kwd, SelectorListObj sel, Block_Obj b, Expression_Obj val)
-  : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
+  AtRule::AtRule(SourceSpan pstate, sass::string kwd, SelectorListObj sel, Block_Obj b, ExpressionObj val)
+  : ParentStatement(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
   { statement_type(DIRECTIVE); }
-  Directive::Directive(const Directive* ptr)
-  : Has_Block(ptr),
+  AtRule::AtRule(const AtRule* ptr)
+  : ParentStatement(ptr),
     keyword_(ptr->keyword_),
     selector_(ptr->selector_),
     value_(ptr->value_) // set value manually if needed
   { statement_type(DIRECTIVE); }
 
-  bool Directive::bubbles() { return is_keyframes() || is_media(); }
+  bool AtRule::bubbles() { return is_keyframes() || is_media(); }
 
-  bool Directive::is_media() {
+  bool AtRule::is_media() {
     return keyword_.compare("@-webkit-media") == 0 ||
             keyword_.compare("@-moz-media") == 0 ||
             keyword_.compare("@-o-media") == 0 ||
             keyword_.compare("@media") == 0;
   }
-  bool Directive::is_keyframes() {
+  bool AtRule::is_keyframes() {
     return keyword_.compare("@-webkit-keyframes") == 0 ||
             keyword_.compare("@-moz-keyframes") == 0 ||
             keyword_.compare("@-o-keyframes") == 0 ||
@@ -240,21 +240,21 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Keyframe_Rule::Keyframe_Rule(ParserState pstate, Block_Obj b)
-  : Has_Block(pstate, b), name_()
+  Keyframe_Rule::Keyframe_Rule(SourceSpan pstate, Block_Obj b)
+  : ParentStatement(pstate, b), name_()
   { statement_type(KEYFRAMERULE); }
   Keyframe_Rule::Keyframe_Rule(const Keyframe_Rule* ptr)
-  : Has_Block(ptr), name_(ptr->name_)
+  : ParentStatement(ptr), name_(ptr->name_)
   { statement_type(KEYFRAMERULE); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Declaration::Declaration(ParserState pstate, String_Obj prop, Expression_Obj val, bool i, bool c, Block_Obj b)
-  : Has_Block(pstate, b), property_(prop), value_(val), is_important_(i), is_custom_property_(c), is_indented_(false)
+  Declaration::Declaration(SourceSpan pstate, String_Obj prop, ExpressionObj val, bool i, bool c, Block_Obj b)
+  : ParentStatement(pstate, b), property_(prop), value_(val), is_important_(i), is_custom_property_(c), is_indented_(false)
   { statement_type(DECLARATION); }
   Declaration::Declaration(const Declaration* ptr)
-  : Has_Block(ptr),
+  : ParentStatement(ptr),
     property_(ptr->property_),
     value_(ptr->value_),
     is_important_(ptr->is_important_),
@@ -271,7 +271,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Assignment::Assignment(ParserState pstate, std::string var, Expression_Obj val, bool is_default, bool is_global)
+  Assignment::Assignment(SourceSpan pstate, sass::string var, ExpressionObj val, bool is_default, bool is_global)
   : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global)
   { statement_type(ASSIGNMENT); }
   Assignment::Assignment(const Assignment* ptr)
@@ -285,10 +285,10 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Import::Import(ParserState pstate)
+  Import::Import(SourceSpan pstate)
   : Statement(pstate),
-    urls_(std::vector<Expression_Obj>()),
-    incs_(std::vector<Include>()),
+    urls_(sass::vector<ExpressionObj>()),
+    incs_(sass::vector<Include>()),
     import_queries_()
   { statement_type(IMPORT); }
   Import::Import(const Import* ptr)
@@ -298,56 +298,56 @@
     import_queries_(ptr->import_queries_)
   { statement_type(IMPORT); }
 
-  std::vector<Include>& Import::incs() { return incs_; }
-  std::vector<Expression_Obj>& Import::urls() { return urls_; }
+  sass::vector<Include>& Import::incs() { return incs_; }
+  sass::vector<ExpressionObj>& Import::urls() { return urls_; }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Import_Stub::Import_Stub(ParserState pstate, Include res)
+  Import_Stub::Import_Stub(SourceSpan pstate, Include res)
   : Statement(pstate), resource_(res)
   { statement_type(IMPORT_STUB); }
   Import_Stub::Import_Stub(const Import_Stub* ptr)
   : Statement(ptr), resource_(ptr->resource_)
   { statement_type(IMPORT_STUB); }
   Include Import_Stub::resource() { return resource_; };
-  std::string Import_Stub::imp_path() { return resource_.imp_path; };
-  std::string Import_Stub::abs_path() { return resource_.abs_path; };
+  sass::string Import_Stub::imp_path() { return resource_.imp_path; };
+  sass::string Import_Stub::abs_path() { return resource_.abs_path; };
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Warning::Warning(ParserState pstate, Expression_Obj msg)
+  WarningRule::WarningRule(SourceSpan pstate, ExpressionObj msg)
   : Statement(pstate), message_(msg)
   { statement_type(WARNING); }
-  Warning::Warning(const Warning* ptr)
+  WarningRule::WarningRule(const WarningRule* ptr)
   : Statement(ptr), message_(ptr->message_)
   { statement_type(WARNING); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Error::Error(ParserState pstate, Expression_Obj msg)
+  ErrorRule::ErrorRule(SourceSpan pstate, ExpressionObj msg)
   : Statement(pstate), message_(msg)
   { statement_type(ERROR); }
-  Error::Error(const Error* ptr)
+  ErrorRule::ErrorRule(const ErrorRule* ptr)
   : Statement(ptr), message_(ptr->message_)
   { statement_type(ERROR); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Debug::Debug(ParserState pstate, Expression_Obj val)
+  DebugRule::DebugRule(SourceSpan pstate, ExpressionObj val)
   : Statement(pstate), value_(val)
   { statement_type(DEBUGSTMT); }
-  Debug::Debug(const Debug* ptr)
+  DebugRule::DebugRule(const DebugRule* ptr)
   : Statement(ptr), value_(ptr->value_)
   { statement_type(DEBUGSTMT); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Comment::Comment(ParserState pstate, String_Obj txt, bool is_important)
+  Comment::Comment(SourceSpan pstate, String_Obj txt, bool is_important)
   : Statement(pstate), text_(txt), is_important_(is_important)
   { statement_type(COMMENT); }
   Comment::Comment(const Comment* ptr)
@@ -364,30 +364,30 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  If::If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt)
-  : Has_Block(pstate, con), predicate_(pred), alternative_(alt)
+  If::If(SourceSpan pstate, ExpressionObj pred, Block_Obj con, Block_Obj alt)
+  : ParentStatement(pstate, con), predicate_(pred), alternative_(alt)
   { statement_type(IF); }
   If::If(const If* ptr)
-  : Has_Block(ptr),
+  : ParentStatement(ptr),
     predicate_(ptr->predicate_),
     alternative_(ptr->alternative_)
   { statement_type(IF); }
 
   bool If::has_content()
   {
-    return Has_Block::has_content() || (alternative_ && alternative_->has_content());
+    return ParentStatement::has_content() || (alternative_ && alternative_->has_content());
   }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  For::For(ParserState pstate,
-      std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc)
-  : Has_Block(pstate, b),
+  ForRule::ForRule(SourceSpan pstate,
+      sass::string var, ExpressionObj lo, ExpressionObj hi, Block_Obj b, bool inc)
+  : ParentStatement(pstate, b),
     variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc)
   { statement_type(FOR); }
-  For::For(const For* ptr)
-  : Has_Block(ptr),
+  ForRule::ForRule(const ForRule* ptr)
+  : ParentStatement(ptr),
     variable_(ptr->variable_),
     lower_bound_(ptr->lower_bound_),
     upper_bound_(ptr->upper_bound_),
@@ -397,27 +397,27 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Each::Each(ParserState pstate, std::vector<std::string> vars, Expression_Obj lst, Block_Obj b)
-  : Has_Block(pstate, b), variables_(vars), list_(lst)
+  EachRule::EachRule(SourceSpan pstate, sass::vector<sass::string> vars, ExpressionObj lst, Block_Obj b)
+  : ParentStatement(pstate, b), variables_(vars), list_(lst)
   { statement_type(EACH); }
-  Each::Each(const Each* ptr)
-  : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_)
+  EachRule::EachRule(const EachRule* ptr)
+  : ParentStatement(ptr), variables_(ptr->variables_), list_(ptr->list_)
   { statement_type(EACH); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  While::While(ParserState pstate, Expression_Obj pred, Block_Obj b)
-  : Has_Block(pstate, b), predicate_(pred)
+  WhileRule::WhileRule(SourceSpan pstate, ExpressionObj pred, Block_Obj b)
+  : ParentStatement(pstate, b), predicate_(pred)
   { statement_type(WHILE); }
-  While::While(const While* ptr)
-  : Has_Block(ptr), predicate_(ptr->predicate_)
+  WhileRule::WhileRule(const WhileRule* ptr)
+  : ParentStatement(ptr), predicate_(ptr->predicate_)
   { statement_type(WHILE); }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Return::Return(ParserState pstate, Expression_Obj val)
+  Return::Return(SourceSpan pstate, ExpressionObj val)
   : Statement(pstate), value_(val)
   { statement_type(RETURN); }
   Return::Return(const Return* ptr)
@@ -427,10 +427,10 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-    ExtendRule::ExtendRule(ParserState pstate, SelectorListObj s)
+    ExtendRule::ExtendRule(SourceSpan pstate, SelectorListObj s)
   : Statement(pstate), isOptional_(false), selector_(s), schema_()
   { statement_type(EXTEND); }
-  ExtendRule::ExtendRule(ParserState pstate, Selector_Schema_Obj s)
+  ExtendRule::ExtendRule(SourceSpan pstate, Selector_Schema_Obj s)
     : Statement(pstate), isOptional_(false), selector_(), schema_(s)
   {
     statement_type(EXTEND);
@@ -446,7 +446,7 @@
   /////////////////////////////////////////////////////////////////////////
 
   Definition::Definition(const Definition* ptr)
-  : Has_Block(ptr),
+  : ParentStatement(ptr),
     name_(ptr->name_),
     parameters_(ptr->parameters_),
     environment_(ptr->environment_),
@@ -458,12 +458,12 @@
     signature_(ptr->signature_)
   { }
 
-  Definition::Definition(ParserState pstate,
-              std::string n,
+  Definition::Definition(SourceSpan pstate,
+              sass::string n,
               Parameters_Obj params,
               Block_Obj b,
               Type t)
-  : Has_Block(pstate, b),
+  : ParentStatement(pstate, b),
     name_(n),
     parameters_(params),
     environment_(0),
@@ -475,13 +475,13 @@
     signature_(0)
   { }
 
-  Definition::Definition(ParserState pstate,
+  Definition::Definition(SourceSpan pstate,
               Signature sig,
-              std::string n,
+              sass::string n,
               Parameters_Obj params,
               Native_Function func_ptr,
               bool overload_stub)
-  : Has_Block(pstate, {}),
+  : ParentStatement(pstate, {}),
     name_(n),
     parameters_(params),
     environment_(0),
@@ -493,12 +493,12 @@
     signature_(sig)
   { }
 
-  Definition::Definition(ParserState pstate,
+  Definition::Definition(SourceSpan pstate,
               Signature sig,
-              std::string n,
+              sass::string n,
               Parameters_Obj params,
               Sass_Function_Entry c_func)
-  : Has_Block(pstate, {}),
+  : ParentStatement(pstate, {}),
     name_(n),
     parameters_(params),
     environment_(0),
@@ -513,11 +513,11 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Mixin_Call::Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Parameters_Obj b_params, Block_Obj b)
-  : Has_Block(pstate, b), name_(n), arguments_(args), block_parameters_(b_params)
+  Mixin_Call::Mixin_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Parameters_Obj b_params, Block_Obj b)
+  : ParentStatement(pstate, b), name_(n), arguments_(args), block_parameters_(b_params)
   { }
   Mixin_Call::Mixin_Call(const Mixin_Call* ptr)
-  : Has_Block(ptr),
+  : ParentStatement(ptr),
     name_(ptr->name_),
     arguments_(ptr->arguments_),
     block_parameters_(ptr->block_parameters_)
@@ -526,7 +526,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Content::Content(ParserState pstate, Arguments_Obj args)
+  Content::Content(SourceSpan pstate, Arguments_Obj args)
   : Statement(pstate),
     arguments_(args)
   { statement_type(CONTENT); }
@@ -538,7 +538,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Expression::Expression(ParserState pstate, bool d, bool e, bool i, Type ct)
+  Expression::Expression(SourceSpan pstate, bool d, bool e, bool i, Type ct)
   : AST_Node(pstate),
     is_delayed_(d),
     is_expanded_(e),
@@ -557,7 +557,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Unary_Expression::Unary_Expression(ParserState pstate, Type t, Expression_Obj o)
+  Unary_Expression::Unary_Expression(SourceSpan pstate, Type t, ExpressionObj o)
   : Expression(pstate), optype_(t), operand_(o), hash_(0)
   { }
   Unary_Expression::Unary_Expression(const Unary_Expression* ptr)
@@ -566,7 +566,7 @@
     operand_(ptr->operand_),
     hash_(ptr->hash_)
   { }
-  const std::string Unary_Expression::type_name() {
+  const sass::string Unary_Expression::type_name() {
     switch (optype_) {
       case PLUS: return "plus";
       case MINUS: return "minus";
@@ -602,7 +602,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Argument::Argument(ParserState pstate, Expression_Obj val, std::string n, bool rest, bool keyword)
+  Argument::Argument(SourceSpan pstate, ExpressionObj val, sass::string n, bool rest, bool keyword)
   : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0)
   {
     if (!name_.empty() && is_rest_argument_) {
@@ -646,7 +646,7 @@
   size_t Argument::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()(name());
+      hash_ = std::hash<sass::string>()(name());
       hash_combine(hash_, value()->hash());
     }
     return hash_;
@@ -655,7 +655,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Arguments::Arguments(ParserState pstate)
+  Arguments::Arguments(SourceSpan pstate)
   : Expression(pstate),
     Vectorized<Argument_Obj>(),
     has_named_arguments_(false),
@@ -738,13 +738,13 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Media_Query::Media_Query(ParserState pstate, String_Obj t, size_t s, bool n, bool r)
-  : Expression(pstate), Vectorized<Media_Query_Expression_Obj>(s),
+  Media_Query::Media_Query(SourceSpan pstate, String_Obj t, size_t s, bool n, bool r)
+  : Expression(pstate), Vectorized<Media_Query_ExpressionObj>(s),
     media_type_(t), is_negated_(n), is_restricted_(r)
   { }
   Media_Query::Media_Query(const Media_Query* ptr)
   : Expression(ptr),
-    Vectorized<Media_Query_Expression_Obj>(*ptr),
+    Vectorized<Media_Query_ExpressionObj>(*ptr),
     media_type_(ptr->media_type_),
     is_negated_(ptr->is_negated_),
     is_restricted_(ptr->is_restricted_)
@@ -753,8 +753,8 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Media_Query_Expression::Media_Query_Expression(ParserState pstate,
-                          Expression_Obj f, Expression_Obj v, bool i)
+  Media_Query_Expression::Media_Query_Expression(SourceSpan pstate,
+                          ExpressionObj f, ExpressionObj v, bool i)
   : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
   { }
   Media_Query_Expression::Media_Query_Expression(const Media_Query_Expression* ptr)
@@ -767,7 +767,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  At_Root_Query::At_Root_Query(ParserState pstate, Expression_Obj f, Expression_Obj v, bool i)
+  At_Root_Query::At_Root_Query(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i)
   : Expression(pstate), feature_(f), value_(v)
   { }
   At_Root_Query::At_Root_Query(const At_Root_Query* ptr)
@@ -776,11 +776,11 @@
     value_(ptr->value_)
   { }
 
-  bool At_Root_Query::exclude(std::string str)
+  bool At_Root_Query::exclude(sass::string str)
   {
     bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
     List* l = static_cast<List*>(value().ptr());
-    std::string v;
+    sass::string v;
 
     if (with)
     {
@@ -807,18 +807,18 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  At_Root_Block::At_Root_Block(ParserState pstate, Block_Obj b, At_Root_Query_Obj e)
-  : Has_Block(pstate, b), expression_(e)
+  AtRootRule::AtRootRule(SourceSpan pstate, Block_Obj b, At_Root_Query_Obj e)
+  : ParentStatement(pstate, b), expression_(e)
   { statement_type(ATROOT); }
-  At_Root_Block::At_Root_Block(const At_Root_Block* ptr)
-  : Has_Block(ptr), expression_(ptr->expression_)
+  AtRootRule::AtRootRule(const AtRootRule* ptr)
+  : ParentStatement(ptr), expression_(ptr->expression_)
   { statement_type(ATROOT); }
 
-  bool At_Root_Block::bubbles() {
+  bool AtRootRule::bubbles() {
     return true;
   }
 
-  bool At_Root_Block::exclude_node(Statement_Obj s) {
+  bool AtRootRule::exclude_node(Statement_Obj s) {
     if (expression() == nullptr)
     {
       return s->statement_type() == Statement::RULESET;
@@ -826,9 +826,9 @@
 
     if (s->statement_type() == Statement::DIRECTIVE)
     {
-      if (Directive_Obj dir = Cast<Directive>(s))
+      if (AtRuleObj dir = Cast<AtRule>(s))
       {
-        std::string keyword(dir->keyword());
+        sass::string keyword(dir->keyword());
         if (keyword.length() > 0) keyword.erase(0, 1);
         return expression()->exclude(keyword);
       }
@@ -845,7 +845,7 @@
     {
       return expression()->exclude("supports");
     }
-    if (Directive_Obj dir = Cast<Directive>(s))
+    if (AtRuleObj dir = Cast<AtRule>(s))
     {
       if (dir->is_keyframes()) return expression()->exclude("keyframes");
     }
@@ -855,7 +855,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Parameter::Parameter(ParserState pstate, std::string n, Expression_Obj def, bool rest)
+  Parameter::Parameter(SourceSpan pstate, sass::string n, ExpressionObj def, bool rest)
   : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest)
   { }
   Parameter::Parameter(const Parameter* ptr)
@@ -868,7 +868,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Parameters::Parameters(ParserState pstate)
+  Parameters::Parameters(SourceSpan pstate)
   : AST_Node(pstate),
     Vectorized<Parameter_Obj>(),
     has_optional_parameters_(false),
@@ -911,25 +911,25 @@
   // If you forget to add a class here you will get
   // undefined reference to `vtable for Sass::Class'
 
-  IMPLEMENT_AST_OPERATORS(Ruleset);
+  IMPLEMENT_AST_OPERATORS(StyleRule);
   IMPLEMENT_AST_OPERATORS(MediaRule);
   IMPLEMENT_AST_OPERATORS(CssMediaRule);
   IMPLEMENT_AST_OPERATORS(CssMediaQuery);
   IMPLEMENT_AST_OPERATORS(Import);
   IMPLEMENT_AST_OPERATORS(Import_Stub);
-  IMPLEMENT_AST_OPERATORS(Directive);
-  IMPLEMENT_AST_OPERATORS(At_Root_Block);
-  IMPLEMENT_AST_OPERATORS(While);
-  IMPLEMENT_AST_OPERATORS(Each);
-  IMPLEMENT_AST_OPERATORS(For);
+  IMPLEMENT_AST_OPERATORS(AtRule);
+  IMPLEMENT_AST_OPERATORS(AtRootRule);
+  IMPLEMENT_AST_OPERATORS(WhileRule);
+  IMPLEMENT_AST_OPERATORS(EachRule);
+  IMPLEMENT_AST_OPERATORS(ForRule);
   IMPLEMENT_AST_OPERATORS(If);
   IMPLEMENT_AST_OPERATORS(Mixin_Call);
   IMPLEMENT_AST_OPERATORS(ExtendRule);
   IMPLEMENT_AST_OPERATORS(Media_Query);
   IMPLEMENT_AST_OPERATORS(Media_Query_Expression);
-  IMPLEMENT_AST_OPERATORS(Debug);
-  IMPLEMENT_AST_OPERATORS(Error);
-  IMPLEMENT_AST_OPERATORS(Warning);
+  IMPLEMENT_AST_OPERATORS(DebugRule);
+  IMPLEMENT_AST_OPERATORS(ErrorRule);
+  IMPLEMENT_AST_OPERATORS(WarningRule);
   IMPLEMENT_AST_OPERATORS(Assignment);
   IMPLEMENT_AST_OPERATORS(Return);
   IMPLEMENT_AST_OPERATORS(At_Root_Query);
diff --git a/libsass/src/ast.hpp b/libsass/src/ast.hpp
--- a/libsass/src/ast.hpp
+++ b/libsass/src/ast.hpp
@@ -55,9 +55,9 @@
   // Abstract base class for all abstract syntax tree nodes.
   //////////////////////////////////////////////////////////
   class AST_Node : public SharedObj {
-    ADD_PROPERTY(ParserState, pstate)
+    ADD_PROPERTY(SourceSpan, pstate)
   public:
-    AST_Node(ParserState pstate)
+    AST_Node(SourceSpan pstate)
     : pstate_(pstate)
     { }
     AST_Node(const AST_Node* ptr)
@@ -66,7 +66,7 @@
 
     // allow implicit conversion to string
     // needed for by SharedPtr implementation
-    operator std::string() {
+    operator sass::string() {
       return to_string();
     }
 
@@ -74,27 +74,25 @@
 
     virtual ~AST_Node() = 0;
     virtual size_t hash() const { return 0; }
-    virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
-    virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
-    virtual std::string to_string(Sass_Inspect_Options opt) const;
-    virtual std::string to_css(Sass_Inspect_Options opt) const;
-    virtual std::string to_string() const;
+    virtual sass::string inspect() const { return to_string({ INSPECT, 5 }); }
+    virtual sass::string to_sass() const { return to_string({ TO_SASS, 5 }); }
+    virtual sass::string to_string(Sass_Inspect_Options opt) const;
+    virtual sass::string to_css(Sass_Inspect_Options opt) const;
+    virtual sass::string to_string() const;
     virtual void cloneChildren() {};
     // generic find function (not fully implemented yet)
-    // ToDo: add specific implementions to all children
+    // ToDo: add specific implementations to all children
     virtual bool find ( bool (*f)(AST_Node_Obj) ) { return f(this); };
-    void update_pstate(const ParserState& pstate);
-    Offset off() { return pstate(); }
-    Position pos() { return pstate(); }
+    void update_pstate(const SourceSpan& pstate);
 
-    // Some obects are not meant to be compared
-    // ToDo: maybe fallback to pointer comparison?
+    // Some objects are not meant to be compared
+    // ToDo: maybe fall-back to pointer comparison?
     virtual bool operator== (const AST_Node& rhs) const {
       throw std::runtime_error("operator== not implemented");
     }
 
     // We can give some reasonable implementations by using
-    // inverst operators on the specialized implementations
+    // invert operators on the specialized implementations
     virtual bool operator!= (const AST_Node& rhs) const {
       // Unequal if not equal
       return !(*this == rhs);
@@ -153,13 +151,13 @@
     ADD_PROPERTY(bool, is_interpolant)
     ADD_PROPERTY(Type, concrete_type)
   public:
-    Expression(ParserState pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
+    Expression(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
     virtual operator bool() { return true; }
     virtual ~Expression() { }
     virtual bool is_invisible() const { return false; }
 
-    virtual std::string type() const { return ""; }
-    static std::string type_name() { return ""; }
+    virtual sass::string type() const { return ""; }
+    static sass::string type_name() { return ""; }
 
     virtual bool is_false() { return false; }
     // virtual bool is_true() { return !is_false(); }
@@ -184,17 +182,17 @@
 
 namespace std {
   template<>
-  struct hash<Sass::Expression_Obj>
+  struct hash<Sass::ExpressionObj>
   {
-    size_t operator()(Sass::Expression_Obj s) const
+    size_t operator()(Sass::ExpressionObj s) const
     {
       return s->hash();
     }
   };
   template<>
-  struct equal_to<Sass::Expression_Obj>
+  struct equal_to<Sass::ExpressionObj>
   {
-    bool operator()( Sass::Expression_Obj lhs,  Sass::Expression_Obj rhs) const
+    bool operator()( Sass::ExpressionObj lhs,  Sass::ExpressionObj rhs) const
     {
       return lhs->hash() == rhs->hash();
     }
@@ -210,7 +208,7 @@
   /////////////////////////////////////////////////////////////////////////////
   template <typename T>
   class Vectorized {
-    std::vector<T> elements_;
+    sass::vector<T> elements_;
   protected:
     mutable size_t hash_;
     void reset_hash() { hash_ = 0; }
@@ -218,7 +216,7 @@
   public:
     Vectorized(size_t s = 0) : hash_(0)
     { elements_.reserve(s); }
-    Vectorized(std::vector<T> vec) :
+    Vectorized(sass::vector<T> vec) :
       elements_(std::move(vec)),
       hash_(0)
     {}
@@ -248,23 +246,23 @@
     const T& get(size_t i) const { return elements_[i]; }
     const T& operator[](size_t i) const { return elements_[i]; }
 
-    // Implicitly get the std::vector from our object
-    // Makes the Vector directly assignable to std::vector
+    // Implicitly get the sass::vector from our object
+    // Makes the Vector directly assignable to sass::vector
     // You are responsible to make a copy if needed
     // Note: since this returns the real object, we can't
     // Note: guarantee that the hash will not get out of sync
-    operator std::vector<T>&() { return elements_; }
-    operator const std::vector<T>&() const { return elements_; }
+    operator sass::vector<T>&() { return elements_; }
+    operator const sass::vector<T>&() const { return elements_; }
 
-    // Explicitly request all elements as a real std::vector
+    // Explicitly request all elements as a real sass::vector
     // You are responsible to make a copy if needed
     // Note: since this returns the real object, we can't
     // Note: guarantee that the hash will not get out of sync
-    std::vector<T>& elements() { return elements_; }
-    const std::vector<T>& elements() const { return elements_; }
+    sass::vector<T>& elements() { return elements_; }
+    const sass::vector<T>& elements() const { return elements_; }
 
     // Insert all items from compatible vector
-    void concat(const std::vector<T>& v)
+    void concat(const sass::vector<T>& v)
     {
       if (!v.empty()) reset_hash();
       elements().insert(end(), v.begin(), v.end());
@@ -320,7 +318,7 @@
     }
 
     // This might be better implemented as `operator=`?
-    void elements(std::vector<T> e) {
+    void elements(sass::vector<T> e) {
       reset_hash();
       elements_ = std::move(e);
     }
@@ -336,17 +334,17 @@
     }
 
     template <typename P, typename V>
-    typename std::vector<T>::iterator insert(P position, const V& val) {
+    typename sass::vector<T>::iterator insert(P position, const V& val) {
       reset_hash();
       return elements_.insert(position, val);
     }
 
-    typename std::vector<T>::iterator end() { return elements_.end(); }
-    typename std::vector<T>::iterator begin() { return elements_.begin(); }
-    typename std::vector<T>::const_iterator end() const { return elements_.end(); }
-    typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
-    typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { reset_hash(); return elements_.erase(el); }
-    typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { reset_hash(); return elements_.erase(el); }
+    typename sass::vector<T>::iterator end() { return elements_.end(); }
+    typename sass::vector<T>::iterator begin() { return elements_.begin(); }
+    typename sass::vector<T>::const_iterator end() const { return elements_.end(); }
+    typename sass::vector<T>::const_iterator begin() const { return elements_.begin(); }
+    typename sass::vector<T>::iterator erase(typename sass::vector<T>::iterator el) { reset_hash(); return elements_.erase(el); }
+    typename sass::vector<T>::const_iterator erase(typename sass::vector<T>::const_iterator el) { reset_hash(); return elements_.erase(el); }
 
   };
   template <typename T>
@@ -354,7 +352,7 @@
 
   /////////////////////////////////////////////////////////////////////////////
   // Mixin class for AST nodes that should behave like a hash table. Uses an
-  // extra <std::vector> internally to maintain insertion order for interation.
+  // extra <sass::vector> internally to maintain insertion order for interation.
   /////////////////////////////////////////////////////////////////////////////
   template <typename K, typename T, typename U>
   class Hashed {
@@ -363,8 +361,8 @@
       K, T, ObjHash, ObjEquality
     > elements_;
 
-    std::vector<K> _keys;
-    std::vector<T> _values;
+    sass::vector<K> _keys;
+    sass::vector<T> _values;
   protected:
     mutable size_t hash_;
     K duplicate_key_;
@@ -437,13 +435,13 @@
       K, T, ObjHash, ObjEquality
     >& pairs() const { return elements_; }
 
-    const std::vector<K>& keys() const { return _keys; }
-    const std::vector<T>& values() const { return _values; }
+    const sass::vector<K>& keys() const { return _keys; }
+    const sass::vector<T>& values() const { return _values; }
 
-//    std::unordered_map<Expression_Obj, Expression_Obj>::iterator end() { return elements_.end(); }
-//    std::unordered_map<Expression_Obj, Expression_Obj>::iterator begin() { return elements_.begin(); }
-//    std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator end() const { return elements_.end(); }
-//    std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator begin() const { return elements_.begin(); }
+//    std::unordered_map<ExpressionObj, ExpressionObj>::iterator end() { return elements_.end(); }
+//    std::unordered_map<ExpressionObj, ExpressionObj>::iterator begin() { return elements_.begin(); }
+//    std::unordered_map<ExpressionObj, ExpressionObj>::const_iterator end() const { return elements_.end(); }
+//    std::unordered_map<ExpressionObj, ExpressionObj>::const_iterator begin() const { return elements_.begin(); }
 
   };
   template <typename K, typename T, typename U>
@@ -486,7 +484,7 @@
     ADD_PROPERTY(size_t, tabs)
     ADD_PROPERTY(bool, group_end)
   public:
-    Statement(ParserState pstate, Type st = NONE, size_t t = 0);
+    Statement(SourceSpan pstate, Type st = NONE, size_t t = 0);
     virtual ~Statement() = 0; // virtual destructor
     // needed for rearranging nested rulesets during CSS emission
     virtual bool bubbles();
@@ -505,7 +503,7 @@
   protected:
     void adjust_after_pushing(Statement_Obj s) override {}
   public:
-    Block(ParserState pstate, size_t s = 0, bool r = false);
+    Block(SourceSpan pstate, size_t s = 0, bool r = false);
     bool isInvisible() const;
     bool has_content() override;
     ATTACH_AST_OPERATIONS(Block)
@@ -515,28 +513,28 @@
   ////////////////////////////////////////////////////////////////////////
   // Abstract base class for statements that contain blocks of statements.
   ////////////////////////////////////////////////////////////////////////
-  class Has_Block : public Statement {
+  class ParentStatement : public Statement {
     ADD_PROPERTY(Block_Obj, block)
   public:
-    Has_Block(ParserState pstate, Block_Obj b);
-    Has_Block(const Has_Block* ptr); // copy constructor
-    virtual ~Has_Block() = 0; // virtual destructor
+    ParentStatement(SourceSpan pstate, Block_Obj b);
+    ParentStatement(const ParentStatement* ptr); // copy constructor
+    virtual ~ParentStatement() = 0; // virtual destructor
     virtual bool has_content() override;
   };
-  inline Has_Block::~Has_Block() { }
+  inline ParentStatement::~ParentStatement() { }
 
   /////////////////////////////////////////////////////////////////////////////
   // Rulesets (i.e., sets of styles headed by a selector and containing a block
   // of style declarations.
   /////////////////////////////////////////////////////////////////////////////
-  class Ruleset final : public Has_Block {
+  class StyleRule final : public ParentStatement {
     ADD_PROPERTY(SelectorListObj, selector)
     ADD_PROPERTY(Selector_Schema_Obj, schema)
     ADD_PROPERTY(bool, is_root);
   public:
-    Ruleset(ParserState pstate, SelectorListObj s = {}, Block_Obj b = {});
+    StyleRule(SourceSpan pstate, SelectorListObj s = {}, Block_Obj b = {});
     bool is_invisible() const override;
-    ATTACH_AST_OPERATIONS(Ruleset)
+    ATTACH_AST_OPERATIONS(StyleRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
@@ -547,7 +545,7 @@
     ADD_PROPERTY(Statement_Obj, node)
     ADD_PROPERTY(bool, group_end)
   public:
-    Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g = {}, size_t t = 0);
+    Bubble(SourceSpan pstate, Statement_Obj n, Statement_Obj g = {}, size_t t = 0);
     bool bubbles() override;
     ATTACH_AST_OPERATIONS(Bubble)
     ATTACH_CRTP_PERFORM_METHODS()
@@ -556,11 +554,11 @@
   /////////////////
   // Trace.
   /////////////////
-  class Trace final : public Has_Block {
+  class Trace final : public ParentStatement {
     ADD_CONSTREF(char, type)
-    ADD_CONSTREF(std::string, name)
+    ADD_CONSTREF(sass::string, name)
   public:
-    Trace(ParserState pstate, std::string n, Block_Obj b = {}, char type = 'm');
+    Trace(SourceSpan pstate, sass::string n, Block_Obj b = {}, char type = 'm');
     ATTACH_AST_OPERATIONS(Trace)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -569,28 +567,28 @@
   // At-rules -- arbitrary directives beginning with "@" that may have an
   // optional statement block.
   ///////////////////////////////////////////////////////////////////////
-  class Directive final : public Has_Block {
-    ADD_CONSTREF(std::string, keyword)
+  class AtRule final : public ParentStatement {
+    ADD_CONSTREF(sass::string, keyword)
     ADD_PROPERTY(SelectorListObj, selector)
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_PROPERTY(ExpressionObj, value)
   public:
-    Directive(ParserState pstate, std::string kwd, SelectorListObj sel = {}, Block_Obj b = {}, Expression_Obj val = {});
+    AtRule(SourceSpan pstate, sass::string kwd, SelectorListObj sel = {}, Block_Obj b = {}, ExpressionObj val = {});
     bool bubbles() override;
     bool is_media();
     bool is_keyframes();
-    ATTACH_AST_OPERATIONS(Directive)
+    ATTACH_AST_OPERATIONS(AtRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////////////////////////////////////////////
   // Keyframe-rules -- the child blocks of "@keyframes" nodes.
   ///////////////////////////////////////////////////////////////////////
-  class Keyframe_Rule final : public Has_Block {
+  class Keyframe_Rule final : public ParentStatement {
     // according to css spec, this should be <keyframes-name>
     // <keyframes-name> = <custom-ident> | <string>
     ADD_PROPERTY(SelectorListObj, name)
   public:
-    Keyframe_Rule(ParserState pstate, Block_Obj b);
+    Keyframe_Rule(SourceSpan pstate, Block_Obj b);
     ATTACH_AST_OPERATIONS(Keyframe_Rule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -598,14 +596,14 @@
   ////////////////////////////////////////////////////////////////////////
   // Declarations -- style rules consisting of a property name and values.
   ////////////////////////////////////////////////////////////////////////
-  class Declaration final : public Has_Block {
+  class Declaration final : public ParentStatement {
     ADD_PROPERTY(String_Obj, property)
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_PROPERTY(ExpressionObj, value)
     ADD_PROPERTY(bool, is_important)
     ADD_PROPERTY(bool, is_custom_property)
     ADD_PROPERTY(bool, is_indented)
   public:
-    Declaration(ParserState pstate, String_Obj prop, Expression_Obj val, bool i = false, bool c = false, Block_Obj b = {});
+    Declaration(SourceSpan pstate, String_Obj prop, ExpressionObj val, bool i = false, bool c = false, Block_Obj b = {});
     bool is_invisible() const override;
     ATTACH_AST_OPERATIONS(Declaration)
     ATTACH_CRTP_PERFORM_METHODS()
@@ -615,12 +613,12 @@
   // Assignments -- variable and value.
   /////////////////////////////////////
   class Assignment final : public Statement {
-    ADD_CONSTREF(std::string, variable)
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_CONSTREF(sass::string, variable)
+    ADD_PROPERTY(ExpressionObj, value)
     ADD_PROPERTY(bool, is_default)
     ADD_PROPERTY(bool, is_global)
   public:
-    Assignment(ParserState pstate, std::string var, Expression_Obj val, bool is_default = false, bool is_global = false);
+    Assignment(SourceSpan pstate, sass::string var, ExpressionObj val, bool is_default = false, bool is_global = false);
     ATTACH_AST_OPERATIONS(Assignment)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -630,13 +628,13 @@
   // necessary to store a list of each in an Import node.
   ////////////////////////////////////////////////////////////////////////////
   class Import final : public Statement {
-    std::vector<Expression_Obj> urls_;
-    std::vector<Include>        incs_;
+    sass::vector<ExpressionObj> urls_;
+    sass::vector<Include>        incs_;
     ADD_PROPERTY(List_Obj,      import_queries);
   public:
-    Import(ParserState pstate);
-    std::vector<Include>& incs();
-    std::vector<Expression_Obj>& urls();
+    Import(SourceSpan pstate);
+    sass::vector<Include>& incs();
+    sass::vector<ExpressionObj>& urls();
     ATTACH_AST_OPERATIONS(Import)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -646,10 +644,10 @@
   class Import_Stub final : public Statement {
     Include resource_;
   public:
-    Import_Stub(ParserState pstate, Include res);
+    Import_Stub(SourceSpan pstate, Include res);
     Include resource();
-    std::string imp_path();
-    std::string abs_path();
+    sass::string imp_path();
+    sass::string abs_path();
     ATTACH_AST_OPERATIONS(Import_Stub)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -657,33 +655,33 @@
   //////////////////////////////
   // The Sass `@warn` directive.
   //////////////////////////////
-  class Warning final : public Statement {
-    ADD_PROPERTY(Expression_Obj, message)
+  class WarningRule final : public Statement {
+    ADD_PROPERTY(ExpressionObj, message)
   public:
-    Warning(ParserState pstate, Expression_Obj msg);
-    ATTACH_AST_OPERATIONS(Warning)
+    WarningRule(SourceSpan pstate, ExpressionObj msg);
+    ATTACH_AST_OPERATIONS(WarningRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////
   // The Sass `@error` directive.
   ///////////////////////////////
-  class Error final : public Statement {
-    ADD_PROPERTY(Expression_Obj, message)
+  class ErrorRule final : public Statement {
+    ADD_PROPERTY(ExpressionObj, message)
   public:
-    Error(ParserState pstate, Expression_Obj msg);
-    ATTACH_AST_OPERATIONS(Error)
+    ErrorRule(SourceSpan pstate, ExpressionObj msg);
+    ATTACH_AST_OPERATIONS(ErrorRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////
   // The Sass `@debug` directive.
   ///////////////////////////////
-  class Debug final : public Statement {
-    ADD_PROPERTY(Expression_Obj, value)
+  class DebugRule final : public Statement {
+    ADD_PROPERTY(ExpressionObj, value)
   public:
-    Debug(ParserState pstate, Expression_Obj val);
-    ATTACH_AST_OPERATIONS(Debug)
+    DebugRule(SourceSpan pstate, ExpressionObj val);
+    ATTACH_AST_OPERATIONS(DebugRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
@@ -694,7 +692,7 @@
     ADD_PROPERTY(String_Obj, text)
     ADD_PROPERTY(bool, is_important)
   public:
-    Comment(ParserState pstate, String_Obj txt, bool is_important);
+    Comment(SourceSpan pstate, String_Obj txt, bool is_important);
     virtual bool is_invisible() const override;
     ATTACH_AST_OPERATIONS(Comment)
     ATTACH_CRTP_PERFORM_METHODS()
@@ -703,11 +701,11 @@
   ////////////////////////////////////
   // The Sass `@if` control directive.
   ////////////////////////////////////
-  class If final : public Has_Block {
-    ADD_PROPERTY(Expression_Obj, predicate)
+  class If final : public ParentStatement {
+    ADD_PROPERTY(ExpressionObj, predicate)
     ADD_PROPERTY(Block_Obj, alternative)
   public:
-    If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt = {});
+    If(SourceSpan pstate, ExpressionObj pred, Block_Obj con, Block_Obj alt = {});
     virtual bool has_content() override;
     ATTACH_AST_OPERATIONS(If)
     ATTACH_CRTP_PERFORM_METHODS()
@@ -716,37 +714,37 @@
   /////////////////////////////////////
   // The Sass `@for` control directive.
   /////////////////////////////////////
-  class For final : public Has_Block {
-    ADD_CONSTREF(std::string, variable)
-    ADD_PROPERTY(Expression_Obj, lower_bound)
-    ADD_PROPERTY(Expression_Obj, upper_bound)
+  class ForRule final : public ParentStatement {
+    ADD_CONSTREF(sass::string, variable)
+    ADD_PROPERTY(ExpressionObj, lower_bound)
+    ADD_PROPERTY(ExpressionObj, upper_bound)
     ADD_PROPERTY(bool, is_inclusive)
   public:
-    For(ParserState pstate, std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc);
-    ATTACH_AST_OPERATIONS(For)
+    ForRule(SourceSpan pstate, sass::string var, ExpressionObj lo, ExpressionObj hi, Block_Obj b, bool inc);
+    ATTACH_AST_OPERATIONS(ForRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   //////////////////////////////////////
   // The Sass `@each` control directive.
   //////////////////////////////////////
-  class Each final : public Has_Block {
-    ADD_PROPERTY(std::vector<std::string>, variables)
-    ADD_PROPERTY(Expression_Obj, list)
+  class EachRule final : public ParentStatement {
+    ADD_PROPERTY(sass::vector<sass::string>, variables)
+    ADD_PROPERTY(ExpressionObj, list)
   public:
-    Each(ParserState pstate, std::vector<std::string> vars, Expression_Obj lst, Block_Obj b);
-    ATTACH_AST_OPERATIONS(Each)
+    EachRule(SourceSpan pstate, sass::vector<sass::string> vars, ExpressionObj lst, Block_Obj b);
+    ATTACH_AST_OPERATIONS(EachRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////////////
   // The Sass `@while` control directive.
   ///////////////////////////////////////
-  class While final : public Has_Block {
-    ADD_PROPERTY(Expression_Obj, predicate)
+  class WhileRule final : public ParentStatement {
+    ADD_PROPERTY(ExpressionObj, predicate)
   public:
-    While(ParserState pstate, Expression_Obj pred, Block_Obj b);
-    ATTACH_AST_OPERATIONS(While)
+    WhileRule(SourceSpan pstate, ExpressionObj pred, Block_Obj b);
+    ATTACH_AST_OPERATIONS(WhileRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
@@ -754,9 +752,9 @@
   // The @return directive for use inside SassScript functions.
   /////////////////////////////////////////////////////////////
   class Return final : public Statement {
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_PROPERTY(ExpressionObj, value)
   public:
-    Return(ParserState pstate, Expression_Obj val);
+    Return(SourceSpan pstate, ExpressionObj val);
     ATTACH_AST_OPERATIONS(Return)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -765,10 +763,10 @@
   // Definitions for both mixins and functions. The two cases are distinguished
   // by a type tag.
   /////////////////////////////////////////////////////////////////////////////
-  class Definition final : public Has_Block {
+  class Definition final : public ParentStatement {
   public:
     enum Type { MIXIN, FUNCTION };
-    ADD_CONSTREF(std::string, name)
+    ADD_CONSTREF(sass::string, name)
     ADD_PROPERTY(Parameters_Obj, parameters)
     ADD_PROPERTY(Env*, environment)
     ADD_PROPERTY(Type, type)
@@ -778,20 +776,20 @@
     ADD_PROPERTY(bool, is_overload_stub)
     ADD_PROPERTY(Signature, signature)
   public:
-    Definition(ParserState pstate,
-               std::string n,
+    Definition(SourceSpan pstate,
+               sass::string n,
                Parameters_Obj params,
                Block_Obj b,
                Type t);
-    Definition(ParserState pstate,
+    Definition(SourceSpan pstate,
                Signature sig,
-               std::string n,
+               sass::string n,
                Parameters_Obj params,
                Native_Function func_ptr,
                bool overload_stub = false);
-    Definition(ParserState pstate,
+    Definition(SourceSpan pstate,
                Signature sig,
-               std::string n,
+               sass::string n,
                Parameters_Obj params,
                Sass_Function_Entry c_func);
     ATTACH_AST_OPERATIONS(Definition)
@@ -801,12 +799,12 @@
   //////////////////////////////////////
   // Mixin calls (i.e., `@include ...`).
   //////////////////////////////////////
-  class Mixin_Call final : public Has_Block {
-    ADD_CONSTREF(std::string, name)
+  class Mixin_Call final : public ParentStatement {
+    ADD_CONSTREF(sass::string, name)
     ADD_PROPERTY(Arguments_Obj, arguments)
     ADD_PROPERTY(Parameters_Obj, block_parameters)
   public:
-    Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Parameters_Obj b_params = {}, Block_Obj b = {});
+    Mixin_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Parameters_Obj b_params = {}, Block_Obj b = {});
     ATTACH_AST_OPERATIONS(Mixin_Call)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -817,7 +815,7 @@
   class Content final : public Statement {
     ADD_PROPERTY(Arguments_Obj, arguments)
   public:
-    Content(ParserState pstate, Arguments_Obj args);
+    Content(SourceSpan pstate, Arguments_Obj args);
     ATTACH_AST_OPERATIONS(Content)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -830,11 +828,11 @@
     enum Type { PLUS, MINUS, NOT, SLASH };
   private:
     HASH_PROPERTY(Type, optype)
-    HASH_PROPERTY(Expression_Obj, operand)
+    HASH_PROPERTY(ExpressionObj, operand)
     mutable size_t hash_;
   public:
-    Unary_Expression(ParserState pstate, Type t, Expression_Obj o);
-    const std::string type_name();
+    Unary_Expression(SourceSpan pstate, Type t, ExpressionObj o);
+    const sass::string type_name();
     virtual bool operator==(const Expression& rhs) const override;
     size_t hash() const override;
     ATTACH_AST_OPERATIONS(Unary_Expression)
@@ -845,13 +843,13 @@
   // Individual argument objects for mixin and function calls.
   ////////////////////////////////////////////////////////////
   class Argument final : public Expression {
-    HASH_PROPERTY(Expression_Obj, value)
-    HASH_CONSTREF(std::string, name)
+    HASH_PROPERTY(ExpressionObj, value)
+    HASH_CONSTREF(sass::string, name)
     ADD_PROPERTY(bool, is_rest_argument)
     ADD_PROPERTY(bool, is_keyword_argument)
     mutable size_t hash_;
   public:
-    Argument(ParserState pstate, Expression_Obj val, std::string n = "", bool rest = false, bool keyword = false);
+    Argument(SourceSpan pstate, ExpressionObj val, sass::string n = "", bool rest = false, bool keyword = false);
     void set_delayed(bool delayed) override;
     bool operator==(const Expression& rhs) const override;
     size_t hash() const override;
@@ -871,7 +869,7 @@
   protected:
     void adjust_after_pushing(Argument_Obj a) override;
   public:
-    Arguments(ParserState pstate);
+    Arguments(SourceSpan pstate);
     void set_delayed(bool delayed) override;
     Argument_Obj get_rest_argument();
     Argument_Obj get_keyword_argument();
@@ -880,12 +878,12 @@
   };
 
 
-  // A Media Ruleset before it has been evaluated
+  // A Media StyleRule before it has been evaluated
   // Could be already final or an interpolation
-  class MediaRule final : public Has_Block {
+  class MediaRule final : public ParentStatement {
     ADD_PROPERTY(List_Obj, schema)
   public:
-    MediaRule(ParserState pstate, Block_Obj block = {});
+    MediaRule(SourceSpan pstate, Block_Obj block = {});
 
     bool bubbles() override { return true; };
     bool is_invisible() const override { return false; };
@@ -893,12 +891,12 @@
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
-  // A Media Ruleset after it has been evaluated
+  // A Media StyleRule after it has been evaluated
   // Representing the static or resulting css
-  class CssMediaRule final : public Has_Block,
+  class CssMediaRule final : public ParentStatement,
     public Vectorized<CssMediaQuery_Obj> {
   public:
-    CssMediaRule(ParserState pstate, Block_Obj b);
+    CssMediaRule(SourceSpan pstate, Block_Obj b);
     bool bubbles() override { return true; };
     bool isInvisible() const { return empty(); }
     bool is_invisible() const override { return false; };
@@ -925,17 +923,17 @@
 
     // The modifier, probably either "not" or "only".
     // This may be `null` if no modifier is in use.
-    ADD_PROPERTY(std::string, modifier);
+    ADD_PROPERTY(sass::string, modifier);
 
     // The media type, for example "screen" or "print".
     // This may be `null`. If so, [features] will not be empty.
-    ADD_PROPERTY(std::string, type);
+    ADD_PROPERTY(sass::string, type);
 
     // Feature queries, including parentheses.
-    ADD_PROPERTY(std::vector<std::string>, features);
+    ADD_PROPERTY(sass::vector<sass::string>, features);
 
   public:
-    CssMediaQuery(ParserState pstate);
+    CssMediaQuery(SourceSpan pstate);
 
     // Check if two instances are considered equal
     bool operator== (const CssMediaQuery& rhs) const;
@@ -970,12 +968,12 @@
   // ToDo: only used for interpolation case
   ////////////////////////////////////////////////////
   class Media_Query final : public Expression,
-                            public Vectorized<Media_Query_Expression_Obj> {
+                            public Vectorized<Media_Query_ExpressionObj> {
     ADD_PROPERTY(String_Obj, media_type)
     ADD_PROPERTY(bool, is_negated)
     ADD_PROPERTY(bool, is_restricted)
   public:
-    Media_Query(ParserState pstate, String_Obj t = {}, size_t s = 0, bool n = false, bool r = false);
+    Media_Query(SourceSpan pstate, String_Obj t = {}, size_t s = 0, bool n = false, bool r = false);
     ATTACH_AST_OPERATIONS(Media_Query)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -985,11 +983,11 @@
   // ToDo: only used for interpolation case
   ////////////////////////////////////////////////////
   class Media_Query_Expression final : public Expression {
-    ADD_PROPERTY(Expression_Obj, feature)
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_PROPERTY(ExpressionObj, feature)
+    ADD_PROPERTY(ExpressionObj, value)
     ADD_PROPERTY(bool, is_interpolated)
   public:
-    Media_Query_Expression(ParserState pstate, Expression_Obj f, Expression_Obj v, bool i = false);
+    Media_Query_Expression(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i = false);
     ATTACH_AST_OPERATIONS(Media_Query_Expression)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -999,11 +997,11 @@
   /////////////////////////////////////////////////
   class At_Root_Query final : public Expression {
   private:
-    ADD_PROPERTY(Expression_Obj, feature)
-    ADD_PROPERTY(Expression_Obj, value)
+    ADD_PROPERTY(ExpressionObj, feature)
+    ADD_PROPERTY(ExpressionObj, value)
   public:
-    At_Root_Query(ParserState pstate, Expression_Obj f = {}, Expression_Obj v = {}, bool i = false);
-    bool exclude(std::string str);
+    At_Root_Query(SourceSpan pstate, ExpressionObj f = {}, ExpressionObj v = {}, bool i = false);
+    bool exclude(sass::string str);
     ATTACH_AST_OPERATIONS(At_Root_Query)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -1011,13 +1009,13 @@
   ///////////
   // At-root.
   ///////////
-  class At_Root_Block final : public Has_Block {
+  class AtRootRule final : public ParentStatement {
     ADD_PROPERTY(At_Root_Query_Obj, expression)
   public:
-    At_Root_Block(ParserState pstate, Block_Obj b = {}, At_Root_Query_Obj e = {});
+    AtRootRule(SourceSpan pstate, Block_Obj b = {}, At_Root_Query_Obj e = {});
     bool bubbles() override;
     bool exclude_node(Statement_Obj s);
-    ATTACH_AST_OPERATIONS(At_Root_Block)
+    ATTACH_AST_OPERATIONS(AtRootRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
@@ -1025,11 +1023,11 @@
   // Individual parameter objects for mixins and functions.
   /////////////////////////////////////////////////////////
   class Parameter final : public AST_Node {
-    ADD_CONSTREF(std::string, name)
-    ADD_PROPERTY(Expression_Obj, default_value)
+    ADD_CONSTREF(sass::string, name)
+    ADD_PROPERTY(ExpressionObj, default_value)
     ADD_PROPERTY(bool, is_rest_parameter)
   public:
-    Parameter(ParserState pstate, std::string n, Expression_Obj def = {}, bool rest = false);
+    Parameter(SourceSpan pstate, sass::string n, ExpressionObj def = {}, bool rest = false);
     ATTACH_AST_OPERATIONS(Parameter)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -1045,7 +1043,7 @@
   protected:
     void adjust_after_pushing(Parameter_Obj p) override;
   public:
-    Parameters(ParserState pstate);
+    Parameters(SourceSpan pstate);
     ATTACH_AST_OPERATIONS(Parameters)
     ATTACH_CRTP_PERFORM_METHODS()
   };
diff --git a/libsass/src/ast_def_macros.hpp b/libsass/src/ast_def_macros.hpp
--- a/libsass/src/ast_def_macros.hpp
+++ b/libsass/src/ast_def_macros.hpp
@@ -70,18 +70,18 @@
 #ifdef DEBUG_SHARED_PTR
 
 #define ATTACH_ABSTRACT_AST_OPERATIONS(klass) \
-  virtual klass* copy(std::string, size_t) const = 0; \
-  virtual klass* clone(std::string, size_t) const = 0; \
+  virtual klass* copy(sass::string, size_t) const = 0; \
+  virtual klass* clone(sass::string, size_t) const = 0; \
 
 #define ATTACH_VIRTUAL_AST_OPERATIONS(klass) \
   klass(const klass* ptr); \
-  virtual klass* copy(std::string, size_t) const override = 0; \
-  virtual klass* clone(std::string, size_t) const override = 0; \
+  virtual klass* copy(sass::string, size_t) const override = 0; \
+  virtual klass* clone(sass::string, size_t) const override = 0; \
 
 #define ATTACH_AST_OPERATIONS(klass) \
   klass(const klass* ptr); \
-  virtual klass* copy(std::string, size_t) const override; \
-  virtual klass* clone(std::string, size_t) const override; \
+  virtual klass* copy(sass::string, size_t) const override; \
+  virtual klass* clone(sass::string, size_t) const override; \
 
 #else
 
@@ -112,12 +112,12 @@
 #ifdef DEBUG_SHARED_PTR
 
   #define IMPLEMENT_AST_OPERATORS(klass) \
-    klass* klass::copy(std::string file, size_t line) const { \
-      klass* cpy = new klass(this); \
+    klass* klass::copy(sass::string file, size_t line) const { \
+      klass* cpy = SASS_MEMORY_NEW(klass, this); \
       cpy->trace(file, line); \
       return cpy; \
     } \
-    klass* klass::clone(std::string file, size_t line) const { \
+    klass* klass::clone(sass::string file, size_t line) const { \
       klass* cpy = copy(file, line); \
       cpy->cloneChildren(); \
       return cpy; \
@@ -127,7 +127,7 @@
 
   #define IMPLEMENT_AST_OPERATORS(klass) \
     klass* klass::copy() const { \
-      return new klass(this); \
+      return SASS_MEMORY_NEW(klass, this); \
     } \
     klass* klass::clone() const { \
       klass* cpy = copy(); \
diff --git a/libsass/src/ast_fwd_decl.cpp b/libsass/src/ast_fwd_decl.cpp
--- a/libsass/src/ast_fwd_decl.cpp
+++ b/libsass/src/ast_fwd_decl.cpp
@@ -16,14 +16,14 @@
   IMPLEMENT_BASE_CAST(AST_Node)
   IMPLEMENT_BASE_CAST(Expression)
   IMPLEMENT_BASE_CAST(Statement)
-  IMPLEMENT_BASE_CAST(Has_Block)
+  IMPLEMENT_BASE_CAST(ParentStatement)
   IMPLEMENT_BASE_CAST(PreValue)
   IMPLEMENT_BASE_CAST(Value)
   IMPLEMENT_BASE_CAST(Color)
   IMPLEMENT_BASE_CAST(List)
   IMPLEMENT_BASE_CAST(String)
   IMPLEMENT_BASE_CAST(String_Constant)
-  IMPLEMENT_BASE_CAST(Supports_Condition)
+  IMPLEMENT_BASE_CAST(SupportsCondition)
   IMPLEMENT_BASE_CAST(Selector)
   IMPLEMENT_BASE_CAST(SelectorComponent)
   IMPLEMENT_BASE_CAST(SimpleSelector)
diff --git a/libsass/src/ast_fwd_decl.hpp b/libsass/src/ast_fwd_decl.hpp
--- a/libsass/src/ast_fwd_decl.hpp
+++ b/libsass/src/ast_fwd_decl.hpp
@@ -4,18 +4,22 @@
 // sass.hpp must go before all system headers to get the
 // __EXTENSIONS__ fix on Solaris.
 #include "sass.hpp"
-
+#include "memory.hpp"
 #include "sass/functions.h"
-#include "memory/SharedPtr.hpp"
 
 /////////////////////////////////////////////
 // Forward declarations for the AST visitors.
 /////////////////////////////////////////////
 namespace Sass {
 
+  class SourceData;
+  class SourceFile;
+  class SynthFile;
+  class ItplFile;
+
   class AST_Node;
 
-  class Has_Block;
+  class ParentStatement;
 
   class SimpleSelector;
 
@@ -27,7 +31,7 @@
   class Statement;
   class Value;
   class Declaration;
-  class Ruleset;
+  class StyleRule;
   class Bubble;
   class Trace;
 
@@ -35,25 +39,25 @@
   class CssMediaRule;
   class CssMediaQuery;
 
-  class Supports_Block;
-  class Directive;
+  class SupportsRule;
+  class AtRule;
 
   class Keyframe_Rule;
-  class At_Root_Block;
+  class AtRootRule;
   class Assignment;
 
   class Import;
   class Import_Stub;
-  class Warning;
+  class WarningRule;
 
-  class Error;
-  class Debug;
+  class ErrorRule;
+  class DebugRule;
   class Comment;
 
   class If;
-  class For;
-  class Each;
-  class While;
+  class ForRule;
+  class EachRule;
+  class WhileRule;
   class Return;
   class Content;
   class ExtendRule;
@@ -85,10 +89,10 @@
 
   class Media_Query;
   class Media_Query_Expression;
-  class Supports_Condition;
-  class Supports_Operator;
-  class Supports_Negation;
-  class Supports_Declaration;
+  class SupportsCondition;
+  class SupportsOperation;
+  class SupportsNegation;
+  class SupportsDeclaration;
   class Supports_Interpolation;
   
   class At_Root_Query;
@@ -100,13 +104,13 @@
 
 
   class Selector_Schema;
-  class Placeholder_Selector;
-  class Type_Selector;
-  class Class_Selector;
-  class Id_Selector;
-  class Attribute_Selector;
+  class PlaceholderSelector;
+  class TypeSelector;
+  class ClassSelector;
+  class IDSelector;
+  class AttributeSelector;
 
-  class Pseudo_Selector;
+  class PseudoSelector;
   
   class SelectorComponent;
   class SelectorCombinator;
@@ -128,33 +132,38 @@
     typedef SharedImpl<type> type##Obj; \
     typedef SharedImpl<type> type##_Obj; \
 
+  IMPL_MEM_OBJ(SourceData);
+  IMPL_MEM_OBJ(SourceFile);
+  IMPL_MEM_OBJ(SynthFile);
+  IMPL_MEM_OBJ(ItplFile);
+
   IMPL_MEM_OBJ(AST_Node);
   IMPL_MEM_OBJ(Statement);
   IMPL_MEM_OBJ(Block);
-  IMPL_MEM_OBJ(Ruleset);
+  IMPL_MEM_OBJ(StyleRule);
   IMPL_MEM_OBJ(Bubble);
   IMPL_MEM_OBJ(Trace);
   IMPL_MEM_OBJ(MediaRule);
   IMPL_MEM_OBJ(CssMediaRule);
   IMPL_MEM_OBJ(CssMediaQuery);
-  IMPL_MEM_OBJ(Supports_Block);
-  IMPL_MEM_OBJ(Directive);
+  IMPL_MEM_OBJ(SupportsRule);
+  IMPL_MEM_OBJ(AtRule);
   IMPL_MEM_OBJ(Keyframe_Rule);
-  IMPL_MEM_OBJ(At_Root_Block);
+  IMPL_MEM_OBJ(AtRootRule);
   IMPL_MEM_OBJ(Declaration);
   IMPL_MEM_OBJ(Assignment);
   IMPL_MEM_OBJ(Import);
   IMPL_MEM_OBJ(Import_Stub);
-  IMPL_MEM_OBJ(Warning);
-  IMPL_MEM_OBJ(Error);
-  IMPL_MEM_OBJ(Debug);
+  IMPL_MEM_OBJ(WarningRule);
+  IMPL_MEM_OBJ(ErrorRule);
+  IMPL_MEM_OBJ(DebugRule);
   IMPL_MEM_OBJ(Comment);
   IMPL_MEM_OBJ(PreValue);
-  IMPL_MEM_OBJ(Has_Block);
+  IMPL_MEM_OBJ(ParentStatement);
   IMPL_MEM_OBJ(If);
-  IMPL_MEM_OBJ(For);
-  IMPL_MEM_OBJ(Each);
-  IMPL_MEM_OBJ(While);
+  IMPL_MEM_OBJ(ForRule);
+  IMPL_MEM_OBJ(EachRule);
+  IMPL_MEM_OBJ(WhileRule);
   IMPL_MEM_OBJ(Return);
   IMPL_MEM_OBJ(Content);
   IMPL_MEM_OBJ(ExtendRule);
@@ -182,10 +191,10 @@
   IMPL_MEM_OBJ(String_Quoted);
   IMPL_MEM_OBJ(Media_Query);
   IMPL_MEM_OBJ(Media_Query_Expression);
-  IMPL_MEM_OBJ(Supports_Condition);
-  IMPL_MEM_OBJ(Supports_Operator);
-  IMPL_MEM_OBJ(Supports_Negation);
-  IMPL_MEM_OBJ(Supports_Declaration);
+  IMPL_MEM_OBJ(SupportsCondition);
+  IMPL_MEM_OBJ(SupportsOperation);
+  IMPL_MEM_OBJ(SupportsNegation);
+  IMPL_MEM_OBJ(SupportsDeclaration);
   IMPL_MEM_OBJ(Supports_Interpolation);
   IMPL_MEM_OBJ(At_Root_Query);
   IMPL_MEM_OBJ(Null);
@@ -197,12 +206,12 @@
   IMPL_MEM_OBJ(Selector);
   IMPL_MEM_OBJ(Selector_Schema);
   IMPL_MEM_OBJ(SimpleSelector);
-  IMPL_MEM_OBJ(Placeholder_Selector);
-  IMPL_MEM_OBJ(Type_Selector);
-  IMPL_MEM_OBJ(Class_Selector);
-  IMPL_MEM_OBJ(Id_Selector);
-  IMPL_MEM_OBJ(Attribute_Selector);
-  IMPL_MEM_OBJ(Pseudo_Selector);
+  IMPL_MEM_OBJ(PlaceholderSelector);
+  IMPL_MEM_OBJ(TypeSelector);
+  IMPL_MEM_OBJ(ClassSelector);
+  IMPL_MEM_OBJ(IDSelector);
+  IMPL_MEM_OBJ(AttributeSelector);
+  IMPL_MEM_OBJ(PseudoSelector);
 
   IMPL_MEM_OBJ(SelectorComponent);
   IMPL_MEM_OBJ(SelectorCombinator);
@@ -214,12 +223,12 @@
   // some often used typedefs
   // ###########################################################################
 
-  typedef std::vector<Block*> BlockStack;
-  typedef std::vector<Sass_Callee> CalleeStack;
-  typedef std::vector<AST_Node_Obj> CallStack;
-  typedef std::vector<CssMediaRuleObj> MediaStack;
-  typedef std::vector<SelectorListObj> SelectorStack;
-  typedef std::vector<Sass_Import_Entry> ImporterStack;
+  typedef sass::vector<Block*> BlockStack;
+  typedef sass::vector<Sass_Callee> CalleeStack;
+  typedef sass::vector<AST_Node_Obj> CallStack;
+  typedef sass::vector<CssMediaRuleObj> MediaStack;
+  typedef sass::vector<SelectorListObj> SelectorStack;
+  typedef sass::vector<Sass_Import_Entry> ImporterStack;
 
   // only to switch implementations for testing
   #define environment_map std::map
@@ -248,14 +257,14 @@
   DECLARE_BASE_CAST(AST_Node)
   DECLARE_BASE_CAST(Expression)
   DECLARE_BASE_CAST(Statement)
-  DECLARE_BASE_CAST(Has_Block)
+  DECLARE_BASE_CAST(ParentStatement)
   DECLARE_BASE_CAST(PreValue)
   DECLARE_BASE_CAST(Value)
   DECLARE_BASE_CAST(List)
   DECLARE_BASE_CAST(Color)
   DECLARE_BASE_CAST(String)
   DECLARE_BASE_CAST(String_Constant)
-  DECLARE_BASE_CAST(Supports_Condition)
+  DECLARE_BASE_CAST(SupportsCondition)
   DECLARE_BASE_CAST(Selector)
   DECLARE_BASE_CAST(SimpleSelector)
   DECLARE_BASE_CAST(SelectorComponent)
diff --git a/libsass/src/ast_helpers.hpp b/libsass/src/ast_helpers.hpp
--- a/libsass/src/ast_helpers.hpp
+++ b/libsass/src/ast_helpers.hpp
@@ -228,7 +228,7 @@
   // that can be written with pseudo-class syntax (CSS2 vs CSS3):
   // `:before`, `:after`, `:first-line`, or `:first-letter`
   // ##########################################################################
-  inline bool isFakePseudoElement(const std::string& name)
+  inline bool isFakePseudoElement(const sass::string& name)
   {
     return Util::equalsLiteral("after", name)
       || Util::equalsLiteral("before", name)
@@ -241,7 +241,7 @@
   // and that are subselectors of their arguments.
   // For example, `.foo` is a superselector of `:matches(.foo)`.
   // ##########################################################################
-  inline bool isSubselectorPseudo(const std::string& norm)
+  inline bool isSubselectorPseudo(const sass::string& norm)
   {
     return Util::equalsLiteral("any", norm)
       || Util::equalsLiteral("matches", norm)
@@ -253,7 +253,7 @@
   // ###########################################################################
   // Pseudo-class selectors that take unadorned selectors as arguments.
   // ###########################################################################
-  inline bool isSelectorPseudoClass(const std::string& test)
+  inline bool isSelectorPseudoClass(const sass::string& test)
   {
     return Util::equalsLiteral("not", test)
       || Util::equalsLiteral("matches", test)
@@ -268,7 +268,7 @@
   // ###########################################################################
   // Pseudo-element selectors that take unadorned selectors as arguments.
   // ###########################################################################
-  inline bool isSelectorPseudoElement(const std::string& test)
+  inline bool isSelectorPseudoElement(const sass::string& test)
   {
     return Util::equalsLiteral("slotted", test);
   }
@@ -277,7 +277,7 @@
   // ###########################################################################
   // Pseudo-element selectors that has binominals
   // ###########################################################################
-  inline bool isSelectorPseudoBinominal(const std::string& test)
+  inline bool isSelectorPseudoBinominal(const sass::string& test)
   {
     return Util::equalsLiteral("nth-child", test)
       || Util::equalsLiteral("nth-last-child", test);
diff --git a/libsass/src/ast_sel_cmp.cpp b/libsass/src/ast_sel_cmp.cpp
--- a/libsass/src/ast_sel_cmp.cpp
+++ b/libsass/src/ast_sel_cmp.cpp
@@ -299,69 +299,69 @@
   /*#########################################################################*/
   /*#########################################################################*/
 
-  bool Id_Selector::operator== (const SimpleSelector& rhs) const
+  bool IDSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Id_Selector>(&rhs);
+    auto sel = Cast<IDSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
-  bool Type_Selector::operator== (const SimpleSelector& rhs) const
+  bool TypeSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Type_Selector>(&rhs);
+    auto sel = Cast<TypeSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
-  bool Class_Selector::operator== (const SimpleSelector& rhs) const
+  bool ClassSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Class_Selector>(&rhs);
+    auto sel = Cast<ClassSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
-  bool Pseudo_Selector::operator== (const SimpleSelector& rhs) const
+  bool PseudoSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Pseudo_Selector>(&rhs);
+    auto sel = Cast<PseudoSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
-  bool Attribute_Selector::operator== (const SimpleSelector& rhs) const
+  bool AttributeSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Attribute_Selector>(&rhs);
+    auto sel = Cast<AttributeSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
-  bool Placeholder_Selector::operator== (const SimpleSelector& rhs) const
+  bool PlaceholderSelector::operator== (const SimpleSelector& rhs) const
   {
-    auto sel = Cast<Placeholder_Selector>(&rhs);
+    auto sel = Cast<PlaceholderSelector>(&rhs);
     return sel ? *this == *sel : false;
   }
 
   /*#########################################################################*/
   /*#########################################################################*/
 
-  bool Id_Selector::operator== (const Id_Selector& rhs) const
+  bool IDSelector::operator== (const IDSelector& rhs) const
   {
     // ID has no namespacing
     return name() == rhs.name();
   }
 
-  bool Type_Selector::operator== (const Type_Selector& rhs) const
+  bool TypeSelector::operator== (const TypeSelector& rhs) const
   {
     return is_ns_eq(rhs) && name() == rhs.name();
   }
 
-  bool Class_Selector::operator== (const Class_Selector& rhs) const
+  bool ClassSelector::operator== (const ClassSelector& rhs) const
   {
     // Class has no namespacing
     return name() == rhs.name();
   }
 
-  bool Placeholder_Selector::operator== (const Placeholder_Selector& rhs) const
+  bool PlaceholderSelector::operator== (const PlaceholderSelector& rhs) const
   {
     // Placeholder has no namespacing
     return name() == rhs.name();
   }
 
-  bool Attribute_Selector::operator== (const Attribute_Selector& rhs) const
+  bool AttributeSelector::operator== (const AttributeSelector& rhs) const
   {
     // smaller return, equal go on, bigger abort
     if (is_ns_eq(rhs)) {
@@ -375,7 +375,7 @@
     else { return false; }
   }
 
-  bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
+  bool PseudoSelector::operator== (const PseudoSelector& rhs) const
   {
     if (is_ns_eq(rhs)) {
       if (name() != rhs.name()) return false;
diff --git a/libsass/src/ast_sel_super.cpp b/libsass/src/ast_sel_super.cpp
--- a/libsass/src/ast_sel_super.cpp
+++ b/libsass/src/ast_sel_super.cpp
@@ -19,8 +19,8 @@
   // [list2] matches, as well as possibly additional elements.
   // ##########################################################################
   bool listIsSuperslector(
-    const std::vector<ComplexSelectorObj>& list1,
-    const std::vector<ComplexSelectorObj>& list2);
+    const sass::vector<ComplexSelectorObj>& list1,
+    const sass::vector<ComplexSelectorObj>& list2);
 
   // ##########################################################################
   // Returns whether [complex1] is a superselector of [complex2].
@@ -28,19 +28,19 @@
   // [complex2] matches, as well as possibly additional elements.
   // ##########################################################################
   bool complexIsSuperselector(
-    const std::vector<SelectorComponentObj>& complex1,
-    const std::vector<SelectorComponentObj>& complex2);
+    const sass::vector<SelectorComponentObj>& complex1,
+    const sass::vector<SelectorComponentObj>& complex2);
 
   // ##########################################################################
   // Returns all pseudo selectors in [compound] that have
   // a selector argument, and that have the given [name].
   // ##########################################################################
-  std::vector<Pseudo_Selector_Obj> selectorPseudoNamed(
-    CompoundSelectorObj compound, std::string name)
+  sass::vector<PseudoSelectorObj> selectorPseudoNamed(
+    CompoundSelectorObj compound, sass::string name)
   {
-    std::vector<Pseudo_Selector_Obj> rv;
+    sass::vector<PseudoSelectorObj> rv;
     for (SimpleSelectorObj sel : compound->elements()) {
-      if (Pseudo_Selector_Obj pseudo = Cast<Pseudo_Selector>(sel)) {
+      if (PseudoSelectorObj pseudo = Cast<PseudoSelector>(sel)) {
         if (pseudo->isClass() && pseudo->selector()) {
           if (sel->name() == name) {
             rv.push_back(sel);
@@ -66,7 +66,7 @@
       return true;
     }
     // Some selector pseudoclasses can match normal selectors.
-    if (const Pseudo_Selector* pseudo = Cast<Pseudo_Selector>(simple2)) {
+    if (const PseudoSelector* pseudo = Cast<PseudoSelector>(simple2)) {
       if (pseudo->selector() && isSubselectorPseudo(pseudo->normalized())) {
         for (auto complex : pseudo->selector()->elements()) {
           // Make sure we have exacly one items
@@ -109,11 +109,11 @@
   // ##########################################################################
   // ##########################################################################
   bool typeIsSuperselectorOfCompound(
-    const Type_Selector_Obj& type,
+    const TypeSelectorObj& type,
     const CompoundSelectorObj& compound)
   {
     for (const SimpleSelectorObj& simple : compound->elements()) {
-      if (const Type_Selector_Obj& rhs = Cast<Type_Selector>(simple)) {
+      if (const TypeSelectorObj& rhs = Cast<TypeSelector>(simple)) {
         if (*type != *rhs) return true;
       }
     }
@@ -124,11 +124,11 @@
   // ##########################################################################
   // ##########################################################################
   bool idIsSuperselectorOfCompound(
-    const Id_Selector_Obj& id,
+    const IDSelectorObj& id,
     const CompoundSelectorObj& compound)
   {
     for (const SimpleSelectorObj& simple : compound->elements()) {
-      if (const Id_Selector_Obj& rhs = Cast<Id_Selector>(simple)) {
+      if (const IDSelectorObj& rhs = Cast<IDSelector>(simple)) {
         if (*id != *rhs) return true;
       }
     }
@@ -139,8 +139,8 @@
   // ##########################################################################
   // ##########################################################################
   bool pseudoIsSuperselectorOfPseudo(
-    const Pseudo_Selector_Obj& pseudo1,
-    const Pseudo_Selector_Obj& pseudo2,
+    const PseudoSelectorObj& pseudo1,
+    const PseudoSelectorObj& pseudo2,
     const ComplexSelectorObj& parent
   )
   {
@@ -156,22 +156,22 @@
   // ##########################################################################
   // ##########################################################################
   bool pseudoNotIsSuperselectorOfCompound(
-    const Pseudo_Selector_Obj& pseudo1,
+    const PseudoSelectorObj& pseudo1,
     const CompoundSelectorObj& compound2,
     const ComplexSelectorObj& parent)
   {
     for (const SimpleSelectorObj& simple2 : compound2->elements()) {
-      if (const Type_Selector_Obj& type2 = Cast<Type_Selector>(simple2)) {
+      if (const TypeSelectorObj& type2 = Cast<TypeSelector>(simple2)) {
         if (const CompoundSelectorObj& compound1 = Cast<CompoundSelector>(parent->last())) {
           if (typeIsSuperselectorOfCompound(type2, compound1)) return true;
         }
       }
-      else if (const Id_Selector_Obj& id2 = Cast<Id_Selector>(simple2)) {
+      else if (const IDSelectorObj& id2 = Cast<IDSelector>(simple2)) {
         if (const CompoundSelectorObj& compound1 = Cast<CompoundSelector>(parent->last())) {
           if (idIsSuperselectorOfCompound(id2, compound1)) return true;
         }
       }
-      else if (const Pseudo_Selector_Obj& pseudo2 = Cast<Pseudo_Selector>(simple2)) {
+      else if (const PseudoSelectorObj& pseudo2 = Cast<PseudoSelector>(simple2)) {
         if (pseudoIsSuperselectorOfPseudo(pseudo1, pseudo2, parent)) return true;
       }
     }
@@ -189,21 +189,21 @@
   // parent selectors in the selector argument match [parents].
   // ##########################################################################
   bool selectorPseudoIsSuperselector(
-    const Pseudo_Selector_Obj& pseudo1,
+    const PseudoSelectorObj& pseudo1,
     const CompoundSelectorObj& compound2,
     // ToDo: is this really the most convenient way to do this?
-    std::vector<SelectorComponentObj>::const_iterator parents_from,
-    std::vector<SelectorComponentObj>::const_iterator parents_to)
+    sass::vector<SelectorComponentObj>::const_iterator parents_from,
+    sass::vector<SelectorComponentObj>::const_iterator parents_to)
   {
 
     // ToDo: move normalization function
-    std::string name(Util::unvendor(pseudo1->name()));
+    sass::string name(Util::unvendor(pseudo1->name()));
 
     if (name == "matches" || name == "any") {
-      std::vector<Pseudo_Selector_Obj> pseudos =
+      sass::vector<PseudoSelectorObj> pseudos =
         selectorPseudoNamed(compound2, pseudo1->name());
       SelectorListObj selector1 = pseudo1->selector();
-      for (Pseudo_Selector_Obj pseudo2 : pseudos) {
+      for (PseudoSelectorObj pseudo2 : pseudos) {
         SelectorListObj selector = pseudo2->selector();
         if (selector1->isSuperselectorOf(selector)) {
           return true;
@@ -211,7 +211,7 @@
       }
 
       for (ComplexSelectorObj complex1 : selector1->elements()) {
-        std::vector<SelectorComponentObj> parents;
+        sass::vector<SelectorComponentObj> parents;
         for (auto cur = parents_from; cur != parents_to; cur++) {
           parents.push_back(*cur);
         }
@@ -223,10 +223,10 @@
 
     }
     else if (name == "has" || name == "host" || name == "host-context" || name == "slotted") {
-      std::vector<Pseudo_Selector_Obj> pseudos =
+      sass::vector<PseudoSelectorObj> pseudos =
         selectorPseudoNamed(compound2, pseudo1->name());
       SelectorListObj selector1 = pseudo1->selector();
-      for (Pseudo_Selector_Obj pseudo2 : pseudos) {
+      for (PseudoSelectorObj pseudo2 : pseudos) {
         SelectorListObj selector = pseudo2->selector();
         if (selector1->isSuperselectorOf(selector)) {
           return true;
@@ -241,16 +241,16 @@
       return true;
     }
     else if (name == "current") {
-      std::vector<Pseudo_Selector_Obj> pseudos =
+      sass::vector<PseudoSelectorObj> pseudos =
         selectorPseudoNamed(compound2, "current");
-      for (Pseudo_Selector_Obj pseudo2 : pseudos) {
+      for (PseudoSelectorObj pseudo2 : pseudos) {
         if (ObjEqualityFn(pseudo1, pseudo2)) return true;
       }
 
     }
     else if (name == "nth-child" || name == "nth-last-child") {
       for (auto simple2 : compound2->elements()) {
-        if (Pseudo_Selector_Obj pseudo2 = simple2->getPseudoSelector()) {
+        if (PseudoSelectorObj pseudo2 = simple2->getPseudoSelector()) {
           if (pseudo1->name() != pseudo2->name()) continue;
           if (!ObjEqualityFn(pseudo1->argument(), pseudo2->argument())) continue;
           if (pseudo1->selector()->isSuperselectorOf(pseudo2->selector())) return true;
@@ -276,13 +276,13 @@
     const CompoundSelectorObj& compound1,
     const CompoundSelectorObj& compound2,
     // ToDo: is this really the most convenient way to do this?
-    const std::vector<SelectorComponentObj>::const_iterator parents_from,
-    const std::vector<SelectorComponentObj>::const_iterator parents_to)
+    const sass::vector<SelectorComponentObj>::const_iterator parents_from,
+    const sass::vector<SelectorComponentObj>::const_iterator parents_to)
   {
     // Every selector in [compound1.components] must have
     // a matching selector in [compound2.components].
     for (SimpleSelectorObj simple1 : compound1->elements()) {
-      Pseudo_Selector_Obj pseudo1 = Cast<Pseudo_Selector>(simple1);
+      PseudoSelectorObj pseudo1 = Cast<PseudoSelector>(simple1);
       if (pseudo1 && pseudo1->selector()) {
         if (!selectorPseudoIsSuperselector(pseudo1, compound2, parents_from, parents_to)) {
           return false;
@@ -295,7 +295,7 @@
     // [compound1] can't be a superselector of a selector
     // with pseudo-elements that [compound2] doesn't share.
     for (SimpleSelectorObj simple2 : compound2->elements()) {
-      Pseudo_Selector_Obj pseudo2 = Cast<Pseudo_Selector>(simple2);
+      PseudoSelectorObj pseudo2 = Cast<PseudoSelector>(simple2);
       if (pseudo2 && pseudo2->isElement()) {
         if (!simpleIsSuperselectorOfCompound(pseudo2, compound1)) {
           return false;
@@ -317,7 +317,7 @@
   bool compoundIsSuperselector(
     const CompoundSelectorObj& compound1,
     const CompoundSelectorObj& compound2,
-    const std::vector<SelectorComponentObj>& parents)
+    const sass::vector<SelectorComponentObj>& parents)
   {
     return compoundIsSuperselector(
       compound1, compound2,
@@ -332,8 +332,8 @@
   // [complex2] matches, as well as possibly additional elements.
   // ##########################################################################
   bool complexIsSuperselector(
-    const std::vector<SelectorComponentObj>& complex1,
-    const std::vector<SelectorComponentObj>& complex2)
+    const sass::vector<SelectorComponentObj>& complex1,
+    const sass::vector<SelectorComponentObj>& complex2)
   {
 
     // Selectors with trailing operators are neither superselectors nor subselectors.
@@ -368,14 +368,14 @@
       CompoundSelectorObj compound2 = Cast<CompoundSelector>(complex2.back());
 
       if (remaining1 == 1) {
-        std::vector<SelectorComponentObj>::const_iterator parents_to = complex2.end();
-        std::vector<SelectorComponentObj>::const_iterator parents_from = complex2.begin();
+        sass::vector<SelectorComponentObj>::const_iterator parents_to = complex2.end();
+        sass::vector<SelectorComponentObj>::const_iterator parents_from = complex2.begin();
         std::advance(parents_from, i2 + 1); // equivalent to dart `.skip(i2 + 1)`
         bool rv = compoundIsSuperselector(compound1, compound2, parents_from, parents_to);
-        std::vector<SelectorComponentObj> pp;
+        sass::vector<SelectorComponentObj> pp;
 
-        std::vector<SelectorComponentObj>::const_iterator end = parents_to;
-        std::vector<SelectorComponentObj>::const_iterator beg = parents_from;
+        sass::vector<SelectorComponentObj>::const_iterator end = parents_to;
+        sass::vector<SelectorComponentObj>::const_iterator beg = parents_from;
         while (beg != end) {
           pp.push_back(*beg);
           beg++;
@@ -393,8 +393,8 @@
       for (; afterSuperselector < complex2.size(); afterSuperselector++) {
         SelectorComponentObj component2 = complex2[afterSuperselector - 1];
         if (CompoundSelectorObj compound2 = Cast<CompoundSelector>(component2)) {
-          std::vector<SelectorComponentObj>::const_iterator parents_to = complex2.begin();
-          std::vector<SelectorComponentObj>::const_iterator parents_from = complex2.begin();
+          sass::vector<SelectorComponentObj>::const_iterator parents_to = complex2.begin();
+          sass::vector<SelectorComponentObj>::const_iterator parents_from = complex2.begin();
           // complex2.take(afterSuperselector - 1).skip(i2 + 1)
           std::advance(parents_from, i2 + 1); // equivalent to dart `.skip`
           std::advance(parents_to, afterSuperselector); // equivalent to dart `.take`
@@ -464,8 +464,8 @@
   // since `B X` is a superselector of `B A X`.
   // ##########################################################################
   bool complexIsParentSuperselector(
-    const std::vector<SelectorComponentObj>& complex1,
-    const std::vector<SelectorComponentObj>& complex2)
+    const sass::vector<SelectorComponentObj>& complex1,
+    const sass::vector<SelectorComponentObj>& complex2)
   {
     // Try some simple heuristics to see if we can avoid allocations.
     if (complex1.empty() && complex2.empty()) return false;
@@ -473,8 +473,8 @@
     if (Cast<SelectorCombinator>(complex2.front())) return false;
     if (complex1.size() > complex2.size()) return false;
     // TODO(nweiz): There's got to be a way to do this without a bunch of extra allocations...
-    std::vector<SelectorComponentObj> cplx1(complex1);
-    std::vector<SelectorComponentObj> cplx2(complex2);
+    sass::vector<SelectorComponentObj> cplx1(complex1);
+    sass::vector<SelectorComponentObj> cplx2(complex2);
     CompoundSelectorObj base = SASS_MEMORY_NEW(CompoundSelector, "[tmp]");
     cplx1.push_back(base); cplx2.push_back(base);
     return complexIsSuperselector(cplx1, cplx2);
@@ -487,7 +487,7 @@
   // [complex] matches, as well as possibly additional elements.
   // ##########################################################################
   bool listHasSuperslectorForComplex(
-    std::vector<ComplexSelectorObj> list,
+    sass::vector<ComplexSelectorObj> list,
     ComplexSelectorObj complex)
   {
     // Return true if every [complex] selector on [list2]
@@ -507,8 +507,8 @@
   // [list2] matches, as well as possibly additional elements.
   // ##########################################################################
   bool listIsSuperslector(
-    const std::vector<ComplexSelectorObj>& list1,
-    const std::vector<ComplexSelectorObj>& list2)
+    const sass::vector<ComplexSelectorObj>& list1,
+    const sass::vector<ComplexSelectorObj>& list2)
   {
     // Return true if every [complex] selector on [list2]
     // is a super selector of the full selector [list1].
diff --git a/libsass/src/ast_sel_unify.cpp b/libsass/src/ast_sel_unify.cpp
--- a/libsass/src/ast_sel_unify.cpp
+++ b/libsass/src/ast_sel_unify.cpp
@@ -13,14 +13,14 @@
   // ##########################################################################
   // ToDo: fine-tune API to avoid unnecessary wrapper allocations
   // ##########################################################################
-  std::vector<std::vector<SelectorComponentObj>> unifyComplex(
-    const std::vector<std::vector<SelectorComponentObj>>& complexes)
+  sass::vector<sass::vector<SelectorComponentObj>> unifyComplex(
+    const sass::vector<sass::vector<SelectorComponentObj>>& complexes)
   {
 
     SASS_ASSERT(!complexes.empty(), "Can't unify empty list");
     if (complexes.size() == 1) return complexes;
 
-    CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, ParserState("[phony]"));
+    CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, SourceSpan("[phony]"));
     for (auto complex : complexes) {
       SelectorComponentObj base = complex.back();
       if (CompoundSelector * comp = base->getCompound()) {
@@ -39,9 +39,9 @@
       }
     }
 
-    std::vector<std::vector<SelectorComponentObj>> complexesWithoutBases;
+    sass::vector<sass::vector<SelectorComponentObj>> complexesWithoutBases;
     for (size_t i = 0; i < complexes.size(); i += 1) {
-      std::vector<SelectorComponentObj> sel = complexes[i];
+      sass::vector<SelectorComponentObj> sel = complexes[i];
       sel.pop_back(); // remove last item (base) from the list
       complexesWithoutBases.push_back(std::move(sel));
     }
@@ -120,13 +120,13 @@
   // ##########################################################################
   // This is implemented in `selector/type.dart` as `PseudoSelector::unify`
   // ##########################################################################
-  CompoundSelector* Type_Selector::unifyWith(CompoundSelector* rhs)
+  CompoundSelector* TypeSelector::unifyWith(CompoundSelector* rhs)
   {
     if (rhs->empty()) {
       rhs->append(this);
       return rhs;
     }
-    Type_Selector* type = Cast<Type_Selector>(rhs->at(0));
+    TypeSelector* type = Cast<TypeSelector>(rhs->at(0));
     if (type != nullptr) {
       SimpleSelector* unified = unifyWith(type);
       if (unified == nullptr) {
@@ -143,10 +143,10 @@
   // ##########################################################################
   // This is implemented in `selector/id.dart` as `PseudoSelector::unify`
   // ##########################################################################
-  CompoundSelector* Id_Selector::unifyWith(CompoundSelector* rhs)
+  CompoundSelector* IDSelector::unifyWith(CompoundSelector* rhs)
   {
     for (const SimpleSelector* sel : rhs->elements()) {
-      if (const Id_Selector* id_sel = Cast<Id_Selector>(sel)) {
+      if (const IDSelector* id_sel = Cast<IDSelector>(sel)) {
         if (id_sel->name() != name()) return nullptr;
       }
     }
@@ -156,7 +156,7 @@
   // ##########################################################################
   // This is implemented in `selector/pseudo.dart` as `PseudoSelector::unify`
   // ##########################################################################
-  CompoundSelector* Pseudo_Selector::unifyWith(CompoundSelector* compound)
+  CompoundSelector* PseudoSelector::unifyWith(CompoundSelector* compound)
   {
 
     if (compound->length() == 1 && compound->first()->is_universal()) {
@@ -174,7 +174,7 @@
     bool addedThis = false;
     for (auto simple : compound->elements()) {
       // Make sure pseudo selectors always come last.
-      if (Pseudo_Selector_Obj pseudo = simple->getPseudoSelector()) {
+      if (PseudoSelectorObj pseudo = simple->getPseudoSelector()) {
         if (pseudo->isElement()) {
           // A given compound selector may only contain one pseudo element. If
           // [compound] has a different one than [this], unification fails.
@@ -197,7 +197,7 @@
     return result.detach();
 
   }
-  // EO Pseudo_Selector::unifyWith(CompoundSelector*
+  // EO PseudoSelector::unifyWith(CompoundSelector*
 
   // ##########################################################################
   // This is implemented in `extend/functions.dart` as `unifyUniversalAndElement`
@@ -206,7 +206,7 @@
   // or [TypeSelector]s. If no such selector can be produced, returns `null`.
   // Note: libsass handles universal selector directly within the type selector
   // ##########################################################################
-  SimpleSelector* Type_Selector::unifyWith(const SimpleSelector* rhs)
+  SimpleSelector* TypeSelector::unifyWith(const SimpleSelector* rhs)
   {
     bool rhs_ns = false;
     if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
@@ -229,7 +229,7 @@
     if (rhs_name) name(rhs->name());
     return this;
   }
-  // EO Type_Selector::unifyWith(const SimpleSelector*)
+  // EO TypeSelector::unifyWith(const SimpleSelector*)
 
   // ##########################################################################
   // Unify two complex selectors. Internally calls `unifyComplex`
@@ -238,9 +238,9 @@
   SelectorList* ComplexSelector::unifyWith(ComplexSelector* rhs)
   {
     SelectorListObj list = SASS_MEMORY_NEW(SelectorList, pstate());
-    std::vector<std::vector<SelectorComponentObj>> rv =
+    sass::vector<sass::vector<SelectorComponentObj>> rv =
        unifyComplex({ elements(), rhs->elements() });
-    for (std::vector<SelectorComponentObj> items : rv) {
+    for (sass::vector<SelectorComponentObj> items : rv) {
       ComplexSelectorObj sel = SASS_MEMORY_NEW(ComplexSelector, pstate());
       sel->elements() = std::move(items);
       list->append(sel);
diff --git a/libsass/src/ast_sel_weave.cpp b/libsass/src/ast_sel_weave.cpp
--- a/libsass/src/ast_sel_weave.cpp
+++ b/libsass/src/ast_sel_weave.cpp
@@ -24,8 +24,8 @@
   // ##########################################################################
   bool isUnique(const SimpleSelector* simple)
   {
-    if (Cast<Id_Selector>(simple)) return true;
-    if (const Pseudo_Selector * pseudo = Cast<Pseudo_Selector>(simple)) {
+    if (Cast<IDSelector>(simple)) return true;
+    if (const PseudoSelector * pseudo = Cast<PseudoSelector>(simple)) {
       if (pseudo->is_pseudo_element()) return true;
     }
     return false;
@@ -38,11 +38,11 @@
   // selectors contain the same unique simple selector, such as an ID.
   // ##########################################################################
   bool mustUnify(
-    const std::vector<SelectorComponentObj>& complex1,
-    const std::vector<SelectorComponentObj>& complex2)
+    const sass::vector<SelectorComponentObj>& complex1,
+    const sass::vector<SelectorComponentObj>& complex2)
   {
 
-    std::vector<const SimpleSelector*> uniqueSelectors1;
+    sass::vector<const SimpleSelector*> uniqueSelectors1;
     for (const SelectorComponent* component : complex1) {
       if (const CompoundSelector * compound = component->getCompound()) {
         for (const SimpleSelector* sel : compound->elements()) {
@@ -76,9 +76,9 @@
   // Helper function used by `weaveParents`
   // ##########################################################################
   bool cmpGroups(
-    const std::vector<SelectorComponentObj>& group1,
-    const std::vector<SelectorComponentObj>& group2,
-    std::vector<SelectorComponentObj>& select)
+    const sass::vector<SelectorComponentObj>& group1,
+    const sass::vector<SelectorComponentObj>& group2,
+    sass::vector<SelectorComponentObj>& select)
   {
 
     if (group1.size() == group2.size() && std::equal(group1.begin(), group1.end(), group2.begin(), PtrObjEqualityFn<SelectorComponent>)) {
@@ -109,7 +109,7 @@
       return false;
     }
 
-    std::vector<std::vector<SelectorComponentObj>> unified
+    sass::vector<sass::vector<SelectorComponentObj>> unified
       = unifyComplex({ group1, group2 });
     if (unified.empty()) return false;
     if (unified.size() > 1) return false;
@@ -131,8 +131,8 @@
   // Helper function used by `weaveParents`
   // ##########################################################################
   bool cmpChunkForEmptySequence(
-    const std::vector<std::vector<SelectorComponentObj>>& seq,
-    const std::vector<SelectorComponentObj>& group)
+    const sass::vector<sass::vector<SelectorComponentObj>>& seq,
+    const sass::vector<SelectorComponentObj>& group)
   {
     return seq.empty();
   }
@@ -142,8 +142,8 @@
   // Helper function used by `weaveParents`
   // ##########################################################################
   bool cmpChunkForParentSuperselector(
-    const std::vector< std::vector<SelectorComponentObj>>& seq,
-    const std::vector<SelectorComponentObj>& group)
+    const sass::vector<sass::vector<SelectorComponentObj>>& seq,
+    const sass::vector<SelectorComponentObj>& group)
   {
     return seq.empty() || complexIsParentSuperselector(seq.front(), group);
   }
@@ -159,18 +159,18 @@
   // (1 2 A B C)]`. The queues would then contain `(D E)` and `(3 4 5)`.
   // ##########################################################################
   template <class T>
-  std::vector<std::vector<T>> getChunks(
-    std::vector<T>& queue1, std::vector<T>& queue2,
-    const T& group, bool(*done)(const std::vector<T>&, const T&)
+  sass::vector<sass::vector<T>> getChunks(
+    sass::vector<T>& queue1, sass::vector<T>& queue2,
+    const T& group, bool(*done)(const sass::vector<T>&, const T&)
   ) {
 
-    std::vector<T> chunk1;
+    sass::vector<T> chunk1;
     while (!done(queue1, group)) {
       chunk1.push_back(queue1.front());
       queue1.erase(queue1.begin());
     }
 
-    std::vector<T> chunk2;
+    sass::vector<T> chunk2;
     while (!done(queue2, group)) {
       chunk2.push_back(queue2.front());
       queue2.erase(queue2.begin());
@@ -180,7 +180,7 @@
     else if (chunk1.empty()) return { chunk2 };
     else if (chunk2.empty()) return { chunk1 };
 
-    std::vector<T> choice1(chunk1), choice2(chunk2);
+    sass::vector<T> choice1(chunk1), choice2(chunk2);
     std::move(std::begin(chunk2), std::end(chunk2),
       std::inserter(choice1, std::end(choice1)));
     std::move(std::begin(chunk1), std::end(chunk1),
@@ -193,7 +193,7 @@
   // If the first element of [queue] has a `::root` 
   // selector, removes and returns that element.
   // ##########################################################################
-  CompoundSelectorObj getFirstIfRoot(std::vector<SelectorComponentObj>& queue) {
+  CompoundSelectorObj getFirstIfRoot(sass::vector<SelectorComponentObj>& queue) {
     if (queue.empty()) return {};
     SelectorComponent* first = queue.front();
     if (CompoundSelector* sel = Cast<CompoundSelector>(first)) {
@@ -210,12 +210,12 @@
   // contains two adjacent [ComplexSelector]s. For example,
   // `(A B > C D + E ~ > G)` is grouped into `[(A) (B > C) (D + E ~ > G)]`.
   // ##########################################################################
-  std::vector<std::vector<SelectorComponentObj>> groupSelectors(
-    const std::vector<SelectorComponentObj>& components)
+  sass::vector<sass::vector<SelectorComponentObj>> groupSelectors(
+    const sass::vector<SelectorComponentObj>& components)
   {
     bool lastWasCompound = false;
-    std::vector<SelectorComponentObj> group;
-    std::vector<std::vector<SelectorComponentObj>> groups;
+    sass::vector<SelectorComponentObj> group;
+    sass::vector<sass::vector<SelectorComponentObj>> groups;
     for (size_t i = 0; i < components.size(); i += 1) {
       if (CompoundSelector* compound = components[i]->getCompound()) {
         if (lastWasCompound) {
@@ -244,19 +244,19 @@
   // If the combinators can't be merged, returns `null`.
   // ##########################################################################
   bool mergeInitialCombinators(
-    std::vector<SelectorComponentObj>& components1,
-    std::vector<SelectorComponentObj>& components2,
-    std::vector<SelectorComponentObj>& result)
+    sass::vector<SelectorComponentObj>& components1,
+    sass::vector<SelectorComponentObj>& components2,
+    sass::vector<SelectorComponentObj>& result)
   {
 
-    std::vector<SelectorComponentObj> combinators1;
+    sass::vector<SelectorComponentObj> combinators1;
     while (!components1.empty() && Cast<SelectorCombinator>(components1.front())) {
       SelectorCombinatorObj front = Cast<SelectorCombinator>(components1.front());
       components1.erase(components1.begin());
       combinators1.push_back(front);
     }
 
-    std::vector<SelectorComponentObj> combinators2;
+    sass::vector<SelectorComponentObj> combinators2;
     while (!components2.empty() && Cast<SelectorCombinator>(components2.front())) {
       SelectorCombinatorObj front = Cast<SelectorCombinator>(components2.front());
       components2.erase(components2.begin());
@@ -265,7 +265,7 @@
 
     // If neither sequence of combinators is a subsequence
     // of the other, they cannot be merged successfully.
-    std::vector<SelectorComponentObj> LCS = lcs<SelectorComponentObj>(combinators1, combinators2);
+    sass::vector<SelectorComponentObj> LCS = lcs<SelectorComponentObj>(combinators1, combinators2);
 
     if (ListEquality(LCS, combinators1, PtrObjEqualityFn<SelectorComponent>)) {
       result = combinators2;
@@ -288,9 +288,9 @@
   // empty list. If the sequences can't be merged, returns `null`.
   // ##########################################################################
   bool mergeFinalCombinators(
-    std::vector<SelectorComponentObj>& components1,
-    std::vector<SelectorComponentObj>& components2,
-    std::vector<std::vector<std::vector<SelectorComponentObj>>>& result)
+    sass::vector<SelectorComponentObj>& components1,
+    sass::vector<SelectorComponentObj>& components2,
+    sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>& result)
   {
 
     if (components1.empty() || !Cast<SelectorCombinator>(components1.back())) {
@@ -299,14 +299,14 @@
       }
     }
     
-    std::vector<SelectorComponentObj> combinators1;
+    sass::vector<SelectorComponentObj> combinators1;
     while (!components1.empty() && Cast<SelectorCombinator>(components1.back())) {
       SelectorCombinatorObj back = Cast<SelectorCombinator>(components1.back());
       components1.erase(components1.end() - 1);
       combinators1.push_back(back);
     }
 
-    std::vector<SelectorComponentObj> combinators2;
+    sass::vector<SelectorComponentObj> combinators2;
     while (!components2.empty() && Cast<SelectorCombinator>(components2.back())) {
       SelectorCombinatorObj back = Cast<SelectorCombinator>(components2.back());
       components2.erase(components2.end() - 1);
@@ -356,7 +356,7 @@
           result.push_back({ { compound1, combinator1 } });
         }
         else {
-          std::vector<std::vector<SelectorComponentObj>> choices;
+          sass::vector<sass::vector<SelectorComponentObj>> choices;
           choices.push_back({ compound1, combinator1, compound2, combinator2 });
           choices.push_back({ compound2, combinator2, compound1, combinator1 });
           if (CompoundSelector* unified = compound1->unifyWith(compound2)) {
@@ -378,7 +378,7 @@
         }
         else {
           CompoundSelectorObj unified = compound1->unifyWith(compound2);
-          std::vector<std::vector<SelectorComponentObj>> items;
+          sass::vector<sass::vector<SelectorComponentObj>> items;
           
           if (!unified.isNull()) {
             items.push_back({
@@ -463,10 +463,10 @@
   // exponential output for very little gain. The selector `.D (.A .B)`
   // is represented as the list `[[.D], [.A, .B]]`.
   // ##########################################################################
-  std::vector<std::vector<SelectorComponentObj>> weave(
-    const std::vector<std::vector<SelectorComponentObj>>& complexes) {
+  sass::vector<sass::vector<SelectorComponentObj>> weave(
+    const sass::vector<sass::vector<SelectorComponentObj>>& complexes) {
 
-    std::vector<std::vector<SelectorComponentObj>> prefixes;
+    sass::vector<sass::vector<SelectorComponentObj>> prefixes;
 
     prefixes.push_back(complexes.at(0));
 
@@ -475,7 +475,7 @@
       if (complexes[i].empty()) {
         continue;
       }
-      const std::vector<SelectorComponentObj>& complex = complexes[i];
+      const sass::vector<SelectorComponentObj>& complex = complexes[i];
       SelectorComponent* target = complex.back();
       if (complex.size() == 1) {
         for (auto& prefix : prefixes) {
@@ -484,13 +484,13 @@
         continue;
       }
 
-      std::vector<SelectorComponentObj> parents(complex);
+      sass::vector<SelectorComponentObj> parents(complex);
 
       parents.pop_back();
 
-      std::vector<std::vector<SelectorComponentObj>> newPrefixes;
-      for (std::vector<SelectorComponentObj> prefix : prefixes) {
-        std::vector<std::vector<SelectorComponentObj>>
+      sass::vector<sass::vector<SelectorComponentObj>> newPrefixes;
+      for (sass::vector<SelectorComponentObj> prefix : prefixes) {
+        sass::vector<sass::vector<SelectorComponentObj>>
           parentPrefixes = weaveParents(prefix, parents);
         if (parentPrefixes.empty()) continue;
         for (auto& parentPrefix : parentPrefixes) {
@@ -519,13 +519,13 @@
   // elements matched by `A X` and all elements matched by `B X`. Some `AB_i`
   // are elided to reduce the size of the output.
   // ##########################################################################
-  std::vector<std::vector<SelectorComponentObj>> weaveParents(
-    std::vector<SelectorComponentObj> queue1,
-    std::vector<SelectorComponentObj> queue2)
+  sass::vector<sass::vector<SelectorComponentObj>> weaveParents(
+    sass::vector<SelectorComponentObj> queue1,
+    sass::vector<SelectorComponentObj> queue2)
   {
 
-    std::vector<SelectorComponentObj> leads;
-    std::vector<std::vector<std::vector<SelectorComponentObj>>> trails;
+    sass::vector<SelectorComponentObj> leads;
+    sass::vector<sass::vector<sass::vector<SelectorComponentObj>>> trails;
     if (!mergeInitialCombinators(queue1, queue2, leads)) return {};
     if (!mergeFinalCombinators(queue1, queue2, trails)) return {};
     // list comes out in reverse order for performance
@@ -550,27 +550,27 @@
     }
 
     // group into sub-lists so no sub-list contains two adjacent ComplexSelectors.
-    std::vector<std::vector<SelectorComponentObj>> groups1 = groupSelectors(queue1);
-    std::vector<std::vector<SelectorComponentObj>> groups2 = groupSelectors(queue2);
+    sass::vector<sass::vector<SelectorComponentObj>> groups1 = groupSelectors(queue1);
+    sass::vector<sass::vector<SelectorComponentObj>> groups2 = groupSelectors(queue2);
 
     // The main array to store our choices that will be permutated
-    std::vector<std::vector<std::vector<SelectorComponentObj>>> choices;
+    sass::vector<sass::vector<sass::vector<SelectorComponentObj>>> choices;
 
     // append initial combinators
     choices.push_back({ leads });
 
-    std::vector<std::vector<SelectorComponentObj>> LCS =
-      lcs<std::vector<SelectorComponentObj>>(groups1, groups2, cmpGroups);
+    sass::vector<sass::vector<SelectorComponentObj>> LCS =
+      lcs<sass::vector<SelectorComponentObj>>(groups1, groups2, cmpGroups);
 
     for (auto group : LCS) {
 
       // Create junks from groups1 and groups2
-      std::vector<std::vector<std::vector<SelectorComponentObj>>>
-        chunks = getChunks<std::vector<SelectorComponentObj>>(
+      sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>
+        chunks = getChunks<sass::vector<SelectorComponentObj>>(
           groups1, groups2, group, cmpChunkForParentSuperselector);
 
       // Create expanded array by flattening chunks2 inner
-      std::vector<std::vector<SelectorComponentObj>>
+      sass::vector<sass::vector<SelectorComponentObj>>
         expanded = flattenInner(chunks);
 
       // Prepare data structures
@@ -586,8 +586,8 @@
     }
 
     // Create junks from groups1 and groups2
-    std::vector<std::vector<std::vector<SelectorComponentObj>>>
-      chunks = getChunks<std::vector<SelectorComponentObj>>(
+    sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>
+      chunks = getChunks<sass::vector<SelectorComponentObj>>(
         groups1, groups2, {}, cmpChunkForEmptySequence);
 
     // Append chunks with inner arrays flattened
@@ -599,10 +599,10 @@
 
     // move all non empty items to the front, then erase the trailing ones
     choices.erase(std::remove_if(choices.begin(), choices.end(), checkForEmptyChild
-      <std::vector<std::vector<SelectorComponentObj>>>), choices.end());
+      <sass::vector<sass::vector<SelectorComponentObj>>>), choices.end());
 
     // permutate all possible paths through selectors
-    std::vector<std::vector<SelectorComponentObj>>
+    sass::vector<sass::vector<SelectorComponentObj>>
       results = flattenInner(permutate(choices));
 
     return results;
diff --git a/libsass/src/ast_selectors.cpp b/libsass/src/ast_selectors.cpp
--- a/libsass/src/ast_selectors.cpp
+++ b/libsass/src/ast_selectors.cpp
@@ -11,7 +11,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Selector::Selector(ParserState pstate)
+  Selector::Selector(SourceSpan pstate)
   : Expression(pstate),
     hash_(0)
   { concrete_type(SELECTOR); }
@@ -30,7 +30,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Selector_Schema::Selector_Schema(ParserState pstate, String_Obj c)
+  Selector_Schema::Selector_Schema(SourceSpan pstate, String_Obj c)
   : AST_Node(pstate),
     contents_(c),
     connect_parent_(true),
@@ -69,12 +69,12 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  SimpleSelector::SimpleSelector(ParserState pstate, std::string n)
+  SimpleSelector::SimpleSelector(SourceSpan pstate, sass::string n)
   : Selector(pstate), ns_(""), name_(n), has_ns_(false)
   {
     size_t pos = n.find('|');
     // found some namespace
-    if (pos != std::string::npos) {
+    if (pos != sass::string::npos) {
       has_ns_ = true;
       ns_ = n.substr(0, pos);
       name_ = n.substr(pos + 1);
@@ -87,7 +87,7 @@
     has_ns_(ptr->has_ns_)
   { }
 
-  std::string SimpleSelector::ns_name() const
+  sass::string SimpleSelector::ns_name() const
   {
     if (!has_ns_) return name_;
     else return ns_ + "|" + name_;
@@ -174,31 +174,31 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Placeholder_Selector::Placeholder_Selector(ParserState pstate, std::string n)
+  PlaceholderSelector::PlaceholderSelector(SourceSpan pstate, sass::string n)
   : SimpleSelector(pstate, n)
   { simple_type(PLACEHOLDER_SEL); }
-  Placeholder_Selector::Placeholder_Selector(const Placeholder_Selector* ptr)
+  PlaceholderSelector::PlaceholderSelector(const PlaceholderSelector* ptr)
   : SimpleSelector(ptr)
   { simple_type(PLACEHOLDER_SEL); }
-  unsigned long Placeholder_Selector::specificity() const
+  unsigned long PlaceholderSelector::specificity() const
   {
     return Constants::Specificity_Base;
   }
-  bool Placeholder_Selector::has_placeholder() {
+  bool PlaceholderSelector::has_placeholder() {
     return true;
   }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Type_Selector::Type_Selector(ParserState pstate, std::string n)
+  TypeSelector::TypeSelector(SourceSpan pstate, sass::string n)
   : SimpleSelector(pstate, n)
   { simple_type(TYPE_SEL); }
-  Type_Selector::Type_Selector(const Type_Selector* ptr)
+  TypeSelector::TypeSelector(const TypeSelector* ptr)
   : SimpleSelector(ptr)
   { simple_type(TYPE_SEL); }
 
-  unsigned long Type_Selector::specificity() const
+  unsigned long TypeSelector::specificity() const
   {
     if (name() == "*") return 0;
     else return Constants::Specificity_Element;
@@ -207,14 +207,14 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Class_Selector::Class_Selector(ParserState pstate, std::string n)
+  ClassSelector::ClassSelector(SourceSpan pstate, sass::string n)
   : SimpleSelector(pstate, n)
   { simple_type(CLASS_SEL); }
-  Class_Selector::Class_Selector(const Class_Selector* ptr)
+  ClassSelector::ClassSelector(const ClassSelector* ptr)
   : SimpleSelector(ptr)
   { simple_type(CLASS_SEL); }
 
-  unsigned long Class_Selector::specificity() const
+  unsigned long ClassSelector::specificity() const
   {
     return Constants::Specificity_Class;
   }
@@ -222,14 +222,14 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Id_Selector::Id_Selector(ParserState pstate, std::string n)
+  IDSelector::IDSelector(SourceSpan pstate, sass::string n)
   : SimpleSelector(pstate, n)
   { simple_type(ID_SEL); }
-  Id_Selector::Id_Selector(const Id_Selector* ptr)
+  IDSelector::IDSelector(const IDSelector* ptr)
   : SimpleSelector(ptr)
   { simple_type(ID_SEL); }
 
-  unsigned long Id_Selector::specificity() const
+  unsigned long IDSelector::specificity() const
   {
     return Constants::Specificity_ID;
   }
@@ -237,27 +237,27 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Attribute_Selector::Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o)
+  AttributeSelector::AttributeSelector(SourceSpan pstate, sass::string n, sass::string m, String_Obj v, char o)
   : SimpleSelector(pstate, n), matcher_(m), value_(v), modifier_(o)
   { simple_type(ATTRIBUTE_SEL); }
-  Attribute_Selector::Attribute_Selector(const Attribute_Selector* ptr)
+  AttributeSelector::AttributeSelector(const AttributeSelector* ptr)
   : SimpleSelector(ptr),
     matcher_(ptr->matcher_),
     value_(ptr->value_),
     modifier_(ptr->modifier_)
   { simple_type(ATTRIBUTE_SEL); }
 
-  size_t Attribute_Selector::hash() const
+  size_t AttributeSelector::hash() const
   {
     if (hash_ == 0) {
       hash_combine(hash_, SimpleSelector::hash());
-      hash_combine(hash_, std::hash<std::string>()(matcher()));
+      hash_combine(hash_, std::hash<sass::string>()(matcher()));
       if (value_) hash_combine(hash_, value_->hash());
     }
     return hash_;
   }
 
-  unsigned long Attribute_Selector::specificity() const
+  unsigned long AttributeSelector::specificity() const
   {
     return Constants::Specificity_Attr;
   }
@@ -265,7 +265,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Pseudo_Selector::Pseudo_Selector(ParserState pstate, std::string name, bool element)
+  PseudoSelector::PseudoSelector(SourceSpan pstate, sass::string name, bool element)
   : SimpleSelector(pstate, name),
     normalized_(Util::unvendor(name)),
     argument_({}),
@@ -273,7 +273,7 @@
     isSyntacticClass_(!element),
     isClass_(!element && !isFakePseudoElement(normalized_))
   { simple_type(PSEUDO_SEL); }
-  Pseudo_Selector::Pseudo_Selector(const Pseudo_Selector* ptr)
+  PseudoSelector::PseudoSelector(const PseudoSelector* ptr)
   : SimpleSelector(ptr),
     normalized_(ptr->normalized()),
     argument_(ptr->argument()),
@@ -290,12 +290,12 @@
   // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
   // :after). This compatibility is not allowed for the new pseudo-elements
   // introduced in this specification.
-  bool Pseudo_Selector::is_pseudo_element() const
+  bool PseudoSelector::is_pseudo_element() const
   {
     return isElement();
   }
 
-  size_t Pseudo_Selector::hash() const
+  size_t PseudoSelector::hash() const
   {
     if (hash_ == 0) {
       hash_combine(hash_, SimpleSelector::hash());
@@ -305,34 +305,34 @@
     return hash_;
   }
 
-  unsigned long Pseudo_Selector::specificity() const
+  unsigned long PseudoSelector::specificity() const
   {
     if (is_pseudo_element())
       return Constants::Specificity_Element;
     return Constants::Specificity_Pseudo;
   }
 
-  Pseudo_Selector_Obj Pseudo_Selector::withSelector(SelectorListObj selector)
+  PseudoSelectorObj PseudoSelector::withSelector(SelectorListObj selector)
   {
-    Pseudo_Selector_Obj pseudo = SASS_MEMORY_COPY(this);
+    PseudoSelectorObj pseudo = SASS_MEMORY_COPY(this);
     pseudo->selector(selector);
     return pseudo;
   }
 
-  bool Pseudo_Selector::empty() const
+  bool PseudoSelector::empty() const
   {
     // Only considered empty if selector is
     // available but has no items in it.
     return selector() && selector()->empty();
   }
 
-  void Pseudo_Selector::cloneChildren()
+  void PseudoSelector::cloneChildren()
   {
     if (selector().isNull()) selector({});
     else selector(SASS_MEMORY_CLONE(selector()));
   }
 
-  bool Pseudo_Selector::has_real_parent_ref() const {
+  bool PseudoSelector::has_real_parent_ref() const {
     if (!selector()) return false;
     return selector()->has_real_parent_ref();
   }
@@ -340,7 +340,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  SelectorList::SelectorList(ParserState pstate, size_t s)
+  SelectorList::SelectorList(SourceSpan pstate, size_t s)
   : Selector(pstate),
     Vectorized<ComplexSelectorObj>(s),
     is_optional_(false)
@@ -391,7 +391,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  ComplexSelector::ComplexSelector(ParserState pstate)
+  ComplexSelector::ComplexSelector(SourceSpan pstate)
   : Selector(pstate),
     Vectorized<SelectorComponentObj>(),
     chroots_(false),
@@ -469,7 +469,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  SelectorComponent::SelectorComponent(ParserState pstate, bool postLineBreak)
+  SelectorComponent::SelectorComponent(SourceSpan pstate, bool postLineBreak)
   : Selector(pstate),
     hasPostLineBreak_(postLineBreak)
   {
@@ -500,7 +500,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  SelectorCombinator::SelectorCombinator(ParserState pstate, SelectorCombinator::Combinator combinator, bool postLineBreak)
+  SelectorCombinator::SelectorCombinator(SourceSpan pstate, SelectorCombinator::Combinator combinator, bool postLineBreak)
     : SelectorComponent(pstate, postLineBreak),
     combinator_(combinator)
   {
@@ -522,7 +522,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  CompoundSelector::CompoundSelector(ParserState pstate, bool postLineBreak)
+  CompoundSelector::CompoundSelector(SourceSpan pstate, bool postLineBreak)
     : SelectorComponent(pstate, postLineBreak),
       Vectorized<SimpleSelectorObj>(),
       hasRealParent_(false),
@@ -549,7 +549,7 @@
   {
     if (hasRealParent()) return true;
     // ToDo: dart sass has another check?
-    // if (Cast<Type_Selector>(front)) {
+    // if (Cast<TypeSelector>(front)) {
     //  if (front->ns() != "") return false;
     // }
     for (const SimpleSelector* s : elements()) {
@@ -590,7 +590,7 @@
     return true;
   }
 
-  bool CompoundSelector::isSuperselectorOf(const CompoundSelector* sub, std::string wrapped) const
+  bool CompoundSelector::isSuperselectorOf(const CompoundSelector* sub, sass::string wrapped) const
   {
     CompoundSelector* rhs2 = const_cast<CompoundSelector*>(sub);
     CompoundSelector* lhs2 = const_cast<CompoundSelector*>(this);
@@ -600,15 +600,15 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  MediaRule::MediaRule(ParserState pstate, Block_Obj block) :
-    Has_Block(pstate, block),
+  MediaRule::MediaRule(SourceSpan pstate, Block_Obj block) :
+    ParentStatement(pstate, block),
     schema_({})
   {
     statement_type(MEDIA);
   }
 
   MediaRule::MediaRule(const MediaRule* ptr) :
-    Has_Block(ptr),
+    ParentStatement(ptr),
     schema_(ptr->schema_)
   {
     statement_type(MEDIA);
@@ -617,21 +617,21 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  CssMediaRule::CssMediaRule(ParserState pstate, Block_Obj block) :
-    Has_Block(pstate, block),
+  CssMediaRule::CssMediaRule(SourceSpan pstate, Block_Obj block) :
+    ParentStatement(pstate, block),
     Vectorized()
   {
     statement_type(MEDIA);
   }
 
   CssMediaRule::CssMediaRule(const CssMediaRule* ptr) :
-    Has_Block(ptr),
+    ParentStatement(ptr),
     Vectorized(*ptr)
   {
     statement_type(MEDIA);
   }
 
-  CssMediaQuery::CssMediaQuery(ParserState pstate) :
+  CssMediaQuery::CssMediaQuery(SourceSpan pstate) :
     AST_Node(pstate),
     modifier_(""),
     type_(""),
@@ -653,26 +653,26 @@
   CssMediaQuery_Obj CssMediaQuery::merge(CssMediaQuery_Obj& other)
   {
 
-    std::string ourType = this->type();
+    sass::string ourType = this->type();
     Util::ascii_str_tolower(&ourType);
 
-    std::string theirType = other->type();
+    sass::string theirType = other->type();
     Util::ascii_str_tolower(&theirType);
 
-    std::string ourModifier = this->modifier();
+    sass::string ourModifier = this->modifier();
     Util::ascii_str_tolower(&ourModifier);
 
-    std::string theirModifier = other->modifier();
+    sass::string theirModifier = other->modifier();
     Util::ascii_str_tolower(&theirModifier);
 
-    std::string type;
-    std::string modifier;
-    std::vector<std::string> features;
+    sass::string type;
+    sass::string modifier;
+    sass::vector<sass::string> features;
 
     if (ourType.empty() && theirType.empty()) {
       CssMediaQuery_Obj query = SASS_MEMORY_NEW(CssMediaQuery, pstate());
-      std::vector<std::string> f1(this->features());
-      std::vector<std::string> f2(other->features());
+      sass::vector<sass::string> f1(this->features());
+      sass::vector<sass::string> f2(other->features());
       features.insert(features.end(), f1.begin(), f1.end());
       features.insert(features.end(), f2.begin(), f2.end());
       query->features(features);
@@ -681,9 +681,9 @@
 
     if ((ourModifier == "not") != (theirModifier == "not")) {
       if (ourType == theirType) {
-        std::vector<std::string> negativeFeatures =
+        sass::vector<sass::string> negativeFeatures =
           ourModifier == "not" ? this->features() : other->features();
-        std::vector<std::string> positiveFeatures =
+        sass::vector<sass::string> positiveFeatures =
           ourModifier == "not" ? other->features() : this->features();
 
         // If the negative features are a subset of the positive features, the
@@ -747,16 +747,16 @@
         // Omit the type if either input query did, since that indicates that they
         // aren't targeting a browser that requires "all and".
         type = (other->matchesAllTypes() && ourType.empty()) ? "" : theirType;
-        std::vector<std::string> f1(this->features());
-        std::vector<std::string> f2(other->features());
+        sass::vector<sass::string> f1(this->features());
+        sass::vector<sass::string> f2(other->features());
         features.insert(features.end(), f1.begin(), f1.end());
         features.insert(features.end(), f2.begin(), f2.end());
       }
       else if (other->matchesAllTypes()) {
         modifier = ourModifier;
         type = ourType;
-        std::vector<std::string> f1(this->features());
-        std::vector<std::string> f2(other->features());
+        sass::vector<sass::string> f1(this->features());
+        sass::vector<sass::string> f2(other->features());
         features.insert(features.end(), f1.begin(), f1.end());
         features.insert(features.end(), f2.begin(), f2.end());
       }
@@ -766,8 +766,8 @@
       else {
         modifier = ourModifier.empty() ? theirModifier : ourModifier;
         type = ourType;
-        std::vector<std::string> f1(this->features());
-        std::vector<std::string> f2(other->features());
+        sass::vector<sass::string> f1(this->features());
+        sass::vector<sass::string> f2(other->features());
         features.insert(features.end(), f1.begin(), f1.end());
         features.insert(features.end(), f2.begin(), f2.end());
       }
@@ -850,15 +850,15 @@
   // ToDo: this might be done easier with new selector format
   /////////////////////////////////////////////////////////////////////////
 
-  std::vector<ComplexSelectorObj>
+  sass::vector<ComplexSelectorObj>
     CompoundSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
   {
 
     auto parent = pstack.back();
-    std::vector<ComplexSelectorObj> rv;
+    sass::vector<ComplexSelectorObj> rv;
 
     for (SimpleSelectorObj simple : elements()) {
-      if (Pseudo_Selector * pseudo = Cast<Pseudo_Selector>(simple)) {
+      if (PseudoSelector * pseudo = Cast<PseudoSelector>(simple)) {
         if (SelectorList* sel = Cast<SelectorList>(pseudo->selector())) {
           if (parent) {
             pseudo->selector(sel->resolve_parent_refs(
@@ -887,7 +887,7 @@
               SimpleSelectorObj back = tail->last();
               SimpleSelectorObj front = first();
               auto simple_back = Cast<SimpleSelector>(back);
-              auto simple_front = Cast<Type_Selector>(front);
+              auto simple_front = Cast<TypeSelector>(front);
               if (simple_front && simple_back) {
                 simple_back = SASS_MEMORY_COPY(simple_back);
                 auto name = simple_back->name();
@@ -940,11 +940,21 @@
 
   }
 
-  /* better return std::vector? only - is empty container anyway? */
+  bool cmpSimpleSelectors(SimpleSelector* a, SimpleSelector* b)
+  {
+    return (a->getSortOrder() < b->getSortOrder());
+  }
+
+  void CompoundSelector::sortChildren()
+  {
+    std::sort(begin(), end(), cmpSimpleSelectors);
+  }
+
+  /* better return sass::vector? only - is empty container anyway? */
   SelectorList* ComplexSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
   {
 
-    std::vector<std::vector<ComplexSelectorObj>> vars;
+    sass::vector<sass::vector<ComplexSelectorObj>> vars;
 
     auto parent = pstack.back();
 
@@ -977,7 +987,7 @@
     }
 
     // Need complex selectors to preserve linefeeds
-    std::vector<std::vector<ComplexSelectorObj>> res = permutateAlt(vars);
+    sass::vector<sass::vector<ComplexSelectorObj>> res = permutateAlt(vars);
 
     // std::reverse(std::begin(res), std::end(res));
 
@@ -1019,12 +1029,12 @@
   /////////////////////////////////////////////////////////////////////////
 
   IMPLEMENT_AST_OPERATORS(Selector_Schema);
-  IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
-  IMPLEMENT_AST_OPERATORS(Attribute_Selector);
-  IMPLEMENT_AST_OPERATORS(Type_Selector);
-  IMPLEMENT_AST_OPERATORS(Class_Selector);
-  IMPLEMENT_AST_OPERATORS(Id_Selector);
-  IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
+  IMPLEMENT_AST_OPERATORS(PlaceholderSelector);
+  IMPLEMENT_AST_OPERATORS(AttributeSelector);
+  IMPLEMENT_AST_OPERATORS(TypeSelector);
+  IMPLEMENT_AST_OPERATORS(ClassSelector);
+  IMPLEMENT_AST_OPERATORS(IDSelector);
+  IMPLEMENT_AST_OPERATORS(PseudoSelector);
   IMPLEMENT_AST_OPERATORS(SelectorCombinator);
   IMPLEMENT_AST_OPERATORS(CompoundSelector);
   IMPLEMENT_AST_OPERATORS(ComplexSelector);
diff --git a/libsass/src/ast_selectors.hpp b/libsass/src/ast_selectors.hpp
--- a/libsass/src/ast_selectors.hpp
+++ b/libsass/src/ast_selectors.hpp
@@ -15,25 +15,25 @@
   bool compoundIsSuperselector(
     const CompoundSelectorObj& compound1,
     const CompoundSelectorObj& compound2,
-    const std::vector<SelectorComponentObj>& parents);
+    const sass::vector<SelectorComponentObj>& parents);
 
   bool complexIsParentSuperselector(
-    const std::vector<SelectorComponentObj>& complex1,
-    const std::vector<SelectorComponentObj>& complex2);
+    const sass::vector<SelectorComponentObj>& complex1,
+    const sass::vector<SelectorComponentObj>& complex2);
 
-    std::vector<std::vector<SelectorComponentObj>> weave(
-    const std::vector<std::vector<SelectorComponentObj>>& complexes);
+    sass::vector<sass::vector<SelectorComponentObj>> weave(
+    const sass::vector<sass::vector<SelectorComponentObj>>& complexes);
 
-  std::vector<std::vector<SelectorComponentObj>> weaveParents(
-    std::vector<SelectorComponentObj> parents1,
-    std::vector<SelectorComponentObj> parents2);
+  sass::vector<sass::vector<SelectorComponentObj>> weaveParents(
+    sass::vector<SelectorComponentObj> parents1,
+    sass::vector<SelectorComponentObj> parents2);
 
-  std::vector<SimpleSelectorObj> unifyCompound(
-    const std::vector<SimpleSelectorObj>& compound1,
-    const std::vector<SimpleSelectorObj>& compound2);
+  sass::vector<SimpleSelectorObj> unifyCompound(
+    const sass::vector<SimpleSelectorObj>& compound1,
+    const sass::vector<SimpleSelectorObj>& compound2);
 
-  std::vector<std::vector<SelectorComponentObj>> unifyComplex(
-    const std::vector<std::vector<SelectorComponentObj>>& complexes);
+  sass::vector<sass::vector<SelectorComponentObj>> unifyComplex(
+    const sass::vector<sass::vector<SelectorComponentObj>>& complexes);
 
   /////////////////////////////////////////
   // Abstract base class for CSS selectors.
@@ -42,7 +42,7 @@
   protected:
     mutable size_t hash_;
   public:
-    Selector(ParserState pstate);
+    Selector(SourceSpan pstate);
     virtual ~Selector() = 0;
     size_t hash() const override = 0;
     virtual bool has_real_parent_ref() const;
@@ -68,7 +68,7 @@
     // store computed hash
     mutable size_t hash_;
   public:
-    Selector_Schema(ParserState pstate, String_Obj c);
+    Selector_Schema(SourceSpan pstate, String_Obj c);
 
     bool has_real_parent_ref() const;
     // selector schema is not yet a final selector, so we do not
@@ -93,13 +93,15 @@
       PLACEHOLDER_SEL,
     };
   public:
-    HASH_CONSTREF(std::string, ns)
-    HASH_CONSTREF(std::string, name)
+    HASH_CONSTREF(sass::string, ns)
+    HASH_CONSTREF(sass::string, name)
     ADD_PROPERTY(Simple_Type, simple_type)
     HASH_PROPERTY(bool, has_ns)
   public:
-    SimpleSelector(ParserState pstate, std::string n = "");
-    virtual std::string ns_name() const;
+    SimpleSelector(SourceSpan pstate, sass::string n = "");
+    // ordering within parent (peudos go last)
+    virtual int getSortOrder() const = 0;
+    virtual sass::string ns_name() const;
     size_t hash() const override;
     virtual bool empty() const;
     // namespace compare functions
@@ -117,9 +119,9 @@
     virtual CompoundSelector* unifyWith(CompoundSelector*);
 
     /* helper function for syntax sugar */
-    virtual Id_Selector* getIdSelector() { return NULL; }
-    virtual Type_Selector* getTypeSelector() { return NULL; }
-    virtual Pseudo_Selector* getPseudoSelector() { return NULL; }
+    virtual IDSelector* getIdSelector() { return NULL; }
+    virtual TypeSelector* getTypeSelector() { return NULL; }
+    virtual PseudoSelector* getPseudoSelector() { return NULL; }
 
     ComplexSelectorObj wrapInComplex();
     CompoundSelectorObj wrapInCompound();
@@ -144,77 +146,82 @@
   /////////////////////////////////////////////////////////////////////////
   // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
   /////////////////////////////////////////////////////////////////////////
-  class Placeholder_Selector final : public SimpleSelector {
+  class PlaceholderSelector final : public SimpleSelector {
   public:
-    Placeholder_Selector(ParserState pstate, std::string n);
+    PlaceholderSelector(SourceSpan pstate, sass::string n);
+    int getSortOrder() const override final { return 0; }
     bool isInvisible() const override { return true; }
     virtual unsigned long specificity() const override;
     virtual bool has_placeholder() override;
     bool operator==(const SimpleSelector& rhs) const override;
-    ATTACH_CMP_OPERATIONS(Placeholder_Selector)
-    ATTACH_AST_OPERATIONS(Placeholder_Selector)
+    ATTACH_CMP_OPERATIONS(PlaceholderSelector)
+    ATTACH_AST_OPERATIONS(PlaceholderSelector)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   /////////////////////////////////////////////////////////////////////
   // Type selectors (and the universal selector) -- e.g., div, span, *.
   /////////////////////////////////////////////////////////////////////
-  class Type_Selector final : public SimpleSelector {
+  class TypeSelector final : public SimpleSelector {
   public:
-    Type_Selector(ParserState pstate, std::string n);
+    TypeSelector(SourceSpan pstate, sass::string n);
+    int getSortOrder() const override final { return 1; }
     virtual unsigned long specificity() const override;
     SimpleSelector* unifyWith(const SimpleSelector*);
     CompoundSelector* unifyWith(CompoundSelector*) override;
-    Type_Selector* getTypeSelector() override { return this; }
+    TypeSelector* getTypeSelector() override { return this; }
     bool operator==(const SimpleSelector& rhs) const final override;
-    ATTACH_CMP_OPERATIONS(Type_Selector)
-    ATTACH_AST_OPERATIONS(Type_Selector)
+    ATTACH_CMP_OPERATIONS(TypeSelector)
+    ATTACH_AST_OPERATIONS(TypeSelector)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ////////////////////////////////////////////////
   // Class selectors  -- i.e., .foo.
   ////////////////////////////////////////////////
-  class Class_Selector final : public SimpleSelector {
+  class ClassSelector final : public SimpleSelector {
   public:
-    Class_Selector(ParserState pstate, std::string n);
+    ClassSelector(SourceSpan pstate, sass::string n);
+    int getSortOrder() const override final { return 3; }
     virtual unsigned long specificity() const override;
     bool operator==(const SimpleSelector& rhs) const final override;
-    ATTACH_CMP_OPERATIONS(Class_Selector)
-    ATTACH_AST_OPERATIONS(Class_Selector)
+    ATTACH_CMP_OPERATIONS(ClassSelector)
+    ATTACH_AST_OPERATIONS(ClassSelector)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ////////////////////////////////////////////////
   // ID selectors -- i.e., #foo.
   ////////////////////////////////////////////////
-  class Id_Selector final : public SimpleSelector {
+  class IDSelector final : public SimpleSelector {
   public:
-    Id_Selector(ParserState pstate, std::string n);
+    IDSelector(SourceSpan pstate, sass::string n);
+    int getSortOrder() const override final { return 2; }
     virtual unsigned long specificity() const override;
     CompoundSelector* unifyWith(CompoundSelector*) override;
-    Id_Selector* getIdSelector() final override { return this; }
+    IDSelector* getIdSelector() final override { return this; }
     bool operator==(const SimpleSelector& rhs) const final override;
-    ATTACH_CMP_OPERATIONS(Id_Selector)
-    ATTACH_AST_OPERATIONS(Id_Selector)
+    ATTACH_CMP_OPERATIONS(IDSelector)
+    ATTACH_AST_OPERATIONS(IDSelector)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////////////////////////
   // Attribute selectors -- e.g., [src*=".jpg"], etc.
   ///////////////////////////////////////////////////
-  class Attribute_Selector final : public SimpleSelector {
-    ADD_CONSTREF(std::string, matcher)
+  class AttributeSelector final : public SimpleSelector {
+    ADD_CONSTREF(sass::string, matcher)
     // this cannot be changed to obj atm!!!!!!????!!!!!!!
     ADD_PROPERTY(String_Obj, value) // might be interpolated
     ADD_PROPERTY(char, modifier);
   public:
-    Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o = 0);
+    AttributeSelector(SourceSpan pstate, sass::string n, sass::string m, String_Obj v, char o = 0);
+    int getSortOrder() const override final { return 4; }
     size_t hash() const override;
     virtual unsigned long specificity() const override;
     bool operator==(const SimpleSelector& rhs) const final override;
-    ATTACH_CMP_OPERATIONS(Attribute_Selector)
-    ATTACH_AST_OPERATIONS(Attribute_Selector)
+    ATTACH_CMP_OPERATIONS(AttributeSelector)
+    ATTACH_AST_OPERATIONS(AttributeSelector)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
@@ -222,14 +229,15 @@
   // Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
   //////////////////////////////////////////////////////////////////
   // Pseudo Selector cannot have any namespace?
-  class Pseudo_Selector final : public SimpleSelector {
-    ADD_PROPERTY(std::string, normalized)
+  class PseudoSelector final : public SimpleSelector {
+    ADD_PROPERTY(sass::string, normalized)
     ADD_PROPERTY(String_Obj, argument)
     ADD_PROPERTY(SelectorListObj, selector)
     ADD_PROPERTY(bool, isSyntacticClass)
     ADD_PROPERTY(bool, isClass)
   public:
-    Pseudo_Selector(ParserState pstate, std::string n, bool element = false);
+    PseudoSelector(SourceSpan pstate, sass::string n, bool element = false);
+    int getSortOrder() const override final { return 5; }
     virtual bool is_pseudo_element() const override;
     size_t hash() const override;
 
@@ -246,13 +254,13 @@
     bool isSyntacticElement() const { return !isSyntacticClass(); }
 
     virtual unsigned long specificity() const override;
-    Pseudo_Selector_Obj withSelector(SelectorListObj selector);
+    PseudoSelectorObj withSelector(SelectorListObj selector);
 
     CompoundSelector* unifyWith(CompoundSelector*) override;
-    Pseudo_Selector* getPseudoSelector() final override { return this; }
+    PseudoSelector* getPseudoSelector() final override { return this; }
     bool operator==(const SimpleSelector& rhs) const final override;
-    ATTACH_CMP_OPERATIONS(Pseudo_Selector)
-    ATTACH_AST_OPERATIONS(Pseudo_Selector)
+    ATTACH_CMP_OPERATIONS(PseudoSelector)
+    ATTACH_AST_OPERATIONS(PseudoSelector)
     void cloneChildren() override;
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -269,7 +277,7 @@
     // line break before list separator
     ADD_PROPERTY(bool, hasPreLineFeed)
   public:
-    ComplexSelector(ParserState pstate);
+    ComplexSelector(SourceSpan pstate);
 
     // Returns true if the first components
     // is a compound selector and fullfills
@@ -310,7 +318,7 @@
     // line break after list separator
     ADD_PROPERTY(bool, hasPostLineBreak)
   public:
-    SelectorComponent(ParserState pstate, bool postLineBreak = false);
+    SelectorComponent(SourceSpan pstate, bool postLineBreak = false);
     size_t hash() const override = 0;
     void cloneChildren() override;
 
@@ -357,7 +365,7 @@
     HASH_CONSTREF(Combinator, combinator)
 
   public:
-    SelectorCombinator(ParserState pstate, Combinator combinator, bool postLineBreak = false);
+    SelectorCombinator(SourceSpan pstate, Combinator combinator, bool postLineBreak = false);
 
     bool has_real_parent_ref() const override { return false; }
     bool has_placeholder() const override { return false; }
@@ -407,7 +415,7 @@
     ADD_PROPERTY(bool, hasRealParent)
     ADD_PROPERTY(bool, extended)
   public:
-    CompoundSelector(ParserState pstate, bool postLineBreak = false);
+    CompoundSelector(SourceSpan pstate, bool postLineBreak = false);
 
     // Returns true if this compound selector
     // fullfills various criteria.
@@ -424,12 +432,12 @@
     CompoundSelector* getCompound() final override { return this; }
     const CompoundSelector* getCompound() const final override { return this; }
 
-    bool isSuperselectorOf(const CompoundSelector* sub, std::string wrapped = "") const;
+    bool isSuperselectorOf(const CompoundSelector* sub, sass::string wrapped = "") const;
 
     void cloneChildren() override;
     bool has_real_parent_ref() const override;
     bool has_placeholder() const override;
-    std::vector<ComplexSelectorObj> resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
+    sass::vector<ComplexSelectorObj> resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
 
     virtual bool isCompound() const override { return true; };
     virtual unsigned long specificity() const override;
@@ -445,6 +453,8 @@
     bool operator==(const ComplexSelector& rhs) const;
     bool operator==(const SimpleSelector& rhs) const;
 
+    void sortChildren();
+
     ATTACH_CMP_OPERATIONS(CompoundSelector)
     ATTACH_AST_OPERATIONS(CompoundSelector)
     ATTACH_CRTP_PERFORM_METHODS()
@@ -459,8 +469,8 @@
     // ToDo: should be at ExtendRule?
     ADD_PROPERTY(bool, is_optional)
   public:
-    SelectorList(ParserState pstate, size_t s = 0);
-    std::string type() const override { return "list"; }
+    SelectorList(SourceSpan pstate, size_t s = 0);
+    sass::string type() const override { return "list"; }
     size_t hash() const override;
 
     SelectorList* unifyWith(SelectorList*);
@@ -501,8 +511,8 @@
     ADD_PROPERTY(SelectorListObj, selector)
     ADD_PROPERTY(Selector_Schema_Obj, schema)
   public:
-    ExtendRule(ParserState pstate, SelectorListObj s);
-    ExtendRule(ParserState pstate, Selector_Schema_Obj s);
+    ExtendRule(SourceSpan pstate, SelectorListObj s);
+    ExtendRule(SourceSpan pstate, Selector_Schema_Obj s);
     ATTACH_AST_OPERATIONS(ExtendRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
diff --git a/libsass/src/ast_supports.cpp b/libsass/src/ast_supports.cpp
--- a/libsass/src/ast_supports.cpp
+++ b/libsass/src/ast_supports.cpp
@@ -9,75 +9,75 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Block::Supports_Block(ParserState pstate, Supports_Condition_Obj condition, Block_Obj block)
-  : Has_Block(pstate, block), condition_(condition)
+  SupportsRule::SupportsRule(SourceSpan pstate, SupportsConditionObj condition, Block_Obj block)
+  : ParentStatement(pstate, block), condition_(condition)
   { statement_type(SUPPORTS); }
-  Supports_Block::Supports_Block(const Supports_Block* ptr)
-  : Has_Block(ptr), condition_(ptr->condition_)
+  SupportsRule::SupportsRule(const SupportsRule* ptr)
+  : ParentStatement(ptr), condition_(ptr->condition_)
   { statement_type(SUPPORTS); }
-  bool Supports_Block::bubbles() { return true; }
+  bool SupportsRule::bubbles() { return true; }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Condition::Supports_Condition(ParserState pstate)
+  SupportsCondition::SupportsCondition(SourceSpan pstate)
   : Expression(pstate)
   { }
 
-  Supports_Condition::Supports_Condition(const Supports_Condition* ptr)
+  SupportsCondition::SupportsCondition(const SupportsCondition* ptr)
   : Expression(ptr)
   { }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Operator::Supports_Operator(ParserState pstate, Supports_Condition_Obj l, Supports_Condition_Obj r, Operand o)
-  : Supports_Condition(pstate), left_(l), right_(r), operand_(o)
+  SupportsOperation::SupportsOperation(SourceSpan pstate, SupportsConditionObj l, SupportsConditionObj r, Operand o)
+  : SupportsCondition(pstate), left_(l), right_(r), operand_(o)
   { }
-  Supports_Operator::Supports_Operator(const Supports_Operator* ptr)
-  : Supports_Condition(ptr),
+  SupportsOperation::SupportsOperation(const SupportsOperation* ptr)
+  : SupportsCondition(ptr),
     left_(ptr->left_),
     right_(ptr->right_),
     operand_(ptr->operand_)
   { }
 
-  bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const
+  bool SupportsOperation::needs_parens(SupportsConditionObj cond) const
   {
-    if (Supports_Operator_Obj op = Cast<Supports_Operator>(cond)) {
+    if (SupportsOperationObj op = Cast<SupportsOperation>(cond)) {
       return op->operand() != operand();
     }
-    return Cast<Supports_Negation>(cond) != NULL;
+    return Cast<SupportsNegation>(cond) != NULL;
   }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Negation::Supports_Negation(ParserState pstate, Supports_Condition_Obj c)
-  : Supports_Condition(pstate), condition_(c)
+  SupportsNegation::SupportsNegation(SourceSpan pstate, SupportsConditionObj c)
+  : SupportsCondition(pstate), condition_(c)
   { }
-  Supports_Negation::Supports_Negation(const Supports_Negation* ptr)
-  : Supports_Condition(ptr), condition_(ptr->condition_)
+  SupportsNegation::SupportsNegation(const SupportsNegation* ptr)
+  : SupportsCondition(ptr), condition_(ptr->condition_)
   { }
 
-  bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const
+  bool SupportsNegation::needs_parens(SupportsConditionObj cond) const
   {
-    return Cast<Supports_Negation>(cond) ||
-           Cast<Supports_Operator>(cond);
+    return Cast<SupportsNegation>(cond) ||
+           Cast<SupportsOperation>(cond);
   }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Declaration::Supports_Declaration(ParserState pstate, Expression_Obj f, Expression_Obj v)
-  : Supports_Condition(pstate), feature_(f), value_(v)
+  SupportsDeclaration::SupportsDeclaration(SourceSpan pstate, ExpressionObj f, ExpressionObj v)
+  : SupportsCondition(pstate), feature_(f), value_(v)
   { }
-  Supports_Declaration::Supports_Declaration(const Supports_Declaration* ptr)
-  : Supports_Condition(ptr),
+  SupportsDeclaration::SupportsDeclaration(const SupportsDeclaration* ptr)
+  : SupportsCondition(ptr),
     feature_(ptr->feature_),
     value_(ptr->value_)
   { }
 
-  bool Supports_Declaration::needs_parens(Supports_Condition_Obj cond) const
+  bool SupportsDeclaration::needs_parens(SupportsConditionObj cond) const
   {
     return false;
   }
@@ -85,15 +85,15 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Supports_Interpolation::Supports_Interpolation(ParserState pstate, Expression_Obj v)
-  : Supports_Condition(pstate), value_(v)
+  Supports_Interpolation::Supports_Interpolation(SourceSpan pstate, ExpressionObj v)
+  : SupportsCondition(pstate), value_(v)
   { }
   Supports_Interpolation::Supports_Interpolation(const Supports_Interpolation* ptr)
-  : Supports_Condition(ptr),
+  : SupportsCondition(ptr),
     value_(ptr->value_)
   { }
 
-  bool Supports_Interpolation::needs_parens(Supports_Condition_Obj cond) const
+  bool Supports_Interpolation::needs_parens(SupportsConditionObj cond) const
   {
     return false;
   }
@@ -101,11 +101,11 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  IMPLEMENT_AST_OPERATORS(Supports_Block);
-  IMPLEMENT_AST_OPERATORS(Supports_Condition);
-  IMPLEMENT_AST_OPERATORS(Supports_Operator);
-  IMPLEMENT_AST_OPERATORS(Supports_Negation);
-  IMPLEMENT_AST_OPERATORS(Supports_Declaration);
+  IMPLEMENT_AST_OPERATORS(SupportsRule);
+  IMPLEMENT_AST_OPERATORS(SupportsCondition);
+  IMPLEMENT_AST_OPERATORS(SupportsOperation);
+  IMPLEMENT_AST_OPERATORS(SupportsNegation);
+  IMPLEMENT_AST_OPERATORS(SupportsDeclaration);
   IMPLEMENT_AST_OPERATORS(Supports_Interpolation);
 
   /////////////////////////////////////////////////////////////////////////
diff --git a/libsass/src/ast_supports.hpp b/libsass/src/ast_supports.hpp
--- a/libsass/src/ast_supports.hpp
+++ b/libsass/src/ast_supports.hpp
@@ -39,79 +39,79 @@
   ////////////////////
   // `@supports` rule.
   ////////////////////
-  class Supports_Block : public Has_Block {
-    ADD_PROPERTY(Supports_Condition_Obj, condition)
+  class SupportsRule : public ParentStatement {
+    ADD_PROPERTY(SupportsConditionObj, condition)
   public:
-    Supports_Block(ParserState pstate, Supports_Condition_Obj condition, Block_Obj block = {});
+    SupportsRule(SourceSpan pstate, SupportsConditionObj condition, Block_Obj block = {});
     bool bubbles() override;
-    ATTACH_AST_OPERATIONS(Supports_Block)
+    ATTACH_AST_OPERATIONS(SupportsRule)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   //////////////////////////////////////////////////////
   // The abstract superclass of all Supports conditions.
   //////////////////////////////////////////////////////
-  class Supports_Condition : public Expression {
+  class SupportsCondition : public Expression {
   public:
-    Supports_Condition(ParserState pstate);
-    virtual bool needs_parens(Supports_Condition_Obj cond) const { return false; }
-    ATTACH_AST_OPERATIONS(Supports_Condition)
+    SupportsCondition(SourceSpan pstate);
+    virtual bool needs_parens(SupportsConditionObj cond) const { return false; }
+    ATTACH_AST_OPERATIONS(SupportsCondition)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ////////////////////////////////////////////////////////////
   // An operator condition (e.g. `CONDITION1 and CONDITION2`).
   ////////////////////////////////////////////////////////////
-  class Supports_Operator : public Supports_Condition {
+  class SupportsOperation : public SupportsCondition {
   public:
     enum Operand { AND, OR };
   private:
-    ADD_PROPERTY(Supports_Condition_Obj, left);
-    ADD_PROPERTY(Supports_Condition_Obj, right);
+    ADD_PROPERTY(SupportsConditionObj, left);
+    ADD_PROPERTY(SupportsConditionObj, right);
     ADD_PROPERTY(Operand, operand);
   public:
-    Supports_Operator(ParserState pstate, Supports_Condition_Obj l, Supports_Condition_Obj r, Operand o);
-    virtual bool needs_parens(Supports_Condition_Obj cond) const override;
-    ATTACH_AST_OPERATIONS(Supports_Operator)
+    SupportsOperation(SourceSpan pstate, SupportsConditionObj l, SupportsConditionObj r, Operand o);
+    virtual bool needs_parens(SupportsConditionObj cond) const override;
+    ATTACH_AST_OPERATIONS(SupportsOperation)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   //////////////////////////////////////////
   // A negation condition (`not CONDITION`).
   //////////////////////////////////////////
-  class Supports_Negation : public Supports_Condition {
+  class SupportsNegation : public SupportsCondition {
   private:
-    ADD_PROPERTY(Supports_Condition_Obj, condition);
+    ADD_PROPERTY(SupportsConditionObj, condition);
   public:
-    Supports_Negation(ParserState pstate, Supports_Condition_Obj c);
-    virtual bool needs_parens(Supports_Condition_Obj cond) const override;
-    ATTACH_AST_OPERATIONS(Supports_Negation)
+    SupportsNegation(SourceSpan pstate, SupportsConditionObj c);
+    virtual bool needs_parens(SupportsConditionObj cond) const override;
+    ATTACH_AST_OPERATIONS(SupportsNegation)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   /////////////////////////////////////////////////////
   // A declaration condition (e.g. `(feature: value)`).
   /////////////////////////////////////////////////////
-  class Supports_Declaration : public Supports_Condition {
+  class SupportsDeclaration : public SupportsCondition {
   private:
-    ADD_PROPERTY(Expression_Obj, feature);
-    ADD_PROPERTY(Expression_Obj, value);
+    ADD_PROPERTY(ExpressionObj, feature);
+    ADD_PROPERTY(ExpressionObj, value);
   public:
-    Supports_Declaration(ParserState pstate, Expression_Obj f, Expression_Obj v);
-    virtual bool needs_parens(Supports_Condition_Obj cond) const override;
-    ATTACH_AST_OPERATIONS(Supports_Declaration)
+    SupportsDeclaration(SourceSpan pstate, ExpressionObj f, ExpressionObj v);
+    virtual bool needs_parens(SupportsConditionObj cond) const override;
+    ATTACH_AST_OPERATIONS(SupportsDeclaration)
     ATTACH_CRTP_PERFORM_METHODS()
   };
 
   ///////////////////////////////////////////////
   // An interpolation condition (e.g. `#{$var}`).
   ///////////////////////////////////////////////
-  class Supports_Interpolation : public Supports_Condition {
+  class Supports_Interpolation : public SupportsCondition {
   private:
-    ADD_PROPERTY(Expression_Obj, value);
+    ADD_PROPERTY(ExpressionObj, value);
   public:
-    Supports_Interpolation(ParserState pstate, Expression_Obj v);
-    virtual bool needs_parens(Supports_Condition_Obj cond) const override;
+    Supports_Interpolation(SourceSpan pstate, ExpressionObj v);
+    virtual bool needs_parens(SupportsConditionObj cond) const override;
     ATTACH_AST_OPERATIONS(Supports_Interpolation)
     ATTACH_CRTP_PERFORM_METHODS()
   };
diff --git a/libsass/src/ast_values.cpp b/libsass/src/ast_values.cpp
--- a/libsass/src/ast_values.cpp
+++ b/libsass/src/ast_values.cpp
@@ -5,7 +5,7 @@
 
 namespace Sass {
 
-  void str_rtrim(std::string& str, const std::string& delimiters = " \f\n\r\t\v")
+  void str_rtrim(sass::string& str, const sass::string& delimiters = " \f\n\r\t\v")
   {
     str.erase( str.find_last_not_of( delimiters ) + 1 );
   }
@@ -13,7 +13,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  PreValue::PreValue(ParserState pstate, bool d, bool e, bool i, Type ct)
+  PreValue::PreValue(SourceSpan pstate, bool d, bool e, bool i, Type ct)
   : Expression(pstate, d, e, i, ct)
   { }
   PreValue::PreValue(const PreValue* ptr)
@@ -23,7 +23,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Value::Value(ParserState pstate, bool d, bool e, bool i, Type ct)
+  Value::Value(SourceSpan pstate, bool d, bool e, bool i, Type ct)
   : PreValue(pstate, d, e, i, ct)
   { }
   Value::Value(const Value* ptr)
@@ -33,9 +33,9 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  List::List(ParserState pstate, size_t size, enum Sass_Separator sep, bool argl, bool bracket)
+  List::List(SourceSpan pstate, size_t size, enum Sass_Separator sep, bool argl, bool bracket)
   : Value(pstate),
-    Vectorized<Expression_Obj>(size),
+    Vectorized<ExpressionObj>(size),
     separator_(sep),
     is_arglist_(argl),
     is_bracketed_(bracket),
@@ -44,7 +44,7 @@
 
   List::List(const List* ptr)
   : Value(ptr),
-    Vectorized<Expression_Obj>(*ptr),
+    Vectorized<ExpressionObj>(*ptr),
     separator_(ptr->separator_),
     is_arglist_(ptr->is_arglist_),
     is_bracketed_(ptr->is_bracketed_),
@@ -54,7 +54,7 @@
   size_t List::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()(sep_string());
+      hash_ = std::hash<sass::string>()(sep_string());
       hash_combine(hash_, std::hash<bool>()(is_bracketed()));
       for (size_t i = 0, L = length(); i < L; ++i)
         hash_combine(hash_, (elements()[i])->hash());
@@ -109,7 +109,7 @@
     // arglist expects a list of arguments
     // so we need to break before keywords
     for (size_t i = 0, L = length(); i < L; ++i) {
-      Expression_Obj obj = this->at(i);
+      ExpressionObj obj = this->at(i);
       if (Argument* arg = Cast<Argument>(obj)) {
         if (!arg->name().empty()) return i;
       }
@@ -118,8 +118,8 @@
   }
 
 
-  Expression_Obj List::value_at_index(size_t i) {
-    Expression_Obj obj = this->at(i);
+  ExpressionObj List::value_at_index(size_t i) {
+    ExpressionObj obj = this->at(i);
     if (is_arglist_) {
       if (Argument* arg = Cast<Argument>(obj)) {
         return arg->value();
@@ -134,7 +134,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Map::Map(ParserState pstate, size_t size)
+  Map::Map(SourceSpan pstate, size_t size)
   : Value(pstate),
     Hashed(size)
   { concrete_type(MAP); }
@@ -185,7 +185,7 @@
     return false;
   }
 
-  List_Obj Map::to_list(ParserState& pstate) {
+  List_Obj Map::to_list(SourceSpan& pstate) {
     List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA);
 
     for (auto key : keys()) {
@@ -213,8 +213,8 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Binary_Expression::Binary_Expression(ParserState pstate,
-                    Operand op, Expression_Obj lhs, Expression_Obj rhs)
+  Binary_Expression::Binary_Expression(SourceSpan pstate,
+                    Operand op, ExpressionObj lhs, ExpressionObj rhs)
   : PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
   { }
 
@@ -235,12 +235,12 @@
     return is_interpolant() || (right() && right()->is_right_interpolant());
   }
 
-  const std::string Binary_Expression::type_name()
+  const sass::string Binary_Expression::type_name()
   {
     return sass_op_to_name(optype());
   }
 
-  const std::string Binary_Expression::separator()
+  const sass::string Binary_Expression::separator()
   {
     return sass_op_separator(optype());
   }
@@ -292,7 +292,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Function::Function(ParserState pstate, Definition_Obj def, bool css)
+  Function::Function(SourceSpan pstate, Definition_Obj def, bool css)
   : Value(pstate), definition_(def), is_css_(css)
   { concrete_type(FUNCTION_VAL); }
 
@@ -326,7 +326,7 @@
     return false;
   }
 
-  std::string Function::name() {
+  sass::string Function::name() {
     if (definition_) {
       return definition_->name();
     }
@@ -336,23 +336,23 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Function_Call::Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, void* cookie)
+  Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, void* cookie)
   : PreValue(pstate), sname_(n), arguments_(args), func_(), via_call_(false), cookie_(cookie), hash_(0)
   { concrete_type(FUNCTION); }
-  Function_Call::Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, Function_Obj func)
+  Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, Function_Obj func)
   : PreValue(pstate), sname_(n), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0)
   { concrete_type(FUNCTION); }
-  Function_Call::Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args)
+  Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args)
   : PreValue(pstate), sname_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0)
   { concrete_type(FUNCTION); }
 
-  Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie)
+  Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, void* cookie)
   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(), via_call_(false), cookie_(cookie), hash_(0)
   { concrete_type(FUNCTION); }
-  Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args, Function_Obj func)
+  Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Function_Obj func)
   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0)
   { concrete_type(FUNCTION); }
-  Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args)
+  Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args)
   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), via_call_(false), cookie_(0), hash_(0)
   { concrete_type(FUNCTION); }
 
@@ -381,14 +381,14 @@
   size_t Function_Call::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()(name());
+      hash_ = std::hash<sass::string>()(name());
       for (auto argument : arguments()->elements())
         hash_combine(hash_, argument->hash());
     }
     return hash_;
   }
 
-  std::string Function_Call::name() const
+  sass::string Function_Call::name() const
   {
     return sname();
   }
@@ -401,7 +401,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Variable::Variable(ParserState pstate, std::string n)
+  Variable::Variable(SourceSpan pstate, sass::string n)
   : PreValue(pstate), name_(n)
   { concrete_type(VARIABLE); }
 
@@ -419,13 +419,13 @@
 
   size_t Variable::hash() const
   {
-    return std::hash<std::string>()(name());
+    return std::hash<sass::string>()(name());
   }
 
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Number::Number(ParserState pstate, double val, std::string u, bool zero)
+  Number::Number(SourceSpan pstate, double val, sass::string u, bool zero)
   : Value(pstate),
     Units(),
     value_(val),
@@ -438,12 +438,12 @@
       bool nominator = true;
       while (true) {
         r = u.find_first_of("*/", l);
-        std::string unit(u.substr(l, r == std::string::npos ? r : r - l));
+        sass::string unit(u.substr(l, r == sass::string::npos ? r : r - l));
         if (!unit.empty()) {
           if (nominator) numerators.push_back(unit);
           else denominators.push_back(unit);
         }
-        if (r == std::string::npos) break;
+        if (r == sass::string::npos) break;
         // ToDo: should error for multiple slashes
         // if (!nominator && u[r] == '/') error(...)
         if (u[r] == '/')
@@ -482,9 +482,9 @@
     if (hash_ == 0) {
       hash_ = std::hash<double>()(value_);
       for (const auto numerator : numerators)
-        hash_combine(hash_, std::hash<std::string>()(numerator));
+        hash_combine(hash_, std::hash<sass::string>()(numerator));
       for (const auto denominator : denominators)
-        hash_combine(hash_, std::hash<std::string>()(denominator));
+        hash_combine(hash_, std::hash<sass::string>()(denominator));
     }
     return hash_;
   }
@@ -549,7 +549,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Color::Color(ParserState pstate, double a, const std::string disp)
+  Color::Color(SourceSpan pstate, double a, const sass::string disp)
   : Value(pstate),
     disp_(disp), a_(a),
     hash_(0)
@@ -595,7 +595,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Color_RGBA::Color_RGBA(ParserState pstate, double r, double g, double b, double a, const std::string disp)
+  Color_RGBA::Color_RGBA(SourceSpan pstate, double r, double g, double b, double a, const sass::string disp)
   : Color(pstate, a, disp),
     r_(r), g_(g), b_(b)
   { concrete_type(COLOR); }
@@ -638,7 +638,7 @@
   size_t Color_RGBA::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()("RGBA");
+      hash_ = std::hash<sass::string>()("RGBA");
       hash_combine(hash_, std::hash<double>()(a_));
       hash_combine(hash_, std::hash<double>()(r_));
       hash_combine(hash_, std::hash<double>()(g_));
@@ -693,7 +693,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Color_HSLA::Color_HSLA(ParserState pstate, double h, double s, double l, double a, const std::string disp)
+  Color_HSLA::Color_HSLA(SourceSpan pstate, double h, double s, double l, double a, const sass::string disp)
   : Color(pstate, a, disp),
     h_(absmod(h, 360.0)),
     s_(clip(s, 0.0, 100.0)),
@@ -740,7 +740,7 @@
   size_t Color_HSLA::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()("HSLA");
+      hash_ = std::hash<sass::string>()("HSLA");
       hash_combine(hash_, std::hash<double>()(a_));
       hash_combine(hash_, std::hash<double>()(h_));
       hash_combine(hash_, std::hash<double>()(s_));
@@ -789,7 +789,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Custom_Error::Custom_Error(ParserState pstate, std::string msg)
+  Custom_Error::Custom_Error(SourceSpan pstate, sass::string msg)
   : Value(pstate), message_(msg)
   { concrete_type(C_ERROR); }
 
@@ -817,7 +817,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Custom_Warning::Custom_Warning(ParserState pstate, std::string msg)
+  Custom_Warning::Custom_Warning(SourceSpan pstate, sass::string msg)
   : Value(pstate), message_(msg)
   { concrete_type(C_WARNING); }
 
@@ -845,7 +845,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Boolean::Boolean(ParserState pstate, bool val)
+  Boolean::Boolean(SourceSpan pstate, bool val)
   : Value(pstate), value_(val),
     hash_(0)
   { concrete_type(BOOLEAN); }
@@ -883,7 +883,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  String::String(ParserState pstate, bool delayed)
+  String::String(SourceSpan pstate, bool delayed)
   : Value(pstate, delayed)
   { concrete_type(STRING); }
   String::String(const String* ptr)
@@ -893,13 +893,13 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  String_Schema::String_Schema(ParserState pstate, size_t size, bool css)
-  : String(pstate), Vectorized<PreValue_Obj>(size), css_(css), hash_(0)
+  String_Schema::String_Schema(SourceSpan pstate, size_t size, bool css)
+  : String(pstate), Vectorized<PreValueObj>(size), css_(css), hash_(0)
   { concrete_type(STRING); }
 
   String_Schema::String_Schema(const String_Schema* ptr)
   : String(ptr),
-    Vectorized<PreValue_Obj>(*ptr),
+    Vectorized<PreValueObj>(*ptr),
     css_(ptr->css_),
     hash_(ptr->hash_)
   { concrete_type(STRING); }
@@ -976,17 +976,17 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  String_Constant::String_Constant(ParserState pstate, std::string val, bool css)
+  String_Constant::String_Constant(SourceSpan pstate, sass::string val, bool css)
   : String(pstate), quote_mark_(0), value_(read_css_string(val, css)), hash_(0)
   { }
-  String_Constant::String_Constant(ParserState pstate, const char* beg, bool css)
-  : String(pstate), quote_mark_(0), value_(read_css_string(std::string(beg), css)), hash_(0)
+  String_Constant::String_Constant(SourceSpan pstate, const char* beg, bool css)
+  : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(beg), css)), hash_(0)
   { }
-  String_Constant::String_Constant(ParserState pstate, const char* beg, const char* end, bool css)
-  : String(pstate), quote_mark_(0), value_(read_css_string(std::string(beg, end-beg), css)), hash_(0)
+  String_Constant::String_Constant(SourceSpan pstate, const char* beg, const char* end, bool css)
+  : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(beg, end-beg), css)), hash_(0)
   { }
-  String_Constant::String_Constant(ParserState pstate, const Token& tok, bool css)
-  : String(pstate), quote_mark_(0), value_(read_css_string(std::string(tok.begin, tok.end), css)), hash_(0)
+  String_Constant::String_Constant(SourceSpan pstate, const Token& tok, bool css)
+  : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(tok.begin, tok.end), css)), hash_(0)
   { }
 
   String_Constant::String_Constant(const String_Constant* ptr)
@@ -1023,7 +1023,7 @@
     return false;
   }
 
-  std::string String_Constant::inspect() const
+  sass::string String_Constant::inspect() const
   {
     return quote(value_, '*');
   }
@@ -1036,7 +1036,7 @@
   size_t String_Constant::hash() const
   {
     if (hash_ == 0) {
-      hash_ = std::hash<std::string>()(value_);
+      hash_ = std::hash<sass::string>()(value_);
     }
     return hash_;
   }
@@ -1044,7 +1044,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  String_Quoted::String_Quoted(ParserState pstate, std::string val, char q,
+  String_Quoted::String_Quoted(SourceSpan pstate, sass::string val, char q,
     bool keep_utf8_escapes, bool skip_unquoting,
     bool strict_unquoting, bool css)
   : String_Constant(pstate, val, css)
@@ -1082,7 +1082,7 @@
     return false;
   }
 
-  std::string String_Quoted::inspect() const
+  sass::string String_Quoted::inspect() const
   {
     return quote(value_, '*');
   }
@@ -1090,7 +1090,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Null::Null(ParserState pstate)
+  Null::Null(SourceSpan pstate)
   : Value(pstate)
   { concrete_type(NULL_VAL); }
 
@@ -1119,7 +1119,7 @@
   /////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////
 
-  Parent_Reference::Parent_Reference(ParserState pstate)
+  Parent_Reference::Parent_Reference(SourceSpan pstate)
   : Value(pstate)
   { concrete_type(PARENT); }
 
diff --git a/libsass/src/ast_values.hpp b/libsass/src/ast_values.hpp
--- a/libsass/src/ast_values.hpp
+++ b/libsass/src/ast_values.hpp
@@ -13,7 +13,7 @@
   //////////////////////////////////////////////////////////////////////
   class PreValue : public Expression {
   public:
-    PreValue(ParserState pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
+    PreValue(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
     ATTACH_VIRTUAL_AST_OPERATIONS(PreValue);
     virtual ~PreValue() { }
   };
@@ -23,7 +23,7 @@
   //////////////////////////////////////////////////////////////////////
   class Value : public PreValue {
   public:
-    Value(ParserState pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
+    Value(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE);
 
     // Some obects are not meant to be compared
     // ToDo: maybe fallback to pointer comparison?
@@ -47,23 +47,23 @@
   // Lists of values, both comma- and space-separated (distinguished by a
   // type-tag.) Also used to represent variable-length argument lists.
   ///////////////////////////////////////////////////////////////////////
-  class List : public Value, public Vectorized<Expression_Obj> {
-    void adjust_after_pushing(Expression_Obj e) override { is_expanded(false); }
+  class List : public Value, public Vectorized<ExpressionObj> {
+    void adjust_after_pushing(ExpressionObj e) override { is_expanded(false); }
   private:
     ADD_PROPERTY(enum Sass_Separator, separator)
     ADD_PROPERTY(bool, is_arglist)
     ADD_PROPERTY(bool, is_bracketed)
     ADD_PROPERTY(bool, from_selector)
   public:
-    List(ParserState pstate, size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false);
-    std::string type() const override { return is_arglist_ ? "arglist" : "list"; }
-    static std::string type_name() { return "list"; }
+    List(SourceSpan pstate, size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false);
+    sass::string type() const override { return is_arglist_ ? "arglist" : "list"; }
+    static sass::string type_name() { return "list"; }
     const char* sep_string(bool compressed = false) const {
       return separator() == SASS_SPACE ?
         " " : (compressed ? "," : ", ");
     }
     bool is_invisible() const override { return empty() && !is_bracketed(); }
-    Expression_Obj value_at_index(size_t i);
+    ExpressionObj value_at_index(size_t i);
 
     virtual size_t hash() const override;
     virtual size_t size() const;
@@ -79,14 +79,14 @@
   ///////////////////////////////////////////////////////////////////////
   // Key value paris.
   ///////////////////////////////////////////////////////////////////////
-  class Map : public Value, public Hashed<Expression_Obj, Expression_Obj, Map_Obj> {
-    void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) override { is_expanded(false); }
+  class Map : public Value, public Hashed<ExpressionObj, ExpressionObj, Map_Obj> {
+    void adjust_after_pushing(std::pair<ExpressionObj, ExpressionObj> p) override { is_expanded(false); }
   public:
-    Map(ParserState pstate, size_t size = 0);
-    std::string type() const override { return "map"; }
-    static std::string type_name() { return "map"; }
+    Map(SourceSpan pstate, size_t size = 0);
+    sass::string type() const override { return "map"; }
+    static sass::string type_name() { return "map"; }
     bool is_invisible() const override { return empty(); }
-    List_Obj to_list(ParserState& pstate);
+    List_Obj to_list(SourceSpan& pstate);
 
     virtual size_t hash() const override;
 
@@ -106,15 +106,15 @@
   class Binary_Expression : public PreValue {
   private:
     HASH_PROPERTY(Operand, op)
-    HASH_PROPERTY(Expression_Obj, left)
-    HASH_PROPERTY(Expression_Obj, right)
+    HASH_PROPERTY(ExpressionObj, left)
+    HASH_PROPERTY(ExpressionObj, right)
     mutable size_t hash_;
   public:
-    Binary_Expression(ParserState pstate,
-                      Operand op, Expression_Obj lhs, Expression_Obj rhs);
+    Binary_Expression(SourceSpan pstate,
+                      Operand op, ExpressionObj lhs, ExpressionObj rhs);
 
-    const std::string type_name();
-    const std::string separator();
+    const sass::string type_name();
+    const sass::string separator();
     bool is_left_interpolant(void) const override;
     bool is_right_interpolant(void) const override;
     bool has_interpolant() const override;
@@ -138,13 +138,13 @@
     ADD_PROPERTY(Definition_Obj, definition)
     ADD_PROPERTY(bool, is_css)
   public:
-    Function(ParserState pstate, Definition_Obj def, bool css);
+    Function(SourceSpan pstate, Definition_Obj def, bool css);
 
-    std::string type() const override { return "function"; }
-    static std::string type_name() { return "function"; }
+    sass::string type() const override { return "function"; }
+    static sass::string type_name() { return "function"; }
     bool is_invisible() const override { return true; }
 
-    std::string name();
+    sass::string name();
 
     bool operator< (const Expression& rhs) const override;
     bool operator== (const Expression& rhs) const override;
@@ -164,15 +164,15 @@
     ADD_PROPERTY(void*, cookie)
     mutable size_t hash_;
   public:
-    Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie);
-    Function_Call(ParserState pstate, std::string n, Arguments_Obj args, Function_Obj func);
-    Function_Call(ParserState pstate, std::string n, Arguments_Obj args);
+    Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, void* cookie);
+    Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Function_Obj func);
+    Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args);
 
-    Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, void* cookie);
-    Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, Function_Obj func);
-    Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args);
+    Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, void* cookie);
+    Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, Function_Obj func);
+    Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args);
 
-    std::string name() const;
+    sass::string name() const;
     bool is_css();
 
     bool operator==(const Expression& rhs) const override;
@@ -187,9 +187,9 @@
   // Variable references.
   ///////////////////////
   class Variable final : public PreValue {
-    ADD_CONSTREF(std::string, name)
+    ADD_CONSTREF(sass::string, name)
   public:
-    Variable(ParserState pstate, std::string n);
+    Variable(SourceSpan pstate, sass::string n);
     virtual bool operator==(const Expression& rhs) const override;
     virtual size_t hash() const override;
     ATTACH_AST_OPERATIONS(Variable)
@@ -204,12 +204,12 @@
     ADD_PROPERTY(bool, zero)
     mutable size_t hash_;
   public:
-    Number(ParserState pstate, double val, std::string u = "", bool zero = true);
+    Number(SourceSpan pstate, double val, sass::string u = "", bool zero = true);
 
     bool zero() { return zero_; }
 
-    std::string type() const override { return "number"; }
-    static std::string type_name() { return "number"; }
+    sass::string type() const override { return "number"; }
+    static sass::string type_name() { return "number"; }
 
     // cancel out unnecessary units
     // result will be in input units
@@ -233,15 +233,15 @@
   // Colors.
   //////////
   class Color : public Value {
-    ADD_CONSTREF(std::string, disp)
+    ADD_CONSTREF(sass::string, disp)
     HASH_PROPERTY(double, a)
   protected:
     mutable size_t hash_;
   public:
-    Color(ParserState pstate, double a = 1, const std::string disp = "");
+    Color(SourceSpan pstate, double a = 1, const sass::string disp = "");
 
-    std::string type() const override { return "color"; }
-    static std::string type_name() { return "color"; }
+    sass::string type() const override { return "color"; }
+    static sass::string type_name() { return "color"; }
 
     virtual size_t hash() const override = 0;
 
@@ -265,10 +265,10 @@
     HASH_PROPERTY(double, g)
     HASH_PROPERTY(double, b)
   public:
-    Color_RGBA(ParserState pstate, double r, double g, double b, double a = 1, const std::string disp = "");
+    Color_RGBA(SourceSpan pstate, double r, double g, double b, double a = 1, const sass::string disp = "");
 
-    std::string type() const override { return "color"; }
-    static std::string type_name() { return "color"; }
+    sass::string type() const override { return "color"; }
+    static sass::string type_name() { return "color"; }
 
     size_t hash() const override;
 
@@ -294,10 +294,10 @@
     HASH_PROPERTY(double, s)
     HASH_PROPERTY(double, l)
   public:
-    Color_HSLA(ParserState pstate, double h, double s, double l, double a = 1, const std::string disp = "");
+    Color_HSLA(SourceSpan pstate, double h, double s, double l, double a = 1, const sass::string disp = "");
 
-    std::string type() const override { return "color"; }
-    static std::string type_name() { return "color"; }
+    sass::string type() const override { return "color"; }
+    static sass::string type_name() { return "color"; }
 
     size_t hash() const override;
 
@@ -318,9 +318,9 @@
   // Errors from Sass_Values.
   //////////////////////////////
   class Custom_Error final : public Value {
-    ADD_CONSTREF(std::string, message)
+    ADD_CONSTREF(sass::string, message)
   public:
-    Custom_Error(ParserState pstate, std::string msg);
+    Custom_Error(SourceSpan pstate, sass::string msg);
     bool operator< (const Expression& rhs) const override;
     bool operator== (const Expression& rhs) const override;
     ATTACH_AST_OPERATIONS(Custom_Error)
@@ -331,9 +331,9 @@
   // Warnings from Sass_Values.
   //////////////////////////////
   class Custom_Warning final : public Value {
-    ADD_CONSTREF(std::string, message)
+    ADD_CONSTREF(sass::string, message)
   public:
-    Custom_Warning(ParserState pstate, std::string msg);
+    Custom_Warning(SourceSpan pstate, sass::string msg);
     bool operator< (const Expression& rhs) const override;
     bool operator== (const Expression& rhs) const override;
     ATTACH_AST_OPERATIONS(Custom_Warning)
@@ -347,11 +347,11 @@
     HASH_PROPERTY(bool, value)
     mutable size_t hash_;
   public:
-    Boolean(ParserState pstate, bool val);
+    Boolean(SourceSpan pstate, bool val);
     operator bool() override { return value_; }
 
-    std::string type() const override { return "bool"; }
-    static std::string type_name() { return "bool"; }
+    sass::string type() const override { return "bool"; }
+    static sass::string type_name() { return "bool"; }
 
     size_t hash() const override;
 
@@ -370,8 +370,8 @@
   ////////////////////////////////////////////////////////////////////////
   class String : public Value {
   public:
-    String(ParserState pstate, bool delayed = false);
-    static std::string type_name() { return "string"; }
+    String(SourceSpan pstate, bool delayed = false);
+    static sass::string type_name() { return "string"; }
     virtual ~String() = 0;
     virtual void rtrim() = 0;
     virtual bool operator<(const Expression& rhs) const override {
@@ -389,14 +389,14 @@
   // Interpolated strings. Meant to be reduced to flat strings during the
   // evaluation phase.
   ///////////////////////////////////////////////////////////////////////
-  class String_Schema final : public String, public Vectorized<PreValue_Obj> {
+  class String_Schema final : public String, public Vectorized<PreValueObj> {
     ADD_PROPERTY(bool, css)
     mutable size_t hash_;
   public:
-    String_Schema(ParserState pstate, size_t size = 0, bool css = true);
+    String_Schema(SourceSpan pstate, size_t size = 0, bool css = true);
 
-    std::string type() const override { return "string"; }
-    static std::string type_name() { return "string"; }
+    sass::string type() const override { return "string"; }
+    static sass::string type_name() { return "string"; }
 
     bool is_left_interpolant(void) const override;
     bool is_right_interpolant(void) const override;
@@ -417,23 +417,23 @@
   ////////////////////////////////////////////////////////
   class String_Constant : public String {
     ADD_PROPERTY(char, quote_mark)
-    HASH_CONSTREF(std::string, value)
+    HASH_CONSTREF(sass::string, value)
   protected:
     mutable size_t hash_;
   public:
-    String_Constant(ParserState pstate, std::string val, bool css = true);
-    String_Constant(ParserState pstate, const char* beg, bool css = true);
-    String_Constant(ParserState pstate, const char* beg, const char* end, bool css = true);
-    String_Constant(ParserState pstate, const Token& tok, bool css = true);
-    std::string type() const override { return "string"; }
-    static std::string type_name() { return "string"; }
+    String_Constant(SourceSpan pstate, sass::string val, bool css = true);
+    String_Constant(SourceSpan pstate, const char* beg, bool css = true);
+    String_Constant(SourceSpan pstate, const char* beg, const char* end, bool css = true);
+    String_Constant(SourceSpan pstate, const Token& tok, bool css = true);
+    sass::string type() const override { return "string"; }
+    static sass::string type_name() { return "string"; }
     bool is_invisible() const override;
     virtual void rtrim() override;
     size_t hash() const override;
     bool operator< (const Expression& rhs) const override;
     bool operator==(const Expression& rhs) const override;
     // quotes are forced on inspection
-    virtual std::string inspect() const override;
+    virtual sass::string inspect() const override;
     ATTACH_AST_OPERATIONS(String_Constant)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -443,13 +443,13 @@
   ////////////////////////////////////////////////////////
   class String_Quoted final : public String_Constant {
   public:
-    String_Quoted(ParserState pstate, std::string val, char q = 0,
+    String_Quoted(SourceSpan pstate, sass::string val, char q = 0,
       bool keep_utf8_escapes = false, bool skip_unquoting = false,
       bool strict_unquoting = true, bool css = true);
     bool operator< (const Expression& rhs) const override;
     bool operator==(const Expression& rhs) const override;
     // quotes are forced on inspection
-    std::string inspect() const override;
+    sass::string inspect() const override;
     ATTACH_AST_OPERATIONS(String_Quoted)
     ATTACH_CRTP_PERFORM_METHODS()
   };
@@ -459,9 +459,9 @@
   //////////////////
   class Null final : public Value {
   public:
-    Null(ParserState pstate);
-    std::string type() const override { return "null"; }
-    static std::string type_name() { return "null"; }
+    Null(SourceSpan pstate);
+    sass::string type() const override { return "null"; }
+    static sass::string type_name() { return "null"; }
     bool is_invisible() const override { return true; }
     operator bool() override { return false; }
     bool is_false() override { return true; }
@@ -480,9 +480,9 @@
   //////////////////////////////////
   class Parent_Reference final : public Value {
   public:
-    Parent_Reference(ParserState pstate);
-    std::string type() const override { return "parent"; }
-    static std::string type_name() { return "parent"; }
+    Parent_Reference(SourceSpan pstate);
+    sass::string type() const override { return "parent"; }
+    static sass::string type_name() { return "parent"; }
     bool operator< (const Expression& rhs) const override {
       return false; // they are always equal
     }
diff --git a/libsass/src/backtrace.cpp b/libsass/src/backtrace.cpp
--- a/libsass/src/backtrace.cpp
+++ b/libsass/src/backtrace.cpp
@@ -2,20 +2,20 @@
 
 namespace Sass {
 
-  const std::string traces_to_string(Backtraces traces, std::string indent) {
+  const sass::string traces_to_string(Backtraces traces, sass::string indent) {
 
-    std::stringstream ss;
-    std::string cwd(File::get_cwd());
+    sass::ostream ss;
+    sass::string cwd(File::get_cwd());
 
     bool first = true;
     size_t i_beg = traces.size() - 1;
-    size_t i_end = std::string::npos;
+    size_t i_end = sass::string::npos;
     for (size_t i = i_beg; i != i_end; i --) {
 
       const Backtrace& trace = traces[i];
 
       // make path relative to the current directory
-      std::string rel_path(File::abs2rel(trace.pstate.path, cwd, cwd));
+      sass::string rel_path(File::abs2rel(trace.pstate.getPath(), cwd, cwd));
 
       // skip functions on error cases (unsure why ruby sass does this)
       // if (trace.caller.substr(0, 6) == ", in f") continue;
@@ -23,9 +23,9 @@
       if (first) {
         ss << indent;
         ss << "on line ";
-        ss << trace.pstate.line + 1;
+        ss << trace.pstate.getLine();
         ss << ":";
-        ss << trace.pstate.column + 1;
+        ss << trace.pstate.getColumn();
         ss << " of " << rel_path;
         // ss << trace.caller;
         first = false;
@@ -34,9 +34,9 @@
         ss << std::endl;
         ss << indent;
         ss << "from line ";
-        ss << trace.pstate.line + 1;
+        ss << trace.pstate.getLine();
         ss << ":";
-        ss << trace.pstate.column + 1;
+        ss << trace.pstate.getColumn();
         ss << " of " << rel_path;
       }
 
diff --git a/libsass/src/backtrace.hpp b/libsass/src/backtrace.hpp
--- a/libsass/src/backtrace.hpp
+++ b/libsass/src/backtrace.hpp
@@ -10,19 +10,19 @@
 
   struct Backtrace {
 
-    ParserState pstate;
-    std::string caller;
+    SourceSpan pstate;
+    sass::string caller;
 
-    Backtrace(ParserState pstate, std::string c = "")
+    Backtrace(SourceSpan pstate, sass::string c = "")
     : pstate(pstate),
       caller(c)
     { }
 
   };
 
-  typedef std::vector<Backtrace> Backtraces;
+  typedef sass::vector<Backtrace> Backtraces;
 
-  const std::string traces_to_string(Backtraces traces, std::string indent = "\t");
+  const sass::string traces_to_string(Backtraces traces, sass::string indent = "\t");
 
 }
 
diff --git a/libsass/src/base64vlq.cpp b/libsass/src/base64vlq.cpp
--- a/libsass/src/base64vlq.cpp
+++ b/libsass/src/base64vlq.cpp
@@ -6,9 +6,9 @@
 
 namespace Sass {
 
-  std::string Base64VLQ::encode(const int number) const
+  sass::string Base64VLQ::encode(const int number) const
   {
-    std::string encoded = "";
+    sass::string encoded = "";
 
     int vlq = to_vlq_signed(number);
 
diff --git a/libsass/src/base64vlq.hpp b/libsass/src/base64vlq.hpp
--- a/libsass/src/base64vlq.hpp
+++ b/libsass/src/base64vlq.hpp
@@ -9,7 +9,7 @@
 
   public:
 
-    std::string encode(const int number) const;
+    sass::string encode(const int number) const;
 
   private:
 
diff --git a/libsass/src/bind.cpp b/libsass/src/bind.cpp
--- a/libsass/src/bind.cpp
+++ b/libsass/src/bind.cpp
@@ -11,11 +11,11 @@
 
 namespace Sass {
 
-  void bind(std::string type, std::string name, Parameters_Obj ps, Arguments_Obj as, Env* env, Eval* eval, Backtraces& traces)
+  void bind(sass::string type, sass::string name, Parameters_Obj ps, Arguments_Obj as, Env* env, Eval* eval, Backtraces& traces)
   {
-    std::string callee(type + " " + name);
+    sass::string callee(type + " " + name);
 
-    std::map<std::string, Parameter_Obj> param_map;
+    std::map<sass::string, Parameter_Obj> param_map;
     List_Obj varargs = SASS_MEMORY_NEW(List, as->pstate());
     varargs->is_arglist(true); // enable keyword size handling
 
@@ -52,7 +52,7 @@
             }
           }
         }
-        std::stringstream msg;
+        sass::ostream msg;
         msg << "wrong number of arguments (" << LA << " for " << LP << ")";
         msg << " for `" << name << "'";
         return error(msg.str(), as->pstate(), traces);
@@ -73,7 +73,7 @@
                                               rest->separator(),
                                               true);
               // wrap each item from list as an argument
-              for (Expression_Obj item : rest->elements()) {
+              for (ExpressionObj item : rest->elements()) {
                 if (Argument_Obj arg = Cast<Argument>(item)) {
                   arglist->append(SASS_MEMORY_COPY(arg)); // copy
                 } else {
@@ -100,7 +100,7 @@
           Map_Obj argmap = Cast<Map>(a->value());
           for (auto key : argmap->keys()) {
             if (String_Constant_Obj str = Cast<String_Constant>(key)) {
-              std::string param = unquote(str->value());
+              sass::string param = unquote(str->value());
               arglist->append(SASS_MEMORY_NEW(Argument,
                                               key->pstate(),
                                               argmap->at(key),
@@ -130,7 +130,7 @@
             // skip any list completely if empty
             if (ls && ls->empty() && a->is_rest_argument()) continue;
 
-            Expression_Obj value = a->value();
+            ExpressionObj value = a->value();
             if (Argument_Obj arg = Cast<Argument>(value)) {
               arglist->append(arg);
             }
@@ -141,7 +141,7 @@
                 arglist->separator(rest->separator());
 
                 for (size_t i = 0, L = rest->length(); i < L; ++i) {
-                  Expression_Obj obj = rest->value_at_index(i);
+                  ExpressionObj obj = rest->value_at_index(i);
                   arglist->append(SASS_MEMORY_NEW(Argument,
                                                 obj->pstate(),
                                                 obj,
@@ -177,7 +177,7 @@
         // normal param and rest arg
         List_Obj arglist = Cast<List>(a->value());
         if (!arglist) {
-          if (Expression_Obj arg = Cast<Expression>(a->value())) {
+          if (ExpressionObj arg = Cast<Expression>(a->value())) {
             arglist = SASS_MEMORY_NEW(List, a->pstate(), 1);
             arglist->append(arg);
           }
@@ -189,7 +189,7 @@
         } else {
           if (arglist->length() > LP - ip && !ps->has_rest_parameter()) {
             size_t arg_count = (arglist->length() + LA - 1);
-            std::stringstream msg;
+            sass::ostream msg;
             msg << callee << " takes " << LP;
             msg << (LP == 1 ? " argument" : " arguments");
             msg << " but " << arg_count;
@@ -202,7 +202,7 @@
           }
         }
         // otherwise move one of the rest args into the param, converting to argument if necessary
-        Expression_Obj obj = arglist->at(0);
+        ExpressionObj obj = arglist->at(0);
         if (!(a = Cast<Argument>(obj))) {
           Expression* a_to_convert = obj;
           a = SASS_MEMORY_NEW(Argument,
@@ -226,10 +226,10 @@
             traces.push_back(Backtrace(key->pstate()));
             throw Exception::InvalidVarKwdType(key->pstate(), traces, key->inspect(), a);
           }
-          std::string param = "$" + unquote(val->value());
+          sass::string param = "$" + unquote(val->value());
 
           if (!param_map.count(param)) {
-            std::stringstream msg;
+            sass::ostream msg;
             msg << callee << " has no parameter named " << param;
             error(msg.str(), a->pstate(), traces);
           }
@@ -243,7 +243,7 @@
 
       if (a->name().empty()) {
         if (env->has_local(p->name())) {
-          std::stringstream msg;
+          sass::ostream msg;
           msg << "parameter " << p->name()
           << " provided more than once in call to " << callee;
           error(msg.str(), a->pstate(), traces);
@@ -258,21 +258,21 @@
           if (ps->has_rest_parameter()) {
             varargs->append(a);
           } else {
-            std::stringstream msg;
+            sass::ostream msg;
             msg << callee << " has no parameter named " << a->name();
             error(msg.str(), a->pstate(), traces);
           }
         }
         if (param_map[a->name()]) {
           if (param_map[a->name()]->is_rest_parameter()) {
-            std::stringstream msg;
+            sass::ostream msg;
             msg << "argument " << a->name() << " of " << callee
                 << "cannot be used as named argument";
             error(msg.str(), a->pstate(), traces);
           }
         }
         if (env->has_local(a->name())) {
-          std::stringstream msg;
+          sass::ostream msg;
           msg << "parameter " << p->name()
               << "provided more than once in call to " << callee;
           error(msg.str(), a->pstate(), traces);
diff --git a/libsass/src/bind.hpp b/libsass/src/bind.hpp
--- a/libsass/src/bind.hpp
+++ b/libsass/src/bind.hpp
@@ -8,7 +8,7 @@
 
 namespace Sass {
 
-  void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Env*, Eval*, Backtraces& traces);
+  void bind(sass::string type, sass::string name, Parameters_Obj, Arguments_Obj, Env*, Eval*, Backtraces& traces);
 
 }
 
diff --git a/libsass/src/c2ast.cpp b/libsass/src/c2ast.cpp
--- a/libsass/src/c2ast.cpp
+++ b/libsass/src/c2ast.cpp
@@ -8,7 +8,7 @@
 
 namespace Sass {
 
-  Value* c2ast(union Sass_Value* v, Backtraces traces, ParserState pstate)
+  Value* c2ast(union Sass_Value* v, Backtraces traces, SourceSpan pstate)
   {
     using std::strlen;
     using std::strcpy;
@@ -51,10 +51,10 @@
         e = SASS_MEMORY_NEW(Null, pstate);
       } break;
       case SASS_ERROR: {
-        error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, traces);
+        error("Error in C function: " + sass::string(sass_error_get_message(v)), pstate, traces);
       } break;
       case SASS_WARNING: {
-        error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, traces);
+        error("Warning in C function: " + sass::string(sass_warning_get_message(v)), pstate, traces);
       } break;
       default: break;
     }
diff --git a/libsass/src/c2ast.hpp b/libsass/src/c2ast.hpp
--- a/libsass/src/c2ast.hpp
+++ b/libsass/src/c2ast.hpp
@@ -7,7 +7,7 @@
 
 namespace Sass {
 
-  Value* c2ast(union Sass_Value* v, Backtraces traces, ParserState pstate);
+  Value* c2ast(union Sass_Value* v, Backtraces traces, SourceSpan pstate);
 
 }
 
diff --git a/libsass/src/check_nesting.cpp b/libsass/src/check_nesting.cpp
--- a/libsass/src/check_nesting.cpp
+++ b/libsass/src/check_nesting.cpp
@@ -7,12 +7,12 @@
 namespace Sass {
 
   CheckNesting::CheckNesting()
-  : parents(std::vector<Statement*>()),
-    traces(std::vector<Backtrace>()),
+  : parents(sass::vector<Statement*>()),
+    traces(sass::vector<Backtrace>()),
     parent(0), current_mixin_definition(0)
   { }
 
-  void error(AST_Node* node, Backtraces traces, std::string msg) {
+  void error(AST_Node* node, Backtraces traces, sass::string msg) {
     traces.push_back(Backtrace(node->pstate()));
     throw Exception::InvalidSass(node->pstate(), traces, msg);
   }
@@ -21,9 +21,9 @@
   {
     Statement* old_parent = this->parent;
 
-    if (At_Root_Block* root = Cast<At_Root_Block>(parent)) {
-      std::vector<Statement*> old_parents = this->parents;
-      std::vector<Statement*> new_parents;
+    if (AtRootRule* root = Cast<AtRootRule>(parent)) {
+      sass::vector<Statement*> old_parents = this->parents;
+      sass::vector<Statement*> new_parents;
 
       for (size_t i = 0, L = this->parents.size(); i < L; i++) {
         Statement* p = this->parents.at(i);
@@ -45,7 +45,7 @@
         }
       }
 
-      At_Root_Block* ar = Cast<At_Root_Block>(parent);
+      AtRootRule* ar = Cast<AtRootRule>(parent);
       Block* ret = ar->block();
 
       if (ret != NULL) {
@@ -75,7 +75,7 @@
     }
 
     if (!b) {
-      if (Has_Block* bb = Cast<Has_Block>(parent)) {
+      if (ParentStatement* bb = Cast<ParentStatement>(parent)) {
         b = bb->block();
       }
     }
@@ -192,7 +192,7 @@
   void CheckNesting::invalid_extend_parent(Statement* parent, AST_Node* node)
   {
     if (!(
-        Cast<Ruleset>(parent) ||
+        Cast<StyleRule>(parent) ||
         Cast<Mixin_Call>(parent) ||
         is_mixin(parent)
     )) {
@@ -204,10 +204,10 @@
   // {
   //   for (auto pp : this->parents) {
   //     if (
-  //         Cast<Each>(pp) ||
-  //         Cast<For>(pp) ||
+  //         Cast<EachRule>(pp) ||
+  //         Cast<ForRule>(pp) ||
   //         Cast<If>(pp) ||
-  //         Cast<While>(pp) ||
+  //         Cast<WhileRule>(pp) ||
   //         Cast<Trace>(pp) ||
   //         Cast<Mixin_Call>(pp) ||
   //         is_mixin(pp)
@@ -229,10 +229,10 @@
   {
     for (Statement* pp : this->parents) {
       if (
-          Cast<Each>(pp) ||
-          Cast<For>(pp) ||
+          Cast<EachRule>(pp) ||
+          Cast<ForRule>(pp) ||
           Cast<If>(pp) ||
-          Cast<While>(pp) ||
+          Cast<WhileRule>(pp) ||
           Cast<Trace>(pp) ||
           Cast<Mixin_Call>(pp) ||
           is_mixin(pp)
@@ -246,10 +246,10 @@
   {
     for (Statement* pp : this->parents) {
       if (
-          Cast<Each>(pp) ||
-          Cast<For>(pp) ||
+          Cast<EachRule>(pp) ||
+          Cast<ForRule>(pp) ||
           Cast<If>(pp) ||
-          Cast<While>(pp) ||
+          Cast<WhileRule>(pp) ||
           Cast<Trace>(pp) ||
           Cast<Mixin_Call>(pp) ||
           is_mixin(pp)
@@ -262,19 +262,19 @@
   void CheckNesting::invalid_function_child(Statement* child)
   {
     if (!(
-        Cast<Each>(child) ||
-        Cast<For>(child) ||
+        Cast<EachRule>(child) ||
+        Cast<ForRule>(child) ||
         Cast<If>(child) ||
-        Cast<While>(child) ||
+        Cast<WhileRule>(child) ||
         Cast<Trace>(child) ||
         Cast<Comment>(child) ||
-        Cast<Debug>(child) ||
+        Cast<DebugRule>(child) ||
         Cast<Return>(child) ||
         Cast<Variable>(child) ||
         // Ruby Sass doesn't distinguish variables and assignments
         Cast<Assignment>(child) ||
-        Cast<Warning>(child) ||
-        Cast<Error>(child)
+        Cast<WarningRule>(child) ||
+        Cast<ErrorRule>(child)
     )) {
       error(child, traces, "Functions can only contain variable declarations and control directives.");
     }
@@ -283,10 +283,10 @@
   void CheckNesting::invalid_prop_child(Statement* child)
   {
     if (!(
-        Cast<Each>(child) ||
-        Cast<For>(child) ||
+        Cast<EachRule>(child) ||
+        Cast<ForRule>(child) ||
         Cast<If>(child) ||
-        Cast<While>(child) ||
+        Cast<WhileRule>(child) ||
         Cast<Trace>(child) ||
         Cast<Comment>(child) ||
         Cast<Declaration>(child) ||
@@ -301,7 +301,7 @@
     if (!(
         is_mixin(parent) ||
         is_directive_node(parent) ||
-        Cast<Ruleset>(parent) ||
+        Cast<StyleRule>(parent) ||
         Cast<Keyframe_Rule>(parent) ||
         Cast<Declaration>(parent) ||
         Cast<Mixin_Call>(parent)
@@ -343,17 +343,17 @@
                              !is_at_root_node(grandparent);
 
     return Cast<Import>(parent) ||
-           Cast<Each>(parent) ||
-           Cast<For>(parent) ||
+           Cast<EachRule>(parent) ||
+           Cast<ForRule>(parent) ||
            Cast<If>(parent) ||
-           Cast<While>(parent) ||
+           Cast<WhileRule>(parent) ||
            Cast<Trace>(parent) ||
            valid_bubble_node;
   }
 
   bool CheckNesting::is_charset(Statement* n)
   {
-    Directive* d = Cast<Directive>(n);
+    AtRule* d = Cast<AtRule>(n);
     return d && d->keyword() == "charset";
   }
 
@@ -371,7 +371,7 @@
 
   bool CheckNesting::is_root_node(Statement* n)
   {
-    if (Cast<Ruleset>(n)) return false;
+    if (Cast<StyleRule>(n)) return false;
 
     Block* b = Cast<Block>(n);
     return b && b->is_root();
@@ -379,15 +379,15 @@
 
   bool CheckNesting::is_at_root_node(Statement* n)
   {
-    return Cast<At_Root_Block>(n) != NULL;
+    return Cast<AtRootRule>(n) != NULL;
   }
 
   bool CheckNesting::is_directive_node(Statement* n)
   {
-    return Cast<Directive>(n) ||
+    return Cast<AtRule>(n) ||
            Cast<Import>(n) ||
       Cast<MediaRule>(n) ||
       Cast<CssMediaRule>(n) ||
-      Cast<Supports_Block>(n);
+      Cast<SupportsRule>(n);
   }
 }
diff --git a/libsass/src/check_nesting.hpp b/libsass/src/check_nesting.hpp
--- a/libsass/src/check_nesting.hpp
+++ b/libsass/src/check_nesting.hpp
@@ -12,7 +12,7 @@
 
   class CheckNesting : public Operation_CRTP<Statement*, CheckNesting> {
 
-    std::vector<Statement*>  parents;
+    sass::vector<Statement*>  parents;
     Backtraces                  traces;
     Statement*               parent;
     Definition*              current_mixin_definition;
@@ -33,7 +33,7 @@
       Statement* s = Cast<Statement>(x);
       if (s && this->should_visit(s)) {
         Block* b1 = Cast<Block>(s);
-        Has_Block* b2 = Cast<Has_Block>(s);
+        ParentStatement* b2 = Cast<ParentStatement>(s);
         if (b1 || b2) return visit_children(s);
       }
       return s;
diff --git a/libsass/src/color_maps.cpp b/libsass/src/color_maps.cpp
--- a/libsass/src/color_maps.cpp
+++ b/libsass/src/color_maps.cpp
@@ -162,7 +162,7 @@
   }
 
   namespace Colors {
-    const ParserState color_table("[COLOR TABLE]");
+    const SourceSpan color_table("[COLOR TABLE]");
     const Color_RGBA aliceblue(color_table, 240, 248, 255, 1);
     const Color_RGBA antiquewhite(color_table, 250, 235, 215, 1);
     const Color_RGBA cyan(color_table, 0, 255, 255, 1);
@@ -456,7 +456,7 @@
     { 102 * 0x10000 +  51 * 0x100 + 153, ColorNames::rebeccapurple }
   };
 
-  static const auto *const names_to_colors = new std::unordered_map<std::string, const Color_RGBA*>
+  static const auto *const names_to_colors = new std::unordered_map<sass::string, const Color_RGBA*>
   {
     { ColorNames::aliceblue, &Colors::aliceblue },
     { ColorNames::antiquewhite, &Colors::antiquewhite },
@@ -611,13 +611,13 @@
 
   const Color_RGBA* name_to_color(const char* key)
   {
-    return name_to_color(std::string(key));
+    return name_to_color(sass::string(key));
   }
 
-  const Color_RGBA* name_to_color(const std::string& key)
+  const Color_RGBA* name_to_color(const sass::string& key)
   {
     // case insensitive lookup.  See #2462
-    std::string lower = key;
+    sass::string lower = key;
     Util::ascii_str_tolower(&lower);
 
     auto p = names_to_colors->find(lower);
diff --git a/libsass/src/color_maps.hpp b/libsass/src/color_maps.hpp
--- a/libsass/src/color_maps.hpp
+++ b/libsass/src/color_maps.hpp
@@ -313,7 +313,7 @@
   }
 
   const Color_RGBA* name_to_color(const char*);
-  const Color_RGBA* name_to_color(const std::string&);
+  const Color_RGBA* name_to_color(const sass::string&);
   const char* color_to_name(const int);
   const char* color_to_name(const Color_RGBA&);
   const char* color_to_name(const double);
diff --git a/libsass/src/context.cpp b/libsass/src/context.cpp
--- a/libsass/src/context.cpp
+++ b/libsass/src/context.cpp
@@ -17,6 +17,7 @@
 #include "expand.hpp"
 #include "parser.hpp"
 #include "cssize.hpp"
+#include "source.hpp"
 
 namespace Sass {
   using namespace Constants;
@@ -26,13 +27,13 @@
   inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j)
   { return sass_importer_get_priority(i) > sass_importer_get_priority(j); }
 
-  static std::string safe_input(const char* in_path)
+  static sass::string safe_input(const char* in_path)
   {
     if (in_path == nullptr || in_path[0] == '\0') return "stdin";
     return in_path;
   }
 
-  static std::string safe_output(const char* out_path, std::string input_path)
+  static sass::string safe_output(const char* out_path, sass::string input_path)
   {
     if (out_path == nullptr || out_path[0] == '\0') {
       if (input_path.empty()) return "stdout";
@@ -59,9 +60,9 @@
     extender(Extender::NORMAL, traces),
     c_compiler(NULL),
 
-    c_headers               (std::vector<Sass_Importer_Entry>()),
-    c_importers             (std::vector<Sass_Importer_Entry>()),
-    c_functions             (std::vector<Sass_Function_Entry>()),
+    c_headers               (sass::vector<Sass_Importer_Entry>()),
+    c_importers             (sass::vector<Sass_Importer_Entry>()),
+    c_functions             (sass::vector<Sass_Function_Entry>()),
 
     indent                  (safe_str(c_options.indent, "  ")),
     linefeed                (safe_str(c_options.linefeed, "\n")),
@@ -155,7 +156,7 @@
       const char* end = Prelexer::find_first<PATH_SEP>(beg);
 
       while (end) {
-        std::string path(beg, end - beg);
+        sass::string path(beg, end - beg);
         if (!path.empty()) {
           if (*path.rbegin() != '/') path += '/';
           include_paths.push_back(path);
@@ -164,7 +165,7 @@
         end = Prelexer::find_first<PATH_SEP>(beg);
       }
 
-      std::string path(beg);
+      sass::string path(beg);
       if (!path.empty()) {
         if (*path.rbegin() != '/') path += '/';
         include_paths.push_back(path);
@@ -188,7 +189,7 @@
       const char* end = Prelexer::find_first<PATH_SEP>(beg);
 
       while (end) {
-        std::string path(beg, end - beg);
+        sass::string path(beg, end - beg);
         if (!path.empty()) {
           if (*path.rbegin() != '/') path += '/';
           plugin_paths.push_back(path);
@@ -197,7 +198,7 @@
         end = Prelexer::find_first<PATH_SEP>(beg);
       }
 
-      std::string path(beg);
+      sass::string path(beg);
       if (!path.empty()) {
         if (*path.rbegin() != '/') path += '/';
         plugin_paths.push_back(path);
@@ -216,17 +217,17 @@
 
   // resolve the imp_path in base_path or include_paths
   // looks for alternatives and returns a list from one directory
-  std::vector<Include> Context::find_includes(const Importer& import)
+  sass::vector<Include> Context::find_includes(const Importer& import)
   {
     // make sure we resolve against an absolute path
-    std::string base_path(rel2abs(import.base_path));
+    sass::string base_path(rel2abs(import.base_path));
     // first try to resolve the load path relative to the base path
-    std::vector<Include> vec(resolve_includes(base_path, import.imp_path));
+    sass::vector<Include> vec(resolve_includes(base_path, import.imp_path));
     // then search in every include path (but only if nothing found yet)
     for (size_t i = 0, S = include_paths.size(); vec.size() == 0 && i < S; ++i)
     {
       // call resolve_includes and individual base path and append all results
-      std::vector<Include> resolved(resolve_includes(include_paths[i], import.imp_path));
+      sass::vector<Include> resolved(resolve_includes(include_paths[i], import.imp_path));
       if (resolved.size()) vec.insert(vec.end(), resolved.begin(), resolved.end());
     }
     // return vector
@@ -273,22 +274,22 @@
 
     // get pointer to the loaded content
     const char* contents = resources[idx].contents;
-    // keep a copy of the path around (for parserstates)
-    // ToDo: we clean it, but still not very elegant!?
-    strings.push_back(sass_copy_c_string(inc.abs_path.c_str()));
+    SourceFileObj source = SASS_MEMORY_NEW(SourceFile,
+      inc.abs_path.c_str(), contents, idx);
+
     // create the initial parser state from resource
-    ParserState pstate(strings.back(), contents, idx);
+    SourceSpan pstate(source);
 
     // check existing import stack for possible recursion
     for (size_t i = 0; i < import_stack.size() - 2; ++i) {
       auto parent = import_stack[i];
       if (std::strcmp(parent->abs_path, import->abs_path) == 0) {
-        std::string cwd(File::get_cwd());
+        sass::string cwd(File::get_cwd());
         // make path relative to the current directory
-        std::string stack("An @import loop has been found:");
+        sass::string stack("An @import loop has been found:");
         for (size_t n = 1; n < i + 2; ++n) {
-          stack += "\n    " + std::string(File::abs2rel(import_stack[n]->abs_path, cwd, cwd)) +
-            " imports " + std::string(File::abs2rel(import_stack[n+1]->abs_path, cwd, cwd));
+          stack += "\n    " + sass::string(File::abs2rel(import_stack[n]->abs_path, cwd, cwd)) +
+            " imports " + sass::string(File::abs2rel(import_stack[n+1]->abs_path, cwd, cwd));
         }
         // implement error throw directly until we
         // decided how to handle full stack traces
@@ -298,7 +299,7 @@
     }
 
     // create a parser instance from the given c_str buffer
-    Parser p(Parser::from_c_str(contents, *this, traces, pstate));
+    Parser p(source, *this, traces);
     // do not yet dispose these buffers
     sass_import_take_source(import);
     sass_import_take_srcmap(import);
@@ -309,7 +310,7 @@
     // remove current stack frame
     import_stack.pop_back();
     // create key/value pair for ast node
-    std::pair<const std::string, StyleSheet>
+    std::pair<const sass::string, StyleSheet>
       ast_pair(inc.abs_path, { res, root });
     // register resulting resource
     sheets.insert(ast_pair);
@@ -317,7 +318,7 @@
 
   // register include with resolved path and its content
   // memory of the resources will be freed by us on exit
-  void Context::register_resource(const Include& inc, const Resource& res, ParserState& prstate)
+  void Context::register_resource(const Include& inc, const Resource& res, SourceSpan& prstate)
   {
     traces.push_back(Backtrace(prstate));
     register_resource(inc, res);
@@ -325,16 +326,16 @@
   }
 
   // Add a new import to the context (called from `import_url`)
-  Include Context::load_import(const Importer& imp, ParserState pstate)
+  Include Context::load_import(const Importer& imp, SourceSpan pstate)
   {
 
     // search for valid imports (ie. partials) on the filesystem
     // this may return more than one valid result (ambiguous imp_path)
-    const std::vector<Include> resolved(find_includes(imp));
+    const sass::vector<Include> resolved(find_includes(imp));
 
     // error nicely on ambiguous imp_path
     if (resolved.size() > 1) {
-      std::stringstream msg_stream;
+      sass::ostream msg_stream;
       msg_stream << "It's not clear which file to import for ";
       msg_stream << "'@import \"" << imp.imp_path << "\"'." << "\n";
       msg_stream << "Candidates:" << "\n";
@@ -364,16 +365,16 @@
 
   }
 
-  void Context::import_url (Import* imp, std::string load_path, const std::string& ctx_path) {
+  void Context::import_url (Import* imp, sass::string load_path, const sass::string& ctx_path) {
 
-    ParserState pstate(imp->pstate());
-    std::string imp_path(unquote(load_path));
-    std::string protocol("file");
+    SourceSpan pstate(imp->pstate());
+    sass::string imp_path(unquote(load_path));
+    sass::string protocol("file");
 
     using namespace Prelexer;
     if (const char* proto = sequence< identifier, exactly<':'>, exactly<'/'>, exactly<'/'> >(imp_path.c_str())) {
 
-      protocol = std::string(imp_path.c_str(), proto - 3);
+      protocol = sass::string(imp_path.c_str(), proto - 3);
       // if (protocol.compare("file") && true) { }
     }
 
@@ -387,7 +388,7 @@
       Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc);
       Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate);
       loc_args->append(loc_arg);
-      Function_Call* new_url = SASS_MEMORY_NEW(Function_Call, pstate, std::string("url"), loc_args);
+      Function_Call* new_url = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), loc_args);
       imp->urls().push_back(new_url);
     }
     else {
@@ -403,7 +404,7 @@
 
 
   // call custom importers on the given (unquoted) load_path and eventually parse the resulting style_sheet
-  bool Context::call_loader(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import* imp, std::vector<Sass_Importer_Entry> importers, bool only_one)
+  bool Context::call_loader(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp, sass::vector<Sass_Importer_Entry> importers, bool only_one)
   {
     // unique counter
     size_t count = 0;
@@ -421,9 +422,9 @@
         Sass_Import_List it_includes = includes;
         while (*it_includes) { ++count;
           // create unique path to use as key
-          std::string uniq_path = load_path;
+          sass::string uniq_path = load_path;
           if (!only_one && count) {
-            std::stringstream path_strm;
+            sass::ostream path_strm;
             path_strm << uniq_path << ":" << count;
             uniq_path = path_strm.str();
           }
@@ -440,14 +441,14 @@
           // it may (or may not) override the line and column info
           if (const char* err_message = sass_import_get_error_message(include_ent)) {
             if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, pstate);
-            if (line == std::string::npos && column == std::string::npos) error(err_message, pstate, traces);
-            else error(err_message, ParserState(ctx_path, source, Position(line, column)), traces);
+            if (line == sass::string::npos && column == sass::string::npos) error(err_message, pstate, traces);
+            else { error(err_message, { pstate.source, { line, column } }, traces); }
           }
           // content for import was set
           else if (source) {
             // resolved abs_path should be set by custom importer
             // use the created uniq_path as fallback (maybe enforce)
-            std::string path_key(abs_path ? abs_path : uniq_path);
+            sass::string path_key(abs_path ? abs_path : uniq_path);
             // create the importer struct
             Include include(importer, path_key);
             // attach information to AST node
@@ -484,7 +485,7 @@
 
   void register_function(Context&, Signature sig, Native_Function f, Env* env);
   void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
-  void register_overload_stub(Context&, std::string name, Env* env);
+  void register_overload_stub(Context&, sass::string name, Env* env);
   void register_built_in_functions(Context&, Env* env);
   void register_c_functions(Context&, Env* env, Sass_Function_List);
   void register_c_function(Context&, Env* env, Sass_Function_Entry);
@@ -517,7 +518,7 @@
     return sass_copy_c_string(emitted.buffer.c_str());
   }
 
-  void Context::apply_custom_headers(Block_Obj root, const char* ctx_path, ParserState pstate)
+  void Context::apply_custom_headers(Block_Obj root, const char* ctx_path, SourceSpan pstate)
   {
     // create a custom import to resolve headers
     Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
@@ -542,7 +543,7 @@
 
     // create absolute path from input filename
     // ToDo: this should be resolved via custom importers
-    std::string abs_path(rel2abs(input_path, CWD));
+    sass::string abs_path(rel2abs(input_path, CWD));
 
     // try to load the entry file
     char* contents = read_file(abs_path);
@@ -557,7 +558,9 @@
     }
 
     // abort early if no content could be loaded (various reasons)
-    if (!contents) throw std::runtime_error("File to read not found or unreadable: " + input_path);
+    if (!contents) throw std::runtime_error(
+      "File to read not found or unreadable: "
+      + std::string(input_path.c_str()));
 
     // store entry path
     entry_path = abs_path;
@@ -600,7 +603,7 @@
     entry_path = input_path.empty() ? "stdin" : input_path;
 
     // ToDo: this may be resolved via custom importers
-    std::string abs_path(rel2abs(entry_path));
+    sass::string abs_path(rel2abs(entry_path));
     char* abs_path_c_str = sass_copy_c_string(abs_path.c_str());
     strings.push_back(abs_path_c_str);
 
@@ -670,38 +673,38 @@
   }
   // EO compile
 
-  std::string Context::format_embedded_source_map()
+  sass::string Context::format_embedded_source_map()
   {
-    std::string map = emitter.render_srcmap(*this);
-    std::istringstream is( map );
-    std::ostringstream buffer;
+    sass::string map = emitter.render_srcmap(*this);
+    sass::istream is( map.c_str() );
+    sass::ostream buffer;
     base64::encoder E;
     E.encode(is, buffer);
-    std::string url = "data:application/json;base64," + buffer.str();
+    sass::string url = "data:application/json;base64," + buffer.str();
     url.erase(url.size() - 1);
     return "/*# sourceMappingURL=" + url + " */";
   }
 
-  std::string Context::format_source_mapping_url(const std::string& file)
+  sass::string Context::format_source_mapping_url(const sass::string& file)
   {
-    std::string url = abs2rel(file, output_path, CWD);
+    sass::string url = abs2rel(file, output_path, CWD);
     return "/*# sourceMappingURL=" + url + " */";
   }
 
   char* Context::render_srcmap()
   {
     if (source_map_file == "") return 0;
-    std::string map = emitter.render_srcmap(*this);
+    sass::string map = emitter.render_srcmap(*this);
     return sass_copy_c_string(map.c_str());
   }
 
 
   // for data context we want to start after "stdin"
   // we probably always want to skip the header includes?
-  std::vector<std::string> Context::get_included_files(bool skip, size_t headers)
+  sass::vector<sass::string> Context::get_included_files(bool skip, size_t headers)
   {
       // create a copy of the vector for manipulations
-      std::vector<std::string> includes = included_files;
+      sass::vector<sass::string> includes = included_files;
       if (includes.size() == 0) return includes;
       if (skip) { includes.erase( includes.begin(), includes.begin() + 1 + headers); }
       else { includes.erase( includes.begin() + 1, includes.begin() + 1 + headers); }
@@ -720,20 +723,20 @@
   void register_function(Context& ctx, Signature sig, Native_Function f, size_t arity, Env* env)
   {
     Definition* def = make_native_function(sig, f, ctx);
-    std::stringstream ss;
+    sass::ostream ss;
     ss << def->name() << "[f]" << arity;
     def->environment(env);
     (*env)[ss.str()] = def;
   }
 
-  void register_overload_stub(Context& ctx, std::string name, Env* env)
+  void register_overload_stub(Context& ctx, sass::string name, Env* env)
   {
     Definition* stub = SASS_MEMORY_NEW(Definition,
-                                       ParserState("[built-in function]"),
-                                       0,
+                                       SourceSpan{ "[built-in function]" },
+                                       nullptr,
                                        name,
-                                       {},
-                                       0,
+                                       Parameters_Obj{},
+                                       nullptr,
                                        true);
     (*env)[name + "[f]"] = stub;
   }
diff --git a/libsass/src/context.hpp b/libsass/src/context.hpp
--- a/libsass/src/context.hpp
+++ b/libsass/src/context.hpp
@@ -19,19 +19,19 @@
 
   class Context {
   public:
-    void import_url (Import* imp, std::string load_path, const std::string& ctx_path);
-    bool call_headers(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import* imp)
+    void import_url (Import* imp, sass::string load_path, const sass::string& ctx_path);
+    bool call_headers(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp)
     { return call_loader(load_path, ctx_path, pstate, imp, c_headers, false); };
-    bool call_importers(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import* imp)
+    bool call_importers(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp)
     { return call_loader(load_path, ctx_path, pstate, imp, c_importers, true); };
 
   private:
-    bool call_loader(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import* imp, std::vector<Sass_Importer_Entry> importers, bool only_one = true);
+    bool call_loader(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp, sass::vector<Sass_Importer_Entry> importers, bool only_one = true);
 
   public:
-    const std::string CWD;
+    const sass::string CWD;
     struct Sass_Options& c_options;
-    std::string entry_path;
+    sass::string entry_path;
     size_t head_imports;
     Plugins plugins;
     Output emitter;
@@ -41,41 +41,41 @@
     CallStack ast_gc;
     // resources add under our control
     // these are guaranteed to be freed
-    std::vector<char*> strings;
-    std::vector<Resource> resources;
-    std::map<const std::string, StyleSheet> sheets;
+    sass::vector<char*> strings;
+    sass::vector<Resource> resources;
+    std::map<const sass::string, StyleSheet> sheets;
     ImporterStack import_stack;
-    std::vector<Sass_Callee> callee_stack;
-    std::vector<Backtrace> traces;
+    sass::vector<Sass_Callee> callee_stack;
+    sass::vector<Backtrace> traces;
     Extender extender;
 
     struct Sass_Compiler* c_compiler;
 
     // absolute paths to includes
-    std::vector<std::string> included_files;
+    sass::vector<sass::string> included_files;
     // relative includes for sourcemap
-    std::vector<std::string> srcmap_links;
+    sass::vector<sass::string> srcmap_links;
     // vectors above have same size
 
-    std::vector<std::string> plugin_paths; // relative paths to load plugins
-    std::vector<std::string> include_paths; // lookup paths for includes
+    sass::vector<sass::string> plugin_paths; // relative paths to load plugins
+    sass::vector<sass::string> include_paths; // lookup paths for includes
 
-    void apply_custom_headers(Block_Obj root, const char* path, ParserState pstate);
+    void apply_custom_headers(Block_Obj root, const char* path, SourceSpan pstate);
 
-    std::vector<Sass_Importer_Entry> c_headers;
-    std::vector<Sass_Importer_Entry> c_importers;
-    std::vector<Sass_Function_Entry> c_functions;
+    sass::vector<Sass_Importer_Entry> c_headers;
+    sass::vector<Sass_Importer_Entry> c_importers;
+    sass::vector<Sass_Function_Entry> c_functions;
 
     void add_c_header(Sass_Importer_Entry header);
     void add_c_importer(Sass_Importer_Entry importer);
     void add_c_function(Sass_Function_Entry function);
 
-    const std::string indent; // String to be used for indentation
-    const std::string linefeed; // String to be used for line feeds
-    const std::string input_path; // for relative paths in src-map
-    const std::string output_path; // for relative paths to the output
-    const std::string source_map_file; // path to source map file (enables feature)
-    const std::string source_map_root; // path for sourceRoot property (pass-through)
+    const sass::string indent; // String to be used for indentation
+    const sass::string linefeed; // String to be used for line feeds
+    const sass::string input_path; // for relative paths in src-map
+    const sass::string output_path; // for relative paths to the output
+    const sass::string source_map_file; // path to source map file (enables feature)
+    const sass::string source_map_root; // path for sourceRoot property (pass-through)
 
     virtual ~Context();
     Context(struct Sass_Context&);
@@ -85,29 +85,29 @@
     virtual char* render_srcmap();
 
     void register_resource(const Include&, const Resource&);
-    void register_resource(const Include&, const Resource&, ParserState&);
-    std::vector<Include> find_includes(const Importer& import);
-    Include load_import(const Importer&, ParserState pstate);
+    void register_resource(const Include&, const Resource&, SourceSpan&);
+    sass::vector<Include> find_includes(const Importer& import);
+    Include load_import(const Importer&, SourceSpan pstate);
 
     Sass_Output_Style output_style() { return c_options.output_style; };
-    std::vector<std::string> get_included_files(bool skip = false, size_t headers = 0);
+    sass::vector<sass::string> get_included_files(bool skip = false, size_t headers = 0);
 
   private:
     void collect_plugin_paths(const char* paths_str);
     void collect_plugin_paths(string_list* paths_array);
     void collect_include_paths(const char* paths_str);
     void collect_include_paths(string_list* paths_array);
-    std::string format_embedded_source_map();
-    std::string format_source_mapping_url(const std::string& out_path);
+    sass::string format_embedded_source_map();
+    sass::string format_source_mapping_url(const sass::string& out_path);
 
 
     // void register_built_in_functions(Env* env);
     // void register_function(Signature sig, Native_Function f, Env* env);
     // void register_function(Signature sig, Native_Function f, size_t arity, Env* env);
-    // void register_overload_stub(std::string name, Env* env);
+    // void register_overload_stub(sass::string name, Env* env);
 
   public:
-    const std::string& cwd() { return CWD; };
+    const sass::string& cwd() { return CWD; };
   };
 
   class File_Context : public Context {
diff --git a/libsass/src/cssize.cpp b/libsass/src/cssize.cpp
--- a/libsass/src/cssize.cpp
+++ b/libsass/src/cssize.cpp
@@ -14,7 +14,7 @@
   Cssize::Cssize(Context& ctx)
   : traces(ctx.traces),
     block_stack(BlockStack()),
-    p_stack(std::vector<Statement*>())
+    p_stack(sass::vector<Statement*>())
   { }
 
   Statement* Cssize::parent()
@@ -80,17 +80,17 @@
     return 0;
   }
 
-  Statement* Cssize::operator()(Directive* r)
+  Statement* Cssize::operator()(AtRule* r)
   {
     if (!r->block() || !r->block()->length()) return r;
 
     if (parent()->statement_type() == Statement::RULESET)
     {
-      return (r->is_keyframes()) ? SASS_MEMORY_NEW(Bubble, r->pstate(), r) : bubble(r);
+      return r->is_keyframes() ? SASS_MEMORY_NEW(Bubble, r->pstate(), r) : bubble(r);
     }
 
     p_stack.push_back(r);
-    Directive_Obj rr = SASS_MEMORY_NEW(Directive,
+    AtRuleObj rr = SASS_MEMORY_NEW(AtRule,
                                   r->pstate(),
                                   r->keyword(),
                                   r->selector(),
@@ -107,7 +107,7 @@
         Bubble_Obj s_obj = Cast<Bubble>(s);
         s = s_obj->node();
         if (s->statement_type() != Statement::DIRECTIVE) directive_exists = false;
-        else directive_exists = (Cast<Directive>(s)->keyword() == rr->keyword());
+        else directive_exists = (Cast<AtRule>(s)->keyword() == rr->keyword());
       }
 
     }
@@ -115,7 +115,7 @@
     Block* result = SASS_MEMORY_NEW(Block, rr->pstate());
     if (!(directive_exists || rr->is_keyframes()))
     {
-      Directive* empty_node = Cast<Directive>(rr);
+      AtRule* empty_node = Cast<AtRule>(rr);
       empty_node->block(SASS_MEMORY_NEW(Block, rr->block() ? rr->block()->pstate() : rr->pstate()));
       result->append(empty_node);
     }
@@ -142,7 +142,7 @@
     return debubble(rr->block(), rr);
   }
 
-  Statement* Cssize::operator()(Ruleset* r)
+  Statement* Cssize::operator()(StyleRule* r)
   {
     p_stack.push_back(r);
     // this can return a string schema
@@ -155,7 +155,7 @@
     if (Cast<Statement>(bb) == NULL) {
       error("Illegal nesting: Only properties may be nested beneath properties.", r->block()->pstate(), traces);
     }
-    Ruleset_Obj rr = SASS_MEMORY_NEW(Ruleset,
+    StyleRuleObj rr = SASS_MEMORY_NEW(StyleRule,
                                   r->pstate(),
                                   r->selector(),
                                   bb);
@@ -238,7 +238,7 @@
     return debubble(mm->block(), mm);
   }
 
-  Statement* Cssize::operator()(Supports_Block* m)
+  Statement* Cssize::operator()(SupportsRule* m)
   {
     if (!m->block()->length())
     { return m; }
@@ -248,7 +248,7 @@
 
     p_stack.push_back(m);
 
-    Supports_Block_Obj mm = SASS_MEMORY_NEW(Supports_Block,
+    SupportsRuleObj mm = SASS_MEMORY_NEW(SupportsRule,
                                        m->pstate(),
                                        m->condition(),
                                        operator()(m->block()));
@@ -259,7 +259,7 @@
     return debubble(mm->block(), mm);
   }
 
-  Statement* Cssize::operator()(At_Root_Block* m)
+  Statement* Cssize::operator()(AtRootRule* m)
   {
     bool tmp = false;
     for (size_t i = 0, L = p_stack.size(); i < L; ++i) {
@@ -287,17 +287,17 @@
     return bubble(m);
   }
 
-  Statement* Cssize::bubble(Directive* m)
+  Statement* Cssize::bubble(AtRule* m)
   {
     Block* bb = SASS_MEMORY_NEW(Block, this->parent()->pstate());
-    Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent()));
+    ParentStatementObj new_rule = Cast<ParentStatement>(SASS_MEMORY_COPY(this->parent()));
     new_rule->block(bb);
     new_rule->tabs(this->parent()->tabs());
     new_rule->block()->concat(m->block());
 
     Block_Obj wrapper_block = SASS_MEMORY_NEW(Block, m->block() ? m->block()->pstate() : m->pstate());
     wrapper_block->append(new_rule);
-    Directive_Obj mm = SASS_MEMORY_NEW(Directive,
+    AtRuleObj mm = SASS_MEMORY_NEW(AtRule,
                                   m->pstate(),
                                   m->keyword(),
                                   m->selector(),
@@ -308,11 +308,11 @@
     return bubble;
   }
 
-  Statement* Cssize::bubble(At_Root_Block* m)
+  Statement* Cssize::bubble(AtRootRule* m)
   {
     if (!m || !m->block()) return NULL;
     Block* bb = SASS_MEMORY_NEW(Block, this->parent()->pstate());
-    Has_Block_Obj new_rule = Cast<Has_Block>(SASS_MEMORY_COPY(this->parent()));
+    ParentStatementObj new_rule = Cast<ParentStatement>(SASS_MEMORY_COPY(this->parent()));
     Block* wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
     if (new_rule) {
       new_rule->block(bb);
@@ -321,7 +321,7 @@
       wrapper_block->append(new_rule);
     }
 
-    At_Root_Block* mm = SASS_MEMORY_NEW(At_Root_Block,
+    AtRootRule* mm = SASS_MEMORY_NEW(AtRootRule,
                                         m->pstate(),
                                         wrapper_block,
                                         m->expression());
@@ -329,12 +329,12 @@
     return bubble;
   }
 
-  Statement* Cssize::bubble(Supports_Block* m)
+  Statement* Cssize::bubble(SupportsRule* m)
   {
-    Ruleset_Obj parent = Cast<Ruleset>(SASS_MEMORY_COPY(this->parent()));
+    StyleRuleObj parent = Cast<StyleRule>(SASS_MEMORY_COPY(this->parent()));
 
     Block* bb = SASS_MEMORY_NEW(Block, parent->block()->pstate());
-    Ruleset* new_rule = SASS_MEMORY_NEW(Ruleset,
+    StyleRule* new_rule = SASS_MEMORY_NEW(StyleRule,
                                         parent->pstate(),
                                         parent->selector(),
                                         bb);
@@ -343,7 +343,7 @@
 
     Block* wrapper_block = SASS_MEMORY_NEW(Block, m->block()->pstate());
     wrapper_block->append(new_rule);
-    Supports_Block* mm = SASS_MEMORY_NEW(Supports_Block,
+    SupportsRule* mm = SASS_MEMORY_NEW(SupportsRule,
                                        m->pstate(),
                                        m->condition(),
                                        wrapper_block);
@@ -356,10 +356,10 @@
 
   Statement* Cssize::bubble(CssMediaRule* m)
   {
-    Ruleset_Obj parent = Cast<Ruleset>(SASS_MEMORY_COPY(this->parent()));
+    StyleRuleObj parent = Cast<StyleRule>(SASS_MEMORY_COPY(this->parent()));
 
     Block* bb = SASS_MEMORY_NEW(Block, parent->block()->pstate());
-    Ruleset* new_rule = SASS_MEMORY_NEW(Ruleset,
+    StyleRule* new_rule = SASS_MEMORY_NEW(StyleRule,
       parent->pstate(),
       parent->selector(),
       bb);
@@ -380,7 +380,7 @@
 
   bool Cssize::bubblable(Statement* s)
   {
-    return Cast<Ruleset>(s) || s->bubbles();
+    return Cast<StyleRule>(s) || (s && s->bubbles());
   }
 
   Block* Cssize::flatten(const Block* b)
@@ -401,9 +401,9 @@
     return result;
   }
 
-  std::vector<std::pair<bool, Block_Obj>> Cssize::slice_by_bubble(Block* b)
+  sass::vector<std::pair<bool, Block_Obj>> Cssize::slice_by_bubble(Block* b)
   {
-    std::vector<std::pair<bool, Block_Obj>> results;
+    sass::vector<std::pair<bool, Block_Obj>> results;
 
     for (size_t i = 0, L = b->length(); i < L; ++i) {
       Statement_Obj value = b->at(i);
@@ -426,8 +426,8 @@
 
   Block* Cssize::debubble(Block* children, Statement* parent)
   {
-    Has_Block_Obj previous_parent;
-    std::vector<std::pair<bool, Block_Obj>> baz = slice_by_bubble(children);
+    ParentStatementObj previous_parent;
+    sass::vector<std::pair<bool, Block_Obj>> baz = slice_by_bubble(children);
     Block_Obj result = SASS_MEMORY_NEW(Block, children->pstate());
 
     for (size_t i = 0, L = baz.size(); i < L; ++i) {
@@ -479,7 +479,8 @@
                                     children->pstate(),
                                     children->length(),
                                     children->is_root());
-        bb->append(ss->perform(this));
+        auto evaled = ss->perform(this);
+        if (evaled) bb->append(evaled);
 
         Block_Obj wrapper_block = SASS_MEMORY_NEW(Block,
                                               children->pstate(),
diff --git a/libsass/src/cssize.hpp b/libsass/src/cssize.hpp
--- a/libsass/src/cssize.hpp
+++ b/libsass/src/cssize.hpp
@@ -14,32 +14,32 @@
 
     Backtraces&                 traces;
     BlockStack      block_stack;
-    std::vector<Statement*>  p_stack;
+    sass::vector<Statement*>  p_stack;
 
   public:
     Cssize(Context&);
     ~Cssize() { }
 
     Block* operator()(Block*);
-    Statement* operator()(Ruleset*);
+    Statement* operator()(StyleRule*);
     // Statement* operator()(Bubble*);
     Statement* operator()(CssMediaRule*);
-    Statement* operator()(Supports_Block*);
-    Statement* operator()(At_Root_Block*);
-    Statement* operator()(Directive*);
+    Statement* operator()(SupportsRule*);
+    Statement* operator()(AtRootRule*);
+    Statement* operator()(AtRule*);
     Statement* operator()(Keyframe_Rule*);
     Statement* operator()(Trace*);
     Statement* operator()(Declaration*);
     // Statement* operator()(Assignment*);
     // Statement* operator()(Import*);
     // Statement* operator()(Import_Stub*);
-    // Statement* operator()(Warning*);
+    // Statement* operator()(WarningRule*);
     // Statement* operator()(Error*);
     // Statement* operator()(Comment*);
     // Statement* operator()(If*);
-    // Statement* operator()(For*);
-    // Statement* operator()(Each*);
-    // Statement* operator()(While*);
+    // Statement* operator()(ForRule*);
+    // Statement* operator()(EachRule*);
+    // Statement* operator()(WhileRule*);
     // Statement* operator()(Return*);
     // Statement* operator()(ExtendRule*);
     // Statement* operator()(Definition*);
@@ -48,11 +48,11 @@
     Statement* operator()(Null*);
 
     Statement* parent();
-    std::vector<std::pair<bool, Block_Obj>> slice_by_bubble(Block*);
-    Statement* bubble(Directive*);
-    Statement* bubble(At_Root_Block*);
+    sass::vector<std::pair<bool, Block_Obj>> slice_by_bubble(Block*);
+    Statement* bubble(AtRule*);
+    Statement* bubble(AtRootRule*);
     Statement* bubble(CssMediaRule*);
-    Statement* bubble(Supports_Block*);
+    Statement* bubble(SupportsRule*);
 
     Block* debubble(Block* children, Statement* parent = 0);
     Block* flatten(const Block*);
diff --git a/libsass/src/dart_helpers.hpp b/libsass/src/dart_helpers.hpp
--- a/libsass/src/dart_helpers.hpp
+++ b/libsass/src/dart_helpers.hpp
@@ -12,7 +12,7 @@
   // Flatten `vector<vector<T>>` to `vector<T>`
   // ##########################################################################
   template <class T>
-  T flatten(const std::vector<T>& all)
+  T flatten(const sass::vector<T>& all)
   {
     T flattened;
     for (const auto& sub : all) {
@@ -42,7 +42,7 @@
   // ##########################################################################
   // ##########################################################################
   template <class T>
-  T flattenInner(const std::vector<T>& vec)
+  T flattenInner(const sass::vector<T>& vec)
   {
     T outer;
     for (const auto& sub : vec) {
@@ -102,8 +102,8 @@
   // Longest common subsequence with predicate
   // ##########################################################################
   template <class T>
-  std::vector<T> lcs(
-    const std::vector<T>& X, const std::vector<T>& Y,
+  sass::vector<T> lcs(
+    const sass::vector<T>& X, const sass::vector<T>& Y,
     bool(*select)(const T&, const T&, T&) = lcsIdentityCmp<T>)
   {
 
@@ -142,7 +142,7 @@
     }
 
     // Following code is used to print LCS
-    std::vector<T> lcs;
+    sass::vector<T> lcs;
     std::size_t index = LEN(m, n);
     lcs.reserve(index);
 
diff --git a/libsass/src/debugger.hpp b/libsass/src/debugger.hpp
--- a/libsass/src/debugger.hpp
+++ b/libsass/src/debugger.hpp
@@ -17,15 +17,15 @@
 
 using namespace Sass;
 
-inline void debug_ast(AST_Node* node, std::string ind = "", Env* env = 0);
+inline void debug_ast(AST_Node* node, sass::string ind = "", Env* env = 0);
 
-inline std::string debug_vec(const AST_Node* node) {
+inline sass::string debug_vec(const AST_Node* node) {
   if (node == NULL) return "null";
   else return node->to_string();
 }
 
-inline std::string debug_dude(std::vector<std::vector<int>> vec) {
-  std::stringstream out;
+inline sass::string debug_dude(sass::vector<sass::vector<int>> vec) {
+  sass::sstream out;
   out << "{";
   bool joinOut = false;
   for (auto ct : vec) {
@@ -44,12 +44,12 @@
   return out.str();
 }
 
-inline std::string debug_vec(std::string& str) {
+inline sass::string debug_vec(sass::string& str) {
   return str;
 }
 
-inline std::string debug_vec(Extension& ext) {
-  std::stringstream out;
+inline sass::string debug_vec(Extension& ext) {
+  sass::sstream out;
   out << debug_vec(ext.extender);
   out << " {@extend ";
   out << debug_vec(ext.target);
@@ -61,8 +61,8 @@
 }
 
 template <class T>
-inline std::string debug_vec(std::vector<T> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(sass::vector<T> vec) {
+  sass::sstream out;
   out << "[";
   for (size_t i = 0; i < vec.size(); i += 1) {
     if (i > 0) out << ", ";
@@ -73,8 +73,8 @@
 }
 
 template <class T>
-inline std::string debug_vec(std::queue<T> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(std::queue<T> vec) {
+  sass::sstream out;
   out << "{";
   for (size_t i = 0; i < vec.size(); i += 1) {
     if (i > 0) out << ", ";
@@ -85,8 +85,8 @@
 }
 
 template <class T, class U, class O>
-inline std::string debug_vec(std::map<T, U, O> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(std::map<T, U, O> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -102,8 +102,8 @@
 }
 
 template <class T, class U, class O, class V>
-inline std::string debug_vec(const ordered_map<T, U, O, V>& vec) {
-  std::stringstream out;
+inline sass::string debug_vec(const ordered_map<T, U, O, V>& vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -118,8 +118,8 @@
 }
 
 template <class T, class U, class O, class V>
-inline std::string debug_vec(std::unordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(std::unordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -135,8 +135,8 @@
 }
 
 template <class T, class U, class O, class V>
-inline std::string debug_keys(std::unordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_keys(std::unordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -149,8 +149,8 @@
   return out.str();
 }
 
-inline std::string debug_vec(ExtListSelSet& vec) {
-  std::stringstream out;
+inline sass::string debug_vec(ExtListSelSet& vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -165,8 +165,8 @@
 
 /*
 template <class T, class U, class O, class V>
-inline std::string debug_values(tsl::ordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_values(tsl::ordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -180,8 +180,8 @@
 }
  
 template <class T, class U, class O, class V>
-inline std::string debug_vec(tsl::ordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(tsl::ordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -197,8 +197,8 @@
 }
 
 template <class T, class U, class O, class V>
-inline std::string debug_vals(tsl::ordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_vals(tsl::ordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -212,8 +212,8 @@
 }
 
 template <class T, class U, class O, class V>
-inline std::string debug_keys(tsl::ordered_map<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_keys(tsl::ordered_map<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto it = vec.begin(); it != vec.end(); it++)
@@ -228,8 +228,8 @@
 */
 
 template <class T, class U>
-inline std::string debug_vec(std::set<T, U> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(std::set<T, U> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto item : vec) {
@@ -243,8 +243,8 @@
 
 /*
 template <class T, class U, class O, class V>
-inline std::string debug_vec(tsl::ordered_set<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(tsl::ordered_set<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto item : vec) {
@@ -258,8 +258,8 @@
 */
 
 template <class T, class U, class O, class V>
-inline std::string debug_vec(std::unordered_set<T, U, O, V> vec) {
-  std::stringstream out;
+inline sass::string debug_vec(std::unordered_set<T, U, O, V> vec) {
+  sass::sstream out;
   out << "{";
   bool joinit = false;
   for (auto item : vec) {
@@ -271,22 +271,22 @@
   return out.str();
 }
 
-inline std::string debug_bool(bool val) {
+inline sass::string debug_bool(bool val) {
   return val ? "true" : "false";
 }
-inline std::string debug_vec(ExtSmplSelSet* node) {
+inline sass::string debug_vec(ExtSmplSelSet* node) {
   if (node == NULL) return "null";
   else return debug_vec(*node);
 }
 
-inline void debug_ast(const AST_Node* node, std::string ind = "", Env* env = 0) {
+inline void debug_ast(const AST_Node* node, sass::string ind = "", Env* env = 0) {
   debug_ast(const_cast<AST_Node*>(node), ind, env);
 }
 
-inline std::string str_replace(std::string str, const std::string& oldStr, const std::string& newStr)
+inline sass::string str_replace(sass::string str, const sass::string& oldStr, const sass::string& newStr)
 {
   size_t pos = 0;
-  while((pos = str.find(oldStr, pos)) != std::string::npos)
+  while((pos = str.find(oldStr, pos)) != sass::string::npos)
   {
      str.replace(pos, oldStr.length(), newStr);
      pos += newStr.length();
@@ -294,25 +294,26 @@
   return str;
 }
 
-inline std::string prettyprint(const std::string& str) {
-  std::string clean = str_replace(str, "\n", "\\n");
+inline sass::string prettyprint(const sass::string& str) {
+  sass::string clean = str_replace(str, "\n", "\\n");
   clean = str_replace(clean, "	", "\\t");
   clean = str_replace(clean, "\r", "\\r");
   return clean;
 }
 
-inline std::string longToHex(long long t) {
-  std::stringstream is;
+inline sass::string longToHex(long long t) {
+  sass::sstream is;
   is << std::hex << t;
   return is.str();
 }
 
-inline std::string pstate_source_position(AST_Node* node)
+inline sass::string pstate_source_position(AST_Node* node)
 {
-  std::stringstream str;
-  Position start(node->pstate());
-  Position end(start + node->pstate().offset);
-  str << (start.file == std::string::npos ? 99999999 : start.file)
+  sass::sstream str;
+  Offset start(node->pstate().position);
+  Offset end(start + node->pstate().offset);
+  size_t file = node->pstate().getSrcId();
+  str << (file == sass::string::npos ? 99999999 : file)
     << "@[" << start.line << ":" << start.column << "]"
     << "-[" << end.line << ":" << end.column << "]";
 #ifdef DEBUG_SHARED_PTR
@@ -323,7 +324,7 @@
   return str.str();
 }
 
-inline void debug_ast(AST_Node* node, std::string ind, Env* env)
+inline void debug_ast(AST_Node* node, sass::string ind, Env* env)
 {
   if (node == 0) return;
   if (ind == "") std::cerr << "####################################################################\n";
@@ -341,9 +342,9 @@
     << " [name:" << trace->name() << ", type: " << trace->type() << "]"
     << std::endl;
     debug_ast(trace->block(), ind + " ", env);
-  } else if (Cast<At_Root_Block>(node)) {
-    At_Root_Block* root_block = Cast<At_Root_Block>(node);
-    std::cerr << ind << "At_Root_Block " << root_block;
+  } else if (Cast<AtRootRule>(node)) {
+    AtRootRule* root_block = Cast<AtRootRule>(node);
+    std::cerr << ind << "AtRootRule " << root_block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << root_block->tabs();
     std::cerr << std::endl;
@@ -392,7 +393,7 @@
       << (selector->has_real_parent_ref() ? " [real parent]": " -")
       << " -- ";
 
-      std::string del;
+      sass::string del;
       switch (selector->combinator()) {
         case SelectorCombinator::CHILD:    del = ">"; break;
         case SelectorCombinator::GENERAL:  del = "~"; break;
@@ -419,11 +420,11 @@
     std::cerr << ind << "Parent_Reference " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
-    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << std::endl;
 
-  } else if (Cast<Pseudo_Selector>(node)) {
-    Pseudo_Selector* selector = Cast<Pseudo_Selector>(node);
-    std::cerr << ind << "Pseudo_Selector " << selector;
+  } else if (Cast<PseudoSelector>(node)) {
+    PseudoSelector* selector = Cast<PseudoSelector>(node);
+    std::cerr << ind << "PseudoSelector " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
     std::cerr << " <<" << selector->ns_name() << ">>";
@@ -432,40 +433,39 @@
     std::cerr << std::endl;
     debug_ast(selector->argument(), ind + " <= ", env);
     debug_ast(selector->selector(), ind + " || ", env);
-  } else if (Cast<Attribute_Selector>(node)) {
-    Attribute_Selector* selector = Cast<Attribute_Selector>(node);
-    std::cerr << ind << "Attribute_Selector " << selector;
+  } else if (Cast<AttributeSelector>(node)) {
+    AttributeSelector* selector = Cast<AttributeSelector>(node);
+    std::cerr << ind << "AttributeSelector " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
     std::cerr << " <<" << selector->ns_name() << ">>";
     std::cerr << std::endl;
     debug_ast(selector->value(), ind + "[" + selector->matcher() + "] ", env);
-  } else if (Cast<Class_Selector>(node)) {
-    Class_Selector* selector = Cast<Class_Selector>(node);
-    std::cerr << ind << "Class_Selector " << selector;
+  } else if (Cast<ClassSelector>(node)) {
+    ClassSelector* selector = Cast<ClassSelector>(node);
+    std::cerr << ind << "ClassSelector " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
     std::cerr << " <<" << selector->ns_name() << ">>";
     std::cerr << std::endl;
-  } else if (Cast<Id_Selector>(node)) {
-    Id_Selector* selector = Cast<Id_Selector>(node);
-    std::cerr << ind << "Id_Selector " << selector;
+  } else if (Cast<IDSelector>(node)) {
+    IDSelector* selector = Cast<IDSelector>(node);
+    std::cerr << ind << "IDSelector " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
     std::cerr << " <<" << selector->ns_name() << ">>";
     std::cerr << std::endl;
-  } else if (Cast<Type_Selector>(node)) {
-    Type_Selector* selector = Cast<Type_Selector>(node);
-    std::cerr << ind << "Type_Selector " << selector;
+  } else if (Cast<TypeSelector>(node)) {
+    TypeSelector* selector = Cast<TypeSelector>(node);
+    std::cerr << ind << "TypeSelector " << selector;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " <" << selector->hash() << ">";
     std::cerr << " <<" << selector->ns_name() << ">>";
-    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">";
     std::cerr << std::endl;
-  } else if (Cast<Placeholder_Selector>(node)) {
+  } else if (Cast<PlaceholderSelector>(node)) {
 
-    Placeholder_Selector* selector = Cast<Placeholder_Selector>(node);
-    std::cerr << ind << "Placeholder_Selector [" << selector->ns_name() << "] " << selector;
+    PlaceholderSelector* selector = Cast<PlaceholderSelector>(node);
+    std::cerr << ind << "PlaceholderSelector [" << selector->ns_name() << "] " << selector;
     std::cerr << " (" << pstate_source_position(selector) << ")"
       << " <" << selector->hash() << ">"
       << (selector->isInvisible() ? " [isInvisible]" : " -")
@@ -537,23 +537,23 @@
     std::cerr << " [" << (query->type()) << "] ";
     std::cerr << " " << debug_vec(query->features());
     std::cerr << std::endl;
-  } else if (Cast<Supports_Block>(node)) {
-    Supports_Block* block = Cast<Supports_Block>(node);
-    std::cerr << ind << "Supports_Block " << block;
+  } else if (Cast<SupportsRule>(node)) {
+    SupportsRule* block = Cast<SupportsRule>(node);
+    std::cerr << ind << "SupportsRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     debug_ast(block->condition(), ind + " =@ ");
     debug_ast(block->block(), ind + " <>");
-  } else if (Cast<Supports_Operator>(node)) {
-    Supports_Operator* block = Cast<Supports_Operator>(node);
-    std::cerr << ind << "Supports_Operator " << block;
+  } else if (Cast<SupportsOperation>(node)) {
+    SupportsOperation* block = Cast<SupportsOperation>(node);
+    std::cerr << ind << "SupportsOperation " << block;
     std::cerr << " (" << pstate_source_position(node) << ")"
     << std::endl;
     debug_ast(block->left(), ind + " left) ");
     debug_ast(block->right(), ind + " right) ");
-  } else if (Cast<Supports_Negation>(node)) {
-    Supports_Negation* block = Cast<Supports_Negation>(node);
-    std::cerr << ind << "Supports_Negation " << block;
+  } else if (Cast<SupportsNegation>(node)) {
+    SupportsNegation* block = Cast<SupportsNegation>(node);
+    std::cerr << ind << "SupportsNegation " << block;
     std::cerr << " (" << pstate_source_position(node) << ")"
     << std::endl;
     debug_ast(block->condition(), ind + " condition) ");
@@ -564,9 +564,9 @@
     << std::endl;
     debug_ast(block->feature(), ind + " feature) ");
     debug_ast(block->value(), ind + " value) ");
-  } else if (Cast<Supports_Declaration>(node)) {
-    Supports_Declaration* block = Cast<Supports_Declaration>(node);
-    std::cerr << ind << "Supports_Declaration " << block;
+  } else if (Cast<SupportsDeclaration>(node)) {
+    SupportsDeclaration* block = Cast<SupportsDeclaration>(node);
+    std::cerr << ind << "SupportsDeclaration " << block;
     std::cerr << " (" << pstate_source_position(node) << ")"
     << std::endl;
     debug_ast(block->feature(), ind + " feature) ");
@@ -579,20 +579,20 @@
     if (root_block->isInvisible()) std::cerr << " [isInvisible]";
     std::cerr << " " << root_block->tabs() << std::endl;
     for(const Statement_Obj& i : root_block->elements()) { debug_ast(i, ind + " ", env); }
-  } else if (Cast<Warning>(node)) {
-    Warning* block = Cast<Warning>(node);
-    std::cerr << ind << "Warning " << block;
+  } else if (Cast<WarningRule>(node)) {
+    WarningRule* block = Cast<WarningRule>(node);
+    std::cerr << ind << "WarningRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     debug_ast(block->message(), ind + " : ");
-  } else if (Cast<Error>(node)) {
-    Error* block = Cast<Error>(node);
-    std::cerr << ind << "Error " << block;
+  } else if (Cast<ErrorRule>(node)) {
+    ErrorRule* block = Cast<ErrorRule>(node);
+    std::cerr << ind << "ErrorRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
-  } else if (Cast<Debug>(node)) {
-    Debug* block = Cast<Debug>(node);
-    std::cerr << ind << "Debug " << block;
+  } else if (Cast<DebugRule>(node)) {
+    DebugRule* block = Cast<DebugRule>(node);
+    std::cerr << ind << "DebugRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     debug_ast(block->value(), ind + " ");
@@ -600,8 +600,7 @@
     Comment* block = Cast<Comment>(node);
     std::cerr << ind << "Comment " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
-    std::cerr << " " << block->tabs() <<
-      " <" << prettyprint(block->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << " " << block->tabs() << std::endl;
     debug_ast(block->text(), ind + "// ", env);
   } else if (Cast<If>(node)) {
     If* block = Cast<If>(node);
@@ -640,7 +639,7 @@
     std::cerr << ind << "Import " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
-    // std::vector<std::string>         files_;
+    // sass::vector<sass::string>         files_;
     for (auto imp : block->urls()) debug_ast(imp, ind + "@: ", env);
     debug_ast(block->import_queries(), ind + "@@ ");
   } else if (Cast<Assignment>(node)) {
@@ -659,35 +658,35 @@
     debug_ast(block->value(), ind + " value: ", env);
     debug_ast(block->block(), ind + " ", env);
   } else if (Cast<Keyframe_Rule>(node)) {
-    Keyframe_Rule* has_block = Cast<Keyframe_Rule>(node);
-    std::cerr << ind << "Keyframe_Rule " << has_block;
+    Keyframe_Rule* ParentStatement = Cast<Keyframe_Rule>(node);
+    std::cerr << ind << "Keyframe_Rule " << ParentStatement;
     std::cerr << " (" << pstate_source_position(node) << ")";
-    std::cerr << " " << has_block->tabs() << std::endl;
-    if (has_block->name()) debug_ast(has_block->name(), ind + "@");
-    if (has_block->block()) for(const Statement_Obj& i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
-  } else if (Cast<Directive>(node)) {
-    Directive* block = Cast<Directive>(node);
-    std::cerr << ind << "Directive " << block;
+    std::cerr << " " << ParentStatement->tabs() << std::endl;
+    if (ParentStatement->name()) debug_ast(ParentStatement->name(), ind + "@");
+    if (ParentStatement->block()) for(const Statement_Obj& i : ParentStatement->block()->elements()) { debug_ast(i, ind + " ", env); }
+  } else if (Cast<AtRule>(node)) {
+    AtRule* block = Cast<AtRule>(node);
+    std::cerr << ind << "AtRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " [" << block->keyword() << "] " << block->tabs() << std::endl;
     debug_ast(block->selector(), ind + "~", env);
     debug_ast(block->value(), ind + "+", env);
     if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
-  } else if (Cast<Each>(node)) {
-    Each* block = Cast<Each>(node);
-    std::cerr << ind << "Each " << block;
+  } else if (Cast<EachRule>(node)) {
+    EachRule* block = Cast<EachRule>(node);
+    std::cerr << ind << "EachRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
-  } else if (Cast<For>(node)) {
-    For* block = Cast<For>(node);
-    std::cerr << ind << "For " << block;
+  } else if (Cast<ForRule>(node)) {
+    ForRule* block = Cast<ForRule>(node);
+    std::cerr << ind << "ForRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
-  } else if (Cast<While>(node)) {
-    While* block = Cast<While>(node);
-    std::cerr << ind << "While " << block;
+  } else if (Cast<WhileRule>(node)) {
+    WhileRule* block = Cast<WhileRule>(node);
+    std::cerr << ind << "WhileRule " << block;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " " << block->tabs() << std::endl;
     if (block->block()) for(const Statement_Obj& i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
@@ -712,8 +711,8 @@
     debug_ast(block->arguments(), ind + " args: ", env);
     debug_ast(block->block_parameters(), ind + " block_params: ", env);
     if (block->block()) debug_ast(block->block(), ind + " ", env);
-  } else if (Ruleset* ruleset = Cast<Ruleset>(node)) {
-    std::cerr << ind << "Ruleset " << ruleset;
+  } else if (StyleRule* ruleset = Cast<StyleRule>(node)) {
+    std::cerr << ind << "StyleRule " << ruleset;
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " [indent: " << ruleset->tabs() << "]";
     std::cerr << (ruleset->is_invisible() ? " [INVISIBLE]" : "");
@@ -734,7 +733,7 @@
     std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
     std::cerr << " (" << pstate_source_position(node) << ")";
     std::cerr << " [" << expression->name() << "]" << std::endl;
-    std::string name(expression->name());
+    sass::string name(expression->name());
     if (env && env->has(name)) debug_ast(Cast<Expression>((*env)[name]), ind + " -> ", env);
   } else if (Cast<Function_Call>(node)) {
     Function_Call* expression = Cast<Function_Call>(node);
@@ -881,7 +880,7 @@
     if (expression->is_delayed()) std::cerr << " [delayed]";
     if (expression->is_interpolant()) std::cerr << " [interpolant]";
     if (expression->quote_mark()) std::cerr << " [quote_mark: " << expression->quote_mark() << "]";
-    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << std::endl;
   } else if (Cast<String_Constant>(node)) {
     String_Constant* expression = Cast<String_Constant>(node);
     std::cerr << ind << "String_Constant " << expression;
@@ -892,7 +891,7 @@
     std::cerr << " [" << prettyprint(expression->value()) << "]";
     if (expression->is_delayed()) std::cerr << " [delayed]";
     if (expression->is_interpolant()) std::cerr << " [interpolant]";
-    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << std::endl;
   } else if (Cast<String_Schema>(node)) {
     String_Schema* expression = Cast<String_Schema>(node);
     std::cerr << ind << "String_Schema " << expression;
@@ -905,7 +904,7 @@
     if (expression->has_interpolant()) std::cerr << " [has interpolant]";
     if (expression->is_left_interpolant()) std::cerr << " [left interpolant] ";
     if (expression->is_right_interpolant()) std::cerr << " [right interpolant] ";
-    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << std::endl;
     for(const auto& i : expression->elements()) { debug_ast(i, ind + " ", env); }
   } else if (Cast<String>(node)) {
     String* expression = Cast<String>(node);
@@ -913,7 +912,7 @@
     std::cerr << " " << expression->concrete_type();
     std::cerr << " (" << pstate_source_position(node) << ")";
     if (expression->is_interpolant()) std::cerr << " [interpolant]";
-    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
+    std::cerr << std::endl;
   } else if (Cast<Expression>(node)) {
     Expression* expression = Cast<Expression>(node);
     std::cerr << ind << "Expression " << expression;
@@ -937,12 +936,12 @@
       case Expression::Type::PARENT: std::cerr << " [PARENT]"; break;
     }
     std::cerr << std::endl;
-  } else if (Cast<Has_Block>(node)) {
-    Has_Block* has_block = Cast<Has_Block>(node);
-    std::cerr << ind << "Has_Block " << has_block;
+  } else if (Cast<ParentStatement>(node)) {
+    ParentStatement* parent = Cast<ParentStatement>(node);
+    std::cerr << ind << "ParentStatement " << parent;
     std::cerr << " (" << pstate_source_position(node) << ")";
-    std::cerr << " " << has_block->tabs() << std::endl;
-    if (has_block->block()) for(const Statement_Obj& i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
+    std::cerr << " " << parent->tabs() << std::endl;
+    if (parent->block()) for(const Statement_Obj& i : parent->block()->elements()) { debug_ast(i, ind + " ", env); }
   } else if (Cast<Statement>(node)) {
     Statement* statement = Cast<Statement>(node);
     std::cerr << ind << "Statement " << statement;
@@ -955,7 +954,7 @@
 
 
 /*
-inline void debug_ast(const AST_Node* node, std::string ind = "", Env* env = 0)
+inline void debug_ast(const AST_Node* node, sass::string ind = "", Env* env = 0)
 {
   debug_ast(const_cast<AST_Node*>(node), ind, env);
 }
diff --git a/libsass/src/emitter.cpp b/libsass/src/emitter.cpp
--- a/libsass/src/emitter.cpp
+++ b/libsass/src/emitter.cpp
@@ -26,7 +26,7 @@
   { }
 
   // return buffer as string
-  std::string Emitter::get_buffer(void)
+  sass::string Emitter::get_buffer(void)
   {
     return wbuf.buffer;
   }
@@ -41,10 +41,10 @@
   void Emitter::add_source_index(size_t idx)
   { wbuf.smap.source_index.push_back(idx); }
 
-  std::string Emitter::render_srcmap(Context &ctx)
+  sass::string Emitter::render_srcmap(Context &ctx)
   { return wbuf.smap.render_srcmap(ctx); }
 
-  void Emitter::set_filename(const std::string& str)
+  void Emitter::set_filename(const sass::string& str)
   { wbuf.smap.file = str; }
 
   void Emitter::schedule_mapping(const AST_Node* node)
@@ -53,7 +53,7 @@
   { wbuf.smap.add_open_mapping(node); }
   void Emitter::add_close_mapping(const AST_Node* node)
   { wbuf.smap.add_close_mapping(node); }
-  ParserState Emitter::remap(const ParserState& pstate)
+  SourceSpan Emitter::remap(const SourceSpan& pstate)
   { return wbuf.smap.remap(pstate); }
 
   // MAIN BUFFER MANIPULATION
@@ -74,7 +74,7 @@
   {
     // check the schedule
     if (scheduled_linefeed) {
-      std::string linefeeds = "";
+      sass::string linefeeds = "";
 
       for (size_t i = 0; i < scheduled_linefeed; i++)
         linefeeds += opt.linefeed;
@@ -83,7 +83,7 @@
       append_string(linefeeds);
 
     } else if (scheduled_space) {
-      std::string spaces(scheduled_space, ' ');
+      sass::string spaces(scheduled_space, ' ');
       scheduled_space = 0;
       append_string(spaces);
     }
@@ -101,7 +101,7 @@
   }
 
   // prepend some text or token to the buffer
-  void Emitter::prepend_string(const std::string& text)
+  void Emitter::prepend_string(const sass::string& text)
   {
     // do not adjust mappings for utf8 bom
     // seems they are not counted in any UA
@@ -128,14 +128,14 @@
   }
 
   // append some text or token to the buffer
-  void Emitter::append_string(const std::string& text)
+  void Emitter::append_string(const sass::string& text)
   {
 
     // write space/lf
     flush_schedules();
 
     if (in_comment) {
-      std::string out = Util::normalize_newlines(text);
+      sass::string out = Util::normalize_newlines(text);
       if (output_style() == COMPACT) {
         out = comment_to_compact_string(out);
       }
@@ -150,7 +150,7 @@
   }
 
   // append some white-space only text
-  void Emitter::append_wspace(const std::string& text)
+  void Emitter::append_wspace(const sass::string& text)
   {
     if (text.empty()) return;
     if (peek_linefeed(text.c_str())) {
@@ -161,7 +161,7 @@
 
   // append some text or token to the buffer
   // this adds source-mappings for node start and end
-  void Emitter::append_token(const std::string& text, const AST_Node* node)
+  void Emitter::append_token(const sass::string& text, const AST_Node* node)
   {
     flush_schedules();
     add_open_mapping(node);
@@ -184,7 +184,7 @@
     if (in_declaration && in_comma_array) return;
     if (scheduled_linefeed && indentation)
       scheduled_linefeed = 1;
-    std::string indent = "";
+    sass::string indent = "";
     for (size_t i = 0; i < indentation; i++)
       indent += opt.indent;
     append_string(indent);
diff --git a/libsass/src/emitter.hpp b/libsass/src/emitter.hpp
--- a/libsass/src/emitter.hpp
+++ b/libsass/src/emitter.hpp
@@ -21,17 +21,17 @@
     protected:
       OutputBuffer wbuf;
     public:
-      const std::string& buffer(void) { return wbuf.buffer; }
+      const sass::string& buffer(void) { return wbuf.buffer; }
       const SourceMap smap(void) { return wbuf.smap; }
       const OutputBuffer output(void) { return wbuf; }
       // proxy methods for source maps
       void add_source_index(size_t idx);
-      void set_filename(const std::string& str);
+      void set_filename(const sass::string& str);
       void add_open_mapping(const AST_Node* node);
       void add_close_mapping(const AST_Node* node);
       void schedule_mapping(const AST_Node* node);
-      std::string render_srcmap(Context &ctx);
-      ParserState remap(const ParserState& pstate);
+      sass::string render_srcmap(Context &ctx);
+      SourceSpan remap(const SourceSpan& pstate);
 
     public:
       struct Sass_Output_Options& opt;
@@ -58,8 +58,8 @@
       bool in_comma_array;
 
     public:
-      // return buffer as std::string
-      std::string get_buffer(void);
+      // return buffer as sass::string
+      sass::string get_buffer(void);
       // flush scheduled space/linefeed
       Sass_Output_Style output_style(void) const;
       // add outstanding linefeed
@@ -67,17 +67,17 @@
       // flush scheduled space/linefeed
       void flush_schedules(void);
       // prepend some text or token to the buffer
-      void prepend_string(const std::string& text);
+      void prepend_string(const sass::string& text);
       void prepend_output(const OutputBuffer& out);
       // append some text or token to the buffer
-      void append_string(const std::string& text);
+      void append_string(const sass::string& text);
       // append a single character to buffer
       void append_char(const char chr);
       // append some white-space only text
-      void append_wspace(const std::string& text);
+      void append_wspace(const sass::string& text);
       // append some text or token to the buffer
       // this adds source-mappings for node start and end
-      void append_token(const std::string& text, const AST_Node* node);
+      void append_token(const sass::string& text, const AST_Node* node);
       // query last appended character
       char last_char();
 
diff --git a/libsass/src/environment.cpp b/libsass/src/environment.cpp
--- a/libsass/src/environment.cpp
+++ b/libsass/src/environment.cpp
@@ -6,17 +6,17 @@
 
   template <typename T>
   Environment<T>::Environment(bool is_shadow)
-  : local_frame_(environment_map<std::string, T>()),
+  : local_frame_(environment_map<sass::string, T>()),
     parent_(0), is_shadow_(false)
   { }
   template <typename T>
   Environment<T>::Environment(Environment<T>* env, bool is_shadow)
-  : local_frame_(environment_map<std::string, T>()),
+  : local_frame_(environment_map<sass::string, T>()),
     parent_(env), is_shadow_(is_shadow)
   { }
   template <typename T>
   Environment<T>::Environment(Environment<T>& env, bool is_shadow)
-  : local_frame_(environment_map<std::string, T>()),
+  : local_frame_(environment_map<sass::string, T>()),
     parent_(&env), is_shadow_(is_shadow)
   { }
 
@@ -45,16 +45,16 @@
   }
 
   template <typename T>
-  environment_map<std::string, T>& Environment<T>::local_frame() {
+  environment_map<sass::string, T>& Environment<T>::local_frame() {
     return local_frame_;
   }
 
   template <typename T>
-  bool Environment<T>::has_local(const std::string& key) const
+  bool Environment<T>::has_local(const sass::string& key) const
   { return local_frame_.find(key) != local_frame_.end(); }
 
   template <typename T> EnvResult
-  Environment<T>::find_local(const std::string& key)
+  Environment<T>::find_local(const sass::string& key)
   {
     auto end = local_frame_.end();
     auto it = local_frame_.find(key);
@@ -62,22 +62,22 @@
   }
 
   template <typename T>
-  T& Environment<T>::get_local(const std::string& key)
+  T& Environment<T>::get_local(const sass::string& key)
   { return local_frame_[key]; }
 
   template <typename T>
-  void Environment<T>::set_local(const std::string& key, const T& val)
+  void Environment<T>::set_local(const sass::string& key, const T& val)
   {
     local_frame_[key] = val;
   }
   template <typename T>
-  void Environment<T>::set_local(const std::string& key, T&& val)
+  void Environment<T>::set_local(const sass::string& key, T&& val)
   {
     local_frame_[key] = val;
   }
 
   template <typename T>
-  void Environment<T>::del_local(const std::string& key)
+  void Environment<T>::del_local(const sass::string& key)
   { local_frame_.erase(key); }
 
   template <typename T>
@@ -91,30 +91,30 @@
   }
 
   template <typename T>
-  bool Environment<T>::has_global(const std::string& key)
+  bool Environment<T>::has_global(const sass::string& key)
   { return global_env()->has(key); }
 
   template <typename T>
-  T& Environment<T>::get_global(const std::string& key)
+  T& Environment<T>::get_global(const sass::string& key)
   { return (*global_env())[key]; }
 
   template <typename T>
-  void Environment<T>::set_global(const std::string& key, const T& val)
+  void Environment<T>::set_global(const sass::string& key, const T& val)
   {
     global_env()->local_frame_[key] = val;
   }
   template <typename T>
-  void Environment<T>::set_global(const std::string& key, T&& val)
+  void Environment<T>::set_global(const sass::string& key, T&& val)
   {
     global_env()->local_frame_[key] = val;
   }
 
   template <typename T>
-  void Environment<T>::del_global(const std::string& key)
+  void Environment<T>::del_global(const sass::string& key)
   { global_env()->local_frame_.erase(key); }
 
   template <typename T>
-  Environment<T>* Environment<T>::lexical_env(const std::string& key)
+  Environment<T>* Environment<T>::lexical_env(const sass::string& key)
   {
     Environment* cur = this;
     while (cur) {
@@ -130,7 +130,7 @@
   // move down the stack but stop before we
   // reach the global frame (is not included)
   template <typename T>
-  bool Environment<T>::has_lexical(const std::string& key) const
+  bool Environment<T>::has_lexical(const sass::string& key) const
   {
     auto cur = this;
     while (cur->is_lexical()) {
@@ -144,7 +144,7 @@
   // either update already existing lexical value
   // or if flag is set, we create one if no lexical found
   template <typename T>
-  void Environment<T>::set_lexical(const std::string& key, const T& val)
+  void Environment<T>::set_lexical(const sass::string& key, const T& val)
   {
     Environment<T>* cur = this;
     bool shadow = false;
@@ -161,7 +161,7 @@
   }
   // this one moves the value
   template <typename T>
-  void Environment<T>::set_lexical(const std::string& key, T&& val)
+  void Environment<T>::set_lexical(const sass::string& key, T&& val)
   {
     Environment<T>* cur = this;
     bool shadow = false;
@@ -180,7 +180,7 @@
   // look on the full stack for key
   // include all scopes available
   template <typename T>
-  bool Environment<T>::has(const std::string& key) const
+  bool Environment<T>::has(const sass::string& key) const
   {
     auto cur = this;
     while (cur) {
@@ -195,7 +195,7 @@
   // look on the full stack for key
   // include all scopes available
   template <typename T> EnvResult
-  Environment<T>::find(const std::string& key)
+  Environment<T>::find(const sass::string& key)
   {
     auto cur = this;
     while (true) {
@@ -208,7 +208,7 @@
 
   // use array access for getter and setter functions
   template <typename T>
-  T& Environment<T>::get(const std::string& key)
+  T& Environment<T>::get(const sass::string& key)
   {
     auto cur = this;
     while (cur) {
@@ -222,7 +222,7 @@
 
   // use array access for getter and setter functions
   template <typename T>
-  T& Environment<T>::operator[](const std::string& key)
+  T& Environment<T>::operator[](const sass::string& key)
   {
     auto cur = this;
     while (cur) {
@@ -236,14 +236,14 @@
 /*
   #ifdef DEBUG
   template <typename T>
-  size_t Environment<T>::print(std::string prefix)
+  size_t Environment<T>::print(sass::string prefix)
   {
     size_t indent = 0;
     if (parent_) indent = parent_->print(prefix) + 1;
-    std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl;
-    for (typename environment_map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
+    std::cerr << prefix << sass::string(indent, ' ') << "== " << this << std::endl;
+    for (typename environment_map<sass::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
       if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
-        std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
+        std::cerr << prefix << sass::string(indent, ' ') << i->first << " " << i->second;
         if (Value* val = Cast<Value>(i->second))
         { std::cerr << " : " << val->to_string(); }
         std::cerr << std::endl;
diff --git a/libsass/src/environment.hpp b/libsass/src/environment.hpp
--- a/libsass/src/environment.hpp
+++ b/libsass/src/environment.hpp
@@ -13,7 +13,7 @@
 namespace Sass {
 
   // this defeats the whole purpose of environment being templatable!!
-  typedef environment_map<std::string, AST_Node_Obj>::iterator EnvIter;
+  typedef environment_map<sass::string, AST_Node_Obj>::iterator EnvIter;
 
   class EnvResult {
     public:
@@ -27,7 +27,7 @@
   template <typename T>
   class Environment {
     // TODO: test with map
-    environment_map<std::string, T> local_frame_;
+    environment_map<sass::string, T> local_frame_;
     ADD_PROPERTY(Environment*, parent)
     ADD_PROPERTY(bool, is_shadow)
 
@@ -52,72 +52,72 @@
 
     // scope operates on the current frame
 
-    environment_map<std::string, T>& local_frame();
+    environment_map<sass::string, T>& local_frame();
 
-    bool has_local(const std::string& key) const;
+    bool has_local(const sass::string& key) const;
 
-    EnvResult find_local(const std::string& key);
+    EnvResult find_local(const sass::string& key);
 
-    T& get_local(const std::string& key);
+    T& get_local(const sass::string& key);
 
     // set variable on the current frame
-    void set_local(const std::string& key, const T& val);
-    void set_local(const std::string& key, T&& val);
+    void set_local(const sass::string& key, const T& val);
+    void set_local(const sass::string& key, T&& val);
 
-    void del_local(const std::string& key);
+    void del_local(const sass::string& key);
 
     // global operates on the global frame
     // which is the second last on the stack
     Environment* global_env();
     // get the env where the variable already exists
     // if it does not yet exist, we return current env
-    Environment* lexical_env(const std::string& key);
+    Environment* lexical_env(const sass::string& key);
 
-    bool has_global(const std::string& key);
+    bool has_global(const sass::string& key);
 
-    T& get_global(const std::string& key);
+    T& get_global(const sass::string& key);
 
     // set a variable on the global frame
-    void set_global(const std::string& key, const T& val);
-    void set_global(const std::string& key, T&& val);
+    void set_global(const sass::string& key, const T& val);
+    void set_global(const sass::string& key, T&& val);
 
-    void del_global(const std::string& key);
+    void del_global(const sass::string& key);
 
     // see if we have a lexical variable
     // move down the stack but stop before we
     // reach the global frame (is not included)
-    bool has_lexical(const std::string& key) const;
+    bool has_lexical(const sass::string& key) const;
 
     // see if we have a lexical we could update
     // either update already existing lexical value
     // or we create a new one on the current frame
-    void set_lexical(const std::string& key, T&& val);
-    void set_lexical(const std::string& key, const T& val);
+    void set_lexical(const sass::string& key, T&& val);
+    void set_lexical(const sass::string& key, const T& val);
 
     // look on the full stack for key
     // include all scopes available
-    bool has(const std::string& key) const;
+    bool has(const sass::string& key) const;
 
     // look on the full stack for key
     // include all scopes available
-    T& get(const std::string& key);
+    T& get(const sass::string& key);
 
     // look on the full stack for key
     // include all scopes available
-    EnvResult find(const std::string& key);
+    EnvResult find(const sass::string& key);
 
     // use array access for getter and setter functions
-    T& operator[](const std::string& key);
+    T& operator[](const sass::string& key);
 
     #ifdef DEBUG
-    size_t print(std::string prefix = "");
+    size_t print(sass::string prefix = "");
     #endif
 
   };
 
   // define typedef for our use case
   typedef Environment<AST_Node_Obj> Env;
-  typedef std::vector<Env*> EnvStack;
+  typedef sass::vector<Env*> EnvStack;
 
 }
 
diff --git a/libsass/src/error_handling.cpp b/libsass/src/error_handling.cpp
--- a/libsass/src/error_handling.cpp
+++ b/libsass/src/error_handling.cpp
@@ -13,13 +13,13 @@
 
   namespace Exception {
 
-    Base::Base(ParserState pstate, std::string msg, Backtraces traces)
-    : std::runtime_error(msg), msg(msg),
+    Base::Base(SourceSpan pstate, sass::string msg, Backtraces traces)
+    : std::runtime_error(msg.c_str()), msg(msg),
       prefix("Error"), pstate(pstate), traces(traces)
     { }
 
-    InvalidSass::InvalidSass(ParserState pstate, Backtraces traces, std::string msg, char* owned_src)
-    : Base(pstate, msg, traces), owned_src(owned_src)
+    InvalidSass::InvalidSass(SourceSpan pstate, Backtraces traces, sass::string msg)
+    : Base(pstate, msg, traces)
     { }
 
 
@@ -31,14 +31,14 @@
         "\"" + parent->to_string(Sass_Inspect_Options()) + "\"";
     }
 
-    InvalidVarKwdType::InvalidVarKwdType(ParserState pstate, Backtraces traces, std::string name, const Argument* arg)
+    InvalidVarKwdType::InvalidVarKwdType(SourceSpan pstate, Backtraces traces, sass::string name, const Argument* arg)
     : Base(pstate, def_msg, traces), name(name), arg(arg)
     {
       msg = "Variable keyword argument map must have string keys.\n" +
         name + " is not a string in " + arg->to_string() + ".";
     }
 
-    InvalidArgumentType::InvalidArgumentType(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string type, const Value* value)
+    InvalidArgumentType::InvalidArgumentType(SourceSpan pstate, Backtraces traces, sass::string fn, sass::string arg, sass::string type, const Value* value)
     : Base(pstate, def_msg, traces), fn(fn), arg(arg), type(type), value(value)
     {
       msg = arg + ": \"";
@@ -46,17 +46,17 @@
       msg += "\" is not a " + type + " for `" + fn + "'";
     }
 
-    MissingArgument::MissingArgument(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string fntype)
+    MissingArgument::MissingArgument(SourceSpan pstate, Backtraces traces, sass::string fn, sass::string arg, sass::string fntype)
     : Base(pstate, def_msg, traces), fn(fn), arg(arg), fntype(fntype)
     {
       msg = fntype + " " + fn + " is missing argument " + arg + ".";
     }
 
-    InvalidSyntax::InvalidSyntax(ParserState pstate, Backtraces traces, std::string msg)
+    InvalidSyntax::InvalidSyntax(SourceSpan pstate, Backtraces traces, sass::string msg)
     : Base(pstate, msg, traces)
     { }
 
-    NestingLimitError::NestingLimitError(ParserState pstate, Backtraces traces, std::string msg)
+    NestingLimitError::NestingLimitError(SourceSpan pstate, Backtraces traces, sass::string msg)
     : Base(pstate, msg, traces)
     { }
 
@@ -66,7 +66,7 @@
       msg = "Duplicate key " + dup.get_duplicate_key()->inspect() + " in map (" + org.inspect() + ").";
     }
 
-    TypeMismatch::TypeMismatch(Backtraces traces, const Expression& var, const std::string type)
+    TypeMismatch::TypeMismatch(Backtraces traces, const Expression& var, const sass::string type)
     : Base(var.pstate(), def_msg, traces), var(var), type(type)
     {
       msg = var.to_string() + " is not an " + type + ".";
@@ -91,7 +91,7 @@
 
     IncompatibleUnits::IncompatibleUnits(const UnitType lhs, const UnitType rhs)
     {
-      msg = std::string("Incompatible units: '") + unit_to_string(rhs) + "' and '" + unit_to_string(lhs) + "'.";
+      msg = sass::string("Incompatible units: '") + unit_to_string(rhs) + "' and '" + unit_to_string(lhs) + "'.";
     }
 
     AlphaChannelsNotEqual::AlphaChannelsNotEqual(const Expression* lhs, const Expression* rhs, enum Sass_OP op)
@@ -125,14 +125,14 @@
       msg = def_op_null_msg + ": \"" + lhs->inspect() + " " + sass_op_to_name(op) + " " + rhs->inspect() + "\".";
     }
 
-    SassValueError::SassValueError(Backtraces traces, ParserState pstate, OperationError& err)
+    SassValueError::SassValueError(Backtraces traces, SourceSpan pstate, OperationError& err)
     : Base(pstate, err.what(), traces)
     {
       msg = err.what();
       prefix = err.errtype();
     }
 
-    TopLevelParent::TopLevelParent(Backtraces traces, ParserState pstate)
+    TopLevelParent::TopLevelParent(Backtraces traces, SourceSpan pstate)
       : Base(pstate, "Top-level selectors may not contain the parent selector \"&\".", traces)
     {
 
@@ -156,48 +156,48 @@
   }
 
 
-  void warn(std::string msg, ParserState pstate)
+  void warn(sass::string msg, SourceSpan pstate)
   {
     std::cerr << "Warning: " << msg << std::endl;
   }
 
-  void warning(std::string msg, ParserState pstate)
+  void warning(sass::string msg, SourceSpan pstate)
   {
-    std::string cwd(Sass::File::get_cwd());
-    std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
-    std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
-    std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
+    sass::string cwd(Sass::File::get_cwd());
+    sass::string abs_path(Sass::File::rel2abs(pstate.getPath(), cwd, cwd));
+    sass::string rel_path(Sass::File::abs2rel(pstate.getPath(), cwd, cwd));
+    sass::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.getPath()));
 
-    std::cerr << "WARNING on line " << pstate.line+1 << ", column " << pstate.column+1 << " of " << output_path << ":" << std::endl;
+    std::cerr << "WARNING on line " << pstate.getLine() << ", column " << pstate.getColumn() << " of " << output_path << ":" << std::endl;
     std::cerr << msg << std::endl << std::endl;
   }
 
-  void warn(std::string msg, ParserState pstate, Backtrace* bt)
+  void warn(sass::string msg, SourceSpan pstate, Backtrace* bt)
   {
     warn(msg, pstate);
   }
 
-  void deprecated_function(std::string msg, ParserState pstate)
+  void deprecated_function(sass::string msg, SourceSpan pstate)
   {
-    std::string cwd(Sass::File::get_cwd());
-    std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
-    std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
-    std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
+    sass::string cwd(Sass::File::get_cwd());
+    sass::string abs_path(Sass::File::rel2abs(pstate.getPath(), cwd, cwd));
+    sass::string rel_path(Sass::File::abs2rel(pstate.getPath(), cwd, cwd));
+    sass::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.getPath()));
 
     std::cerr << "DEPRECATION WARNING: " << msg << std::endl;
     std::cerr << "will be an error in future versions of Sass." << std::endl;
-    std::cerr << "        on line " << pstate.line+1 << " of " << output_path << std::endl;
+    std::cerr << "        on line " << pstate.getLine() << " of " << output_path << std::endl;
   }
 
-  void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate)
+  void deprecated(sass::string msg, sass::string msg2, bool with_column, SourceSpan pstate)
   {
-    std::string cwd(Sass::File::get_cwd());
-    std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
-    std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
-    std::string output_path(Sass::File::path_for_console(rel_path, pstate.path, pstate.path));
+    sass::string cwd(Sass::File::get_cwd());
+    sass::string abs_path(Sass::File::rel2abs(pstate.getPath(), cwd, cwd));
+    sass::string rel_path(Sass::File::abs2rel(pstate.getPath(), cwd, cwd));
+    sass::string output_path(Sass::File::path_for_console(rel_path, pstate.getPath(), pstate.getPath()));
 
-    std::cerr << "DEPRECATION WARNING on line " << pstate.line + 1;
-    if (with_column) std::cerr << ", column " << pstate.column + pstate.offset.column + 1;
+    std::cerr << "DEPRECATION WARNING on line " << pstate.getLine();
+    // if (with_column) std::cerr << ", column " << pstate.column + pstate.offset.column + 1;
     if (output_path.length()) std::cerr << " of " << output_path;
     std::cerr << ":" << std::endl;
     std::cerr << msg << std::endl;
@@ -205,26 +205,26 @@
     std::cerr << std::endl;
   }
 
-  void deprecated_bind(std::string msg, ParserState pstate)
+  void deprecated_bind(sass::string msg, SourceSpan pstate)
   {
-    std::string cwd(Sass::File::get_cwd());
-    std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
-    std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
-    std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
+    sass::string cwd(Sass::File::get_cwd());
+    sass::string abs_path(Sass::File::rel2abs(pstate.getPath(), cwd, cwd));
+    sass::string rel_path(Sass::File::abs2rel(pstate.getPath(), cwd, cwd));
+    sass::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.getPath()));
 
     std::cerr << "WARNING: " << msg << std::endl;
-    std::cerr << "        on line " << pstate.line+1 << " of " << output_path << std::endl;
+    std::cerr << "        on line " << pstate.getLine() << " of " << output_path << std::endl;
     std::cerr << "This will be an error in future versions of Sass." << std::endl;
   }
 
   // should be replaced with error with backtraces
-  void coreError(std::string msg, ParserState pstate)
+  void coreError(sass::string msg, SourceSpan pstate)
   {
     Backtraces traces;
     throw Exception::InvalidSyntax(pstate, traces, msg);
   }
 
-  void error(std::string msg, ParserState pstate, Backtraces& traces)
+  void error(sass::string msg, SourceSpan pstate, Backtraces& traces)
   {
     traces.push_back(Backtrace(pstate));
     throw Exception::InvalidSyntax(pstate, traces, msg);
diff --git a/libsass/src/error_handling.hpp b/libsass/src/error_handling.hpp
--- a/libsass/src/error_handling.hpp
+++ b/libsass/src/error_handling.hpp
@@ -20,20 +20,20 @@
 
   namespace Exception {
 
-    const std::string def_msg = "Invalid sass detected";
-    const std::string def_op_msg = "Undefined operation";
-    const std::string def_op_null_msg = "Invalid null operation";
-    const std::string def_nesting_limit = "Code too deeply neested";
+    const sass::string def_msg = "Invalid sass detected";
+    const sass::string def_op_msg = "Undefined operation";
+    const sass::string def_op_null_msg = "Invalid null operation";
+    const sass::string def_nesting_limit = "Code too deeply nested";
 
     class Base : public std::runtime_error {
       protected:
-        std::string msg;
-        std::string prefix;
+        sass::string msg;
+        sass::string prefix;
       public:
-        ParserState pstate;
+        SourceSpan pstate;
         Backtraces traces;
       public:
-        Base(ParserState pstate, std::string msg, Backtraces traces);
+        Base(SourceSpan pstate, sass::string msg, Backtraces traces);
         virtual const char* errtype() const { return prefix.c_str(); }
         virtual const char* what() const throw() { return msg.c_str(); }
         virtual ~Base() throw() {};
@@ -41,20 +41,8 @@
 
     class InvalidSass : public Base {
       public:
-        InvalidSass(InvalidSass& other) : Base(other), owned_src(other.owned_src) {
-          // Assumes that `this` will outlive `other`.
-          other.owned_src = nullptr;
-        }
-
-        // Required because the copy constructor's argument is not const.
-        // Can't use `std::move` here because we build on Visual Studio 2013.
-        InvalidSass(InvalidSass &&other) : Base(other), owned_src(other.owned_src) {
-          other.owned_src = nullptr;
-        }
-
-        InvalidSass(ParserState pstate, Backtraces traces, std::string msg, char* owned_src = nullptr);
-        virtual ~InvalidSass() throw() { sass_free_memory(owned_src); };
-        char *owned_src;
+        InvalidSass(SourceSpan pstate, Backtraces traces, sass::string msg);
+        virtual ~InvalidSass() throw() {};
     };
 
     class InvalidParent : public Base {
@@ -68,43 +56,43 @@
 
     class MissingArgument : public Base {
       protected:
-        std::string fn;
-        std::string arg;
-        std::string fntype;
+        sass::string fn;
+        sass::string arg;
+        sass::string fntype;
       public:
-        MissingArgument(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string fntype);
+        MissingArgument(SourceSpan pstate, Backtraces traces, sass::string fn, sass::string arg, sass::string fntype);
         virtual ~MissingArgument() throw() {};
     };
 
     class InvalidArgumentType : public Base {
       protected:
-        std::string fn;
-        std::string arg;
-        std::string type;
+        sass::string fn;
+        sass::string arg;
+        sass::string type;
         const Value* value;
       public:
-        InvalidArgumentType(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string type, const Value* value = 0);
+        InvalidArgumentType(SourceSpan pstate, Backtraces traces, sass::string fn, sass::string arg, sass::string type, const Value* value = 0);
         virtual ~InvalidArgumentType() throw() {};
     };
 
     class InvalidVarKwdType : public Base {
       protected:
-        std::string name;
+        sass::string name;
         const Argument* arg;
       public:
-        InvalidVarKwdType(ParserState pstate, Backtraces traces, std::string name, const Argument* arg = 0);
+        InvalidVarKwdType(SourceSpan pstate, Backtraces traces, sass::string name, const Argument* arg = 0);
         virtual ~InvalidVarKwdType() throw() {};
     };
 
     class InvalidSyntax : public Base {
       public:
-        InvalidSyntax(ParserState pstate, Backtraces traces, std::string msg);
+        InvalidSyntax(SourceSpan pstate, Backtraces traces, sass::string msg);
         virtual ~InvalidSyntax() throw() {};
     };
 
     class NestingLimitError : public Base {
       public:
-        NestingLimitError(ParserState pstate, Backtraces traces, std::string msg = def_nesting_limit);
+        NestingLimitError(SourceSpan pstate, Backtraces traces, sass::string msg = def_nesting_limit);
         virtual ~NestingLimitError() throw() {};
     };
 
@@ -121,9 +109,9 @@
     class TypeMismatch : public Base {
       protected:
         const Expression& var;
-        const std::string type;
+        const sass::string type;
       public:
-        TypeMismatch(Backtraces traces, const Expression& var, const std::string type);
+        TypeMismatch(Backtraces traces, const Expression& var, const sass::string type);
         virtual const char* errtype() const { return "Error"; }
         virtual ~TypeMismatch() throw() {};
     };
@@ -149,10 +137,10 @@
     /* common virtual base class (has no pstate or trace) */
     class OperationError : public std::runtime_error {
       protected:
-        std::string msg;
+        sass::string msg;
       public:
-        OperationError(std::string msg = def_op_msg)
-        : std::runtime_error(msg), msg(msg)
+        OperationError(sass::string msg = def_op_msg)
+        : std::runtime_error(msg.c_str()), msg(msg)
         {};
       public:
         virtual const char* errtype() const { return "Error"; }
@@ -210,13 +198,13 @@
 
     class SassValueError : public Base {
     public:
-      SassValueError(Backtraces traces, ParserState pstate, OperationError& err);
+      SassValueError(Backtraces traces, SourceSpan pstate, OperationError& err);
       virtual ~SassValueError() throw() {};
     };
 
     class TopLevelParent : public Base {
     public:
-      TopLevelParent(Backtraces traces, ParserState pstate);
+      TopLevelParent(Backtraces traces, SourceSpan pstate);
       virtual ~TopLevelParent() throw() {};
     };
 
@@ -234,17 +222,17 @@
 
   }
 
-  void warn(std::string msg, ParserState pstate);
-  void warn(std::string msg, ParserState pstate, Backtrace* bt);
-  void warning(std::string msg, ParserState pstate);
+  void warn(sass::string msg, SourceSpan pstate);
+  void warn(sass::string msg, SourceSpan pstate, Backtrace* bt);
+  void warning(sass::string msg, SourceSpan pstate);
 
-  void deprecated_function(std::string msg, ParserState pstate);
-  void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate);
-  void deprecated_bind(std::string msg, ParserState pstate);
-  // void deprecated(std::string msg, ParserState pstate, Backtrace* bt);
+  void deprecated_function(sass::string msg, SourceSpan pstate);
+  void deprecated(sass::string msg, sass::string msg2, bool with_column, SourceSpan pstate);
+  void deprecated_bind(sass::string msg, SourceSpan pstate);
+  // void deprecated(sass::string msg, SourceSpan pstate, Backtrace* bt);
 
-  void coreError(std::string msg, ParserState pstate);
-  void error(std::string msg, ParserState pstate, Backtraces& traces);
+  void coreError(sass::string msg, SourceSpan pstate);
+  void error(sass::string msg, SourceSpan pstate, Backtraces& traces);
 
 }
 
diff --git a/libsass/src/eval.cpp b/libsass/src/eval.cpp
--- a/libsass/src/eval.cpp
+++ b/libsass/src/eval.cpp
@@ -30,6 +30,7 @@
 #include "expand.hpp"
 #include "color_maps.hpp"
 #include "sass_functions.hpp"
+#include "error_handling.hpp"
 #include "util_string.hpp"
 
 namespace Sass {
@@ -52,7 +53,7 @@
     return exp.environment();
   }
 
-  const std::string Eval::cwd()
+  const sass::string Eval::cwd()
   {
     return ctx.cwd();
   }
@@ -72,7 +73,7 @@
     return exp.env_stack;
   }
 
-  std::vector<Sass_Callee>& Eval::callee_stack()
+  sass::vector<Sass_Callee>& Eval::callee_stack()
   {
     return ctx.callee_stack;
   }
@@ -90,8 +91,14 @@
   Expression* Eval::operator()(Assignment* a)
   {
     Env* env = environment();
-    std::string var(a->variable());
+    sass::string var(a->variable());
     if (a->is_global()) {
+      if (!env->has_global(var)) {
+        deprecated(
+          "!global assignments won't be able to declare new variables in future versions.",
+          "Consider adding `" + var + ": null` at the top level.",
+          true, a->pstate());
+      }
       if (a->is_default()) {
         if (env->has_global(var)) {
           Expression* e = Cast<Expression>(env->get_global(var));
@@ -150,10 +157,10 @@
 
   Expression* Eval::operator()(If* i)
   {
-    Expression_Obj rv;
+    ExpressionObj rv;
     Env env(environment());
     env_stack().push_back(&env);
-    Expression_Obj cond = i->predicate()->perform(this);
+    ExpressionObj cond = i->predicate()->perform(this);
     if (!cond->is_false()) {
       rv = i->block()->perform(this);
     }
@@ -167,15 +174,15 @@
 
   // For does not create a new env scope
   // But iteration vars are reset afterwards
-  Expression* Eval::operator()(For* f)
+  Expression* Eval::operator()(ForRule* f)
   {
-    std::string variable(f->variable());
-    Expression_Obj low = f->lower_bound()->perform(this);
+    sass::string variable(f->variable());
+    ExpressionObj low = f->lower_bound()->perform(this);
     if (low->concrete_type() != Expression::NUMBER) {
       traces.push_back(Backtrace(low->pstate()));
       throw Exception::TypeMismatch(traces, *low, "integer");
     }
-    Expression_Obj high = f->upper_bound()->perform(this);
+    ExpressionObj high = f->upper_bound()->perform(this);
     if (high->concrete_type() != Expression::NUMBER) {
       traces.push_back(Backtrace(high->pstate()));
       throw Exception::TypeMismatch(traces, *high, "integer");
@@ -184,7 +191,7 @@
     Number_Obj sass_end = Cast<Number>(high);
     // check if units are valid for sequence
     if (sass_start->unit() != sass_end->unit()) {
-      std::stringstream msg; msg << "Incompatible units: '"
+      sass::ostream msg; msg << "Incompatible units: '"
         << sass_end->unit() << "' and '"
         << sass_start->unit() << "'.";
       error(msg.str(), low->pstate(), traces);
@@ -223,10 +230,10 @@
 
   // Eval does not create a new env scope
   // But iteration vars are reset afterwards
-  Expression* Eval::operator()(Each* e)
+  Expression* Eval::operator()(EachRule* e)
   {
-    std::vector<std::string> variables(e->variables());
-    Expression_Obj expr = e->list()->perform(this);
+    sass::vector<sass::string> variables(e->variables());
+    ExpressionObj expr = e->list()->perform(this);
     Env env(environment(), true);
     env_stack().push_back(&env);
     List_Obj list;
@@ -235,7 +242,7 @@
       map = Cast<Map>(expr);
     }
     else if (SelectorList * ls = Cast<SelectorList>(expr)) {
-      Expression_Obj rv = Listize::perform(ls);
+      ExpressionObj rv = Listize::perform(ls);
       list = Cast<List>(rv);
     }
     else if (expr->concrete_type() != Expression::LIST) {
@@ -247,11 +254,11 @@
     }
 
     Block_Obj body = e->block();
-    Expression_Obj val;
+    ExpressionObj val;
 
     if (map) {
-      for (Expression_Obj key : map->keys()) {
-        Expression_Obj value = map->at(key);
+      for (ExpressionObj key : map->keys()) {
+        ExpressionObj value = map->at(key);
 
         if (variables.size() == 1) {
           List* variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
@@ -281,12 +288,10 @@
             Expression* var = scalars;
             env.set_local(variables[0], var);
           } else {
-            // XXX: this is never hit via spec tests
+            // https://github.com/sass/libsass/issues/3078
             for (size_t j = 0, K = variables.size(); j < K; ++j) {
-              Expression* res = j >= scalars->length()
-                ? SASS_MEMORY_NEW(Null, expr->pstate())
-                : scalars->at(j);
-              env.set_local(variables[j], res);
+              env.set_local(variables[j], j >= scalars->length()
+                ? SASS_MEMORY_NEW(Null, expr->pstate()) : scalars->at(j));
             }
           }
         } else {
@@ -307,15 +312,15 @@
     return val.detach();
   }
 
-  Expression* Eval::operator()(While* w)
+  Expression* Eval::operator()(WhileRule* w)
   {
-    Expression_Obj pred = w->predicate();
+    ExpressionObj pred = w->predicate();
     Block_Obj body = w->block();
     Env env(environment(), true);
     env_stack().push_back(&env);
-    Expression_Obj cond = pred->perform(this);
+    ExpressionObj cond = pred->perform(this);
     while (!cond->is_false()) {
-      Expression_Obj val = body->perform(this);
+      ExpressionObj val = body->perform(this);
       if (val) {
         env_stack().pop_back();
         return val.detach();
@@ -331,11 +336,11 @@
     return r->value()->perform(this);
   }
 
-  Expression* Eval::operator()(Warning* w)
+  Expression* Eval::operator()(WarningRule* w)
   {
     Sass_Output_Style outstyle = options().output_style;
     options().output_style = NESTED;
-    Expression_Obj message = w->message()->perform(this);
+    ExpressionObj message = w->message()->perform(this);
     Env* env = environment();
 
     // try to use generic function
@@ -344,9 +349,9 @@
       // add call stack entry
       callee_stack().push_back({
         "@warn",
-        w->pstate().path,
-        w->pstate().line + 1,
-        w->pstate().column + 1,
+        w->pstate().getPath(),
+        w->pstate().getLine(),
+        w->pstate().getColumn(),
         SASS_CALLEE_FUNCTION,
         { env }
       });
@@ -369,7 +374,7 @@
 
     }
 
-    std::string result(unquote(message->to_sass()));
+    sass::string result(unquote(message->to_sass()));
     std::cerr << "WARNING: " << result << std::endl;
     traces.push_back(Backtrace(w->pstate()));
     std::cerr << traces_to_string(traces, "         ");
@@ -379,11 +384,11 @@
     return 0;
   }
 
-  Expression* Eval::operator()(Error* e)
+  Expression* Eval::operator()(ErrorRule* e)
   {
     Sass_Output_Style outstyle = options().output_style;
     options().output_style = NESTED;
-    Expression_Obj message = e->message()->perform(this);
+    ExpressionObj message = e->message()->perform(this);
     Env* env = environment();
 
     // try to use generic function
@@ -392,9 +397,9 @@
       // add call stack entry
       callee_stack().push_back({
         "@error",
-        e->pstate().path,
-        e->pstate().line + 1,
-        e->pstate().column + 1,
+        e->pstate().getPath(),
+        e->pstate().getLine(),
+        e->pstate().getColumn(),
         SASS_CALLEE_FUNCTION,
         { env }
       });
@@ -417,17 +422,17 @@
 
     }
 
-    std::string result(unquote(message->to_sass()));
+    sass::string result(unquote(message->to_sass()));
     options().output_style = outstyle;
     error(result, e->pstate(), traces);
     return 0;
   }
 
-  Expression* Eval::operator()(Debug* d)
+  Expression* Eval::operator()(DebugRule* d)
   {
     Sass_Output_Style outstyle = options().output_style;
     options().output_style = NESTED;
-    Expression_Obj message = d->value()->perform(this);
+    ExpressionObj message = d->value()->perform(this);
     Env* env = environment();
 
     // try to use generic function
@@ -436,9 +441,9 @@
       // add call stack entry
       callee_stack().push_back({
         "@debug",
-        d->pstate().path,
-        d->pstate().line + 1,
-        d->pstate().column + 1,
+        d->pstate().getPath(),
+        d->pstate().getLine(),
+        d->pstate().getColumn(),
         SASS_CALLEE_FUNCTION,
         { env }
       });
@@ -461,13 +466,13 @@
 
     }
 
-    std::string result(unquote(message->to_sass()));
-    std::string abs_path(Sass::File::rel2abs(d->pstate().path, cwd(), cwd()));
-    std::string rel_path(Sass::File::abs2rel(d->pstate().path, cwd(), cwd()));
-    std::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().path));
+    sass::string result(unquote(message->to_sass()));
+    sass::string abs_path(Sass::File::rel2abs(d->pstate().getPath(), cwd(), cwd()));
+    sass::string rel_path(Sass::File::abs2rel(d->pstate().getPath(), cwd(), cwd()));
+    sass::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().getPath()));
     options().output_style = outstyle;
 
-    std::cerr << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result;
+    std::cerr << output_path << ":" << d->pstate().getLine() << " DEBUG: " << result;
     std::cerr << std::endl;
     return 0;
   }
@@ -482,8 +487,8 @@
                                 l->length() / 2);
       for (size_t i = 0, L = l->length(); i < L; i += 2)
       {
-        Expression_Obj key = (*l)[i+0]->perform(this);
-        Expression_Obj val = (*l)[i+1]->perform(this);
+        ExpressionObj key = (*l)[i+0]->perform(this);
+        ExpressionObj val = (*l)[i+1]->perform(this);
         // make sure the color key never displays its real name
         key->is_delayed(true); // verified
         *lm << std::make_pair(key, val);
@@ -549,8 +554,8 @@
   Expression* Eval::operator()(Binary_Expression* b_in)
   {
 
-    Expression_Obj lhs = b_in->left();
-    Expression_Obj rhs = b_in->right();
+    ExpressionObj lhs = b_in->left();
+    ExpressionObj rhs = b_in->right();
     enum Sass_OP op_type = b_in->optype();
 
     if (op_type == Sass_OP::AND) {
@@ -574,7 +579,7 @@
       rhs = operator()(r_v);
     }
 
-    Binary_Expression_Obj b = b_in;
+    Binary_ExpressionObj b = b_in;
 
     // Evaluate sub-expressions early on
     while (Binary_Expression* l_b = Cast<Binary_Expression>(lhs)) {
@@ -686,7 +691,7 @@
     if (String_Schema* s_l = Cast<String_Schema>(b->left())) {
       if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
         ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
-        Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
+        Binary_ExpressionObj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
                                                     b->op(), s_l->last(), b->right());
         bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
         for (size_t i = 0; i < s_l->length() - 1; ++i) {
@@ -700,7 +705,7 @@
 
       if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
         ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
-        Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
+        Binary_ExpressionObj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
                                                     b->op(), b->left(), s_r->first());
         bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
         ret_schema->append(bin_ex->perform(this));
@@ -742,8 +747,8 @@
     // Is one of the operands an interpolant?
     String_Schema_Obj s1 = Cast<String_Schema>(b->left());
     String_Schema_Obj s2 = Cast<String_Schema>(b->right());
-    Binary_Expression_Obj b1 = Cast<Binary_Expression>(b->left());
-    Binary_Expression_Obj b2 = Cast<Binary_Expression>(b->right());
+    Binary_ExpressionObj b1 = Cast<Binary_Expression>(b->left());
+    Binary_ExpressionObj b2 = Cast<Binary_Expression>(b->right());
 
     bool schema_op = false;
 
@@ -758,7 +763,7 @@
           op_type == Sass_OP::EQ) {
         // If possible upgrade LHS to a number (for number to string compare)
         if (String_Constant* str = Cast<String_Constant>(lhs)) {
-          std::string value(str->value());
+          sass::string value(str->value());
           const char* start = value.c_str();
           if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
             lhs = Parser::lexed_dimension(b->pstate(), str->value());
@@ -766,7 +771,7 @@
         }
         // If possible upgrade RHS to a number (for string to number compare)
         if (String_Constant* str = Cast<String_Constant>(rhs)) {
-          std::string value(str->value());
+          sass::string value(str->value());
           const char* start = value.c_str();
           if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
             rhs = Parser::lexed_dimension(b->pstate(), str->value());
@@ -775,11 +780,11 @@
       }
 
       To_Value to_value(ctx);
-      Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
-      Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
+      ValueObj v_l = Cast<Value>(lhs->perform(&to_value));
+      ValueObj v_r = Cast<Value>(rhs->perform(&to_value));
 
       if (force_delay) {
-        std::string str("");
+        sass::string str("");
         str += v_l->to_string(options());
         if (b->op().ws_before) str += " ";
         str += b->separator();
@@ -814,9 +819,9 @@
 
     // ToDo: throw error in op functions
     // ToDo: then catch and re-throw them
-    Expression_Obj rv;
+    ExpressionObj rv;
     try {
-      ParserState pstate(b->pstate());
+      SourceSpan pstate(b->pstate());
       if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
         Number* l_n = Cast<Number>(lhs);
         Number* r_n = Cast<Number>(rhs);
@@ -841,8 +846,8 @@
       else {
         To_Value to_value(ctx);
         // this will leak if perform does not return a value!
-        Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
-        Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
+        ValueObj v_l = Cast<Value>(lhs->perform(&to_value));
+        ValueObj v_r = Cast<Value>(rhs->perform(&to_value));
         bool interpolant = b->is_right_interpolant() ||
                            b->is_left_interpolant() ||
                            b->is_interpolant();
@@ -895,7 +900,7 @@
 
   Expression* Eval::operator()(Unary_Expression* u)
   {
-    Expression_Obj operand = u->operand()->perform(this);
+    ExpressionObj operand = u->operand()->perform(this);
     if (u->optype() == Unary_Expression::NOT) {
       Boolean* result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
       result->value(!result->value());
@@ -909,7 +914,7 @@
         return cpy.detach(); // return the copy
       }
       else if (u->optype() == Unary_Expression::SLASH) {
-        std::string str = '/' + nr->to_string(options());
+        sass::string str = '/' + nr->to_string(options());
         return SASS_MEMORY_NEW(String_Constant, u->pstate(), str);
       }
       // nothing for positive
@@ -925,7 +930,7 @@
       else if (Color* color = Cast<Color>(operand)) {
         // Use the color name if this was eval with one
         if (color->disp().length() > 0) {
-          Unary_Expression_Obj cpy = SASS_MEMORY_COPY(u);
+          Unary_ExpressionObj cpy = SASS_MEMORY_COPY(u);
           cpy->operand(SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp()));
           return SASS_MEMORY_NEW(String_Quoted,
                                  cpy->pstate(),
@@ -933,7 +938,7 @@
         }
       }
       else {
-        Unary_Expression_Obj cpy = SASS_MEMORY_COPY(u);
+        Unary_ExpressionObj cpy = SASS_MEMORY_COPY(u);
         cpy->operand(operand);
         return SASS_MEMORY_NEW(String_Quoted,
                                cpy->pstate(),
@@ -952,21 +957,21 @@
   {
     if (traces.size() > Constants::MaxCallStack) {
         // XXX: this is never hit via spec tests
-        std::ostringstream stm;
+        sass::ostream stm;
         stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
         error(stm.str(), c->pstate(), traces);
     }
 
     if (Cast<String_Schema>(c->sname())) {
-      Expression_Obj evaluated_name = c->sname()->perform(this);
-      Expression_Obj evaluated_args = c->arguments()->perform(this);
-      std::string str(evaluated_name->to_string());
+      ExpressionObj evaluated_name = c->sname()->perform(this);
+      ExpressionObj evaluated_args = c->arguments()->perform(this);
+      sass::string str(evaluated_name->to_string());
       str += evaluated_args->to_string();
       return SASS_MEMORY_NEW(String_Constant, c->pstate(), str);
     }
 
-    std::string name(Util::normalize_underscores(c->name()));
-    std::string full_name(name + "[f]");
+    sass::string name(Util::normalize_underscores(c->name()));
+    sass::string full_name(name + "[f]");
 
     // we make a clone here, need to implement that further
     Arguments_Obj args = c->arguments();
@@ -1010,7 +1015,7 @@
     if (c->func()) def = c->func()->definition();
 
     if (def->is_overload_stub()) {
-      std::stringstream ss;
+      sass::ostream ss;
       size_t L = args->length();
       // account for rest arguments
       if (args->has_rest_argument() && args->length() > 0) {
@@ -1021,12 +1026,12 @@
       }
       ss << full_name << L;
       full_name = ss.str();
-      std::string resolved_name(full_name);
-      if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate(), traces);
+      sass::string resolved_name(full_name);
+      if (!env->has(resolved_name)) error("overloaded function `" + sass::string(c->name()) + "` given wrong number of arguments", c->pstate(), traces);
       def = Cast<Definition>((*env)[resolved_name]);
     }
 
-    Expression_Obj     result = c;
+    ExpressionObj     result = c;
     Block_Obj          body   = def->block();
     Native_Function func   = def->native_function();
     Sass_Function_Entry c_function = def->c_function();
@@ -1038,14 +1043,14 @@
     env_stack().push_back(&fn_env);
 
     if (func || body) {
-      bind(std::string("Function"), c->name(), params, args, &fn_env, this, traces);
-      std::string msg(", in function `" + c->name() + "`");
+      bind(sass::string("Function"), c->name(), params, args, &fn_env, this, traces);
+      sass::string msg(", in function `" + c->name() + "`");
       traces.push_back(Backtrace(c->pstate(), msg));
       callee_stack().push_back({
         c->name().c_str(),
-        c->pstate().path,
-        c->pstate().line + 1,
-        c->pstate().column + 1,
+        c->pstate().getPath(),
+        c->pstate().getLine(),
+        c->pstate().getColumn(),
         SASS_CALLEE_FUNCTION,
         { env }
       });
@@ -1058,7 +1063,7 @@
         result = func(fn_env, *env, ctx, def->signature(), c->pstate(), traces, exp.getSelectorStack(), exp.originalStack);
       }
       if (!result) {
-        error(std::string("Function ") + c->name() + " finished without @return", c->pstate(), traces);
+        error(sass::string("Function ") + c->name() + " finished without @return", c->pstate(), traces);
       }
       callee_stack().pop_back();
       traces.pop_back();
@@ -1077,15 +1082,15 @@
       }
 
       // populates env with default values for params
-      std::string ff(c->name());
-      bind(std::string("Function"), c->name(), params, args, &fn_env, this, traces);
-      std::string msg(", in function `" + c->name() + "`");
+      sass::string ff(c->name());
+      bind(sass::string("Function"), c->name(), params, args, &fn_env, this, traces);
+      sass::string msg(", in function `" + c->name() + "`");
       traces.push_back(Backtrace(c->pstate(), msg));
       callee_stack().push_back({
         c->name().c_str(),
-        c->pstate().path,
-        c->pstate().line + 1,
-        c->pstate().column + 1,
+        c->pstate().getPath(),
+        c->pstate().getLine(),
+        c->pstate().getColumn(),
         SASS_CALLEE_C_FUNCTION,
         { env }
       });
@@ -1094,19 +1099,19 @@
       union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false);
       for(size_t i = 0; i < params->length(); i++) {
         Parameter_Obj param = params->at(i);
-        std::string key = param->name();
+        sass::string key = param->name();
         AST_Node_Obj node = fn_env.get_local(key);
-        Expression_Obj arg = Cast<Expression>(node);
+        ExpressionObj arg = Cast<Expression>(node);
         sass_list_set_value(c_args, i, arg->perform(&ast2c));
       }
       union Sass_Value* c_val = c_func(c_args, c_function, compiler());
       if (sass_value_get_tag(c_val) == SASS_ERROR) {
-        std::string message("error in C function " + c->name() + ": " + sass_error_get_message(c_val));
+        sass::string message("error in C function " + c->name() + ": " + sass_error_get_message(c_val));
         sass_delete_value(c_val);
         sass_delete_value(c_args);
         error(message, c->pstate(), traces);
       } else if (sass_value_get_tag(c_val) == SASS_WARNING) {
-        std::string message("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val));
+        sass::string message("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val));
         sass_delete_value(c_val);
         sass_delete_value(c_args);
         error(message, c->pstate(), traces);
@@ -1122,7 +1127,7 @@
 
     // link back to function definition
     // only do this for custom functions
-    if (result->pstate().file == std::string::npos)
+    if (result->pstate().getSrcId() == sass::string::npos)
       result->pstate(c->pstate());
 
     result = result->perform(this);
@@ -1133,9 +1138,9 @@
 
   Expression* Eval::operator()(Variable* v)
   {
-    Expression_Obj value;
+    ExpressionObj value;
     Env* env = environment();
-    const std::string& name(v->name());
+    const sass::string& name(v->name());
     EnvResult rv(env->find(name));
     if (rv.found) value = static_cast<Expression*>(rv.it->second.ptr());
     else error("Undefined variable: \"" + v->name() + "\".", v->pstate(), traces);
@@ -1169,7 +1174,7 @@
     return b;
   }
 
-  void Eval::interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl) {
+  void Eval::interpolation(Context& ctx, sass::string& res, ExpressionObj ex, bool into_quotes, bool was_itpl) {
 
     bool needs_closing_brace = false;
 
@@ -1214,9 +1219,9 @@
       List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
       // this fixes an issue with bourbon sample, not really sure why
       // if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
-      for(Expression_Obj item : *l) {
+      for(ExpressionObj item : *l) {
         item->is_interpolant(l->is_interpolant());
-        std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
+        sass::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
         bool is_null = Cast<Null>(item) != 0; // rl != ""
         if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
       }
@@ -1224,7 +1229,7 @@
       // here. Normally single list items are already unwrapped.
       if (l->size() > 1) {
         // string_to_output would fail "#{'_\a' '_\a'}";
-        std::string str(ll->to_string(options()));
+        sass::string str(ll->to_string(options()));
         str = read_hex_escapes(str); // read escapes
         newline_to_space(str); // replace directly
         res += str; // append to result string
@@ -1245,7 +1250,7 @@
       if (into_quotes && ex->is_interpolant()) {
         res += evacuate_escapes(ex ? ex->to_string(options()) : "");
       } else {
-        std::string str(ex ? ex->to_string(options()) : "");
+        sass::string str(ex ? ex->to_string(options()) : "");
         if (into_quotes) str = read_hex_escapes(str);
         res += str; // append to result string
       }
@@ -1273,12 +1278,12 @@
     }
     bool was_quoted = false;
     bool was_interpolant = false;
-    std::string res("");
+    sass::string res("");
     for (size_t i = 0; i < L; ++i) {
       bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
       if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
       else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
-      Expression_Obj ex = (*s)[i]->perform(this);
+      ExpressionObj ex = (*s)[i]->perform(this);
       interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
       was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
       was_interpolant = (*s)[i]->is_interpolant();
@@ -1286,7 +1291,8 @@
     }
     if (!s->is_interpolant()) {
       if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
-      return SASS_MEMORY_NEW(String_Constant, s->pstate(), res, s->css());
+      String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res, s->css());
+      return str.detach();
     }
     // string schema seems to have a special unquoting behavior (also handles "nested" quotes)
     String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false, s->css());
@@ -1313,32 +1319,32 @@
     return str;
   }
 
-  Expression* Eval::operator()(Supports_Operator* c)
+  Expression* Eval::operator()(SupportsOperation* c)
   {
     Expression* left = c->left()->perform(this);
     Expression* right = c->right()->perform(this);
-    Supports_Operator* cc = SASS_MEMORY_NEW(Supports_Operator,
+    SupportsOperation* cc = SASS_MEMORY_NEW(SupportsOperation,
                                  c->pstate(),
-                                 Cast<Supports_Condition>(left),
-                                 Cast<Supports_Condition>(right),
+                                 Cast<SupportsCondition>(left),
+                                 Cast<SupportsCondition>(right),
                                  c->operand());
     return cc;
   }
 
-  Expression* Eval::operator()(Supports_Negation* c)
+  Expression* Eval::operator()(SupportsNegation* c)
   {
     Expression* condition = c->condition()->perform(this);
-    Supports_Negation* cc = SASS_MEMORY_NEW(Supports_Negation,
+    SupportsNegation* cc = SASS_MEMORY_NEW(SupportsNegation,
                                  c->pstate(),
-                                 Cast<Supports_Condition>(condition));
+                                 Cast<SupportsCondition>(condition));
     return cc;
   }
 
-  Expression* Eval::operator()(Supports_Declaration* c)
+  Expression* Eval::operator()(SupportsDeclaration* c)
   {
     Expression* feature = c->feature()->perform(this);
     Expression* value = c->value()->perform(this);
-    Supports_Declaration* cc = SASS_MEMORY_NEW(Supports_Declaration,
+    SupportsDeclaration* cc = SASS_MEMORY_NEW(SupportsDeclaration,
                               c->pstate(),
                               feature,
                               value);
@@ -1356,9 +1362,9 @@
 
   Expression* Eval::operator()(At_Root_Query* e)
   {
-    Expression_Obj feature = e->feature();
+    ExpressionObj feature = e->feature();
     feature = (feature ? feature->perform(this) : 0);
-    Expression_Obj value = e->value();
+    ExpressionObj value = e->value();
     value = (value ? value->perform(this) : 0);
     Expression* ee = SASS_MEMORY_NEW(At_Root_Query,
                                      e->pstate(),
@@ -1385,14 +1391,14 @@
 
   Expression* Eval::operator()(Media_Query_Expression* e)
   {
-    Expression_Obj feature = e->feature();
+    ExpressionObj feature = e->feature();
     feature = (feature ? feature->perform(this) : 0);
     if (feature && Cast<String_Quoted>(feature)) {
       feature = SASS_MEMORY_NEW(String_Quoted,
                                   feature->pstate(),
                                   Cast<String_Quoted>(feature)->value());
     }
-    Expression_Obj value = e->value();
+    ExpressionObj value = e->value();
     value = (value ? value->perform(this) : 0);
     if (value && Cast<String_Quoted>(value)) {
       // XXX: this is never hit via spec tests
@@ -1414,7 +1420,7 @@
 
   Expression* Eval::operator()(Argument* a)
   {
-    Expression_Obj val = a->value()->perform(this);
+    ExpressionObj val = a->value()->perform(this);
     bool is_rest_argument = a->is_rest_argument();
     bool is_keyword_argument = a->is_keyword_argument();
 
@@ -1446,7 +1452,7 @@
     Arguments_Obj aa = SASS_MEMORY_NEW(Arguments, a->pstate());
     if (a->length() == 0) return aa.detach();
     for (size_t i = 0, L = a->length(); i < L; ++i) {
-      Expression_Obj rv = (*a)[i]->perform(this);
+      ExpressionObj rv = (*a)[i]->perform(this);
       Argument* arg = Cast<Argument>(rv);
       if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
         aa->append(arg);
@@ -1454,8 +1460,8 @@
     }
 
     if (a->has_rest_argument()) {
-      Expression_Obj rest = a->get_rest_argument()->perform(this);
-      Expression_Obj splat = Cast<Argument>(rest)->value()->perform(this);
+      ExpressionObj rest = a->get_rest_argument()->perform(this);
+      ExpressionObj splat = Cast<Argument>(rest)->value()->perform(this);
 
       Sass_Separator separator = SASS_COMMA;
       List* ls = Cast<List>(splat);
@@ -1482,9 +1488,9 @@
     }
 
     if (a->has_keyword_argument()) {
-      Expression_Obj rv = a->get_keyword_argument()->perform(this);
+      ExpressionObj rv = a->get_keyword_argument()->perform(this);
       Argument* rvarg = Cast<Argument>(rv);
-      Expression_Obj kwarg = rvarg->value()->perform(this);
+      ExpressionObj kwarg = rvarg->value()->perform(this);
 
       aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
     }
@@ -1500,12 +1506,12 @@
   {
     LOCAL_FLAG(is_in_selector_schema, true);
     // the parser will look for a brace to end the selector
-    Expression_Obj sel = s->contents()->perform(this);
-    std::string result_str(sel->to_string(options()));
+    ExpressionObj sel = s->contents()->perform(this);
+    sass::string result_str(sel->to_string(options()));
     result_str = unquote(Util::rtrim(result_str));
-    char* temp_cstr = sass_copy_c_string(result_str.c_str());
-    ctx.strings.push_back(temp_cstr); // attach to context
-    Parser p = Parser::from_c_str(temp_cstr, ctx, traces, s->pstate());
+    ItplFile* source = SASS_MEMORY_NEW(ItplFile,
+      result_str.c_str(), s->pstate());
+    Parser p(source, ctx, traces);
 
     // If a schema contains a reference to parent it is already
     // connected to it, so don't connect implicitly anymore
@@ -1528,7 +1534,7 @@
     return s;
   }
 
-  Pseudo_Selector* Eval::operator()(Pseudo_Selector* pseudo)
+  PseudoSelector* Eval::operator()(PseudoSelector* pseudo)
   {
     // ToDo: should we eval selector?
     return pseudo;
diff --git a/libsass/src/eval.hpp b/libsass/src/eval.hpp
--- a/libsass/src/eval.hpp
+++ b/libsass/src/eval.hpp
@@ -34,7 +34,7 @@
 
     Env* environment();
     EnvStack& env_stack();
-    const std::string cwd();
+    const sass::string cwd();
     CalleeStack& callee_stack();
     struct Sass_Inspect_Options& options();
     struct Sass_Compiler* compiler();
@@ -43,13 +43,13 @@
     Expression* operator()(Block*);
     Expression* operator()(Assignment*);
     Expression* operator()(If*);
-    Expression* operator()(For*);
-    Expression* operator()(Each*);
-    Expression* operator()(While*);
+    Expression* operator()(ForRule*);
+    Expression* operator()(EachRule*);
+    Expression* operator()(WhileRule*);
     Expression* operator()(Return*);
-    Expression* operator()(Warning*);
-    Expression* operator()(Error*);
-    Expression* operator()(Debug*);
+    Expression* operator()(WarningRule*);
+    Expression* operator()(ErrorRule*);
+    Expression* operator()(DebugRule*);
 
     Expression* operator()(List*);
     Expression* operator()(Map*);
@@ -67,9 +67,9 @@
     Media_Query* operator()(Media_Query*);
     Expression* operator()(Media_Query_Expression*);
     Expression* operator()(At_Root_Query*);
-    Expression* operator()(Supports_Operator*);
-    Expression* operator()(Supports_Negation*);
-    Expression* operator()(Supports_Declaration*);
+    Expression* operator()(SupportsOperation*);
+    Expression* operator()(SupportsNegation*);
+    Expression* operator()(SupportsDeclaration*);
     Expression* operator()(Supports_Interpolation*);
     Expression* operator()(Null*);
     Expression* operator()(Argument*);
@@ -82,14 +82,14 @@
     CompoundSelector* operator()(CompoundSelector*);
     SelectorComponent* operator()(SelectorComponent*);
     SimpleSelector* operator()(SimpleSelector* s);
-    Pseudo_Selector* operator()(Pseudo_Selector* s);
+    PseudoSelector* operator()(PseudoSelector* s);
 
     // they don't have any specific implementation (yet)
-    Id_Selector* operator()(Id_Selector* s) { return s; };
-    Class_Selector* operator()(Class_Selector* s) { return s; };
-    Type_Selector* operator()(Type_Selector* s) { return s; };
-    Attribute_Selector* operator()(Attribute_Selector* s) { return s; };
-    Placeholder_Selector* operator()(Placeholder_Selector* s) { return s; };
+    IDSelector* operator()(IDSelector* s) { return s; };
+    ClassSelector* operator()(ClassSelector* s) { return s; };
+    TypeSelector* operator()(TypeSelector* s) { return s; };
+    AttributeSelector* operator()(AttributeSelector* s) { return s; };
+    PlaceholderSelector* operator()(PlaceholderSelector* s) { return s; };
 
     // actual evaluated selectors
     SelectorList* operator()(Selector_Schema*);
@@ -101,7 +101,7 @@
     { return Cast<Expression>(x); }
 
   private:
-    void interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl = false);
+    void interpolation(Context& ctx, sass::string& res, ExpressionObj ex, bool into_quotes, bool was_itpl = false);
 
   };
 
diff --git a/libsass/src/eval_selectors.cpp b/libsass/src/eval_selectors.cpp
--- a/libsass/src/eval_selectors.cpp
+++ b/libsass/src/eval_selectors.cpp
@@ -10,7 +10,7 @@
 
   SelectorList* Eval::operator()(SelectorList* s)
   {
-    std::vector<SelectorListObj> rv;
+    sass::vector<SelectorListObj> rv;
     SelectorListObj sl = SASS_MEMORY_NEW(SelectorList, s->pstate());
     for (size_t i = 0, iL = s->length(); i < iL; ++i) {
       rv.push_back(operator()(s->get(i)));
@@ -19,7 +19,7 @@
     // we should actually permutate parent first
     // but here we have permutated the selector first
     size_t round = 0;
-    while (round != std::string::npos) {
+    while (round != sass::string::npos) {
       bool abort = true;
       for (size_t i = 0, iL = rv.size(); i < iL; ++i) {
         if (rv[i]->length() > round) {
@@ -28,7 +28,7 @@
         }
       }
       if (abort) {
-        round = std::string::npos;
+        round = sass::string::npos;
       }
       else {
         ++round;
diff --git a/libsass/src/expand.cpp b/libsass/src/expand.cpp
--- a/libsass/src/expand.cpp
+++ b/libsass/src/expand.cpp
@@ -13,6 +13,7 @@
 #include "context.hpp"
 #include "parser.hpp"
 #include "sass_functions.hpp"
+#include "error_handling.hpp"
 
 namespace Sass {
 
@@ -162,7 +163,7 @@
     return bb.detach();
   }
 
-  Statement* Expand::operator()(Ruleset* r)
+  Statement* Expand::operator()(StyleRule* r)
   {
     LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
 
@@ -188,9 +189,9 @@
     if (r->schema()) {
       SelectorListObj sel = eval(r->schema());
       r->selector(sel);
-      bool chroot = sel->has_real_parent_ref();
       for (auto complex : sel->elements()) {
-        complex->chroots(chroot);
+        // ToDo: maybe we can get rid of chroots?
+        complex->chroots(complex->has_real_parent_ref());
       }
 
     }
@@ -213,7 +214,7 @@
     if (r->block()) blk = operator()(r->block());
     popFromOriginalStack();
     popFromSelectorStack();
-    Ruleset* rr = SASS_MEMORY_NEW(Ruleset,
+    StyleRule* rr = SASS_MEMORY_NEW(StyleRule,
                                   r->pstate(),
                                   evaled,
                                   blk);
@@ -228,21 +229,21 @@
     return rr;
   }
 
-  Statement* Expand::operator()(Supports_Block* f)
+  Statement* Expand::operator()(SupportsRule* f)
   {
-    Expression_Obj condition = f->condition()->perform(&eval);
-    Supports_Block_Obj ff = SASS_MEMORY_NEW(Supports_Block,
+    ExpressionObj condition = f->condition()->perform(&eval);
+    SupportsRuleObj ff = SASS_MEMORY_NEW(SupportsRule,
                                        f->pstate(),
-                                       Cast<Supports_Condition>(condition),
+                                       Cast<SupportsCondition>(condition),
                                        operator()(f->block()));
     return ff.detach();
   }
 
-  std::vector<CssMediaQuery_Obj> Expand::mergeMediaQueries(
-    const std::vector<CssMediaQuery_Obj>& lhs,
-    const std::vector<CssMediaQuery_Obj>& rhs)
+  sass::vector<CssMediaQuery_Obj> Expand::mergeMediaQueries(
+    const sass::vector<CssMediaQuery_Obj>& lhs,
+    const sass::vector<CssMediaQuery_Obj>& rhs)
   {
-    std::vector<CssMediaQuery_Obj> queries;
+    sass::vector<CssMediaQuery_Obj> queries;
     for (CssMediaQuery_Obj query1 : lhs) {
       for (CssMediaQuery_Obj query2 : rhs) {
         CssMediaQuery_Obj result = query1->merge(query2);
@@ -256,14 +257,14 @@
 
   Statement* Expand::operator()(MediaRule* m)
   {
-    Expression_Obj mq = eval(m->schema());
-    std::string str_mq(mq->to_css(ctx.c_options));
-    char* str = sass_copy_c_string(str_mq.c_str());
-    ctx.strings.push_back(str);
-    Parser parser(Parser::from_c_str(str, ctx, traces, mq->pstate()));
+    ExpressionObj mq = eval(m->schema());
+    sass::string str_mq(mq->to_css(ctx.c_options));
+    ItplFile* source = SASS_MEMORY_NEW(ItplFile,
+      str_mq.c_str(), m->pstate());
+    Parser parser(source, ctx, traces);
     // Create a new CSS only representation of the media rule
     CssMediaRuleObj css = SASS_MEMORY_NEW(CssMediaRule, m->pstate(), m->block());
-    std::vector<CssMediaQuery_Obj> parsed = parser.parseCssMediaQueries();
+    sass::vector<CssMediaQuery_Obj> parsed = parser.parseCssMediaQueries();
     if (mediaStack.size() && mediaStack.back()) {
       auto& parent = mediaStack.back()->elements();
       css->concat(mergeMediaQueries(parent, parsed));
@@ -278,10 +279,10 @@
 
   }
 
-  Statement* Expand::operator()(At_Root_Block* a)
+  Statement* Expand::operator()(AtRootRule* a)
   {
     Block_Obj ab = a->block();
-    Expression_Obj ae = a->expression();
+    ExpressionObj ae = a->expression();
 
     if (ae) ae = ae->perform(&eval);
     else ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate());
@@ -292,14 +293,14 @@
                                        ;
 
     Block_Obj bb = ab ? operator()(ab) : NULL;
-    At_Root_Block_Obj aa = SASS_MEMORY_NEW(At_Root_Block,
+    AtRootRuleObj aa = SASS_MEMORY_NEW(AtRootRule,
                                         a->pstate(),
                                         bb,
                                         Cast<At_Root_Query>(ae));
     return aa.detach();
   }
 
-  Statement* Expand::operator()(Directive* a)
+  Statement* Expand::operator()(AtRule* a)
   {
     LOCAL_FLAG(in_keyframes, a->is_keyframes());
     Block* ab = a->block();
@@ -310,7 +311,7 @@
     if (as) as = eval(as);
     popNullSelector();
     Block* bb = ab ? operator()(ab) : NULL;
-    Directive* aa = SASS_MEMORY_NEW(Directive,
+    AtRule* aa = SASS_MEMORY_NEW(AtRule,
                                   a->pstate(),
                                   a->keyword(),
                                   as,
@@ -323,14 +324,14 @@
   {
     Block_Obj ab = d->block();
     String_Obj old_p = d->property();
-    Expression_Obj prop = old_p->perform(&eval);
+    ExpressionObj prop = old_p->perform(&eval);
     String_Obj new_p = Cast<String>(prop);
     // we might get a color back
     if (!new_p) {
-      std::string str(prop->to_string(ctx.c_options));
+      sass::string str(prop->to_string(ctx.c_options));
       new_p = SASS_MEMORY_NEW(String_Constant, old_p->pstate(), str);
     }
-    Expression_Obj value = d->value();
+    ExpressionObj value = d->value();
     if (value) value = value->perform(&eval);
     Block_Obj bb = ab ? operator()(ab) : NULL;
     if (!bb) {
@@ -356,11 +357,17 @@
   Statement* Expand::operator()(Assignment* a)
   {
     Env* env = environment();
-    const std::string& var(a->variable());
+    const sass::string& var(a->variable());
     if (a->is_global()) {
+      if (!env->has_global(var)) {
+        deprecated(
+          "!global assignments won't be able to declare new variables in future versions.",
+          "Consider adding `" + var + ": null` at the top level.",
+          true, a->pstate());
+      }
       if (a->is_default()) {
         if (env->has_global(var)) {
-          Expression_Obj e = Cast<Expression>(env->get_global(var));
+          ExpressionObj e = Cast<Expression>(env->get_global(var));
           if (!e || e->concrete_type() == Expression::NULL_VAL) {
             env->set_global(var, a->value()->perform(&eval));
           }
@@ -379,7 +386,7 @@
         while (cur && cur->is_lexical()) {
           if (cur->has_local(var)) {
             if (AST_Node_Obj node = cur->get_local(var)) {
-              Expression_Obj e = Cast<Expression>(node);
+              ExpressionObj e = Cast<Expression>(node);
               if (!e || e->concrete_type() == Expression::NULL_VAL) {
                 cur->set_local(var, a->value()->perform(&eval));
               }
@@ -395,7 +402,7 @@
       }
       else if (env->has_global(var)) {
         if (AST_Node_Obj node = env->get_global(var)) {
-          Expression_Obj e = Cast<Expression>(node);
+          ExpressionObj e = Cast<Expression>(node);
           if (!e || e->concrete_type() == Expression::NULL_VAL) {
             env->set_global(var, a->value()->perform(&eval));
           }
@@ -418,7 +425,7 @@
   {
     Import_Obj result = SASS_MEMORY_NEW(Import, imp->pstate());
     if (imp->import_queries() && imp->import_queries()->size()) {
-      Expression_Obj ex = imp->import_queries()->perform(&eval);
+      ExpressionObj ex = imp->import_queries()->perform(&eval);
       result->import_queries(Cast<List>(ex));
     }
     for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) {
@@ -450,7 +457,7 @@
     block_stack.back()->append(trace);
     block_stack.push_back(trace_block);
 
-    const std::string& abs_path(i->resource().abs_path);
+    const sass::string& abs_path(i->resource().abs_path);
     append_block(ctx.sheets.at(abs_path).root);
     sass_delete_import(ctx.import_stack.back());
     ctx.import_stack.pop_back();
@@ -459,21 +466,21 @@
     return 0;
   }
 
-  Statement* Expand::operator()(Warning* w)
+  Statement* Expand::operator()(WarningRule* w)
   {
     // eval handles this too, because warnings may occur in functions
     w->perform(&eval);
     return 0;
   }
 
-  Statement* Expand::operator()(Error* e)
+  Statement* Expand::operator()(ErrorRule* e)
   {
     // eval handles this too, because errors may occur in functions
     e->perform(&eval);
     return 0;
   }
 
-  Statement* Expand::operator()(Debug* d)
+  Statement* Expand::operator()(DebugRule* d)
   {
     // eval handles this too, because warnings may occur in functions
     d->perform(&eval);
@@ -499,7 +506,7 @@
     Env env(environment(), true);
     env_stack.push_back(&env);
     call_stack.push_back(i);
-    Expression_Obj rv = i->predicate()->perform(&eval);
+    ExpressionObj rv = i->predicate()->perform(&eval);
     if (*rv) {
       append_block(i->block());
     }
@@ -514,15 +521,15 @@
 
   // For does not create a new env scope
   // But iteration vars are reset afterwards
-  Statement* Expand::operator()(For* f)
+  Statement* Expand::operator()(ForRule* f)
   {
-    std::string variable(f->variable());
-    Expression_Obj low = f->lower_bound()->perform(&eval);
+    sass::string variable(f->variable());
+    ExpressionObj low = f->lower_bound()->perform(&eval);
     if (low->concrete_type() != Expression::NUMBER) {
       traces.push_back(Backtrace(low->pstate()));
       throw Exception::TypeMismatch(traces, *low, "integer");
     }
-    Expression_Obj high = f->upper_bound()->perform(&eval);
+    ExpressionObj high = f->upper_bound()->perform(&eval);
     if (high->concrete_type() != Expression::NUMBER) {
       traces.push_back(Backtrace(high->pstate()));
       throw Exception::TypeMismatch(traces, *high, "integer");
@@ -531,7 +538,7 @@
     Number_Obj sass_end = Cast<Number>(high);
     // check if units are valid for sequence
     if (sass_start->unit() != sass_end->unit()) {
-      std::stringstream msg; msg << "Incompatible units: '"
+      sass::ostream msg; msg << "Incompatible units: '"
         << sass_start->unit() << "' and '"
         << sass_end->unit() << "'.";
       error(msg.str(), low->pstate(), traces);
@@ -569,17 +576,17 @@
 
   // Eval does not create a new env scope
   // But iteration vars are reset afterwards
-  Statement* Expand::operator()(Each* e)
+  Statement* Expand::operator()(EachRule* e)
   {
-    std::vector<std::string> variables(e->variables());
-    Expression_Obj expr = e->list()->perform(&eval);
+    sass::vector<sass::string> variables(e->variables());
+    ExpressionObj expr = e->list()->perform(&eval);
     List_Obj list;
     Map_Obj map;
     if (expr->concrete_type() == Expression::MAP) {
       map = Cast<Map>(expr);
     }
     else if (SelectorList * ls = Cast<SelectorList>(expr)) {
-      Expression_Obj rv = Listize::perform(ls);
+      ExpressionObj rv = Listize::perform(ls);
       list = Cast<List>(rv);
     }
     else if (expr->concrete_type() != Expression::LIST) {
@@ -597,8 +604,8 @@
 
     if (map) {
       for (auto key : map->keys()) {
-        Expression_Obj k = key->perform(&eval);
-        Expression_Obj v = map->at(key)->perform(&eval);
+        ExpressionObj k = key->perform(&eval);
+        ExpressionObj v = map->at(key)->perform(&eval);
 
         if (variables.size() == 1) {
           List_Obj variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
@@ -618,7 +625,7 @@
         list = Cast<List>(list);
       }
       for (size_t i = 0, L = list->length(); i < L; ++i) {
-        Expression_Obj item = list->at(i);
+        ExpressionObj item = list->at(i);
         // unwrap value if the expression is an argument
         if (Argument_Obj arg = Cast<Argument>(item)) item = arg->value();
         // check if we got passed a list of args (investigate)
@@ -629,17 +636,16 @@
             env.set_local(variables[0], var);
           } else {
             for (size_t j = 0, K = variables.size(); j < K; ++j) {
-              Expression_Obj res = j >= scalars->length()
+              env.set_local(variables[j], j >= scalars->length()
                 ? SASS_MEMORY_NEW(Null, expr->pstate())
-                : (*scalars)[j]->perform(&eval);
-              env.set_local(variables[j], res);
+                : (*scalars)[j]->perform(&eval));
             }
           }
         } else {
           if (variables.size() > 0) {
             env.set_local(variables.at(0), item);
             for (size_t j = 1, K = variables.size(); j < K; ++j) {
-              Expression_Obj res = SASS_MEMORY_NEW(Null, expr->pstate());
+              ExpressionObj res = SASS_MEMORY_NEW(Null, expr->pstate());
               env.set_local(variables[j], res);
             }
           }
@@ -652,14 +658,14 @@
     return 0;
   }
 
-  Statement* Expand::operator()(While* w)
+  Statement* Expand::operator()(WhileRule* w)
   {
-    Expression_Obj pred = w->predicate();
+    ExpressionObj pred = w->predicate();
     Block* body = w->block();
     Env env(environment(), true);
     env_stack.push_back(&env);
     call_stack.push_back(w);
-    Expression_Obj cond = pred->perform(&eval);
+    ExpressionObj cond = pred->perform(&eval);
     while (!cond->is_false()) {
       append_block(body);
       cond = pred->perform(&eval);
@@ -698,7 +704,7 @@
 
           if (compound->length() != 1) {
 
-            std::stringstream sels; bool addComma = false;
+            sass::ostream sels; bool addComma = false;
             sels << "Compound selectors may no longer be extended.\n";
             sels << "Consider `@extend ";
             for (auto sel : compound->elements()) {
@@ -769,7 +775,7 @@
     recursions ++;
 
     Env* env = environment();
-    std::string full_name(c->name() + "[m]");
+    sass::string full_name(c->name() + "[m]");
     if (!env->has(full_name)) {
       error("no mixin named " + c->name(), c->pstate(), traces);
     }
@@ -780,15 +786,15 @@
     if (c->block() && c->name() != "@content" && !body->has_content()) {
       error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), traces);
     }
-    Expression_Obj rv = c->arguments()->perform(&eval);
+    ExpressionObj rv = c->arguments()->perform(&eval);
     Arguments_Obj args = Cast<Arguments>(rv);
-    std::string msg(", in mixin `" + c->name() + "`");
+    sass::string msg(", in mixin `" + c->name() + "`");
     traces.push_back(Backtrace(c->pstate(), msg));
     ctx.callee_stack.push_back({
       c->name().c_str(),
-      c->pstate().path,
-      c->pstate().line + 1,
-      c->pstate().column + 1,
+      c->pstate().getPath(),
+      c->pstate().getLine(),
+      c->pstate().getColumn(),
       SASS_CALLEE_MIXIN,
       { env }
     });
@@ -809,7 +815,7 @@
       new_env.local_frame()["@content[m]"] = thunk;
     }
 
-    bind(std::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
+    bind(sass::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
 
     Block_Obj trace_block = SASS_MEMORY_NEW(Block, c->pstate());
     Trace_Obj trace = SASS_MEMORY_NEW(Trace, c->pstate(), c->name(), trace_block);
@@ -820,7 +826,7 @@
     }
     block_stack.push_back(trace_block);
     for (auto bb : body->elements()) {
-      if (Ruleset* r = Cast<Ruleset>(bb)) {
+      if (StyleRule* r = Cast<StyleRule>(bb)) {
         r->is_root(trace_block->is_root());
       }
       Statement_Obj ith = bb->perform(this);
diff --git a/libsass/src/expand.hpp b/libsass/src/expand.hpp
--- a/libsass/src/expand.hpp
+++ b/libsass/src/expand.hpp
@@ -54,35 +54,35 @@
 
   private:
 
-    std::vector<CssMediaQuery_Obj> mergeMediaQueries(const std::vector<CssMediaQuery_Obj>& lhs, const std::vector<CssMediaQuery_Obj>& rhs);
+    sass::vector<CssMediaQuery_Obj> mergeMediaQueries(const sass::vector<CssMediaQuery_Obj>& lhs, const sass::vector<CssMediaQuery_Obj>& rhs);
 
   public:
     Expand(Context&, Env*, SelectorStack* stack = nullptr, SelectorStack* original = nullptr);
     ~Expand() { }
 
     Block* operator()(Block*);
-    Statement* operator()(Ruleset*);
+    Statement* operator()(StyleRule*);
 
     Statement* operator()(MediaRule*);
 
-    // Css Ruleset is already static
+    // Css StyleRule is already static
     // Statement* operator()(CssMediaRule*);
 
-    Statement* operator()(Supports_Block*);
-    Statement* operator()(At_Root_Block*);
-    Statement* operator()(Directive*);
+    Statement* operator()(SupportsRule*);
+    Statement* operator()(AtRootRule*);
+    Statement* operator()(AtRule*);
     Statement* operator()(Declaration*);
     Statement* operator()(Assignment*);
     Statement* operator()(Import*);
     Statement* operator()(Import_Stub*);
-    Statement* operator()(Warning*);
-    Statement* operator()(Error*);
-    Statement* operator()(Debug*);
+    Statement* operator()(WarningRule*);
+    Statement* operator()(ErrorRule*);
+    Statement* operator()(DebugRule*);
     Statement* operator()(Comment*);
     Statement* operator()(If*);
-    Statement* operator()(For*);
-    Statement* operator()(Each*);
-    Statement* operator()(While*);
+    Statement* operator()(ForRule*);
+    Statement* operator()(EachRule*);
+    Statement* operator()(WhileRule*);
     Statement* operator()(Return*);
     Statement* operator()(ExtendRule*);
     Statement* operator()(Definition*);
diff --git a/libsass/src/extender.cpp b/libsass/src/extender.cpp
--- a/libsass/src/extender.cpp
+++ b/libsass/src/extender.cpp
@@ -142,10 +142,12 @@
   // ##########################################################################
   bool Extender::checkForUnsatisfiedExtends(Extension& unsatisfied) const
   {
+    if (selectors.empty()) return false;
     ExtSmplSelSet originals = getSimpleSelectors();
     for (auto target : extensions) {
       SimpleSelector* key = target.first;
       ExtSelExtMapEntry& val = target.second;
+      if (val.empty()) continue;
       if (originals.find(key) == originals.end()) {
         const Extension& extension = val.front().second;
         if (extension.isOptional) continue;
@@ -387,7 +389,7 @@
       CssMediaRuleObj mediaContext;
       if (mediaContexts.hasKey(rule)) mediaContext = mediaContexts.get(rule);
       SelectorListObj ext = extendList(rule, newExtensions, mediaContext);
-      // If no extends actually happenedit (for example becaues unification
+      // If no extends actually happened (for example because unification
       // failed), we don't need to re-register the selector.
       if (ObjEqualityFn(oldValue, ext)) continue;
       rule->elements(ext->elements());
@@ -417,7 +419,7 @@
   // ##########################################################################
   ExtSelExtMap Extender::extendExistingExtensions(
     // Taking in a reference here makes MSVC debug stuck!?
-    const std::vector<Extension>& oldExtensions,
+    const sass::vector<Extension>& oldExtensions,
     const ExtSelExtMap& newExtensions)
   {
 
@@ -429,7 +431,7 @@
     for (size_t i = 0, iL = oldExtensions.size(); i < iL; i += 1) {
       const Extension& extension = oldExtensions[i];
       ExtSelExtMapEntry& sources = extensions[extension.target];
-      std::vector<ComplexSelectorObj> selectors(extendComplex(
+      sass::vector<ComplexSelectorObj> selectors(extendComplex(
         extension.extender,
         newExtensions,
         extension.mediaContext
@@ -503,10 +505,10 @@
 
     // This could be written more simply using [List.map], but we want to
     // avoid any allocations in the common case where no extends apply.
-    std::vector<ComplexSelectorObj> extended;
+    sass::vector<ComplexSelectorObj> extended;
     for (size_t i = 0; i < list->length(); i++) {
       const ComplexSelectorObj& complex = list->get(i);
-      std::vector<ComplexSelectorObj> result =
+      sass::vector<ComplexSelectorObj> result =
         extendComplex(complex, extensions, mediaQueryContext);
       if (result.empty()) {
         if (!extended.empty()) {
@@ -540,7 +542,7 @@
   // Extends [complex] using [extensions], and
   // returns the contents of a [SelectorList].
   // ##########################################################################
-  std::vector<ComplexSelectorObj> Extender::extendComplex(
+  sass::vector<ComplexSelectorObj> Extender::extendComplex(
     // Taking in a reference here makes MSVC debug stuck!?
     const ComplexSelectorObj& complex,
     const ExtSelExtMap& extensions,
@@ -565,13 +567,13 @@
     // This could be written more simply using [List.map], but we want to avoid
     // any allocations in the common case where no extends apply.
 
-    std::vector<ComplexSelectorObj> result;
-    std::vector<std::vector<ComplexSelectorObj>> extendedNotExpanded;
+    sass::vector<ComplexSelectorObj> result;
+    sass::vector<sass::vector<ComplexSelectorObj>> extendedNotExpanded;
     bool isOriginal = originals.find(complex) != originals.end();
     for (size_t i = 0; i < complex->length(); i += 1) {
       const SelectorComponentObj& component = complex->get(i);
       if (CompoundSelector* compound = Cast<CompoundSelector>(component)) {
-        std::vector<ComplexSelectorObj> extended = extendCompound(
+        sass::vector<ComplexSelectorObj> extended = extendCompound(
           compound, extensions, mediaQueryContext, isOriginal);
         if (extended.empty()) {
           if (!extendedNotExpanded.empty()) {
@@ -610,19 +612,19 @@
     bool first = true;
 
     // ToDo: either change weave or paths to work with the same data?
-    std::vector<std::vector<ComplexSelectorObj>>
+    sass::vector<sass::vector<ComplexSelectorObj>>
       paths = permutate(extendedNotExpanded);
     
-    for (const std::vector<ComplexSelectorObj>& path : paths) {
+    for (const sass::vector<ComplexSelectorObj>& path : paths) {
       // Unpack the inner complex selector to component list
-      std::vector<std::vector<SelectorComponentObj>> _paths;
+      sass::vector<sass::vector<SelectorComponentObj>> _paths;
       for (const ComplexSelectorObj& sel : path) {
         _paths.insert(_paths.end(), sel->elements());
       }
 
-      std::vector<std::vector<SelectorComponentObj>> weaved = weave(_paths);
+      sass::vector<sass::vector<SelectorComponentObj>> weaved = weave(_paths);
 
-      for (std::vector<SelectorComponentObj>& components : weaved) {
+      for (sass::vector<SelectorComponentObj>& components : weaved) {
 
         ComplexSelectorObj cplx = SASS_MEMORY_NEW(ComplexSelector, "[phony]");
         cplx->hasPreLineFeed(complex->hasPreLineFeed());
@@ -671,9 +673,9 @@
   // ##########################################################################
   Extension Extender::extensionForCompound(
     // Taking in a reference here makes MSVC debug stuck!?
-    const std::vector<SimpleSelectorObj>& simples) const
+    const sass::vector<SimpleSelectorObj>& simples) const
   {
-    CompoundSelectorObj compound = SASS_MEMORY_NEW(CompoundSelector, ParserState("[ext]"));
+    CompoundSelectorObj compound = SASS_MEMORY_NEW(CompoundSelector, SourceSpan("[ext]"));
     compound->concat(simples);
     Extension extension(compound->wrapInComplex());
     // extension.specificity = sourceSpecificity[simple];
@@ -688,7 +690,7 @@
   // indicates whether this is in an original complex selector,
   // meaning that [compound] should not be trimmed out.
   // ##########################################################################
-  std::vector<ComplexSelectorObj> Extender::extendCompound(
+  sass::vector<ComplexSelectorObj> Extender::extendCompound(
     const CompoundSelectorObj& compound,
     const ExtSelExtMap& extensions,
     const CssMediaRuleObj& mediaQueryContext,
@@ -705,9 +707,9 @@
       targetsUsed = &targetsUsed2;
     }
 
-    std::vector<ComplexSelectorObj> result;
+    sass::vector<ComplexSelectorObj> result;
     // The complex selectors produced from each component of [compound].
-    std::vector<std::vector<Extension>> options;
+    sass::vector<sass::vector<Extension>> options;
 
     for (size_t i = 0; i < compound->length(); i++) {
       const SimpleSelectorObj& simple = compound->get(i);
@@ -720,7 +722,7 @@
       else {
         if (options.empty()) {
           if (i != 0) {
-            std::vector<SimpleSelectorObj> in;
+            sass::vector<SimpleSelectorObj> in;
             for (size_t n = 0; n < i; n += 1) {
               in.push_back(compound->get(n));
             }
@@ -750,7 +752,7 @@
     // Optimize for the simple case of a single simple
     // selector that doesn't need any unification.
     if (options.size() == 1) {
-      std::vector<Extension> exts = options[0];
+      sass::vector<Extension> exts = options[0];
       for (size_t n = 0; n < exts.size(); n += 1) {
         exts[n].assertCompatibleMediaContext(mediaQueryContext, traces);
         result.push_back(exts[n].extender);
@@ -784,12 +786,12 @@
     //     ]
 
     bool first = mode != ExtendMode::REPLACE;
-    std::vector<ComplexSelectorObj> unifiedPaths;
-    std::vector<std::vector<Extension>> prePaths = permutate(options);
+    sass::vector<ComplexSelectorObj> unifiedPaths;
+    sass::vector<sass::vector<Extension>> prePaths = permutate(options);
 
     for (size_t i = 0; i < prePaths.size(); i += 1) {
-      std::vector<std::vector<SelectorComponentObj>> complexes;
-      const std::vector<Extension>& path = prePaths[i];
+      sass::vector<sass::vector<SelectorComponentObj>> complexes;
+      const sass::vector<Extension>& path = prePaths[i];
       if (first) {
         // The first path is always the original selector. We can't just
         // return [compound] directly because pseudo selectors may be
@@ -806,8 +808,8 @@
         complexes.push_back({ mergedSelector });
       }
       else {
-        std::vector<SimpleSelectorObj> originals;
-        std::vector<std::vector<SelectorComponentObj>> toUnify;
+        sass::vector<SimpleSelectorObj> originals;
+        sass::vector<sass::vector<SelectorComponentObj>> toUnify;
 
         for (auto& state : path) {
           if (state.isOriginal) {
@@ -841,7 +843,7 @@
         // specificity = math.max(specificity, state.specificity);
       }
 
-      for (std::vector<SelectorComponentObj>& components : complexes) {
+      for (sass::vector<SelectorComponentObj>& components : complexes) {
         auto sel = SASS_MEMORY_NEW(ComplexSelector, "[ext]");
         sel->hasPreLineFeed(lineBreak);
         sel->elements(components);
@@ -858,7 +860,7 @@
   // Extends [simple] without extending the
   // contents of any selector pseudos it contains.
   // ##########################################################################
-  std::vector<Extension> Extender::extendWithoutPseudo(
+  sass::vector<Extension> Extender::extendWithoutPseudo(
     const SimpleSelectorObj& simple,
     const ExtSelExtMap& extensions,
     ExtSmplSelSet* targetsUsed) const
@@ -875,9 +877,9 @@
       return extenders.values();
     }
 
-    const std::vector<Extension>&
+    const sass::vector<Extension>&
       values = extenders.values();
-    std::vector<Extension> result;
+    sass::vector<Extension> result;
     result.reserve(values.size() + 1);
     result.push_back(extensionForSimple(simple));
     result.insert(result.end(), values.begin(), values.end());
@@ -889,20 +891,20 @@
   // Extends [simple] and also extending the
   // contents of any selector pseudos it contains.
   // ##########################################################################
-  std::vector<std::vector<Extension>> Extender::extendSimple(
+  sass::vector<sass::vector<Extension>> Extender::extendSimple(
     const SimpleSelectorObj& simple,
     const ExtSelExtMap& extensions,
     const CssMediaRuleObj& mediaQueryContext,
     ExtSmplSelSet* targetsUsed)
   {
-    if (Pseudo_Selector* pseudo = Cast<Pseudo_Selector>(simple)) {
+    if (PseudoSelector* pseudo = Cast<PseudoSelector>(simple)) {
       if (pseudo->selector()) {
-        std::vector<std::vector<Extension>> merged;
-        std::vector<Pseudo_Selector_Obj> extended =
+        sass::vector<sass::vector<Extension>> merged;
+        sass::vector<PseudoSelectorObj> extended =
           extendPseudo(pseudo, extensions, mediaQueryContext);
-        for (Pseudo_Selector_Obj& extend : extended) {
+        for (PseudoSelectorObj& extend : extended) {
           SimpleSelectorObj simple = extend;
-          std::vector<Extension> result =
+          sass::vector<Extension> result =
             extendWithoutPseudo(simple, extensions, targetsUsed);
           if (result.empty()) result = { extensionForSimple(extend) };
           merged.push_back(result);
@@ -912,7 +914,7 @@
         }
       }
     }
-    std::vector<Extension> result =
+    sass::vector<Extension> result =
       extendWithoutPseudo(simple, extensions, targetsUsed);
     if (result.empty()) return {};
     return { result };
@@ -922,9 +924,9 @@
   // ##########################################################################
   // Inner loop helper for [extendPseudo] function
   // ##########################################################################
-  std::vector<ComplexSelectorObj> Extender::extendPseudoComplex(
+  sass::vector<ComplexSelectorObj> Extender::extendPseudoComplex(
     const ComplexSelectorObj& complex,
-    const Pseudo_Selector_Obj& pseudo,
+    const PseudoSelectorObj& pseudo,
     const CssMediaRuleObj& mediaQueryContext)
   {
 
@@ -932,11 +934,11 @@
     auto compound = Cast<CompoundSelector>(complex->get(0));
     if (compound == nullptr) { return { complex }; }
     if (compound->length() != 1) { return { complex }; }
-    auto innerPseudo = Cast<Pseudo_Selector>(compound->get(0));
+    auto innerPseudo = Cast<PseudoSelector>(compound->get(0));
     if (innerPseudo == nullptr) { return { complex }; }
     if (!innerPseudo->selector()) { return { complex }; }
 
-    std::string name(pseudo->normalized());
+    sass::string name(pseudo->normalized());
 
     if (name == "not") {
       // In theory, if there's a `:not` nested within another `:not`, the
@@ -972,8 +974,8 @@
   // Extends [pseudo] using [extensions], and returns
   // a list of resulting pseudo selectors.
   // ##########################################################################
-  std::vector<Pseudo_Selector_Obj> Extender::extendPseudo(
-    const Pseudo_Selector_Obj& pseudo,
+  sass::vector<PseudoSelectorObj> Extender::extendPseudo(
+    const PseudoSelectorObj& pseudo,
     const ExtSelExtMap& extensions,
     const CssMediaRuleObj& mediaQueryContext)
   {
@@ -988,7 +990,7 @@
     // writing. We can keep them if either the original selector had a complex
     // selector, or the result of extending has only complex selectors, because
     // either way we aren't breaking anything that isn't already broken.
-    std::vector<ComplexSelectorObj> complexes = extended->elements();
+    sass::vector<ComplexSelectorObj> complexes = extended->elements();
 
     if (pseudo->normalized() == "not") {
       if (!hasAny(pseudo->selector()->elements(), hasMoreThanOne)) {
@@ -1003,7 +1005,7 @@
       }
     }
     
-    std::vector<ComplexSelectorObj> expanded = expand(
+    sass::vector<ComplexSelectorObj> expanded = expand(
       complexes, extendPseudoComplex, pseudo, mediaQueryContext);
 
     // Older browsers support `:not`, but only with a single complex selector.
@@ -1011,7 +1013,7 @@
     // unless it originally contained a selector list.
     if (pseudo->normalized() == "not") {
       if (pseudo->selector()->length() == 1) {
-        std::vector<Pseudo_Selector_Obj> pseudos;
+        sass::vector<PseudoSelectorObj> pseudos;
         for (size_t i = 0; i < expanded.size(); i += 1) {
           pseudos.push_back(pseudo->withSelector(
             expanded[i]->wrapInList()
@@ -1033,7 +1035,7 @@
   // one index higher, looping the final element back to [start].
   // ##########################################################################
   void Extender::rotateSlice(
-    std::vector<ComplexSelectorObj>& list,
+    sass::vector<ComplexSelectorObj>& list,
     size_t start, size_t end)
   {
     auto element = list[end - 1];
@@ -1053,8 +1055,8 @@
   // Note: for adaption I pass in the set directly, there is some
   // code path in selector-trim that might need this special callback
   // ##########################################################################
-  std::vector<ComplexSelectorObj> Extender::trim(
-    const std::vector<ComplexSelectorObj>& selectors,
+  sass::vector<ComplexSelectorObj> Extender::trim(
+    const sass::vector<ComplexSelectorObj>& selectors,
     const ExtCplxSelSet& existing) const
   {
 
@@ -1062,17 +1064,17 @@
     // TODO(nweiz): I think there may be a way to get perfect trimming 
     // without going quadratic by building some sort of trie-like
     // data structure that can be used to look up superselectors.
-    // TODO(mgreter): Check how this perfoms in C++ (up the limit)
+    // TODO(mgreter): Check how this performs in C++ (up the limit)
     if (selectors.size() > 100) return selectors;
 
     // This is n² on the sequences, but only comparing between separate sequences
     // should limit the quadratic behavior. We iterate from last to first and reverse
     // the result so that, if two selectors are identical, we keep the first one.
-    std::vector<ComplexSelectorObj> result; size_t numOriginals = 0;
+    sass::vector<ComplexSelectorObj> result; size_t numOriginals = 0;
 
     size_t i = selectors.size();
   outer: // Use label to continue loop
-    while (--i != std::string::npos) {
+    while (--i != sass::string::npos) {
 
       const ComplexSelectorObj& complex1 = selectors[i];
       // Check if selector in known in existing "originals"
diff --git a/libsass/src/extender.hpp b/libsass/src/extender.hpp
--- a/libsass/src/extender.hpp
+++ b/libsass/src/extender.hpp
@@ -60,7 +60,7 @@
 
   typedef std::unordered_map <
     SimpleSelectorObj,
-    std::vector<
+    sass::vector<
       Extension
     >,
     ObjHash,
@@ -267,7 +267,7 @@
     // ##########################################################################
     ExtSelExtMap extendExistingExtensions(
       // Taking in a reference here makes MSVC debug stuck!?
-      const std::vector<Extension>& extensions,
+      const sass::vector<Extension>& extensions,
       const ExtSelExtMap& newExtensions);
 
     // ##########################################################################
@@ -282,7 +282,7 @@
     // Extends [complex] using [extensions], and
     // returns the contents of a [SelectorList].
     // ##########################################################################
-    std::vector<ComplexSelectorObj> extendComplex(
+    sass::vector<ComplexSelectorObj> extendComplex(
       // Taking in a reference here makes MSVC debug stuck!?
       const ComplexSelectorObj& list,
       const ExtSelExtMap& extensions,
@@ -301,7 +301,7 @@
     // ##########################################################################
     Extension extensionForCompound(
       // Taking in a reference here makes MSVC debug stuck!?
-      const std::vector<SimpleSelectorObj>& simples) const;
+      const sass::vector<SimpleSelectorObj>& simples) const;
 
     // ##########################################################################
     // Extends [compound] using [extensions], and returns the
@@ -309,7 +309,7 @@
     // indicates whether this is in an original complex selector,
     // meaning that [compound] should not be trimmed out.
     // ##########################################################################
-    std::vector<ComplexSelectorObj> extendCompound(
+    sass::vector<ComplexSelectorObj> extendCompound(
       const CompoundSelectorObj& compound,
       const ExtSelExtMap& extensions,
       const CssMediaRuleObj& mediaQueryContext,
@@ -319,7 +319,7 @@
     // Extends [simple] without extending the
     // contents of any selector pseudos it contains.
     // ##########################################################################
-    std::vector<Extension> extendWithoutPseudo(
+    sass::vector<Extension> extendWithoutPseudo(
       const SimpleSelectorObj& simple,
       const ExtSelExtMap& extensions,
       ExtSmplSelSet* targetsUsed) const;
@@ -328,7 +328,7 @@
     // Extends [simple] and also extending the
     // contents of any selector pseudos it contains.
     // ##########################################################################
-    std::vector<std::vector<Extension>> extendSimple(
+    sass::vector<sass::vector<Extension>> extendSimple(
       const SimpleSelectorObj& simple,
       const ExtSelExtMap& extensions,
       const CssMediaRuleObj& mediaQueryContext,
@@ -337,17 +337,17 @@
     // ##########################################################################
     // Inner loop helper for [extendPseudo] function
     // ##########################################################################
-    static std::vector<ComplexSelectorObj> extendPseudoComplex(
+    static sass::vector<ComplexSelectorObj> extendPseudoComplex(
       const ComplexSelectorObj& complex,
-      const Pseudo_Selector_Obj& pseudo,
+      const PseudoSelectorObj& pseudo,
       const CssMediaRuleObj& mediaQueryContext);
 
     // ##########################################################################
     // Extends [pseudo] using [extensions], and returns
     // a list of resulting pseudo selectors.
     // ##########################################################################
-    std::vector<Pseudo_Selector_Obj> extendPseudo(
-      const Pseudo_Selector_Obj& pseudo,
+    sass::vector<PseudoSelectorObj> extendPseudo(
+      const PseudoSelectorObj& pseudo,
       const ExtSelExtMap& extensions,
       const CssMediaRuleObj& mediaQueryContext);
 
@@ -356,7 +356,7 @@
     // one index higher, looping the final element back to [start].
     // ##########################################################################
     static void rotateSlice(
-      std::vector<ComplexSelectorObj>& list,
+      sass::vector<ComplexSelectorObj>& list,
       size_t start, size_t end);
 
     // ##########################################################################
@@ -364,8 +364,8 @@
     // elements. The [isOriginal] callback indicates which selectors are
     // original to the document, and thus should never be trimmed.
     // ##########################################################################
-    std::vector<ComplexSelectorObj> trim(
-      const std::vector<ComplexSelectorObj>& selectors,
+    sass::vector<ComplexSelectorObj> trim(
+      const sass::vector<ComplexSelectorObj>& selectors,
       const ExtCplxSelSet& set) const;
 
     // ##########################################################################
diff --git a/libsass/src/file.cpp b/libsass/src/file.cpp
--- a/libsass/src/file.cpp
+++ b/libsass/src/file.cpp
@@ -32,16 +32,16 @@
 
 # ifdef _MSC_VER
 # include <codecvt>
-inline static std::string wstring_to_string(const std::wstring& wstr)
+inline static Sass::sass::string wstring_to_string(const std::wstring& wstr)
 {
     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_converter;
     return wchar_converter.to_bytes(wstr);
 }
 # else // mingw(/gcc) does not support C++11's codecvt yet.
-inline static std::string wstring_to_string(const std::wstring &wstr)
+inline static Sass::sass::string wstring_to_string(const std::wstring &wstr)
 {
     int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
-    std::string strTo(size_needed, 0);
+    Sass::sass::string strTo(size_needed, 0);
     WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
     return strTo;
 }
@@ -54,7 +54,7 @@
     // return the current directory
     // always with forward slashes
     // always with trailing slash
-    std::string get_cwd()
+    sass::string get_cwd()
     {
       const size_t wd_len = 4096;
       #ifndef _WIN32
@@ -63,12 +63,12 @@
         // we should check error for more detailed info (e.g. ENOENT)
         // http://man7.org/linux/man-pages/man2/getcwd.2.html#ERRORS
         if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
-        std::string cwd = pwd;
+        sass::string cwd = pwd;
       #else
         wchar_t wd[wd_len];
         wchar_t* pwd = _wgetcwd(wd, wd_len);
         if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
-        std::string cwd = wstring_to_string(pwd);
+        sass::string cwd = wstring_to_string(pwd);
         //convert backslashes to forward slashes
         replace(cwd.begin(), cwd.end(), '\\', '/');
       #endif
@@ -77,12 +77,12 @@
     }
 
     // test if path exists and is a file
-    bool file_exists(const std::string& path)
+    bool file_exists(const sass::string& path)
     {
       #ifdef _WIN32
         wchar_t resolved[32768];
         // windows unicode filepaths are encoded in utf16
-        std::string abspath(join_paths(get_cwd(), path));
+        sass::string abspath(join_paths(get_cwd(), path));
         if (!(abspath[0] == '/' && abspath[1] == '/')) {
           abspath = "//?/" + abspath;
         }
@@ -103,7 +103,7 @@
 
     // return if given path is absolute
     // works with *nix and windows paths
-    bool is_absolute_path(const std::string& path)
+    bool is_absolute_path(const sass::string& path)
     {
       #ifdef _WIN32
         if (path.length() >= 2 && Util::ascii_isalpha(path[0]) && path[1] == ':') return true;
@@ -119,19 +119,19 @@
     }
 
     // helper function to find the last directory separator
-    inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
+    inline size_t find_last_folder_separator(const sass::string& path, size_t limit = sass::string::npos)
     {
       size_t pos;
       size_t pos_p = path.find_last_of('/', limit);
       #ifdef _WIN32
         size_t pos_w = path.find_last_of('\\', limit);
       #else
-        size_t pos_w = std::string::npos;
+        size_t pos_w = sass::string::npos;
       #endif
-      if (pos_p != std::string::npos && pos_w != std::string::npos) {
+      if (pos_p != sass::string::npos && pos_w != sass::string::npos) {
         pos = std::max(pos_p, pos_w);
       }
-      else if (pos_p != std::string::npos) {
+      else if (pos_p != sass::string::npos) {
         pos = pos_p;
       }
       else {
@@ -141,24 +141,24 @@
     }
 
     // return only the directory part of path
-    std::string dir_name(const std::string& path)
+    sass::string dir_name(const sass::string& path)
     {
       size_t pos = find_last_folder_separator(path);
-      if (pos == std::string::npos) return "";
+      if (pos == sass::string::npos) return "";
       else return path.substr(0, pos+1);
     }
 
     // return only the filename part of path
-    std::string base_name(const std::string& path)
+    sass::string base_name(const sass::string& path)
     {
       size_t pos = find_last_folder_separator(path);
-      if (pos == std::string::npos) return path;
+      if (pos == sass::string::npos) return path;
       else return path.substr(pos+1);
     }
 
     // do a logical clean up of the path
     // no physical check on the filesystem
-    std::string make_canonical_path (std::string path)
+    sass::string make_canonical_path (sass::string path)
     {
 
       // declarations
@@ -170,7 +170,7 @@
       #endif
 
       pos = 0; // remove all self references inside the path string
-      while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
+      while((pos = path.find("/./", pos)) != sass::string::npos) path.erase(pos, 2);
 
       // remove all leading and trailing self references
       while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2);
@@ -190,7 +190,7 @@
       while (path[proto++] == '/') {}
 
       pos = proto; // collapse multiple delimiters into a single one
-      while((pos = path.find("//", pos)) != std::string::npos) path.erase(pos, 1);
+      while((pos = path.find("//", pos)) != sass::string::npos) path.erase(pos, 1);
 
       return path;
 
@@ -198,7 +198,7 @@
 
     // join two path segments cleanly together
     // but only if right side is not absolute yet
-    std::string join_paths(std::string l, std::string r)
+    sass::string join_paths(sass::string l, sass::string r)
     {
 
       #ifdef _WIN32
@@ -225,16 +225,16 @@
         bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
         bool is_self = pos + 3 == L && (l[pos+1] == '.');
         if (!is_self && !is_slash) r = r.substr(3);
-        else if (pos == std::string::npos) break;
-        l = l.substr(0, pos == std::string::npos ? pos : pos + 1);
+        else if (pos == sass::string::npos) break;
+        l = l.substr(0, pos == sass::string::npos ? pos : pos + 1);
       }
 
       return l + r;
     }
 
-    std::string path_for_console(const std::string& rel_path, const std::string& abs_path, const std::string& orig_path)
+    sass::string path_for_console(const sass::string& rel_path, const sass::string& abs_path, const sass::string& orig_path)
     {
-      // magic algorith goes here!!
+      // magic algorithm goes here!!
 
       // if the file is outside this directory show the absolute path
       if (rel_path.substr(0, 3) == "../") {
@@ -245,18 +245,26 @@
     }
 
     // create an absolute path by resolving relative paths with cwd
-    std::string rel2abs(const std::string& path, const std::string& base, const std::string& cwd)
+    sass::string rel2abs(const sass::string& path, const sass::string& base, const sass::string& cwd)
     {
-      return make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
+      sass::string rv = make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
+      #ifdef _WIN32
+      // On windows we may get an absolute path without directory
+      // In that case we should prepend the directory from the root
+      if (rv[0] == '/' && rv[1] != '/') {
+        rv.insert(0, cwd, 0, 2);
+      }
+      #endif
+      return rv;
     }
 
     // create a path that is relative to the given base directory
     // path and base will first be resolved against cwd to make them absolute
-    std::string abs2rel(const std::string& path, const std::string& base, const std::string& cwd)
+    sass::string abs2rel(const sass::string& path, const sass::string& base, const sass::string& cwd)
     {
 
-      std::string abs_path = rel2abs(path, cwd);
-      std::string abs_base = rel2abs(base, cwd);
+      sass::string abs_path = rel2abs(path, cwd);
+      sass::string abs_base = rel2abs(base, cwd);
 
       size_t proto = 0;
       // check if we have a protocol
@@ -277,8 +285,8 @@
         if (abs_base[0] != abs_path[0]) return abs_path;
       #endif
 
-      std::string stripped_uri = "";
-      std::string stripped_base = "";
+      sass::string stripped_uri = "";
+      sass::string stripped_base = "";
 
       size_t index = 0;
       size_t minSize = std::min(abs_path.size(), abs_base.size());
@@ -317,7 +325,7 @@
         }
       }
 
-      std::string result = "";
+      sass::string result = "";
       for (size_t i = 0; i < directories; ++i) {
         result += "../";
       }
@@ -333,16 +341,16 @@
     // (4) given + extension
     // (5) given + _index.scss
     // (6) given + _index.sass
-    std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
+    sass::vector<Include> resolve_includes(const sass::string& root, const sass::string& file, const sass::vector<sass::string>& exts)
     {
-      std::string filename = join_paths(root, file);
+      sass::string filename = join_paths(root, file);
       // split the filename
-      std::string base(dir_name(file));
-      std::string name(base_name(file));
-      std::vector<Include> includes;
+      sass::string base(dir_name(file));
+      sass::string name(base_name(file));
+      sass::vector<Include> includes;
       // create full path (maybe relative)
-      std::string rel_path(join_paths(base, name));
-      std::string abs_path(join_paths(root, rel_path));
+      sass::string rel_path(join_paths(base, name));
+      sass::string abs_path(join_paths(root, rel_path));
       if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
       // next test variation with underscore
       rel_path = join_paths(base, "_" + name);
@@ -383,24 +391,24 @@
       return includes;
     }
 
-    std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
+    sass::vector<sass::string> find_files(const sass::string& file, const sass::vector<sass::string> paths)
     {
-      std::vector<std::string> includes;
-      for (std::string path : paths) {
-        std::string abs_path(join_paths(path, file));
+      sass::vector<sass::string> includes;
+      for (sass::string path : paths) {
+        sass::string abs_path(join_paths(path, file));
         if (file_exists(abs_path)) includes.push_back(abs_path);
       }
       return includes;
     }
 
-    std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
+    sass::vector<sass::string> find_files(const sass::string& file, struct Sass_Compiler* compiler)
     {
       // get the last import entry to get current base directory
       // struct Sass_Options* options = sass_compiler_get_options(compiler);
       Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
-      const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
+      const sass::vector<sass::string>& incs = compiler->cpp_ctx->include_paths;
       // create the vector with paths to lookup
-      std::vector<std::string> paths(1 + incs.size());
+      sass::vector<sass::string> paths(1 + incs.size());
       paths.push_back(dir_name(import->abs_path));
       paths.insert(paths.end(), incs.begin(), incs.end());
       // dispatch to find files in paths
@@ -409,7 +417,7 @@
 
     // helper function to search one file in all include paths
     // this is normally not used internally by libsass (C-API sugar)
-    std::string find_file(const std::string& file, const std::vector<std::string> paths)
+    sass::string find_file(const sass::string& file, const sass::vector<sass::string> paths)
     {
       if (file.empty()) return file;
       auto res = find_files(file, paths);
@@ -417,29 +425,29 @@
     }
 
     // helper function to resolve a filename
-    std::string find_include(const std::string& file, const std::vector<std::string> paths)
+    sass::string find_include(const sass::string& file, const sass::vector<sass::string> paths)
     {
       // search in every include path for a match
       for (size_t i = 0, S = paths.size(); i < S; ++i)
       {
-        std::vector<Include> resolved(resolve_includes(paths[i], file));
+        sass::vector<Include> resolved(resolve_includes(paths[i], file));
         if (resolved.size()) return resolved[0].abs_path;
       }
       // nothing found
-      return std::string("");
+      return sass::string("");
     }
 
     // try to load the given filename
     // returned memory must be freed
     // will auto convert .sass files
-    char* read_file(const std::string& path)
+    char* read_file(const sass::string& path)
     {
       #ifdef _WIN32
         BYTE* pBuffer;
         DWORD dwBytes;
         wchar_t resolved[32768];
         // windows unicode filepaths are encoded in utf16
-        std::string abspath(join_paths(get_cwd(), path));
+        sass::string abspath(join_paths(get_cwd(), path));
         if (!(abspath[0] == '/' && abspath[1] == '/')) {
           abspath = "//?/" + abspath;
         }
@@ -485,7 +493,7 @@
         contents[size] = '\0';
         contents[size + 1] = '\0';
       #endif
-      std::string extension;
+      sass::string extension;
       if (path.length() > 5) {
         extension = path.substr(path.length() - 5, 5);
       }
@@ -500,21 +508,21 @@
     }
 
     // split a path string delimited by semicolons or colons (OS dependent)
-    std::vector<std::string> split_path_list(const char* str)
+    sass::vector<sass::string> split_path_list(const char* str)
     {
-      std::vector<std::string> paths;
+      sass::vector<sass::string> paths;
       if (str == NULL) return paths;
       // find delimiter via prelexer (return zero at end)
       const char* end = Prelexer::find_first<PATH_SEP>(str);
       // search until null delimiter
       while (end) {
         // add path from current position to delimiter
-        paths.push_back(std::string(str, end - str));
+        paths.push_back(sass::string(str, end - str));
         str = end + 1; // skip delimiter
         end = Prelexer::find_first<PATH_SEP>(str);
       }
       // add path from current position to end
-      paths.push_back(std::string(str));
+      paths.push_back(sass::string(str));
       // return back
       return paths;
     }
diff --git a/libsass/src/file.hpp b/libsass/src/file.hpp
--- a/libsass/src/file.hpp
+++ b/libsass/src/file.hpp
@@ -17,56 +17,56 @@
 
     // return the current directory
     // always with forward slashes
-    std::string get_cwd();
+    sass::string get_cwd();
 
     // test if path exists and is a file
-    bool file_exists(const std::string& file);
+    bool file_exists(const sass::string& file);
 
     // return if given path is absolute
     // works with *nix and windows paths
-    bool is_absolute_path(const std::string& path);
+    bool is_absolute_path(const sass::string& path);
 
     // return only the directory part of path
-    std::string dir_name(const std::string& path);
+    sass::string dir_name(const sass::string& path);
 
     // return only the filename part of path
-    std::string base_name(const std::string&);
+    sass::string base_name(const sass::string&);
 
     // do a locigal clean up of the path
     // no physical check on the filesystem
-    std::string make_canonical_path (std::string path);
+    sass::string make_canonical_path (sass::string path);
 
     // join two path segments cleanly together
     // but only if right side is not absolute yet
-    std::string join_paths(std::string root, std::string name);
+    sass::string join_paths(sass::string root, sass::string name);
 
     // if the relative path is outside of the cwd we want want to
     // show the absolute path in console messages
-    std::string path_for_console(const std::string& rel_path, const std::string& abs_path, const std::string& orig_path);
+    sass::string path_for_console(const sass::string& rel_path, const sass::string& abs_path, const sass::string& orig_path);
 
     // create an absolute path by resolving relative paths with cwd
-    std::string rel2abs(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
+    sass::string rel2abs(const sass::string& path, const sass::string& base = ".", const sass::string& cwd = get_cwd());
 
     // create a path that is relative to the given base directory
     // path and base will first be resolved against cwd to make them absolute
-    std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
+    sass::string abs2rel(const sass::string& path, const sass::string& base = ".", const sass::string& cwd = get_cwd());
 
     // helper function to resolve a filename
     // searching without variations in all paths
-    std::string find_file(const std::string& file, struct Sass_Compiler* options);
-    std::string find_file(const std::string& file, const std::vector<std::string> paths);
+    sass::string find_file(const sass::string& file, struct Sass_Compiler* options);
+    sass::string find_file(const sass::string& file, const sass::vector<sass::string> paths);
 
     // helper function to resolve a include filename
     // this has the original resolve logic for sass include
-    std::string find_include(const std::string& file, const std::vector<std::string> paths);
+    sass::string find_include(const sass::string& file, const sass::vector<sass::string> paths);
 
     // split a path string delimited by semicolons or colons (OS dependent)
-    std::vector<std::string> split_path_list(const char* paths);
+    sass::vector<sass::string> split_path_list(const char* paths);
 
     // try to load the given filename
     // returned memory must be freed
     // will auto convert .sass files
-    char* read_file(const std::string& file);
+    char* read_file(const sass::string& file);
 
   }
 
@@ -74,14 +74,14 @@
   class Importer {
     public:
       // requested import path
-      std::string imp_path;
+      sass::string imp_path;
       // parent context path
-      std::string ctx_path;
+      sass::string ctx_path;
       // base derived from context path
       // this really just acts as a cache
-      std::string base_path;
+      sass::string base_path;
     public:
-      Importer(std::string imp_path, std::string ctx_path)
+      Importer(sass::string imp_path, sass::string ctx_path)
       : imp_path(File::make_canonical_path(imp_path)),
         ctx_path(File::make_canonical_path(ctx_path)),
         base_path(File::dir_name(ctx_path))
@@ -92,9 +92,9 @@
   class Include : public Importer {
     public:
       // resolved absolute path
-      std::string abs_path;
+      sass::string abs_path;
     public:
-      Include(const Importer& imp, std::string abs_path)
+      Include(const Importer& imp, sass::string abs_path)
       : Importer(imp), abs_path(abs_path)
       { }
   };
@@ -114,10 +114,8 @@
 
   namespace File {
 
-    static std::vector<std::string> defaultExtensions = { ".scss", ".sass", ".css" };
-
-    std::vector<Include> resolve_includes(const std::string& root, const std::string& file,
-      const std::vector<std::string>& exts = defaultExtensions);
+    sass::vector<Include> resolve_includes(const sass::string& root, const sass::string& file,
+      const sass::vector<sass::string>& exts = { ".scss", ".sass", ".css" });
 
   }
 
diff --git a/libsass/src/fn_colors.cpp b/libsass/src/fn_colors.cpp
--- a/libsass/src/fn_colors.cpp
+++ b/libsass/src/fn_colors.cpp
@@ -16,16 +16,16 @@
     bool string_argument(AST_Node_Obj obj) {
       String_Constant* s = Cast<String_Constant>(obj);
       if (s == nullptr) return false;
-      const std::string& str = s->value();
+      const sass::string& str = s->value();
       return starts_with(str, "calc(") ||
              starts_with(str, "var(");
     }
 
-    void hsla_alpha_percent_deprecation(const ParserState& pstate, const std::string val)
+    void hsla_alpha_percent_deprecation(const SourceSpan& pstate, const sass::string val)
     {
 
-      std::string msg("Passing a percentage as the alpha value to hsla() will be interpreted");
-      std::string tail("differently in future versions of Sass. For now, use " + val + " instead.");
+      sass::string msg("Passing a percentage as the alpha value to hsla() will be interpreted");
+      sass::string tail("differently in future versions of Sass. For now, use " + val + " instead.");
 
       deprecated(msg, tail, false, pstate);
 
@@ -104,7 +104,7 @@
       if (
         string_argument(env["$alpha"])
       ) {
-        std::stringstream strm;
+        sass::ostream strm;
         strm << "rgba("
                  << (int)c_arg->r() << ", "
                  << (int)c_arg->g() << ", "
@@ -145,7 +145,7 @@
       return SASS_MEMORY_NEW(Number, pstate, color->b());
     }
 
-    Color_RGBA* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, double weight) {
+    Color_RGBA* colormix(Context& ctx, SourceSpan& pstate, Color* color1, Color* color2, double weight) {
       Color_RGBA_Obj c1 = color1->toRGBA();
       Color_RGBA_Obj c2 = color2->toRGBA();
       double p = weight/100;
@@ -230,7 +230,7 @@
         Number_Obj val = SASS_MEMORY_COPY(alpha);
         val->numerators.clear(); // convert
         val->value(val->value() / 100.0);
-        std::string nr(val->to_string(ctx.c_options));
+        sass::string nr(val->to_string(ctx.c_options));
         hsla_alpha_percent_deprecation(pstate, nr);
       }
 
@@ -579,14 +579,14 @@
       double b = clip(c->b(), 0.0, 255.0);
       double a = clip(c->a(), 0.0, 1.0) * 255.0;
 
-      std::stringstream ss;
+      sass::ostream ss;
       ss << '#' << std::setw(2) << std::setfill('0');
       ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(a, ctx.c_options.precision));
       ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(r, ctx.c_options.precision));
       ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(g, ctx.c_options.precision));
       ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(b, ctx.c_options.precision));
 
-      std::string result = ss.str();
+      sass::string result = ss.str();
       Util::ascii_str_toupper(&result);
       return SASS_MEMORY_NEW(String_Quoted, pstate, result);
     }
diff --git a/libsass/src/fn_lists.cpp b/libsass/src/fn_lists.cpp
--- a/libsass/src/fn_lists.cpp
+++ b/libsass/src/fn_lists.cpp
@@ -21,9 +21,9 @@
       List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List)); // copy
       Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1);
       for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) {
-        Expression_Obj obj = arglist->at(i);
+        ExpressionObj obj = arglist->at(i);
         Argument_Obj arg = (Argument*) obj.ptr(); // XXX
-        std::string name = std::string(arg->name());
+        sass::string name = sass::string(arg->name());
         name = name.erase(0, 1); // sanitize name (remove dollar sign)
         *result << std::make_pair(SASS_MEMORY_NEW(String_Quoted,
                  pstate, name),
@@ -67,13 +67,13 @@
       if (SelectorList * sl = Cast<SelectorList>(env["$list"])) {
         size_t len = m ? m->length() : sl->length();
         bool empty = m ? m->empty() : sl->empty();
-        if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
+        if (empty) error("argument `$list` of `" + sass::string(sig) + "` must not be empty", pstate, traces);
         double index = std::floor(nr < 0 ? len + nr : nr - 1);
-        if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
+        if (index < 0 || index > len - 1) error("index out of bounds for `" + sass::string(sig) + "`", pstate, traces);
         return Cast<Value>(Listize::perform(sl->get(static_cast<int>(index))));
       }
       List_Obj l = Cast<List>(env["$list"]);
-      if (nr == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate, traces);
+      if (nr == 0) error("argument `$n` of `" + sass::string(sig) + "` must be non-zero", pstate, traces);
       // if the argument isn't a list, then wrap it in a singleton list
       if (!m && !l) {
         l = SASS_MEMORY_NEW(List, pstate, 1);
@@ -81,9 +81,9 @@
       }
       size_t len = m ? m->length() : l->length();
       bool empty = m ? m->empty() : l->empty();
-      if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
+      if (empty) error("argument `$list` of `" + sass::string(sig) + "` must not be empty", pstate, traces);
       double index = std::floor(nr < 0 ? len + nr : nr - 1);
-      if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
+      if (index < 0 || index > len - 1) error("index out of bounds for `" + sass::string(sig) + "`", pstate, traces);
 
       if (m) {
         l = SASS_MEMORY_NEW(List, pstate, 2);
@@ -92,7 +92,7 @@
         return l.detach();
       }
       else {
-        Value_Obj rv = l->value_at_index(static_cast<int>(index));
+        ValueObj rv = l->value_at_index(static_cast<int>(index));
         rv->set_delayed(false);
         return rv.detach();
       }
@@ -104,7 +104,7 @@
       Map_Obj m = Cast<Map>(env["$list"]);
       List_Obj l = Cast<List>(env["$list"]);
       Number_Obj n = ARG("$n", Number);
-      Expression_Obj v = ARG("$value", Expression);
+      ExpressionObj v = ARG("$value", Expression);
       if (!l) {
         l = SASS_MEMORY_NEW(List, pstate, 1);
         l->append(ARG("$list", Expression));
@@ -112,9 +112,9 @@
       if (m) {
         l = m->to_list(pstate);
       }
-      if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
+      if (l->empty()) error("argument `$list` of `" + sass::string(sig) + "` must not be empty", pstate, traces);
       double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
-      if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
+      if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + sass::string(sig) + "`", pstate, traces);
       List* result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed());
       for (size_t i = 0, L = l->length(); i < L; ++i) {
         result->append(((i == index) ? v : (*l)[i]));
@@ -127,7 +127,7 @@
     {
       Map_Obj m = Cast<Map>(env["$list"]);
       List_Obj l = Cast<List>(env["$list"]);
-      Expression_Obj v = ARG("$value", Expression);
+      ExpressionObj v = ARG("$value", Expression);
       if (!l) {
         l = SASS_MEMORY_NEW(List, pstate, 1);
         l->append(ARG("$list", Expression));
@@ -170,10 +170,10 @@
         l2 = m2->to_list(pstate);
       }
       size_t len = l1->length() + l2->length();
-      std::string sep_str = unquote(sep->value());
+      sass::string sep_str = unquote(sep->value());
       if (sep_str == "space") sep_val = SASS_SPACE;
       else if (sep_str == "comma") sep_val = SASS_COMMA;
-      else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
+      else if (sep_str != "auto") error("argument `$separator` of `" + sass::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
       String_Constant_Obj bracketed_as_str = Cast<String_Constant>(bracketed);
       bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto";
       if (!bracketed_is_auto) {
@@ -190,7 +190,7 @@
     {
       Map_Obj m = Cast<Map>(env["$list"]);
       List_Obj l = Cast<List>(env["$list"]);
-      Expression_Obj v = ARG("$val", Expression);
+      ExpressionObj v = ARG("$val", Expression);
       if (SelectorList * sl = Cast<SelectorList>(env["$list"])) {
         l = Cast<List>(Listize::perform(sl));
       }
@@ -203,11 +203,11 @@
         l = m->to_list(pstate);
       }
       List* result = SASS_MEMORY_COPY(l);
-      std::string sep_str(unquote(sep->value()));
+      sass::string sep_str(unquote(sep->value()));
       if (sep_str != "auto") { // check default first
         if (sep_str == "space") result->separator(SASS_SPACE);
         else if (sep_str == "comma") result->separator(SASS_COMMA);
-        else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
+        else error("argument `$separator` of `" + sass::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
       }
       if (l->is_arglist()) {
         result->append(SASS_MEMORY_NEW(Argument,
@@ -275,7 +275,7 @@
     Signature is_bracketed_sig = "is-bracketed($list)";
     BUILT_IN(is_bracketed)
     {
-      Value_Obj value = ARG("$list", Value);
+      ValueObj value = ARG("$list", Value);
       List_Obj list = Cast<List>(value);
       return SASS_MEMORY_NEW(Boolean, pstate, list && list->is_bracketed());
     }
diff --git a/libsass/src/fn_maps.cpp b/libsass/src/fn_maps.cpp
--- a/libsass/src/fn_maps.cpp
+++ b/libsass/src/fn_maps.cpp
@@ -16,9 +16,9 @@
       // leaks for "map-get((), foo)" if not Obj
       // investigate why this is (unexpected)
       Map_Obj m = ARGM("$map", Map);
-      Expression_Obj v = ARG("$key", Expression);
+      ExpressionObj v = ARG("$key", Expression);
       try {
-        Value_Obj val = m->at(v);
+        ValueObj val = m->at(v);
         if (!val) return SASS_MEMORY_NEW(Null, pstate);
         val->set_delayed(false);
         return val.detach();
@@ -32,7 +32,7 @@
     BUILT_IN(map_has_key)
     {
       Map_Obj m = ARGM("$map", Map);
-      Expression_Obj v = ARG("$key", Expression);
+      ExpressionObj v = ARG("$key", Expression);
       return SASS_MEMORY_NEW(Boolean, pstate, m->has(v));
     }
 
diff --git a/libsass/src/fn_miscs.cpp b/libsass/src/fn_miscs.cpp
--- a/libsass/src/fn_miscs.cpp
+++ b/libsass/src/fn_miscs.cpp
@@ -22,7 +22,7 @@
     Signature variable_exists_sig = "variable-exists($name)";
     BUILT_IN(variable_exists)
     {
-      std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
+      sass::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
 
       if(d_env.has("$"+s)) {
         return SASS_MEMORY_NEW(Boolean, pstate, true);
@@ -35,7 +35,7 @@
     Signature global_variable_exists_sig = "global-variable-exists($name)";
     BUILT_IN(global_variable_exists)
     {
-      std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
+      sass::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
 
       if(d_env.has_global("$"+s)) {
         return SASS_MEMORY_NEW(Boolean, pstate, true);
@@ -53,7 +53,7 @@
         error("$name: " + (env["$name"]->to_string()) + " is not a string for `function-exists'", pstate, traces);
       }
 
-      std::string name = Util::normalize_underscores(unquote(ss->value()));
+      sass::string name = Util::normalize_underscores(unquote(ss->value()));
 
       if(d_env.has(name+"[f]")) {
         return SASS_MEMORY_NEW(Boolean, pstate, true);
@@ -66,7 +66,7 @@
     Signature mixin_exists_sig = "mixin-exists($name)";
     BUILT_IN(mixin_exists)
     {
-      std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
+      sass::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
 
       if(d_env.has(s+"[m]")) {
         return SASS_MEMORY_NEW(Boolean, pstate, true);
@@ -79,9 +79,9 @@
     Signature feature_exists_sig = "feature-exists($feature)";
     BUILT_IN(feature_exists)
     {
-      std::string s = unquote(ARG("$feature", String_Constant)->value());
+      sass::string s = unquote(ARG("$feature", String_Constant)->value());
 
-      static const auto *const features = new std::unordered_set<std::string> {
+      static const auto *const features = new std::unordered_set<sass::string> {
         "global-variable-shadowing",
         "extend-selector-pseudoclass",
         "at-error",
@@ -94,7 +94,7 @@
     Signature call_sig = "call($function, $args...)";
     BUILT_IN(call)
     {
-      std::string function;
+      sass::string function;
       Function* ff = Cast<Function>(env["$function"]);
       String_Constant* ss = Cast<String_Constant>(env["$function"]);
 
@@ -111,19 +111,19 @@
       List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));
 
       Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
-      // std::string full_name(name + "[f]");
+      // sass::string full_name(name + "[f]");
       // Definition* def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
       // Parameters* params = def ? def->parameters() : 0;
       // size_t param_size = params ? params->length() : 0;
       for (size_t i = 0, L = arglist->length(); i < L; ++i) {
-        Expression_Obj expr = arglist->value_at_index(i);
+        ExpressionObj expr = arglist->value_at_index(i);
         // if (params && params->has_rest_parameter()) {
         //   Parameter_Obj p = param_size > i ? (*params)[i] : 0;
         //   List* list = Cast<List>(expr);
         //   if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
         // }
         if (arglist->is_arglist()) {
-          Expression_Obj obj = arglist->at(i);
+          ExpressionObj obj = arglist->at(i);
           Argument_Obj arg = (Argument*) obj.ptr(); // XXX
           args->append(SASS_MEMORY_NEW(Argument,
                                        pstate,
@@ -157,10 +157,10 @@
     BUILT_IN(sass_if)
     {
       Expand expand(ctx, &d_env, &selector_stack, &original_stack);
-      Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
+      ExpressionObj cond = ARG("$condition", Expression)->perform(&expand.eval);
       bool is_true = !cond->is_false();
-      Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
-      Value_Obj qwe = Cast<Value>(res->perform(&expand.eval));
+      ExpressionObj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
+      ValueObj qwe = Cast<Value>(res->perform(&expand.eval));
       // res = res->perform(&expand.eval.val_eval);
       qwe->set_delayed(false); // clone?
       return qwe.detach();
@@ -216,8 +216,8 @@
         error("$name: " + (env["$name"]->to_string()) + " is not a string for `get-function'", pstate, traces);
       }
 
-      std::string name = Util::normalize_underscores(unquote(ss->value()));
-      std::string full_name = name + "[f]";
+      sass::string name = Util::normalize_underscores(unquote(ss->value()));
+      sass::string full_name = name + "[f]";
 
       Boolean_Obj css = ARG("$css", Boolean);
       if (!css->is_false()) {
diff --git a/libsass/src/fn_numbers.cpp b/libsass/src/fn_numbers.cpp
--- a/libsass/src/fn_numbers.cpp
+++ b/libsass/src/fn_numbers.cpp
@@ -60,7 +60,7 @@
     BUILT_IN(percentage)
     {
       Number_Obj n = ARGN("$number");
-      if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
+      if (!n->is_unitless()) error("argument $number of `" + sass::string(sig) + "` must be unitless", pstate, traces);
       return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
     }
 
@@ -110,7 +110,7 @@
         error("At least one argument must be passed.", pstate, traces);
       }
       for (size_t i = 0; i < L; ++i) {
-        Expression_Obj val = arglist->value_at_index(i);
+        ExpressionObj val = arglist->value_at_index(i);
         Number_Obj xi = Cast<Number>(val);
         if (!xi) {
           error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
@@ -132,7 +132,7 @@
         error("At least one argument must be passed.", pstate, traces);
       }
       for (size_t i = 0; i < L; ++i) {
-        Expression_Obj val = arglist->value_at_index(i);
+        ExpressionObj val = arglist->value_at_index(i);
         Number_Obj xi = Cast<Number>(val);
         if (!xi) {
           error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
@@ -154,13 +154,13 @@
       if (l) {
         double lv = l->value();
         if (lv < 1) {
-          std::stringstream err;
+          sass::ostream err;
           err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
           error(err.str(), pstate, traces);
         }
         bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
         if (!eq_int) {
-          std::stringstream err;
+          sass::ostream err;
           err << "Expected $limit to be an integer but got " << lv << " for `random'";
           error(err.str(), pstate, traces);
         }
@@ -184,7 +184,7 @@
     Signature unique_id_sig = "unique-id()";
     BUILT_IN(unique_id)
     {
-      std::stringstream ss;
+      sass::ostream ss;
       std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8
       uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
       ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
@@ -195,7 +195,7 @@
     BUILT_IN(unit)
     {
       Number_Obj arg = ARGN("$number");
-      std::string str(quote(arg->unit(), '"'));
+      sass::string str(quote(arg->unit(), '"'));
       return SASS_MEMORY_NEW(String_Quoted, pstate, str);
     }
 
diff --git a/libsass/src/fn_selectors.cpp b/libsass/src/fn_selectors.cpp
--- a/libsass/src/fn_selectors.cpp
+++ b/libsass/src/fn_selectors.cpp
@@ -25,7 +25,7 @@
       // Parse args into vector of selectors
       SelectorStack parsedSelectors;
       for (size_t i = 0, L = arglist->length(); i < L; ++i) {
-        Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
+        ExpressionObj exp = Cast<Expression>(arglist->value_at_index(i));
         if (exp->concrete_type() == Expression::NULL_VAL) {
           error(
             "$selectors: null is not a valid selector: it must be a string,\n"
@@ -35,8 +35,9 @@
         if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
           str->quote_mark(0);
         }
-        std::string exp_src = exp->to_string(ctx.c_options);
-        SelectorListObj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
+        sass::string exp_src = exp->to_string(ctx.c_options);
+        ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
+        SelectorListObj sel = Parser::parse_selector(source, ctx, traces);
         parsedSelectors.push_back(sel);
       }
 
@@ -89,10 +90,9 @@
         if (String_Constant* str = Cast<String_Constant>(exp)) {
           str->quote_mark(0);
         }
-        std::string exp_src = exp->to_string();
-        SelectorListObj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces,
-                                                     exp->pstate(), pstate.src,
-                                                     /*allow_parent=*/true);
+        sass::string exp_src = exp->to_string();
+        ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
+        SelectorListObj sel = Parser::parse_selector(source, ctx, traces, true);
 
         for (auto& complex : sel->elements()) {
           if (complex->empty()) {
@@ -157,7 +157,7 @@
 
       for (size_t i = 0, L = sel->length(); i < L; ++i) {
         const SimpleSelectorObj& ss = sel->get(i);
-        std::string ss_string = ss->to_string() ;
+        sass::string ss_string = ss->to_string() ;
         l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string));
       }
 
diff --git a/libsass/src/fn_strings.cpp b/libsass/src/fn_strings.cpp
--- a/libsass/src/fn_strings.cpp
+++ b/libsass/src/fn_strings.cpp
@@ -12,21 +12,21 @@
 
   namespace Functions {
 
-    void handle_utf8_error (const ParserState& pstate, Backtraces traces)
+    void handle_utf8_error (const SourceSpan& pstate, Backtraces traces)
     {
       try {
        throw;
       }
       catch (utf8::invalid_code_point&) {
-        std::string msg("utf8::invalid_code_point");
+        sass::string msg("utf8::invalid_code_point");
         error(msg, pstate, traces);
       }
       catch (utf8::not_enough_room&) {
-        std::string msg("utf8::not_enough_room");
+        sass::string msg("utf8::not_enough_room");
         error(msg, pstate, traces);
       }
       catch (utf8::invalid_utf8&) {
-        std::string msg("utf8::invalid_utf8");
+        sass::string msg("utf8::invalid_utf8");
         error(msg, pstate, traces);
       }
       catch (...) { throw; }
@@ -52,7 +52,7 @@
       else if (Value* ex = Cast<Value>(arg)) {
         Sass_Output_Style oldstyle = ctx.c_options.output_style;
         ctx.c_options.output_style = SASS_STYLE_NESTED;
-        std::string val(arg->to_string(ctx.c_options));
+        sass::string val(arg->to_string(ctx.c_options));
         val = Cast<Null>(arg) ? "null" : val;
         ctx.c_options.output_style = oldstyle;
 
@@ -76,7 +76,7 @@
     Signature str_length_sig = "str-length($string)";
     BUILT_IN(str_length)
     {
-      size_t len = std::string::npos;
+      size_t len = sass::string::npos;
       try {
         String_Constant* s = ARG("$string", String_Constant);
         len = UTF_8::code_point_count(s->value(), 0, s->value().size());
@@ -92,15 +92,19 @@
     Signature str_insert_sig = "str-insert($string, $insert, $index)";
     BUILT_IN(str_insert)
     {
-      std::string str;
+      sass::string str;
       try {
         String_Constant* s = ARG("$string", String_Constant);
         str = s->value();
         String_Constant* i = ARG("$insert", String_Constant);
-        std::string ins = i->value();
+        sass::string ins = i->value();
         double index = ARGVAL("$index");
         if (index != (int)index) {
-          error("$index: " + std::to_string(index) + " is not an int", pstate, traces);
+          sass::ostream strm;
+          strm << "$index: ";
+          strm << std::to_string(index);
+          strm << " is not an int";
+          error(strm.str(), pstate, traces);
         }
         size_t len = UTF_8::code_point_count(str, 0, str.size());
 
@@ -138,15 +142,15 @@
     Signature str_index_sig = "str-index($string, $substring)";
     BUILT_IN(str_index)
     {
-      size_t index = std::string::npos;
+      size_t index = sass::string::npos;
       try {
         String_Constant* s = ARG("$string", String_Constant);
         String_Constant* t = ARG("$substring", String_Constant);
-        std::string str = s->value();
-        std::string substr = t->value();
+        sass::string str = s->value();
+        sass::string substr = t->value();
 
         size_t c_index = str.find(substr);
-        if(c_index == std::string::npos) {
+        if(c_index == sass::string::npos) {
           return SASS_MEMORY_NEW(Null, pstate);
         }
         index = UTF_8::code_point_count(str, 0, c_index) + 1;
@@ -161,19 +165,23 @@
     Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
     BUILT_IN(str_slice)
     {
-      std::string newstr;
+      sass::string newstr;
       try {
         String_Constant* s = ARG("$string", String_Constant);
         double start_at = ARGVAL("$start-at");
         double end_at = ARGVAL("$end-at");
 
         if (start_at != (int)start_at) {
-          error("$start-at: " + std::to_string(start_at) + " is not an int", pstate, traces);
+          sass::ostream strm;
+          strm << "$start-at: ";
+          strm << std::to_string(start_at);
+          strm << " is not an int";
+          error(strm.str(), pstate, traces);
         }
 
         String_Quoted* ss = Cast<String_Quoted>(s);
 
-        std::string str(s->value());
+        sass::string str(s->value());
 
         size_t size = utf8::distance(str.begin(), str.end());
 
@@ -182,7 +190,11 @@
         }
 
         if (end_at != (int)end_at) {
-          error("$end-at: " + std::to_string(end_at) + " is not an int", pstate, traces);
+          sass::ostream strm;
+          strm << "$end-at: ";
+          strm << std::to_string(end_at);
+          strm << " is not an int";
+          error(strm.str(), pstate, traces);
         }
 
         if (end_at == 0 || (end_at + size) < 0) {
@@ -203,11 +215,11 @@
 
         if (start_at <= end_at)
         {
-          std::string::iterator start = str.begin();
+          sass::string::iterator start = str.begin();
           utf8::advance(start, start_at - 1, str.end());
-          std::string::iterator end = start;
+          sass::string::iterator end = start;
           utf8::advance(end, end_at - start_at + 1, str.end());
-          newstr = std::string(start, end);
+          newstr = sass::string(start, end);
         }
         if (ss) {
           if(ss->quote_mark()) newstr = quote(newstr);
@@ -223,7 +235,7 @@
     BUILT_IN(to_upper_case)
     {
       String_Constant* s = ARG("$string", String_Constant);
-      std::string str = s->value();
+      sass::string str = s->value();
       Util::ascii_str_toupper(&str);
 
       if (String_Quoted* ss = Cast<String_Quoted>(s)) {
@@ -239,7 +251,7 @@
     BUILT_IN(to_lower_case)
     {
       String_Constant* s = ARG("$string", String_Constant);
-      std::string str = s->value();
+      sass::string str = s->value();
       Util::ascii_str_tolower(&str);
 
       if (String_Quoted* ss = Cast<String_Quoted>(s)) {
diff --git a/libsass/src/fn_utils.cpp b/libsass/src/fn_utils.cpp
--- a/libsass/src/fn_utils.cpp
+++ b/libsass/src/fn_utils.cpp
@@ -10,12 +10,13 @@
 
   Definition* make_native_function(Signature sig, Native_Function func, Context& ctx)
   {
-    Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]"));
+    SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[built-in function]", sig, std::string::npos);
+    Parser sig_parser(source, ctx, ctx.traces);
     sig_parser.lex<Prelexer::identifier>();
-    std::string name(Util::normalize_underscores(sig_parser.lexed));
+    sass::string name(Util::normalize_underscores(sig_parser.lexed));
     Parameters_Obj params = sig_parser.parse_parameters();
     return SASS_MEMORY_NEW(Definition,
-                          ParserState("[built-in function]"),
+                          SourceSpan(source),
                           sig,
                           name,
                           params,
@@ -26,19 +27,19 @@
   Definition* make_c_function(Sass_Function_Entry c_func, Context& ctx)
   {
     using namespace Prelexer;
-
     const char* sig = sass_function_get_signature(c_func);
-    Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]"));
+    SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[c function]", sig, std::string::npos);
+    Parser sig_parser(source, ctx, ctx.traces);
     // allow to overload generic callback plus @warn, @error and @debug with custom functions
     sig_parser.lex < alternatives < identifier, exactly <'*'>,
                                     exactly < Constants::warn_kwd >,
                                     exactly < Constants::error_kwd >,
                                     exactly < Constants::debug_kwd >
                   >              >();
-    std::string name(Util::normalize_underscores(sig_parser.lexed));
+    sass::string name(Util::normalize_underscores(sig_parser.lexed));
     Parameters_Obj params = sig_parser.parse_parameters();
     return SASS_MEMORY_NEW(Definition,
-                          ParserState("[c function]"),
+                          SourceSpan(source),
                           sig,
                           name,
                           params,
@@ -47,13 +48,13 @@
 
   namespace Functions {
 
-    std::string function_name(Signature sig)
+    sass::string function_name(Signature sig)
     {
-      std::string str(sig);
+      sass::string str(sig);
       return str.substr(0, str.find('('));
     }
 
-    Map* get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
+    Map* get_arg_m(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
     {
       AST_Node* value = env[argname];
       if (Map* map = Cast<Map>(value)) return map;
@@ -64,14 +65,14 @@
       return get_arg<Map>(argname, env, sig, pstate, traces);
     }
 
-    double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi)
+    double get_arg_r(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, double lo, double hi)
     {
       Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
       Number tmpnr(val);
       tmpnr.reduce();
       double v = tmpnr.value();
       if (!(lo <= v && v <= hi)) {
-        std::stringstream msg;
+        sass::ostream msg;
         msg << "argument `" << argname << "` of `" << sig << "` must be between ";
         msg << lo << " and " << hi;
         error(msg.str(), pstate, traces);
@@ -79,7 +80,7 @@
       return v;
     }
 
-    Number* get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
+    Number* get_arg_n(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
     {
       Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
       val = SASS_MEMORY_COPY(val);
@@ -87,7 +88,7 @@
       return val;
     }
 
-    double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
+    double get_arg_val(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
     {
       Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
       Number tmpnr(val);
@@ -95,7 +96,7 @@
       return tmpnr.value();
     }
 
-    double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
+    double color_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
     {
       Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
       Number tmpnr(val);
@@ -107,7 +108,7 @@
       }
     }
 
-    double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) {
+    double alpha_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) {
       Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
       Number tmpnr(val);
       tmpnr.reduce();
@@ -118,10 +119,10 @@
       }
     }
 
-    SelectorListObj get_arg_sels(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
-      Expression_Obj exp = ARG(argname, Expression);
+    SelectorListObj get_arg_sels(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) {
+      ExpressionObj exp = ARG(argname, Expression);
       if (exp->concrete_type() == Expression::NULL_VAL) {
-        std::stringstream msg;
+        sass::ostream msg;
         msg << argname << ": null is not a valid selector: it must be a string,\n";
         msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
         error(msg.str(), exp->pstate(), traces);
@@ -129,22 +130,24 @@
       if (String_Constant* str = Cast<String_Constant>(exp)) {
         str->quote_mark(0);
       }
-      std::string exp_src = exp->to_string(ctx.c_options);
-      return Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src, /*allow_parent=*/false);
+      sass::string exp_src = exp->to_string(ctx.c_options);
+      ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
+      return Parser::parse_selector(source, ctx, traces, false);
     }
 
-    CompoundSelectorObj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
-      Expression_Obj exp = ARG(argname, Expression);
+    CompoundSelectorObj get_arg_sel(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) {
+      ExpressionObj exp = ARG(argname, Expression);
       if (exp->concrete_type() == Expression::NULL_VAL) {
-        std::stringstream msg;
+        sass::ostream msg;
         msg << argname << ": null is not a string for `" << function_name(sig) << "'";
         error(msg.str(), exp->pstate(), traces);
       }
       if (String_Constant* str = Cast<String_Constant>(exp)) {
         str->quote_mark(0);
       }
-      std::string exp_src = exp->to_string(ctx.c_options);
-      SelectorListObj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src, /*allow_parent=*/false);
+      sass::string exp_src = exp->to_string(ctx.c_options);
+      ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
+      SelectorListObj sel_list = Parser::parse_selector(source, ctx, traces, false);
       if (sel_list->length() == 0) return {};
       return sel_list->first()->first();
     }
diff --git a/libsass/src/fn_utils.hpp b/libsass/src/fn_utils.hpp
--- a/libsass/src/fn_utils.hpp
+++ b/libsass/src/fn_utils.hpp
@@ -18,7 +18,7 @@
     Env& d_env, \
     Context& ctx, \
     Signature sig, \
-    ParserState pstate, \
+    SourceSpan pstate, \
     Backtraces& traces, \
     SelectorStack selector_stack, \
     SelectorStack original_stack \
@@ -37,7 +37,7 @@
   namespace Functions {
 
     template <typename T>
-    T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
+    T* get_arg(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
     {
       T* val = Cast<T>(env[argname]);
       if (!val) {
@@ -46,14 +46,14 @@
       return val;
     }
 
-    Map* get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // maps only
-    Number* get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // numbers only
-    double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // colors only
-    double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // colors only
-    double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi); // colors only
-    double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // shared
-    SelectorListObj get_arg_sels(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx); // selectors only
-    CompoundSelectorObj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx); // selectors only
+    Map* get_arg_m(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // maps only
+    Number* get_arg_n(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // numbers only
+    double alpha_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // colors only
+    double color_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // colors only
+    double get_arg_r(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, double lo, double hi); // colors only
+    double get_arg_val(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // shared
+    SelectorListObj get_arg_sels(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx); // selectors only
+    CompoundSelectorObj get_arg_sel(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx); // selectors only
 
   }
 
diff --git a/libsass/src/inspect.cpp b/libsass/src/inspect.cpp
--- a/libsass/src/inspect.cpp
+++ b/libsass/src/inspect.cpp
@@ -42,7 +42,7 @@
 
   }
 
-  void Inspect::operator()(Ruleset* ruleset)
+  void Inspect::operator()(StyleRule* ruleset)
   {
     if (ruleset->selector()) {
       ruleset->selector()->perform(this);
@@ -124,7 +124,7 @@
     }
   }
 
-  void Inspect::operator()(Supports_Block* feature_block)
+  void Inspect::operator()(SupportsRule* feature_block)
   {
     append_indentation();
     append_token("@supports", feature_block);
@@ -133,7 +133,7 @@
     feature_block->block()->perform(this);
   }
 
-  void Inspect::operator()(At_Root_Block* at_root_block)
+  void Inspect::operator()(AtRootRule* at_root_block)
   {
     append_indentation();
     append_token("@at-root ", at_root_block);
@@ -142,7 +142,7 @@
     if(at_root_block->block()) at_root_block->block()->perform(this);
   }
 
-  void Inspect::operator()(Directive* at_rule)
+  void Inspect::operator()(AtRule* at_rule)
   {
     append_indentation();
     append_token(at_rule->keyword(), at_rule);
@@ -180,7 +180,7 @@
     append_colon_separator();
 
     if (dec->value()->concrete_type() == Expression::SELECTOR) {
-      Expression_Obj ls = Listize::perform(dec->value());
+      ExpressionObj ls = Listize::perform(dec->value());
       ls->perform(this);
     } else {
       dec->value()->perform(this);
@@ -248,7 +248,7 @@
     append_delimiter();
   }
 
-  void Inspect::operator()(Warning* warning)
+  void Inspect::operator()(WarningRule* warning)
   {
     append_indentation();
     append_token("@warn", warning);
@@ -257,7 +257,7 @@
     append_delimiter();
   }
 
-  void Inspect::operator()(Error* error)
+  void Inspect::operator()(ErrorRule* error)
   {
     append_indentation();
     append_token("@error", error);
@@ -266,7 +266,7 @@
     append_delimiter();
   }
 
-  void Inspect::operator()(Debug* debug)
+  void Inspect::operator()(DebugRule* debug)
   {
     append_indentation();
     append_token("@debug", debug);
@@ -297,7 +297,7 @@
     }
   }
 
-  void Inspect::operator()(For* loop)
+  void Inspect::operator()(ForRule* loop)
   {
     append_indentation();
     append_token("@for", loop);
@@ -310,7 +310,7 @@
     loop->block()->perform(this);
   }
 
-  void Inspect::operator()(Each* loop)
+  void Inspect::operator()(EachRule* loop)
   {
     append_indentation();
     append_token("@each", loop);
@@ -325,7 +325,7 @@
     loop->block()->perform(this);
   }
 
-  void Inspect::operator()(While* loop)
+  void Inspect::operator()(WhileRule* loop)
   {
     append_indentation();
     append_token("@while", loop);
@@ -412,11 +412,11 @@
     append_string(")");
   }
 
-  std::string Inspect::lbracket(List* list) {
+  sass::string Inspect::lbracket(List* list) {
     return list->is_bracketed() ? "[" : "(";
   }
 
-  std::string Inspect::rbracket(List* list) {
+  sass::string Inspect::rbracket(List* list) {
     return list->is_bracketed() ? "]" : ")";
   }
 
@@ -427,7 +427,7 @@
       append_string(rbracket(list));
       return;
     }
-    std::string sep(list->separator() == SASS_SPACE ? " " : ",");
+    sass::string sep(list->separator() == SASS_SPACE ? " " : ",");
     if ((output_style() != COMPRESSED) && sep == ",") sep += " ";
     else if (in_media_block && sep != " ") sep += " "; // verified
     if (list->empty()) return;
@@ -461,7 +461,7 @@
     for (size_t i = 0, L = list->size(); i < L; ++i) {
       if (list->separator() == SASS_HASH)
       { sep[0] = i % 2 ? ':' : ','; }
-      Expression_Obj list_item = list->at(i);
+      ExpressionObj list_item = list->at(i);
       if (output_style() != TO_SASS) {
         if (list_item->is_invisible()) {
           // this fixes an issue with "" in a list
@@ -570,11 +570,11 @@
     // reduce units
     n->reduce();
 
-    std::stringstream ss;
+    sass::ostream ss;
     ss.precision(opt.precision);
     ss << std::fixed << n->value();
 
-    std::string res = ss.str();
+    sass::string res = ss.str();
     size_t s = res.length();
 
     // delete trailing zeros
@@ -627,14 +627,14 @@
   void Inspect::operator()(Color_RGBA* c)
   {
     // output the final token
-    std::stringstream ss;
+    sass::ostream ss;
 
     // original color name
     // maybe an unknown token
-    std::string name = c->disp();
+    sass::string name = c->disp();
 
     // resolved color
-    std::string res_name = name;
+    sass::string res_name = name;
 
     double r = Sass::round(cap_channel<0xff>(c->r()), opt.precision);
     double g = Sass::round(cap_channel<0xff>(c->g()), opt.precision);
@@ -656,7 +656,7 @@
         res_name = color_to_name(numval);
     }
 
-    std::stringstream hexlet;
+    sass::ostream hexlet;
     // dart sass compressed all colors in regular css always
     // ruby sass and libsass does it only when not delayed
     // since color math is going to be removed, this can go too
@@ -757,18 +757,18 @@
     append_token(w->message(), w);
   }
 
-  void Inspect::operator()(Supports_Operator* so)
+  void Inspect::operator()(SupportsOperation* so)
   {
 
     if (so->needs_parens(so->left())) append_string("(");
     so->left()->perform(this);
     if (so->needs_parens(so->left())) append_string(")");
 
-    if (so->operand() == Supports_Operator::AND) {
+    if (so->operand() == SupportsOperation::AND) {
       append_mandatory_space();
       append_token("and", so);
       append_mandatory_space();
-    } else if (so->operand() == Supports_Operator::OR) {
+    } else if (so->operand() == SupportsOperation::OR) {
       append_mandatory_space();
       append_token("or", so);
       append_mandatory_space();
@@ -779,7 +779,7 @@
     if (so->needs_parens(so->right())) append_string(")");
   }
 
-  void Inspect::operator()(Supports_Negation* sn)
+  void Inspect::operator()(SupportsNegation* sn)
   {
     append_token("not", sn);
     append_mandatory_space();
@@ -788,7 +788,7 @@
     if (sn->needs_parens(sn->condition())) append_string(")");
   }
 
-  void Inspect::operator()(Supports_Declaration* sd)
+  void Inspect::operator()(SupportsDeclaration* sd)
   {
     append_string("(");
     sd->feature()->perform(this);
@@ -934,28 +934,28 @@
     append_string("&");
   }
 
-  void Inspect::operator()(Placeholder_Selector* s)
+  void Inspect::operator()(PlaceholderSelector* s)
   {
     append_token(s->name(), s);
 
   }
 
-  void Inspect::operator()(Type_Selector* s)
+  void Inspect::operator()(TypeSelector* s)
   {
     append_token(s->ns_name(), s);
   }
 
-  void Inspect::operator()(Class_Selector* s)
+  void Inspect::operator()(ClassSelector* s)
   {
     append_token(s->ns_name(), s);
   }
 
-  void Inspect::operator()(Id_Selector* s)
+  void Inspect::operator()(IDSelector* s)
   {
     append_token(s->ns_name(), s);
   }
 
-  void Inspect::operator()(Attribute_Selector* s)
+  void Inspect::operator()(AttributeSelector* s)
   {
     append_string("[");
     add_open_mapping(s);
@@ -974,7 +974,7 @@
     append_string("]");
   }
 
-  void Inspect::operator()(Pseudo_Selector* s)
+  void Inspect::operator()(PseudoSelector* s)
   {
 
     if (s->name() != "") {
@@ -1033,6 +1033,7 @@
 
       if (!in_wrapped && i == 0) append_indentation();
       if ((*g)[i] == nullptr) continue;
+      if (g->at(i)->length() == 0) continue;
       schedule_mapping(g->at(i)->last());
       // add_open_mapping((*g)[i]->last());
       (*g)[i]->perform(this);
@@ -1066,8 +1067,7 @@
     const SelectorComponent* prev = nullptr;
     for (auto& item : sel->elements()) {
       if (prev != nullptr) {
-        if (typeid(*item) == typeid(SelectorCombinator) ||
-            typeid(*prev) == typeid(SelectorCombinator)) {
+        if (item->getCombinator() || prev->getCombinator()) {
           append_optional_space();
         } else {
           append_mandatory_space();
@@ -1091,6 +1091,7 @@
     if (sel->hasRealParent()) {
       append_string("&");
     }
+    sel->sortChildren();
     for (auto& item : sel->elements()) {
       item->perform(this);
     }
diff --git a/libsass/src/inspect.hpp b/libsass/src/inspect.hpp
--- a/libsass/src/inspect.hpp
+++ b/libsass/src/inspect.hpp
@@ -20,24 +20,24 @@
 
     // statements
     virtual void operator()(Block*);
-    virtual void operator()(Ruleset*);
+    virtual void operator()(StyleRule*);
     virtual void operator()(Bubble*);
-    virtual void operator()(Supports_Block*);
-    virtual void operator()(At_Root_Block*);
-    virtual void operator()(Directive*);
+    virtual void operator()(SupportsRule*);
+    virtual void operator()(AtRootRule*);
+    virtual void operator()(AtRule*);
     virtual void operator()(Keyframe_Rule*);
     virtual void operator()(Declaration*);
     virtual void operator()(Assignment*);
     virtual void operator()(Import*);
     virtual void operator()(Import_Stub*);
-    virtual void operator()(Warning*);
-    virtual void operator()(Error*);
-    virtual void operator()(Debug*);
+    virtual void operator()(WarningRule*);
+    virtual void operator()(ErrorRule*);
+    virtual void operator()(DebugRule*);
     virtual void operator()(Comment*);
     virtual void operator()(If*);
-    virtual void operator()(For*);
-    virtual void operator()(Each*);
-    virtual void operator()(While*);
+    virtual void operator()(ForRule*);
+    virtual void operator()(EachRule*);
+    virtual void operator()(WhileRule*);
     virtual void operator()(Return*);
     virtual void operator()(ExtendRule*);
     virtual void operator()(Definition*);
@@ -62,9 +62,9 @@
     virtual void operator()(String_Quoted*);
     virtual void operator()(Custom_Error*);
     virtual void operator()(Custom_Warning*);
-    virtual void operator()(Supports_Operator*);
-    virtual void operator()(Supports_Negation*);
-    virtual void operator()(Supports_Declaration*);
+    virtual void operator()(SupportsOperation*);
+    virtual void operator()(SupportsNegation*);
+    virtual void operator()(SupportsDeclaration*);
     virtual void operator()(Supports_Interpolation*);
     virtual void operator()(MediaRule*);
     virtual void operator()(CssMediaRule*);
@@ -81,19 +81,19 @@
     virtual void operator()(Arguments*);
     // selectors
     virtual void operator()(Selector_Schema*);
-    virtual void operator()(Placeholder_Selector*);
-    virtual void operator()(Type_Selector*);
-    virtual void operator()(Class_Selector*);
-    virtual void operator()(Id_Selector*);
-    virtual void operator()(Attribute_Selector*);
-    virtual void operator()(Pseudo_Selector*);
+    virtual void operator()(PlaceholderSelector*);
+    virtual void operator()(TypeSelector*);
+    virtual void operator()(ClassSelector*);
+    virtual void operator()(IDSelector*);
+    virtual void operator()(AttributeSelector*);
+    virtual void operator()(PseudoSelector*);
     virtual void operator()(SelectorComponent*);
     virtual void operator()(SelectorCombinator*);
     virtual void operator()(CompoundSelector*);
     virtual void operator()(ComplexSelector*);
     virtual void operator()(SelectorList*);
-    virtual std::string lbracket(List*);
-    virtual std::string rbracket(List*);
+    virtual sass::string lbracket(List*);
+    virtual sass::string rbracket(List*);
 
   };
 
diff --git a/libsass/src/lexer.cpp b/libsass/src/lexer.cpp
--- a/libsass/src/lexer.cpp
+++ b/libsass/src/lexer.cpp
@@ -93,7 +93,9 @@
     const char* re_linebreak(const char* src)
     {
       // end of file or unix linefeed return here
-      if (*src == 0 || *src == '\n' || *src == '\f') return src + 1;
+      if (*src == 0) return src;
+      // end of file or unix linefeed return here
+      if (*src == '\n' || *src == '\f') return src + 1;
       // a carriage return may optionally be followed by a linefeed
       if (*src == '\r') return *(src + 1) == '\n' ? src + 2 : src + 1;
       // no linefeed
diff --git a/libsass/src/listize.cpp b/libsass/src/listize.cpp
--- a/libsass/src/listize.cpp
+++ b/libsass/src/listize.cpp
@@ -36,7 +36,7 @@
 
   Expression* Listize::operator()(CompoundSelector* sel)
   {
-    std::string str;
+    sass::string str;
     for (size_t i = 0, L = sel->length(); i < L; ++i) {
       Expression* e = (*sel)[i]->perform(this);
       if (e) str += e->to_string();
@@ -54,7 +54,7 @@
     for (auto component : sel->elements()) {
       if (CompoundSelectorObj compound = Cast<CompoundSelector>(component)) {
         if (!compound->empty()) {
-          Expression_Obj hh = compound->perform(this);
+          ExpressionObj hh = compound->perform(this);
           if (hh) l->append(hh);
         }
       }
diff --git a/libsass/src/mapping.hpp b/libsass/src/mapping.hpp
--- a/libsass/src/mapping.hpp
+++ b/libsass/src/mapping.hpp
@@ -2,6 +2,7 @@
 #define SASS_MAPPING_H
 
 #include "position.hpp"
+#include "backtrace.hpp"
 
 namespace Sass {
 
diff --git a/libsass/src/memory.hpp b/libsass/src/memory.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory.hpp
@@ -0,0 +1,12 @@
+#ifndef SASS_MEMORY_H
+#define SASS_MEMORY_H
+
+#include "settings.hpp"
+
+// Include memory headers
+#include "memory/config.hpp"
+#include "memory/allocator.hpp"
+#include "memory/shared_ptr.hpp"
+#include "memory/memory_pool.hpp"
+
+#endif
diff --git a/libsass/src/memory/SharedPtr.cpp b/libsass/src/memory/SharedPtr.cpp
deleted file mode 100644
--- a/libsass/src/memory/SharedPtr.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "../sass.hpp"
-#include <iostream>
-#include <typeinfo>
-
-#include "SharedPtr.hpp"
-#include "../ast_fwd_decl.hpp"
-
-#ifdef DEBUG_SHARED_PTR
-#include "../debugger.hpp"
-#endif
-
-namespace Sass {
-
-  #ifdef DEBUG_SHARED_PTR
-  void SharedObj::dumpMemLeaks() {
-    if (!all.empty()) {
-      std::cerr << "###################################\n";
-      std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n";
-      std::cerr << "###################################\n";
-      for (SharedObj* var : all) {
-        if (AST_Node* ast = dynamic_cast<AST_Node*>(var)) {
-          debug_ast(ast);
-        } else {
-          std::cerr << "LEAKED " << var << "\n";
-        }
-      }
-    }
-  }
-  std::vector<SharedObj*> SharedObj::all;
-  #endif
-
-  bool SharedObj::taint = false;
-}
diff --git a/libsass/src/memory/SharedPtr.hpp b/libsass/src/memory/SharedPtr.hpp
deleted file mode 100644
--- a/libsass/src/memory/SharedPtr.hpp
+++ /dev/null
@@ -1,320 +0,0 @@
-#ifndef SASS_MEMORY_SHARED_PTR_H
-#define SASS_MEMORY_SHARED_PTR_H
-
-#include "sass/base.h"
-
-#include <cstddef>
-#include <iostream>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-// https://lokiastari.com/blog/2014/12/30/c-plus-plus-by-example-smart-pointer/index.html
-// https://lokiastari.com/blog/2015/01/15/c-plus-plus-by-example-smart-pointer-part-ii/index.html
-// https://lokiastari.com/blog/2015/01/23/c-plus-plus-by-example-smart-pointer-part-iii/index.html
-
-namespace Sass {
-
-  class SharedPtr;
-
-  ///////////////////////////////////////////////////////////////////////////////
-  // Use macros for the allocation task, since overloading operator `new`
-  // has been proven to be flaky under certain compilers (see comment below).
-  ///////////////////////////////////////////////////////////////////////////////
-
-  #ifdef DEBUG_SHARED_PTR
-
-    #define SASS_MEMORY_NEW(Class, ...) \
-      ((Class*)(new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
-
-    #define SASS_MEMORY_COPY(obj) \
-      ((obj)->copy(__FILE__, __LINE__)) \
-
-    #define SASS_MEMORY_CLONE(obj) \
-      ((obj)->clone(__FILE__, __LINE__)) \
-
-  #else
-
-    #define SASS_MEMORY_NEW(Class, ...) \
-      new Class(__VA_ARGS__) \
-
-    #define SASS_MEMORY_COPY(obj) \
-      ((obj)->copy()) \
-
-    #define SASS_MEMORY_CLONE(obj) \
-      ((obj)->clone()) \
-
-  #endif
-
-  // SharedObj is the base class for all objects that can be stored as a shared object
-  // It adds the reference counter and other values directly to the objects
-  // This gives a slight overhead when directly used as a stack object, but has some
-  // advantages for our code. It is safe to create two shared pointers from the same
-  // objects, as the "control block" is directly attached to it. This would lead
-  // to undefined behavior with std::shared_ptr. This also avoids the need to
-  // allocate additional control blocks and/or the need to dereference two
-  // pointers on each operation. This can be optimized in `std::shared_ptr`
-  // too by using `std::make_shared` (where the control block and the actual
-  // object are allocated in one continuous memory block via one single call).
-  class SharedObj {
-   public:
-    SharedObj() : refcount(0), detached(false) {
-      #ifdef DEBUG_SHARED_PTR
-      if (taint) all.push_back(this);
-      #endif
-    }
-    virtual ~SharedObj() {
-      #ifdef DEBUG_SHARED_PTR
-      for (size_t i = 0; i < all.size(); i++) {
-        if (all[i] == this) {
-          all.erase(all.begin() + i);
-          break;
-        }
-      }
-      #endif
-    }
-
-    #ifdef DEBUG_SHARED_PTR
-    static void dumpMemLeaks();
-    SharedObj* trace(std::string file, size_t line) {
-      this->file = file;
-      this->line = line;
-      return this;
-    }
-    std::string getDbgFile() { return file; }
-    size_t getDbgLine() { return line; }
-    void setDbg(bool dbg) { this->dbg = dbg; }
-    size_t getRefCount() const { return refcount; }
-    #endif
-
-    static void setTaint(bool val) { taint = val; }
-
-    virtual std::string to_string() const = 0;
-   protected:
-    friend class SharedPtr;
-    friend class Memory_Manager;
-    size_t refcount;
-    bool detached;
-    static bool taint;
-    #ifdef DEBUG_SHARED_PTR
-    std::string file;
-    size_t line;
-    bool dbg = false;
-    static std::vector<SharedObj*> all;
-    #endif
-  };
-
-  // SharedPtr is a intermediate (template-less) base class for SharedImpl.
-  // ToDo: there should be a way to include this in SharedImpl and to get
-  // ToDo: rid of all the static_cast that are now needed in SharedImpl.
-  class SharedPtr {
-   public:
-    SharedPtr() : node(nullptr) {}
-    SharedPtr(SharedObj* ptr) : node(ptr) {
-      incRefCount();
-    }
-    SharedPtr(const SharedPtr& obj) : SharedPtr(obj.node) {}
-    ~SharedPtr() {
-      decRefCount();
-    }
-
-    SharedPtr& operator=(SharedObj* other_node) {
-      if (node != other_node) {
-        decRefCount();
-        node = other_node;
-        incRefCount();
-      } else if (node != nullptr) {
-        node->detached = false;
-      }
-      return *this;
-    }
-
-    SharedPtr& operator=(const SharedPtr& obj) {
-      return *this = obj.node;
-    }
-
-    // Prevents all SharedPtrs from freeing this node until it is assigned to another SharedPtr.
-    SharedObj* detach() {
-      if (node != nullptr) node->detached = true;
-      #ifdef DEBUG_SHARED_PTR
-      if (node->dbg) {
-        std::cerr << "DETACHING NODE\n";
-      }
-      #endif 
-      return node;
-    }
-
-    SharedObj* obj() const { return node; }
-    SharedObj* operator->() const { return node; }
-    bool isNull() const { return node == nullptr; }
-    operator bool() const { return node != nullptr; }
-
-   protected:
-    SharedObj* node;
-    void decRefCount() {
-      if (node == nullptr) return;
-      --node->refcount;
-      #ifdef DEBUG_SHARED_PTR
-      if (node->dbg) std::cerr << "- " << node << " X " << node->refcount << " (" << this << ") " << "\n";
-      #endif
-      if (node->refcount == 0 && !node->detached) {
-        #ifdef DEBUG_SHARED_PTR
-        if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
-        #endif
-        delete node;
-      }
-      else if (node->refcount == 0) {
-        #ifdef DEBUG_SHARED_PTR
-        if (node->dbg) std::cerr << "NODE EVAEDED DELETE " << node << "\n";
-        #endif
-      }
-    }
-    void incRefCount() {
-      if (node == nullptr) return;
-      node->detached = false;
-      ++node->refcount;
-      #ifdef DEBUG_SHARED_PTR
-      if (node->dbg) std::cerr << "+ " << node << " X " << node->refcount << " (" << this << ") " << "\n";
-      #endif
-    }
-  };
-
-  template <class T>
-  class SharedImpl : private SharedPtr {
-
-  public:
-    SharedImpl() : SharedPtr(nullptr) {}
-
-    template <class U>
-    SharedImpl(U* node) :
-      SharedPtr(static_cast<T*>(node)) {}
-
-    template <class U>
-    SharedImpl(const SharedImpl<U>& impl) :
-      SharedImpl(impl.ptr()) {}
-
-    template <class U>
-    SharedImpl<T>& operator=(U *rhs) {
-      return static_cast<SharedImpl<T>&>(
-        SharedPtr::operator=(static_cast<T*>(rhs)));
-    }
-
-    template <class U>
-    SharedImpl<T>& operator=(const SharedImpl<U>& rhs) {
-      return static_cast<SharedImpl<T>&>(
-        SharedPtr::operator=(static_cast<const SharedImpl<T>&>(rhs)));
-    }
-
-    operator std::string() const {
-      if (node) return node->to_string();
-      return "null";
-    }
-
-    using SharedPtr::isNull;
-    using SharedPtr::operator bool;
-    operator T*() const { return static_cast<T*>(this->obj()); }
-    operator T&() const { return *static_cast<T*>(this->obj()); }
-    T& operator* () const { return *static_cast<T*>(this->obj()); };
-    T* operator-> () const { return static_cast<T*>(this->obj()); };
-    T* ptr () const { return static_cast<T*>(this->obj()); };
-    T* detach() { return static_cast<T*>(SharedPtr::detach()); }
-
-  };
-
-  // Comparison operators, based on:
-  // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp
-
-  template<class T1, class T2>
-  bool operator==(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    return x.ptr() == y.ptr();
-  }
-
-  template<class T1, class T2>
-  bool operator!=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    return x.ptr() != y.ptr();
-  }
-
-  template<class T1, class T2>
-  bool operator<(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    using CT = typename std::common_type<T1*, T2*>::type;
-    return std::less<CT>()(x.get(), y.get());
-  }
-
-  template<class T1, class T2>
-  bool operator<=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    return !(y < x);
-  }
-
-  template<class T1, class T2>
-  bool operator>(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    return y < x;
-  }
-
-  template<class T1, class T2>
-  bool operator>=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
-    return !(x < y);
-  }
-
-  template <class T>
-  bool operator==(const SharedImpl<T>& x, std::nullptr_t) noexcept {
-    return x.isNull();
-  }
-
-  template <class T>
-  bool operator==(std::nullptr_t, const SharedImpl<T>& x) noexcept {
-    return x.isNull();
-  }
-
-  template <class T>
-  bool operator!=(const SharedImpl<T>& x, std::nullptr_t) noexcept {
-    return !x.isNull();
-  }
-
-  template <class T>
-  bool operator!=(std::nullptr_t, const SharedImpl<T>& x) noexcept {
-    return !x.isNull();
-  }
-
-  template <class T>
-  bool operator<(const SharedImpl<T>& x, std::nullptr_t) {
-    return std::less<T*>()(x.get(), nullptr);
-  }
-
-  template <class T>
-  bool operator<(std::nullptr_t, const SharedImpl<T>& y) {
-    return std::less<T*>()(nullptr, y.get());
-  }
-
-  template <class T>
-  bool operator<=(const SharedImpl<T>& x, std::nullptr_t) {
-    return !(nullptr < x);
-  }
-
-  template <class T>
-  bool operator<=(std::nullptr_t, const SharedImpl<T>& y) {
-    return !(y < nullptr);
-  }
-
-  template <class T>
-  bool operator>(const SharedImpl<T>& x, std::nullptr_t) {
-    return nullptr < x;
-  }
-
-  template <class T>
-  bool operator>(std::nullptr_t, const SharedImpl<T>& y) {
-    return y < nullptr;
-  }
-
-  template <class T>
-  bool operator>=(const SharedImpl<T>& x, std::nullptr_t) {
-    return !(x < nullptr);
-  }
-
-  template <class T>
-  bool operator>=(std::nullptr_t, const SharedImpl<T>& y) {
-    return !(nullptr < y);
-  }
-
-}  // namespace Sass
-
-#endif
diff --git a/libsass/src/memory/allocator.cpp b/libsass/src/memory/allocator.cpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/allocator.cpp
@@ -0,0 +1,48 @@
+#include "../sass.hpp"
+#include "allocator.hpp"
+#include "memory_pool.hpp"
+
+#if defined (_MSC_VER) // Visual studio
+#define thread_local __declspec( thread )
+#elif defined (__GCC__) // GCC
+#define thread_local __thread
+#endif
+
+namespace Sass {
+
+#ifdef SASS_CUSTOM_ALLOCATOR
+
+  // Only use PODs for thread_local
+  // Objects get unpredictable init order
+  static thread_local MemoryPool* pool;
+  static thread_local size_t allocations;
+
+  void* allocateMem(size_t size)
+  {
+    if (pool == nullptr) {
+      pool = new MemoryPool();
+    }
+    allocations++;
+    return pool->allocate(size);
+  }
+
+  void deallocateMem(void* ptr, size_t size)
+  {
+
+    // It seems thread_local variable might be discharged!?
+    // But the destructors of e.g. static strings is still
+    // called, although their memory was discharged too.
+    // Fine with me as long as address sanitizer is happy.
+    if (pool == nullptr || allocations == 0) { return; }
+
+    pool->deallocate(ptr);
+    if (--allocations == 0) {
+      delete pool;
+      pool = nullptr;
+    }
+
+  }
+
+#endif
+
+}
diff --git a/libsass/src/memory/allocator.hpp b/libsass/src/memory/allocator.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/allocator.hpp
@@ -0,0 +1,138 @@
+#ifndef SASS_ALLOCATOR_H
+#define SASS_ALLOCATOR_H
+
+#include "config.hpp"
+#include "../settings.hpp"
+#include "../MurmurHash2.hpp"
+
+#include <vector>
+#include <limits>
+#include <iostream>
+#include <algorithm>
+#include <functional>
+
+namespace Sass {
+
+#ifndef SASS_CUSTOM_ALLOCATOR
+
+  template <typename T> using Allocator = std::allocator<T>;
+
+#else
+
+  void* allocateMem(size_t size);
+
+  void deallocateMem(void* ptr, size_t size = 1);
+
+  template<typename T>
+  class Allocator
+  {
+  public:
+
+    // Allocator traits
+    typedef T                 type;            
+    typedef type              value_type;      
+    typedef value_type*       pointer;         
+    typedef value_type const* const_pointer;   
+    typedef value_type&       reference;       
+    typedef value_type const& const_reference; 
+    typedef std::size_t       size_type;       
+    typedef std::ptrdiff_t    difference_type; 
+
+    template<typename U>
+    struct rebind
+    {
+      typedef Allocator<U> other;
+    };
+
+    // Constructor
+    Allocator(void) {}
+
+    // Copy Constructor
+    template<typename U>
+    Allocator(Allocator<U> const&)
+    {}
+
+    // allocate but don't initialize count of elements of type T
+    pointer allocate(size_type count, const_pointer /* hint */ = 0)
+    {
+      return (pointer)(Sass::allocateMem(count * sizeof(T)));
+    }
+
+    // deallocate storage ptr of deleted elements
+    void deallocate(pointer ptr, size_type count)
+    {
+      Sass::deallocateMem(ptr, count);
+    }
+
+    // return maximum number of elements that can be allocated
+    size_type max_size() const throw()
+    {
+      return std::numeric_limits<size_type>::max() / sizeof(T);
+    }
+
+    // Address of object
+    type* address(type& obj) const { return &obj; }
+    type const* address(type const& obj) const { return &obj; }
+
+    // Construct object
+    void construct(type* ptr, type const& ref) const
+    {
+      // In-place copy construct
+      new(ptr) type(ref);
+    }
+
+    // Destroy object
+    void destroy(type* ptr) const
+    {
+      // Call destructor
+      ptr->~type();
+    }
+
+  };
+
+  template<typename T, typename U>
+    bool operator==(Allocator<T> const& left,
+      Allocator<U> const& right)
+  {
+    return true;
+  }
+
+  template<typename T, typename U>
+    bool operator!=(Allocator<T> const& left,
+      Allocator<U> const& right)
+  {
+    return !(left == right);
+  }
+
+#endif
+
+  namespace sass {
+    template <typename T> using vector = std::vector<T, Sass::Allocator<T>>;
+    using string = std::basic_string<char, std::char_traits<char>, Sass::Allocator<char>>;
+    using sstream = std::basic_stringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
+    using ostream = std::basic_ostringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
+    using istream = std::basic_istringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
+  }
+
+}
+
+#ifdef SASS_CUSTOM_ALLOCATOR
+
+namespace std {
+  // Only GCC seems to need this specialization!?
+  template <> struct hash<Sass::sass::string> {
+  public:
+    inline size_t operator()(
+      const Sass::sass::string& name) const
+    {
+      return MurmurHash2(
+        (void*)name.c_str(),
+        (int)name.size(),
+        0x73617373);
+    }
+  };
+}
+
+#endif
+
+#endif
diff --git a/libsass/src/memory/config.hpp b/libsass/src/memory/config.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/config.hpp
@@ -0,0 +1,20 @@
+#ifndef SASS_MEMORY_CONFIG_H
+#define SASS_MEMORY_CONFIG_H
+
+// Define memory alignment requirements
+#define SASS_MEM_ALIGN sizeof(unsigned int)
+
+// Minimal alignment for memory fragments. Must be a multiple
+// of `SASS_MEM_ALIGN` and should not be too big (maybe 1 or 2)
+#define SassAllocatorHeadSize sizeof(unsigned int)
+
+// The number of bytes we use for our book-keeping before every
+// memory fragment. Needed to know to which bucket we belongs on
+// deallocations, or if it should go directly to the `free` call.
+#define SassAllocatorBookSize sizeof(unsigned int)
+
+// Bytes reserve for book-keeping on the arenas
+// Currently unused and for later optimization
+#define SassAllocatorArenaHeadSize 0
+
+#endif
diff --git a/libsass/src/memory/memory_pool.hpp b/libsass/src/memory/memory_pool.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/memory_pool.hpp
@@ -0,0 +1,186 @@
+#ifndef SASS_MEMORY_POOL_H
+#define SASS_MEMORY_POOL_H
+
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+#include <climits>
+#include <vector>
+
+namespace Sass {
+
+  // SIMPLE MEMORY-POOL ALLOCATOR WITH FREE-LIST ON TOP
+
+  // This is a memory pool allocator with a free list on top.
+  // We only allocate memory arenas from the system in specific
+  // sizes (`SassAllocatorArenaSize`). Users claim memory slices
+  // of certain sizes from the pool. If the allocation is too big
+  // to fit into our buckets, we use regular malloc/free instead.
+
+  // When the systems starts, we allocate the first arena and then
+  // start to give out addresses to memory slices. During that
+  // we steadily increase `offset` until the current arena is full.
+  // Once that happens we allocate a new arena and continue.
+  // https://en.wikipedia.org/wiki/Memory_pool
+
+  // Fragments that get deallocated are not really freed, we put
+  // them on our free-list. For every bucket we have a pointer to
+  // the first item for reuse. That item itself holds a pointer to
+  // the previously free item (regular free-list implementation).
+  // https://en.wikipedia.org/wiki/Free_list
+
+  // On allocation calls we first check if there is any suitable
+  // item on the free-list. If there is we pop it from the stack
+  // and return it to the caller. Otherwise we have to take out
+  // a new slice from the current `arena` and increase `offset`.
+
+  // Note that this is not thread safe. This is on purpose as we
+  // want to use the memory pool in a thread local usage. In order
+  // to get this thread safe you need to only allocate one pool
+  // per thread. This can be achieved by using thread local PODs.
+  // Simply create a pool on the first allocation and dispose
+  // it once all allocations have been returned. E.g. by using:
+  // static thread_local size_t allocations;
+  // static thread_local MemoryPool* pool;
+
+  class MemoryPool {
+
+    // Current arena we fill up
+    char* arena;
+
+    // Position into the arena
+    size_t offset = std::string::npos;
+
+    // A list of full arenas
+    std::vector<void*> arenas;
+
+    // One pointer for every bucket (zero init)
+    #ifdef _MSC_VER
+    #pragma warning (suppress:4351)
+    #endif
+    void* freeList[SassAllocatorBuckets]{};
+
+    // Increase the address until it sits on a
+    // memory aligned address (maybe use `aligned`).
+    inline static size_t alignMemAddr(size_t addr) {
+      return (addr + SASS_MEM_ALIGN - 1) & ~(SASS_MEM_ALIGN - 1);
+    }
+
+  public:
+
+    // Default ctor
+    MemoryPool() :
+      // Wait for first allocation
+      arena(nullptr),
+      // Set to maximum value in order to
+      // make an allocation on the first run
+      offset(std::string::npos)
+    {
+    }
+
+    // Destructor
+    ~MemoryPool() {
+      // Delete full arenas
+      for (auto area : arenas) {
+        free(area);
+      }
+      // Delete current arena
+      free(arena);
+
+    }
+
+    // Allocate a slice of the memory pool
+    void* allocate(size_t size)
+    {
+
+      // Increase size so its memory is aligned
+      size = alignMemAddr(
+        // Make sure we have enough space for us to
+        // create the pointer to the free list later
+        std::max(sizeof(void*), size)
+        // and the size needed for our book-keeping
+        + SassAllocatorBookSize);
+
+      // Size must be multiple of alignment
+      // So we can derive bucket index from it
+      size_t bucket = size / SASS_MEM_ALIGN;
+
+      // Everything bigger is allocated via malloc
+      // Malloc is optimized for exactly this case
+      if (bucket >= SassAllocatorBuckets) {
+        char* buffer = (char*)malloc(size);
+        if (buffer == nullptr) {
+          throw std::bad_alloc();
+        }
+        // Mark it for deallocation via free
+        ((unsigned int*)buffer)[0] = UINT_MAX;
+        // Return pointer after our book-keeping space
+        return (void*)(buffer + SassAllocatorBookSize);
+      }
+      // Use custom allocator
+      else {
+        // Get item from free list
+        void*& free = freeList[bucket];
+        // Do we have a free item?
+        if (free != nullptr) {
+          // Copy pointer to return
+          void* ptr = free;
+          // Update free list pointer
+          free = ((void**)ptr)[0];
+          // Return popped item
+          return ptr;
+        }
+      }
+
+      // Make sure we have enough space in the arena
+      if (!arena || offset > SassAllocatorArenaSize - size) {
+        if (arena) arenas.emplace_back(arena);
+        arena = (char*)malloc(SassAllocatorArenaSize);
+        if (arena == nullptr) throw std::bad_alloc();
+        offset = SassAllocatorArenaHeadSize;
+      }
+
+      // Get pointer into the arena
+      char* buffer = arena + offset;
+      // Consume object size
+      offset += size;
+
+      // Set the bucket index for this slice
+      ((unsigned int*)buffer)[0] = (unsigned int)bucket;
+
+      // Return pointer after our book-keeping space
+      return (void*)(buffer + SassAllocatorBookSize);
+
+    }
+    // EO allocate
+
+    void deallocate(void* ptr)
+    {
+
+      // Rewind buffer from pointer
+      char* buffer = (char*)ptr -
+        SassAllocatorBookSize;
+
+      // Get the bucket index stored in the header
+      unsigned int bucket = ((unsigned int*)buffer)[0];
+
+      // Check allocation method
+      if (bucket != UINT_MAX) {
+        // Let memory point to previous item in free list
+        ((void**)ptr)[0] = freeList[bucket];
+        // Free list now points to our memory
+        freeList[bucket] = (void*)ptr;
+      }
+      else {
+        // Release memory
+        free(buffer);
+      }
+
+    }
+    // EO deallocate
+
+  };
+
+}
+
+#endif
diff --git a/libsass/src/memory/shared_ptr.cpp b/libsass/src/memory/shared_ptr.cpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/shared_ptr.cpp
@@ -0,0 +1,33 @@
+#include "../sass.hpp"
+#include <iostream>
+#include <typeinfo>
+
+#include "shared_ptr.hpp"
+#include "../ast_fwd_decl.hpp"
+
+#ifdef DEBUG_SHARED_PTR
+#include "../debugger.hpp"
+#endif
+
+namespace Sass {
+
+  #ifdef DEBUG_SHARED_PTR
+  void SharedObj::dumpMemLeaks() {
+    if (!all.empty()) {
+      std::cerr << "###################################\n";
+      std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n";
+      std::cerr << "###################################\n";
+      for (SharedObj* var : all) {
+        if (AST_Node* ast = dynamic_cast<AST_Node*>(var)) {
+          debug_ast(ast);
+        } else {
+          std::cerr << "LEAKED " << var << "\n";
+        }
+      }
+    }
+  }
+  sass::vector<SharedObj*> SharedObj::all;
+  #endif
+
+  bool SharedObj::taint = false;
+}
diff --git a/libsass/src/memory/shared_ptr.hpp b/libsass/src/memory/shared_ptr.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/memory/shared_ptr.hpp
@@ -0,0 +1,332 @@
+#ifndef SASS_MEMORY_SHARED_PTR_H
+#define SASS_MEMORY_SHARED_PTR_H
+
+#include "sass/base.h"
+
+#include "../sass.hpp"
+#include "allocator.hpp"
+#include <cstddef>
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+// https://lokiastari.com/blog/2014/12/30/c-plus-plus-by-example-smart-pointer/index.html
+// https://lokiastari.com/blog/2015/01/15/c-plus-plus-by-example-smart-pointer-part-ii/index.html
+// https://lokiastari.com/blog/2015/01/23/c-plus-plus-by-example-smart-pointer-part-iii/index.html
+
+namespace Sass {
+
+  // Forward declaration
+  class SharedPtr;
+
+  ///////////////////////////////////////////////////////////////////////////////
+  // Use macros for the allocation task, since overloading operator `new`
+  // has been proven to be flaky under certain compilers (see comment below).
+  ///////////////////////////////////////////////////////////////////////////////
+
+  #ifdef DEBUG_SHARED_PTR
+
+    #define SASS_MEMORY_NEW(Class, ...) \
+      ((Class*)(new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
+
+    #define SASS_MEMORY_COPY(obj) \
+      ((obj)->copy(__FILE__, __LINE__)) \
+
+    #define SASS_MEMORY_CLONE(obj) \
+      ((obj)->clone(__FILE__, __LINE__)) \
+
+  #else
+
+    #define SASS_MEMORY_NEW(Class, ...) \
+      new Class(__VA_ARGS__) \
+
+    #define SASS_MEMORY_COPY(obj) \
+      ((obj)->copy()) \
+
+    #define SASS_MEMORY_CLONE(obj) \
+      ((obj)->clone()) \
+
+  #endif
+
+  // SharedObj is the base class for all objects that can be stored as a shared object
+  // It adds the reference counter and other values directly to the objects
+  // This gives a slight overhead when directly used as a stack object, but has some
+  // advantages for our code. It is safe to create two shared pointers from the same
+  // objects, as the "control block" is directly attached to it. This would lead
+  // to undefined behavior with std::shared_ptr. This also avoids the need to
+  // allocate additional control blocks and/or the need to dereference two
+  // pointers on each operation. This can be optimized in `std::shared_ptr`
+  // too by using `std::make_shared` (where the control block and the actual
+  // object are allocated in one continuous memory block via one single call).
+  class SharedObj {
+   public:
+    SharedObj() : refcount(0), detached(false) {
+      #ifdef DEBUG_SHARED_PTR
+      if (taint) all.push_back(this);
+      #endif
+    }
+    virtual ~SharedObj() {
+      #ifdef DEBUG_SHARED_PTR
+      for (size_t i = 0; i < all.size(); i++) {
+        if (all[i] == this) {
+          all.erase(all.begin() + i);
+          break;
+        }
+      }
+      #endif
+    }
+
+    #ifdef DEBUG_SHARED_PTR
+    static void dumpMemLeaks();
+    SharedObj* trace(sass::string file, size_t line) {
+      this->file = file;
+      this->line = line;
+      return this;
+    }
+    sass::string getDbgFile() { return file; }
+    size_t getDbgLine() { return line; }
+    void setDbg(bool dbg) { this->dbg = dbg; }
+    size_t getRefCount() const { return refcount; }
+    #endif
+
+    static void setTaint(bool val) { taint = val; }
+
+    #ifdef SASS_CUSTOM_ALLOCATOR
+    inline void* operator new(size_t nbytes) {
+      return allocateMem(nbytes);
+    }
+    inline void operator delete(void* ptr) {
+      return deallocateMem(ptr);
+    }
+    #endif
+
+    virtual sass::string to_string() const = 0;
+   protected:
+    friend class SharedPtr;
+    friend class Memory_Manager;
+    size_t refcount;
+    bool detached;
+    static bool taint;
+    #ifdef DEBUG_SHARED_PTR
+    sass::string file;
+    size_t line;
+    bool dbg = false;
+    static sass::vector<SharedObj*> all;
+    #endif
+  };
+
+  // SharedPtr is a intermediate (template-less) base class for SharedImpl.
+  // ToDo: there should be a way to include this in SharedImpl and to get
+  // ToDo: rid of all the static_cast that are now needed in SharedImpl.
+  class SharedPtr {
+   public:
+    SharedPtr() : node(nullptr) {}
+    SharedPtr(SharedObj* ptr) : node(ptr) {
+      incRefCount();
+    }
+    SharedPtr(const SharedPtr& obj) : SharedPtr(obj.node) {}
+    ~SharedPtr() {
+      decRefCount();
+    }
+
+    SharedPtr& operator=(SharedObj* other_node) {
+      if (node != other_node) {
+        decRefCount();
+        node = other_node;
+        incRefCount();
+      } else if (node != nullptr) {
+        node->detached = false;
+      }
+      return *this;
+    }
+
+    SharedPtr& operator=(const SharedPtr& obj) {
+      return *this = obj.node;
+    }
+
+    // Prevents all SharedPtrs from freeing this node until it is assigned to another SharedPtr.
+    SharedObj* detach() {
+      if (node != nullptr) node->detached = true;
+      #ifdef DEBUG_SHARED_PTR
+      if (node->dbg) {
+        std::cerr << "DETACHING NODE\n";
+      }
+      #endif 
+      return node;
+    }
+
+    SharedObj* obj() const { return node; }
+    SharedObj* operator->() const { return node; }
+    bool isNull() const { return node == nullptr; }
+    operator bool() const { return node != nullptr; }
+
+   protected:
+    SharedObj* node;
+    void decRefCount() {
+      if (node == nullptr) return;
+      --node->refcount;
+      #ifdef DEBUG_SHARED_PTR
+      if (node->dbg) std::cerr << "- " << node << " X " << node->refcount << " (" << this << ") " << "\n";
+      #endif
+      if (node->refcount == 0 && !node->detached) {
+        #ifdef DEBUG_SHARED_PTR
+        if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
+        #endif
+        delete node;
+      }
+      else if (node->refcount == 0) {
+        #ifdef DEBUG_SHARED_PTR
+        if (node->dbg) std::cerr << "NODE EVAEDED DELETE " << node << "\n";
+        #endif
+      }
+    }
+    void incRefCount() {
+      if (node == nullptr) return;
+      node->detached = false;
+      ++node->refcount;
+      #ifdef DEBUG_SHARED_PTR
+      if (node->dbg) std::cerr << "+ " << node << " X " << node->refcount << " (" << this << ") " << "\n";
+      #endif
+    }
+  };
+
+  template <class T>
+  class SharedImpl : private SharedPtr {
+
+  public:
+    SharedImpl() : SharedPtr(nullptr) {}
+
+    template <class U>
+    SharedImpl(U* node) :
+      SharedPtr(static_cast<T*>(node)) {}
+
+    template <class U>
+    SharedImpl(const SharedImpl<U>& impl) :
+      SharedImpl(impl.ptr()) {}
+
+    template <class U>
+    SharedImpl<T>& operator=(U *rhs) {
+      return static_cast<SharedImpl<T>&>(
+        SharedPtr::operator=(static_cast<T*>(rhs)));
+    }
+
+    template <class U>
+    SharedImpl<T>& operator=(const SharedImpl<U>& rhs) {
+      return static_cast<SharedImpl<T>&>(
+        SharedPtr::operator=(static_cast<const SharedImpl<T>&>(rhs)));
+    }
+
+    operator sass::string() const {
+      if (node) return node->to_string();
+      return "null";
+    }
+
+    using SharedPtr::isNull;
+    using SharedPtr::operator bool;
+    operator T*() const { return static_cast<T*>(this->obj()); }
+    operator T&() const { return *static_cast<T*>(this->obj()); }
+    T& operator* () const { return *static_cast<T*>(this->obj()); };
+    T* operator-> () const { return static_cast<T*>(this->obj()); };
+    T* ptr () const { return static_cast<T*>(this->obj()); };
+    T* detach() { return static_cast<T*>(SharedPtr::detach()); }
+
+  };
+
+  // Comparison operators, based on:
+  // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp
+
+  template<class T1, class T2>
+  bool operator==(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    return x.ptr() == y.ptr();
+  }
+
+  template<class T1, class T2>
+  bool operator!=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    return x.ptr() != y.ptr();
+  }
+
+  template<class T1, class T2>
+  bool operator<(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    using CT = typename std::common_type<T1*, T2*>::type;
+    return std::less<CT>()(x.get(), y.get());
+  }
+
+  template<class T1, class T2>
+  bool operator<=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    return !(y < x);
+  }
+
+  template<class T1, class T2>
+  bool operator>(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    return y < x;
+  }
+
+  template<class T1, class T2>
+  bool operator>=(const SharedImpl<T1>& x, const SharedImpl<T2>& y) {
+    return !(x < y);
+  }
+
+  template <class T>
+  bool operator==(const SharedImpl<T>& x, std::nullptr_t) noexcept {
+    return x.isNull();
+  }
+
+  template <class T>
+  bool operator==(std::nullptr_t, const SharedImpl<T>& x) noexcept {
+    return x.isNull();
+  }
+
+  template <class T>
+  bool operator!=(const SharedImpl<T>& x, std::nullptr_t) noexcept {
+    return !x.isNull();
+  }
+
+  template <class T>
+  bool operator!=(std::nullptr_t, const SharedImpl<T>& x) noexcept {
+    return !x.isNull();
+  }
+
+  template <class T>
+  bool operator<(const SharedImpl<T>& x, std::nullptr_t) {
+    return std::less<T*>()(x.get(), nullptr);
+  }
+
+  template <class T>
+  bool operator<(std::nullptr_t, const SharedImpl<T>& y) {
+    return std::less<T*>()(nullptr, y.get());
+  }
+
+  template <class T>
+  bool operator<=(const SharedImpl<T>& x, std::nullptr_t) {
+    return !(nullptr < x);
+  }
+
+  template <class T>
+  bool operator<=(std::nullptr_t, const SharedImpl<T>& y) {
+    return !(y < nullptr);
+  }
+
+  template <class T>
+  bool operator>(const SharedImpl<T>& x, std::nullptr_t) {
+    return nullptr < x;
+  }
+
+  template <class T>
+  bool operator>(std::nullptr_t, const SharedImpl<T>& y) {
+    return y < nullptr;
+  }
+
+  template <class T>
+  bool operator>=(const SharedImpl<T>& x, std::nullptr_t) {
+    return !(x < nullptr);
+  }
+
+  template <class T>
+  bool operator>=(std::nullptr_t, const SharedImpl<T>& y) {
+    return !(nullptr < y);
+  }
+
+}  // namespace Sass
+
+#endif
diff --git a/libsass/src/operation.hpp b/libsass/src/operation.hpp
--- a/libsass/src/operation.hpp
+++ b/libsass/src/operation.hpp
@@ -19,13 +19,13 @@
   #define ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()\
     virtual void perform(Operation<void>* op) = 0; \
     virtual Value* perform(Operation<Value*>* op) = 0; \
-    virtual std::string perform(Operation<std::string>* op) = 0; \
+    virtual sass::string perform(Operation<sass::string>* op) = 0; \
     virtual AST_Node* perform(Operation<AST_Node*>* op) = 0; \
     virtual Selector* perform(Operation<Selector*>* op) = 0; \
     virtual Statement* perform(Operation<Statement*>* op) = 0; \
     virtual Expression* perform(Operation<Expression*>* op) = 0; \
     virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) = 0; \
-    virtual Supports_Condition* perform(Operation<Supports_Condition*>* op) = 0; \
+    virtual SupportsCondition* perform(Operation<SupportsCondition*>* op) = 0; \
 
   // you must add operators to every class
   // ensures `this` of actual instance type
@@ -34,13 +34,13 @@
   #define ATTACH_CRTP_PERFORM_METHODS()\
     virtual void perform(Operation<void>* op) override { return (*op)(this); } \
     virtual Value* perform(Operation<Value*>* op) override { return (*op)(this); } \
-    virtual std::string perform(Operation<std::string>* op) override { return (*op)(this); } \
+    virtual sass::string perform(Operation<sass::string>* op) override { return (*op)(this); } \
     virtual AST_Node* perform(Operation<AST_Node*>* op) override { return (*op)(this); } \
     virtual Selector* perform(Operation<Selector*>* op) override { return (*op)(this); } \
     virtual Statement* perform(Operation<Statement*>* op) override { return (*op)(this); } \
     virtual Expression* perform(Operation<Expression*>* op) override { return (*op)(this); } \
     virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) override { return (*op)(this); } \
-    virtual Supports_Condition* perform(Operation<Supports_Condition*>* op) override { return (*op)(this); } \
+    virtual SupportsCondition* perform(Operation<SupportsCondition*>* op) override { return (*op)(this); } \
 
   template<typename T>
   class Operation {
@@ -48,28 +48,28 @@
     virtual T operator()(AST_Node* x)               = 0;
     // statements
     virtual T operator()(Block* x)                  = 0;
-    virtual T operator()(Ruleset* x)                = 0;
+    virtual T operator()(StyleRule* x)                = 0;
     virtual T operator()(Bubble* x)                 = 0;
     virtual T operator()(Trace* x)                  = 0;
-    virtual T operator()(Supports_Block* x)         = 0;
+    virtual T operator()(SupportsRule* x)         = 0;
     virtual T operator()(MediaRule* x) = 0;
     virtual T operator()(CssMediaRule* x) = 0;
     virtual T operator()(CssMediaQuery* x) = 0;
-    virtual T operator()(At_Root_Block* x)          = 0;
-    virtual T operator()(Directive* x)              = 0;
+    virtual T operator()(AtRootRule* x)          = 0;
+    virtual T operator()(AtRule* x)              = 0;
     virtual T operator()(Keyframe_Rule* x)          = 0;
     virtual T operator()(Declaration* x)            = 0;
     virtual T operator()(Assignment* x)             = 0;
     virtual T operator()(Import* x)                 = 0;
     virtual T operator()(Import_Stub* x)            = 0;
-    virtual T operator()(Warning* x)                = 0;
-    virtual T operator()(Error* x)                  = 0;
-    virtual T operator()(Debug* x)                  = 0;
+    virtual T operator()(WarningRule* x)                = 0;
+    virtual T operator()(ErrorRule* x)                  = 0;
+    virtual T operator()(DebugRule* x)                  = 0;
     virtual T operator()(Comment* x)                = 0;
     virtual T operator()(If* x)                     = 0;
-    virtual T operator()(For* x)                    = 0;
-    virtual T operator()(Each* x)                   = 0;
-    virtual T operator()(While* x)                  = 0;
+    virtual T operator()(ForRule* x)                    = 0;
+    virtual T operator()(EachRule* x)                   = 0;
+    virtual T operator()(WhileRule* x)                  = 0;
     virtual T operator()(Return* x)                 = 0;
     virtual T operator()(Content* x)                = 0;
     virtual T operator()(ExtendRule* x)              = 0;
@@ -94,10 +94,10 @@
     virtual T operator()(String_Schema* x)          = 0;
     virtual T operator()(String_Quoted* x)          = 0;
     virtual T operator()(String_Constant* x)        = 0;
-    virtual T operator()(Supports_Condition* x)     = 0;
-    virtual T operator()(Supports_Operator* x)      = 0;
-    virtual T operator()(Supports_Negation* x)      = 0;
-    virtual T operator()(Supports_Declaration* x)   = 0;
+    virtual T operator()(SupportsCondition* x)     = 0;
+    virtual T operator()(SupportsOperation* x)      = 0;
+    virtual T operator()(SupportsNegation* x)      = 0;
+    virtual T operator()(SupportsDeclaration* x)   = 0;
     virtual T operator()(Supports_Interpolation* x) = 0;
     virtual T operator()(Media_Query* x) = 0;
     virtual T operator()(Media_Query_Expression* x) = 0;
@@ -110,12 +110,12 @@
     virtual T operator()(Arguments* x)              = 0;
     // selectors
     virtual T operator()(Selector_Schema* x)        = 0;
-    virtual T operator()(Placeholder_Selector* x)   = 0;
-    virtual T operator()(Type_Selector* x)       = 0;
-    virtual T operator()(Class_Selector* x)         = 0;
-    virtual T operator()(Id_Selector* x)            = 0;
-    virtual T operator()(Attribute_Selector* x)     = 0;
-    virtual T operator()(Pseudo_Selector* x)        = 0;
+    virtual T operator()(PlaceholderSelector* x)   = 0;
+    virtual T operator()(TypeSelector* x)       = 0;
+    virtual T operator()(ClassSelector* x)         = 0;
+    virtual T operator()(IDSelector* x)            = 0;
+    virtual T operator()(AttributeSelector* x)     = 0;
+    virtual T operator()(PseudoSelector* x)        = 0;
     virtual T operator()(SelectorComponent* x) = 0;
     virtual T operator()(SelectorCombinator* x) = 0;
     virtual T operator()(CompoundSelector* x) = 0;
@@ -134,28 +134,28 @@
     T operator()(AST_Node* x)               { return static_cast<D*>(this)->fallback(x); }
     // statements
     T operator()(Block* x)                  { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Ruleset* x)                { return static_cast<D*>(this)->fallback(x); }
+    T operator()(StyleRule* x)                { return static_cast<D*>(this)->fallback(x); }
     T operator()(Bubble* x)                 { return static_cast<D*>(this)->fallback(x); }
     T operator()(Trace* x)                  { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Supports_Block* x)         { return static_cast<D*>(this)->fallback(x); }
+    T operator()(SupportsRule* x)         { return static_cast<D*>(this)->fallback(x); }
     T operator()(MediaRule* x) { return static_cast<D*>(this)->fallback(x); }
     T operator()(CssMediaRule* x) { return static_cast<D*>(this)->fallback(x); }
     T operator()(CssMediaQuery* x) { return static_cast<D*>(this)->fallback(x); }
-    T operator()(At_Root_Block* x)          { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Directive* x)              { return static_cast<D*>(this)->fallback(x); }
+    T operator()(AtRootRule* x)          { return static_cast<D*>(this)->fallback(x); }
+    T operator()(AtRule* x)              { return static_cast<D*>(this)->fallback(x); }
     T operator()(Keyframe_Rule* x)          { return static_cast<D*>(this)->fallback(x); }
     T operator()(Declaration* x)            { return static_cast<D*>(this)->fallback(x); }
     T operator()(Assignment* x)             { return static_cast<D*>(this)->fallback(x); }
     T operator()(Import* x)                 { return static_cast<D*>(this)->fallback(x); }
     T operator()(Import_Stub* x)            { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Warning* x)                { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Error* x)                  { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Debug* x)                  { return static_cast<D*>(this)->fallback(x); }
+    T operator()(WarningRule* x)                { return static_cast<D*>(this)->fallback(x); }
+    T operator()(ErrorRule* x)                  { return static_cast<D*>(this)->fallback(x); }
+    T operator()(DebugRule* x)                  { return static_cast<D*>(this)->fallback(x); }
     T operator()(Comment* x)                { return static_cast<D*>(this)->fallback(x); }
     T operator()(If* x)                     { return static_cast<D*>(this)->fallback(x); }
-    T operator()(For* x)                    { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Each* x)                   { return static_cast<D*>(this)->fallback(x); }
-    T operator()(While* x)                  { return static_cast<D*>(this)->fallback(x); }
+    T operator()(ForRule* x)                    { return static_cast<D*>(this)->fallback(x); }
+    T operator()(EachRule* x)                   { return static_cast<D*>(this)->fallback(x); }
+    T operator()(WhileRule* x)                  { return static_cast<D*>(this)->fallback(x); }
     T operator()(Return* x)                 { return static_cast<D*>(this)->fallback(x); }
     T operator()(Content* x)                { return static_cast<D*>(this)->fallback(x); }
     T operator()(ExtendRule* x)              { return static_cast<D*>(this)->fallback(x); }
@@ -180,10 +180,10 @@
     T operator()(String_Schema* x)          { return static_cast<D*>(this)->fallback(x); }
     T operator()(String_Constant* x)        { return static_cast<D*>(this)->fallback(x); }
     T operator()(String_Quoted* x)          { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Supports_Condition* x)     { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Supports_Operator* x)      { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Supports_Negation* x)      { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Supports_Declaration* x)   { return static_cast<D*>(this)->fallback(x); }
+    T operator()(SupportsCondition* x)     { return static_cast<D*>(this)->fallback(x); }
+    T operator()(SupportsOperation* x)      { return static_cast<D*>(this)->fallback(x); }
+    T operator()(SupportsNegation* x)      { return static_cast<D*>(this)->fallback(x); }
+    T operator()(SupportsDeclaration* x)   { return static_cast<D*>(this)->fallback(x); }
     T operator()(Supports_Interpolation* x) { return static_cast<D*>(this)->fallback(x); }
     T operator()(Media_Query* x)            { return static_cast<D*>(this)->fallback(x); }
     T operator()(Media_Query_Expression* x) { return static_cast<D*>(this)->fallback(x); }
@@ -196,12 +196,12 @@
     T operator()(Arguments* x)              { return static_cast<D*>(this)->fallback(x); }
     // selectors
     T operator()(Selector_Schema* x)        { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Placeholder_Selector* x)   { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Type_Selector* x)       { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Class_Selector* x)         { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Id_Selector* x)            { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Attribute_Selector* x)     { return static_cast<D*>(this)->fallback(x); }
-    T operator()(Pseudo_Selector* x)        { return static_cast<D*>(this)->fallback(x); }
+    T operator()(PlaceholderSelector* x)   { return static_cast<D*>(this)->fallback(x); }
+    T operator()(TypeSelector* x)       { return static_cast<D*>(this)->fallback(x); }
+    T operator()(ClassSelector* x)         { return static_cast<D*>(this)->fallback(x); }
+    T operator()(IDSelector* x)            { return static_cast<D*>(this)->fallback(x); }
+    T operator()(AttributeSelector* x)     { return static_cast<D*>(this)->fallback(x); }
+    T operator()(PseudoSelector* x)        { return static_cast<D*>(this)->fallback(x); }
     T operator()(SelectorComponent* x) { return static_cast<D*>(this)->fallback(x); }
     T operator()(SelectorCombinator* x) { return static_cast<D*>(this)->fallback(x); }
     T operator()(CompoundSelector* x) { return static_cast<D*>(this)->fallback(x); }
diff --git a/libsass/src/operators.cpp b/libsass/src/operators.cpp
--- a/libsass/src/operators.cpp
+++ b/libsass/src/operators.cpp
@@ -31,7 +31,7 @@
     };
 
     /* static function, has no pstate or traces */
-    bool eq(Expression_Obj lhs, Expression_Obj rhs)
+    bool eq(ExpressionObj lhs, ExpressionObj rhs)
     {
       // operation is undefined if one is not a number
       if (!lhs || !rhs) throw Exception::UndefinedOperation(lhs, rhs, Sass_OP::EQ);
@@ -40,7 +40,7 @@
     }
 
     /* static function, throws OperationError, has no pstate or traces */
-    bool cmp(Expression_Obj lhs, Expression_Obj rhs, const Sass_OP op)
+    bool cmp(ExpressionObj lhs, ExpressionObj rhs, const Sass_OP op)
     {
       // can only compare numbers!?
       Number_Obj l = Cast<Number>(lhs);
@@ -52,14 +52,14 @@
     }
 
     /* static functions, throws OperationError, has no pstate or traces */
-    bool lt(Expression_Obj lhs, Expression_Obj rhs) { return cmp(lhs, rhs, Sass_OP::LT); }
-    bool neq(Expression_Obj lhs, Expression_Obj rhs) { return eq(lhs, rhs) == false; }
-    bool gt(Expression_Obj lhs, Expression_Obj rhs) { return !cmp(lhs, rhs, Sass_OP::GT) && neq(lhs, rhs); }
-    bool lte(Expression_Obj lhs, Expression_Obj rhs) { return cmp(lhs, rhs, Sass_OP::LTE) || eq(lhs, rhs); }
-    bool gte(Expression_Obj lhs, Expression_Obj rhs) { return !cmp(lhs, rhs, Sass_OP::GTE) || eq(lhs, rhs); }
+    bool lt(ExpressionObj lhs, ExpressionObj rhs) { return cmp(lhs, rhs, Sass_OP::LT); }
+    bool neq(ExpressionObj lhs, ExpressionObj rhs) { return eq(lhs, rhs) == false; }
+    bool gt(ExpressionObj lhs, ExpressionObj rhs) { return !cmp(lhs, rhs, Sass_OP::GT) && neq(lhs, rhs); }
+    bool lte(ExpressionObj lhs, ExpressionObj rhs) { return cmp(lhs, rhs, Sass_OP::LTE) || eq(lhs, rhs); }
+    bool gte(ExpressionObj lhs, ExpressionObj rhs) { return !cmp(lhs, rhs, Sass_OP::GTE) || eq(lhs, rhs); }
 
     /* colour math deprecation warning */
-    void op_color_deprecation(enum Sass_OP op, std::string lsh, std::string rhs, const ParserState& pstate)
+    void op_color_deprecation(enum Sass_OP op, sass::string lsh, sass::string rhs, const SourceSpan& pstate)
     {
       deprecated(
         "The operation `" + lsh + " " + sass_op_to_name(op) + " " + rhs +
@@ -70,20 +70,20 @@
     }
 
     /* static function, throws OperationError, has no traces but optional pstate for returned value */
-    Value* op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
+    Value* op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed)
     {
       enum Sass_OP op = operand.operand;
 
       String_Quoted* lqstr = Cast<String_Quoted>(&lhs);
       String_Quoted* rqstr = Cast<String_Quoted>(&rhs);
 
-      std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
-      std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
+      sass::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
+      sass::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
 
       if (Cast<Null>(&lhs)) throw Exception::InvalidNullOperation(&lhs, &rhs, op);
       if (Cast<Null>(&rhs)) throw Exception::InvalidNullOperation(&lhs, &rhs, op);
 
-      std::string sep;
+      sass::string sep;
       switch (op) {
         case Sass_OP::ADD: sep = "";   break;
         case Sass_OP::SUB: sep = "-";  break;
@@ -121,7 +121,7 @@
 
     /* ToDo: allow to operate also with hsla colors */
     /* static function, throws OperationError, has no traces but optional pstate for returned value */
-    Value* op_colors(enum Sass_OP op, const Color_RGBA& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
+    Value* op_colors(enum Sass_OP op, const Color_RGBA& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed)
     {
 
       if (lhs.a() != rhs.a()) {
@@ -142,7 +142,7 @@
     }
 
     /* static function, throws OperationError, has no traces but optional pstate for returned value */
-    Value* op_numbers(enum Sass_OP op, const Number& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
+    Value* op_numbers(enum Sass_OP op, const Number& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed)
     {
       double lval = lhs.value();
       double rval = rhs.value();
@@ -152,7 +152,7 @@
       }
 
       if (op == Sass_OP::DIV && rval == 0) {
-        std::string result(lval ? "Infinity" : "NaN");
+        sass::string result(lval ? "Infinity" : "NaN");
         return SASS_MEMORY_NEW(String_Quoted, pstate, result);
       }
 
@@ -212,7 +212,7 @@
     }
 
     /* static function, throws OperationError, has no traces but optional pstate for returned value */
-    Value* op_number_color(enum Sass_OP op, const Number& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
+    Value* op_number_color(enum Sass_OP op, const Number& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed)
     {
       double lval = lhs.value();
 
@@ -229,7 +229,7 @@
         }
         case Sass_OP::SUB:
         case Sass_OP::DIV: {
-          std::string color(rhs.to_string(opt));
+          sass::string color(rhs.to_string(opt));
           op_color_deprecation(op, lhs.to_string(), color, pstate);
           return SASS_MEMORY_NEW(String_Quoted,
                                 pstate,
@@ -243,7 +243,7 @@
     }
 
     /* static function, throws OperationError, has no traces but optional pstate for returned value */
-    Value* op_color_number(enum Sass_OP op, const Color_RGBA& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
+    Value* op_color_number(enum Sass_OP op, const Color_RGBA& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed)
     {
       double rval = rhs.value();
 
diff --git a/libsass/src/operators.hpp b/libsass/src/operators.hpp
--- a/libsass/src/operators.hpp
+++ b/libsass/src/operators.hpp
@@ -9,19 +9,19 @@
   namespace Operators {
 
     // equality operator using AST Node operator==
-    bool eq(Expression_Obj, Expression_Obj);
-    bool neq(Expression_Obj, Expression_Obj);
+    bool eq(ExpressionObj, ExpressionObj);
+    bool neq(ExpressionObj, ExpressionObj);
     // specific operators based on cmp and eq
-    bool lt(Expression_Obj, Expression_Obj);
-    bool gt(Expression_Obj, Expression_Obj);
-    bool lte(Expression_Obj, Expression_Obj);
-    bool gte(Expression_Obj, Expression_Obj);
+    bool lt(ExpressionObj, ExpressionObj);
+    bool gt(ExpressionObj, ExpressionObj);
+    bool lte(ExpressionObj, ExpressionObj);
+    bool gte(ExpressionObj, ExpressionObj);
     // arithmetic for all the combinations that matter
-    Value* op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
-    Value* op_colors(enum Sass_OP, const Color_RGBA&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
-    Value* op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
-    Value* op_number_color(enum Sass_OP, const Number&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
-    Value* op_color_number(enum Sass_OP, const Color_RGBA&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
+    Value* op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed = false);
+    Value* op_colors(enum Sass_OP, const Color_RGBA&, const Color_RGBA&, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed = false);
+    Value* op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed = false);
+    Value* op_number_color(enum Sass_OP, const Number&, const Color_RGBA&, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed = false);
+    Value* op_color_number(enum Sass_OP, const Color_RGBA&, const Number&, struct Sass_Inspect_Options opt, const SourceSpan& pstate, bool delayed = false);
 
   };
 
diff --git a/libsass/src/ordered_map.hpp b/libsass/src/ordered_map.hpp
--- a/libsass/src/ordered_map.hpp
+++ b/libsass/src/ordered_map.hpp
@@ -5,7 +5,7 @@
 
   // ##########################################################################
   // Very simple and limited container for insert ordered hash map.
-  // Piggy-back implementation on std::unordered_map and std::vector
+  // Piggy-back implementation on std::unordered_map and sass::vector
   // ##########################################################################
   template<
     class Key,
@@ -26,8 +26,8 @@
     map_type _map;
 
     // Keep insertion order
-    std::vector<Key> _keys;
-    std::vector<T> _values;
+    sass::vector<Key> _keys;
+    sass::vector<T> _values;
 
     const KeyEqual _keyEqual;
 
@@ -81,8 +81,8 @@
       return false;
     }
 
-    const std::vector<Key>& keys() const { return _keys; }
-    const std::vector<T>& values() const { return _values; }
+    const sass::vector<Key>& keys() const { return _keys; }
+    const sass::vector<T>& values() const { return _values; }
 
     const T& get(const Key& key) {
       if (hasKey(key)) {
@@ -91,19 +91,19 @@
       throw std::runtime_error("Key does not exist");
     }
 
-    using iterator = typename std::vector<Key>::iterator;
-    using const_iterator = typename std::vector<Key>::const_iterator;
-    using reverse_iterator = typename std::vector<Key>::reverse_iterator;
-    using const_reverse_iterator = typename std::vector<Key>::const_reverse_iterator;
+    using iterator = typename sass::vector<Key>::iterator;
+    using const_iterator = typename sass::vector<Key>::const_iterator;
+    using reverse_iterator = typename sass::vector<Key>::reverse_iterator;
+    using const_reverse_iterator = typename sass::vector<Key>::const_reverse_iterator;
 
-    typename std::vector<Key>::iterator end() { return _keys.end(); }
-    typename std::vector<Key>::iterator begin() { return _keys.begin(); }
-    typename std::vector<Key>::reverse_iterator rend() { return _keys.rend(); }
-    typename std::vector<Key>::reverse_iterator rbegin() { return _keys.rbegin(); }
-    typename std::vector<Key>::const_iterator end() const { return _keys.end(); }
-    typename std::vector<Key>::const_iterator begin() const { return _keys.begin(); }
-    typename std::vector<Key>::const_reverse_iterator rend() const { return _keys.rend(); }
-    typename std::vector<Key>::const_reverse_iterator rbegin() const { return _keys.rbegin(); }
+    typename sass::vector<Key>::iterator end() { return _keys.end(); }
+    typename sass::vector<Key>::iterator begin() { return _keys.begin(); }
+    typename sass::vector<Key>::reverse_iterator rend() { return _keys.rend(); }
+    typename sass::vector<Key>::reverse_iterator rbegin() { return _keys.rbegin(); }
+    typename sass::vector<Key>::const_iterator end() const { return _keys.end(); }
+    typename sass::vector<Key>::const_iterator begin() const { return _keys.begin(); }
+    typename sass::vector<Key>::const_reverse_iterator rend() const { return _keys.rend(); }
+    typename sass::vector<Key>::const_reverse_iterator rbegin() const { return _keys.rbegin(); }
 
   };
 
diff --git a/libsass/src/output.cpp b/libsass/src/output.cpp
--- a/libsass/src/output.cpp
+++ b/libsass/src/output.cpp
@@ -30,7 +30,7 @@
       throw Exception::InvalidValue({}, *n);
     }
     // use values to_string facility
-    std::string res = n->to_string(opt);
+    sass::string res = n->to_string(opt);
     // output the final token
     append_token(res, n);
   }
@@ -77,7 +77,7 @@
       // declare the charset
       if (output_style() != COMPRESSED)
         charset = "@charset \"UTF-8\";"
-                + std::string(opt.linefeed);
+                + sass::string(opt.linefeed);
       else charset = "\xEF\xBB\xBF";
       // abort search
       break;
@@ -111,7 +111,7 @@
     }
   }
 
-  void Output::operator()(Ruleset* r)
+  void Output::operator()(StyleRule* r)
   {
     Block_Obj b = r->block();
     SelectorListObj s = r->selector();
@@ -122,7 +122,7 @@
     if (!Util::isPrintable(r, output_style())) {
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         const Statement_Obj& stm = b->get(i);
-        if (Cast<Has_Block>(stm)) {
+        if (Cast<ParentStatement>(stm)) {
           if (!Cast<Declaration>(stm)) {
             stm->perform(this);
           }
@@ -135,10 +135,10 @@
       indentation += r->tabs();
     }
     if (opt.source_comments) {
-      std::stringstream ss;
+      sass::ostream ss;
       append_indentation();
-      std::string path(File::abs2rel(r->pstate().path));
-      ss << "/* line " << r->pstate().line + 1 << ", " << path << " */";
+      sass::string path(File::abs2rel(r->pstate().getPath()));
+      ss << "/* line " << r->pstate().getLine() << ", " << path << " */";
       append_string(ss.str());
       append_optional_linefeed();
     }
@@ -151,7 +151,7 @@
       // Check print conditions
       if (Declaration* dec = Cast<Declaration>(stm)) {
         if (const String_Constant* valConst = Cast<String_Constant>(dec->value())) {
-          const std::string& val = valConst->value();
+          const sass::string& val = valConst->value();
           if (const String_Quoted* qstr = Cast<const String_Quoted>(valConst)) {
             if (!qstr->quote_mark() && val.empty()) {
               bPrintExpression = false;
@@ -199,18 +199,18 @@
     append_scope_closer();
   }
 
-  void Output::operator()(Supports_Block* f)
+  void Output::operator()(SupportsRule* f)
   {
     if (f->is_invisible()) return;
 
-    Supports_Condition_Obj c = f->condition();
+    SupportsConditionObj c = f->condition();
     Block_Obj b              = f->block();
 
     // Filter out feature blocks that aren't printable (process its children though)
     if (!Util::isPrintable(f, output_style())) {
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         Statement_Obj stm = b->get(i);
-        if (Cast<Has_Block>(stm)) {
+        if (Cast<ParentStatement>(stm)) {
           stm->perform(this);
         }
       }
@@ -253,11 +253,11 @@
     }
   }
 
-  void Output::operator()(Directive* a)
+  void Output::operator()(AtRule* a)
   {
-    std::string      kwd   = a->keyword();
+    sass::string      kwd   = a->keyword();
     Selector_Obj   s     = a->selector();
-    Expression_Obj v     = a->value();
+    ExpressionObj v     = a->value();
     Block_Obj      b     = a->block();
 
     append_indentation();
@@ -289,7 +289,7 @@
 
     for (size_t i = 0, L = b->length(); i < L; ++i) {
       Statement_Obj stm = b->get(i);
-      stm->perform(this);
+      if (stm) stm->perform(this);
       if (i < L - 1 && format) append_special_linefeed();
     }
 
@@ -309,7 +309,7 @@
 
   void Output::operator()(String_Constant* s)
   {
-    std::string value(s->value());
+    sass::string value(s->value());
     if (!in_comment && !in_custom_property) {
       append_token(string_to_output(value), s);
     } else {
diff --git a/libsass/src/output.hpp b/libsass/src/output.hpp
--- a/libsass/src/output.hpp
+++ b/libsass/src/output.hpp
@@ -20,17 +20,17 @@
     virtual ~Output();
 
   protected:
-    std::string charset;
-    std::vector<AST_Node*> top_nodes;
+    sass::string charset;
+    sass::vector<AST_Node*> top_nodes;
 
   public:
     OutputBuffer get_buffer(void);
 
     virtual void operator()(Map*);
-    virtual void operator()(Ruleset*);
-    virtual void operator()(Supports_Block*);
+    virtual void operator()(StyleRule*);
+    virtual void operator()(SupportsRule*);
     virtual void operator()(CssMediaRule*);
-    virtual void operator()(Directive*);
+    virtual void operator()(AtRule*);
     virtual void operator()(Keyframe_Rule*);
     virtual void operator()(Import*);
     virtual void operator()(Comment*);
diff --git a/libsass/src/parser.cpp b/libsass/src/parser.cpp
--- a/libsass/src/parser.cpp
+++ b/libsass/src/parser.cpp
@@ -23,45 +23,39 @@
   using namespace Constants;
   using namespace Prelexer;
 
-  Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
-  {
-    pstate.offset.column = 0;
-    pstate.offset.line = 0;
-    Parser p(ctx, pstate, traces, allow_parent);
-    p.source   = source ? source : beg;
-    p.position = beg ? beg : p.source;
-    p.end      = p.position + strlen(p.position);
-    Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
-    p.block_stack.push_back(root);
-    root->is_root(true);
-    return p;
-  }
 
-  Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
+  Parser::Parser(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent) :
+    SourceSpan(source),
+    ctx(ctx),
+    source(source),
+    begin(source->begin()),
+    position(source->begin()),
+    end(source->end()),
+    before_token(0, 0),
+    after_token(0, 0),
+    pstate(source->getSourceSpan()),
+    traces(traces),
+    indentation(0),
+    nestings(0),
+    allow_parent(allow_parent)
   {
-    pstate.offset.column = 0;
-    pstate.offset.line = 0;
-    Parser p(ctx, pstate, traces, allow_parent);
-    p.source   = source ? source : beg;
-    p.position = beg ? beg : p.source;
-    p.end      = end ? end : p.position + strlen(p.position);
     Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
-    p.block_stack.push_back(root);
+    stack.push_back(Scope::Root);
+    block_stack.push_back(root);
     root->is_root(true);
-    return p;
   }
 
-   void Parser::advanceToNextToken() {
+  void Parser::advanceToNextToken() {
       lex < css_comments >(false);
       // advance to position
-      pstate += pstate.offset;
+      pstate.position += pstate.offset;
       pstate.offset.column = 0;
       pstate.offset.line = 0;
     }
 
-  SelectorListObj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
+  SelectorListObj Parser::parse_selector(SourceData* source, Context& ctx, Backtraces traces, bool allow_parent)
   {
-    Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
+    Parser p(source, ctx, traces, allow_parent);
     // ToDo: remap the source-map entries somehow
     return p.parseSelectorList(false);
   }
@@ -72,18 +66,6 @@
            && ! peek_css<exactly<'{'>>(start);
   }
 
-  Parser Parser::from_token(Token t, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
-  {
-    Parser p(ctx, pstate, traces);
-    p.source   = source ? source : t.begin;
-    p.position = t.begin ? t.begin : p.source;
-    p.end      = t.end ? t.end : p.position + strlen(p.position);
-    Block_Obj root = SASS_MEMORY_NEW(Block, pstate);
-    p.block_stack.push_back(root);
-    root->is_root(true);
-    return p;
-  }
-
   /* main entry point to parse root block */
   Block_Obj Parser::parse()
   {
@@ -96,7 +78,7 @@
 
     // report invalid utf8
     if (it != end) {
-      pstate += Offset::init(position, it);
+      pstate.position += Offset::init(position, it);
       traces.push_back(Backtrace(pstate));
       throw Exception::InvalidSass(pstate, traces, "Invalid UTF-8 sequence");
     }
@@ -107,7 +89,7 @@
     // check seems a bit esoteric but works
     if (ctx.resources.size() == 1) {
       // apply headers only on very first include
-      ctx.apply_custom_headers(root, path, pstate);
+      ctx.apply_custom_headers(root, getPath(), pstate);
     }
 
     // parse children nodes
@@ -327,33 +309,33 @@
   Import_Obj Parser::parse_import()
   {
     Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
-    std::vector<std::pair<std::string,Function_Call_Obj>> to_import;
+    sass::vector<std::pair<sass::string,Function_Call_Obj>> to_import;
     bool first = true;
     do {
       while (lex< block_comment >());
       if (lex< quoted_string >()) {
-        to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), {}));
+        to_import.push_back(std::pair<sass::string,Function_Call_Obj>(sass::string(lexed), {}));
       }
       else if (lex< uri_prefix >()) {
         Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
-        Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, std::string("url"), args);
+        Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), args);
 
         if (lex< quoted_string >()) {
-          Expression_Obj quoted_url = parse_string();
+          ExpressionObj quoted_url = parse_string();
           args->append(SASS_MEMORY_NEW(Argument, quoted_url->pstate(), quoted_url));
         }
         else if (String_Obj string_url = parse_url_function_argument()) {
           args->append(SASS_MEMORY_NEW(Argument, string_url->pstate(), string_url));
         }
         else if (peek < skip_over_scopes < exactly < '(' >, exactly < ')' > > >(position)) {
-          Expression_Obj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
+          ExpressionObj braced_url = parse_list(); // parse_interpolated_chunk(lexed);
           args->append(SASS_MEMORY_NEW(Argument, braced_url->pstate(), braced_url));
         }
         else {
           error("malformed URL");
         }
         if (!lex< exactly<')'> >()) error("URI is missing ')'");
-        to_import.push_back(std::pair<std::string, Function_Call_Obj>("", result));
+        to_import.push_back(std::pair<sass::string, Function_Call_Obj>("", result));
       }
       else {
         if (first) error("@import directive requires a url or quoted path");
@@ -372,9 +354,9 @@
         imp->urls().push_back(location.second);
       }
       // check if custom importers want to take over the handling
-      else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
+      else if (!ctx.call_importers(unquote(location.first), getPath(), pstate, imp)) {
         // nobody wants it, so we do our import
-        ctx.import_url(imp, location.first, path);
+        ctx.import_url(imp, location.first, getPath());
       }
     }
 
@@ -383,12 +365,12 @@
 
   Definition_Obj Parser::parse_definition(Definition::Type which_type)
   {
-    std::string which_str(lexed);
+    sass::string which_str(lexed);
     if (!lex< identifier >()) error("invalid name in " + which_str + " definition");
-    std::string name(Util::normalize_underscores(lexed));
+    sass::string name(Util::normalize_underscores(lexed));
     if (which_type == Definition::FUNCTION && (name == "and" || name == "or" || name == "not"))
     { error("Invalid function name \"" + name + "\"."); }
-    ParserState source_position_of_def = pstate;
+    SourceSpan source_position_of_def = pstate;
     Parameters_Obj params = parse_parameters();
     if (which_type == Definition::MIXIN) stack.push_back(Scope::Mixin);
     else stack.push_back(Scope::Function);
@@ -422,9 +404,9 @@
     }
     while (lex< alternatives < spaces, block_comment > >());
     lex < variable >();
-    std::string name(Util::normalize_underscores(lexed));
-    ParserState pos = pstate;
-    Expression_Obj val;
+    sass::string name(Util::normalize_underscores(lexed));
+    SourceSpan pos = pstate;
+    ExpressionObj val;
     bool is_rest = false;
     while (lex< alternatives < spaces, block_comment > >());
     if (lex< exactly<':'> >()) { // there's a default value
@@ -468,16 +450,16 @@
     Argument_Obj arg;
     if (peek_css< sequence < variable, optional_css_comments, exactly<':'> > >()) {
       lex_css< variable >();
-      std::string name(Util::normalize_underscores(lexed));
-      ParserState p = pstate;
+      sass::string name(Util::normalize_underscores(lexed));
+      SourceSpan p = pstate;
       lex_css< exactly<':'> >();
-      Expression_Obj val = parse_space_list();
+      ExpressionObj val = parse_space_list();
       arg = SASS_MEMORY_NEW(Argument, p, val, name);
     }
     else {
       bool is_arglist = false;
       bool is_keyword = false;
-      Expression_Obj val = parse_space_list();
+      ExpressionObj val = parse_space_list();
       List* l = Cast<List>(val);
       if (lex_css< exactly< ellipsis > >()) {
         if (val->concrete_type() == Expression::MAP || (
@@ -492,13 +474,13 @@
 
   Assignment_Obj Parser::parse_assignment()
   {
-    std::string name(Util::normalize_underscores(lexed));
-    ParserState var_source_position = pstate;
+    sass::string name(Util::normalize_underscores(lexed));
+    SourceSpan var_source_position = pstate;
     if (!lex< exactly<':'> >()) error("expected ':' after " + name + " in assignment statement");
     if (peek_css< alternatives < exactly<';'>, end_of_file > >()) {
       css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
     }
-    Expression_Obj val;
+    ExpressionObj val;
     Lookahead lookahead = lookahead_for_value(position);
     if (lookahead.has_interpolants && lookahead.found) {
       val = parse_value_schema(lookahead.found);
@@ -515,7 +497,7 @@
   }
 
   // a ruleset connects a selector and a block
-  Ruleset_Obj Parser::parse_ruleset(Lookahead lookahead)
+  StyleRuleObj Parser::parse_ruleset(Lookahead lookahead)
   {
     NESTING_GUARD(nestings);
     // inherit is_root from parent block
@@ -524,7 +506,7 @@
     // make sure to move up the the last position
     lex < optional_css_whitespace >(false, true);
     // create the connector object (add parts later)
-    Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate);
+    StyleRuleObj ruleset = SASS_MEMORY_NEW(StyleRule, pstate);
     // parse selector static or as schema to be evaluated later
     if (lookahead.parsable) {
       ruleset->selector(parseSelectorList(false));
@@ -569,9 +551,9 @@
       if (const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, end_of_selector)) {
         // accumulate the preceding segment if the position has advanced
         if (i < p) {
-          std::string parsed(i, p);
+          sass::string parsed(i, p);
           String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
-          pstate += Offset(parsed);
+          pstate.position += Offset(parsed);
           str->update_pstate(pstate);
           schema->append(str);
         }
@@ -584,15 +566,16 @@
           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
         }
         // pass inner expression to the parser to resolve nested interpolations
-        pstate.add(p, p+2);
-        Expression_Obj interpolant = Parser::from_c_str(p+2, j, ctx, traces, pstate).parse_list();
+        LocalOption<const char*> partEnd(end, j);
+        LocalOption<const char*> partBeg(position, p + 2);
+        ExpressionObj interpolant = parse_list();
         // set status on the list expression
         interpolant->is_interpolant(true);
         // schema->has_interpolants(true);
         // add to the string schema
         schema->append(interpolant);
         // advance parser state
-        pstate.add(p+2, j);
+        pstate.position.add(p+2, j);
         // advance position
         i = j;
       }
@@ -601,9 +584,9 @@
       else {
         // make sure to add the last bits of the string up to the end (if any)
         if (i < end_of_selector) {
-          std::string parsed(i, end_of_selector);
+          sass::string parsed(i, end_of_selector);
           String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
-          pstate += Offset(parsed);
+          pstate.position += Offset(parsed);
           str->update_pstate(pstate);
           i = end_of_selector;
           schema->append(str);
@@ -620,7 +603,7 @@
     selector_schema->update_pstate(pstate);
     schema->update_pstate(pstate);
 
-    after_token = before_token = pstate;
+    after_token = before_token = pstate.position;
 
     // return parsed result
     return selector_schema.detach();
@@ -644,9 +627,9 @@
     // lex identifier into `lexed` var
     lex_identifier(); // may error out
     // normalize underscores to hyphens
-    std::string name(Util::normalize_underscores(lexed));
+    sass::string name(Util::normalize_underscores(lexed));
     // create the initial mixin call object
-    Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, {}, {}, {});
+    Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, Arguments_Obj{});
     // parse mandatory arguments
     call->arguments(parse_arguments());
     // parse using and optional block parameters
@@ -677,13 +660,13 @@
   {
     lex < css_comments >(false);
     if (lex< class_name >()) {
-      return SASS_MEMORY_NEW(Class_Selector, pstate, lexed);
+      return SASS_MEMORY_NEW(ClassSelector, pstate, lexed);
     }
     else if (lex< id_name >()) {
-      return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
+      return SASS_MEMORY_NEW(IDSelector, pstate, lexed);
     }
     else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
-      return SASS_MEMORY_NEW(Type_Selector, pstate, lexed);
+      return SASS_MEMORY_NEW(TypeSelector, pstate, lexed);
     }
     else if (peek< pseudo_not >()) {
       return parse_negated_selector2();
@@ -698,7 +681,7 @@
       return parse_attribute_selector();
     }
     else if (lex< placeholder >()) {
-      return SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
+      return SASS_MEMORY_NEW(PlaceholderSelector, pstate, lexed);
     }
     else {
       css_error("Invalid CSS", " after ", ": expected selector, was ");
@@ -707,18 +690,18 @@
     return {};
   }
 
-  Pseudo_Selector_Obj Parser::parse_negated_selector2()
+  PseudoSelectorObj Parser::parse_negated_selector2()
   {
     lex< pseudo_not >();
-    std::string name(lexed);
-    ParserState nsource_position = pstate;
+    sass::string name(lexed);
+    SourceSpan nsource_position = pstate;
     SelectorListObj negated = parseSelectorList(true);
     if (!lex< exactly<')'> >()) {
       error("negated selector is missing ')'");
     }
     name.erase(name.size() - 1);
 
-    Pseudo_Selector* sel = SASS_MEMORY_NEW(Pseudo_Selector, nsource_position, name.substr(1));
+    PseudoSelector* sel = SASS_MEMORY_NEW(PseudoSelector, nsource_position, name.substr(1));
     sel->selector(negated);
     return sel;
   }
@@ -732,7 +715,7 @@
 
     // Lex one or two colon characters
     if (lex<pseudo_prefix>()) {
-      std::string colons(lexed);
+      sass::string colons(lexed);
       // Check if it is a pseudo element
       bool element = colons.size() == 2;
 
@@ -744,16 +727,16 @@
       > >())
       {
 
-        std::string name(lexed);
+        sass::string name(lexed);
         name.erase(name.size() - 1);
-        ParserState p = pstate;
+        SourceSpan p = pstate;
 
         // specially parse nth-child pseudo selectors
         if (lex_css < sequence < binomial, word_boundary >>()) {
-          std::string parsed(lexed); // always compacting binominals (as dart-sass)
+          sass::string parsed(lexed); // always compacting binominals (as dart-sass)
           parsed.erase(std::unique(parsed.begin(), parsed.end(), BothAreSpaces), parsed.end());
           String_Constant_Obj arg = SASS_MEMORY_NEW(String_Constant, pstate, parsed);
-          Pseudo_Selector* pseudo = SASS_MEMORY_NEW(Pseudo_Selector, p, name, element);
+          PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
           if (lex < sequence < css_whitespace, insensitive < of_kwd >>>(false)) {
             pseudo->selector(parseSelectorList(true));
           }
@@ -767,19 +750,19 @@
             css_error("Invalid CSS", " after ", ": expected An+B expression, was ");
           }
 
-          std::string unvendored = Util::unvendor(name);
+          sass::string unvendored = Util::unvendor(name);
 
           if (unvendored == "not" || unvendored == "matches" || unvendored == "current"  || unvendored == "any" || unvendored == "has" || unvendored == "host" || unvendored == "host-context" || unvendored == "slotted") {
              if (SelectorListObj wrapped = parseSelectorList(true)) {
                 if (wrapped && lex_css< exactly<')'> >()) {
-                  Pseudo_Selector* pseudo = SASS_MEMORY_NEW(Pseudo_Selector, p, name, element);
+                  PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
                   pseudo->selector(wrapped);
                   return pseudo;
                 }
               }
           } else {
             String_Schema_Obj arg = parse_css_variable_value();
-            Pseudo_Selector* pseudo = SASS_MEMORY_NEW(Pseudo_Selector, p, name, element);
+            PseudoSelector* pseudo = SASS_MEMORY_NEW(PseudoSelector, p, name, element);
             pseudo->argument(arg);
 
             if (lex_css< exactly<')'> >()) {
@@ -792,7 +775,7 @@
       // EO if pseudo selector
 
       else if (lex < sequence< optional < pseudo_prefix >, identifier > >()) {
-        return SASS_MEMORY_NEW(Pseudo_Selector, pstate, lexed, element);
+        return SASS_MEMORY_NEW(PseudoSelector, pstate, lexed, element);
       }
       else if (lex < pseudo_prefix >()) {
         css_error("Invalid CSS", " after ", ": expected pseudoclass or pseudoelement, was ");
@@ -821,23 +804,23 @@
     return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
   }
 
-  Attribute_Selector_Obj Parser::parse_attribute_selector()
+  AttributeSelectorObj Parser::parse_attribute_selector()
   {
-    ParserState p = pstate;
+    SourceSpan p = pstate;
     if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
-    std::string name(lexed);
+    sass::string name(lexed);
     if (lex_css< re_attr_sensitive_close >()) {
-      return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, {});
+      return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{});
     }
     else if (lex_css< re_attr_insensitive_close >()) {
       char modifier = lexed.begin[0];
-      return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, modifier);
+      return SASS_MEMORY_NEW(AttributeSelector, p, name, "", String_Obj{}, modifier);
     }
     if (!lex_css< alternatives< exact_match, class_match, dash_match,
                                 prefix_match, suffix_match, substring_match > >()) {
       error("invalid operator in attribute selector for " + name);
     }
-    std::string matcher(lexed);
+    sass::string matcher(lexed);
 
     String_Obj value;
     if (lex_css< identifier >()) {
@@ -851,11 +834,11 @@
     }
 
     if (lex_css< re_attr_sensitive_close >()) {
-      return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, 0);
+      return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, 0);
     }
     else if (lex_css< re_attr_insensitive_close >()) {
       char modifier = lexed.begin[0];
-      return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
+      return SASS_MEMORY_NEW(AttributeSelector, p, name, matcher, value, modifier);
     }
     error("unterminated attribute selector for " + name);
     return {}; // to satisfy compilers (error must not return)
@@ -878,12 +861,12 @@
     String_Obj prop;
     bool is_custom_property = false;
     if (lex< sequence< optional< exactly<'*'> >, identifier_schema > >()) {
-      const std::string property(lexed);
+      const sass::string property(lexed);
       is_custom_property = property.compare(0, 2, "--") == 0;
       prop = parse_identifier_schema();
     }
     else if (lex< sequence< optional< exactly<'*'> >, identifier, zero_plus< block_comment > > >()) {
-      const std::string property(lexed);
+      const sass::string property(lexed);
       is_custom_property = property.compare(0, 2, "--") == 0;
       prop = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
     }
@@ -891,7 +874,7 @@
       css_error("Invalid CSS", " after ", ": expected \"}\", was ");
     }
     bool is_indented = true;
-    const std::string property(lexed);
+    const sass::string property(lexed);
     if (!lex_css< one_plus< exactly<':'> > >()) error("property \"" + escape_string(property)  + "\" must be followed by a ':'");
     if (!is_custom_property && match< sequence< optional_css_comments, exactly<';'> > >()) error("style declaration must contain a value");
     if (match< sequence< optional_css_comments, exactly<'{'> > >()) is_indented = false; // don't indent if value is empty
@@ -903,7 +886,7 @@
       return SASS_MEMORY_NEW(Declaration, prop->pstate(), prop, parse_static_value()/*, lex<kwd_important>()*/);
     }
     else {
-      Expression_Obj value;
+      ExpressionObj value;
       Lookahead lookahead = lookahead_for_value(position);
       if (lookahead.found) {
         if (lookahead.has_interpolants) {
@@ -928,10 +911,10 @@
     }
   }
 
-  Expression_Obj Parser::parse_map()
+  ExpressionObj Parser::parse_map()
   {
     NESTING_GUARD(nestings);
-    Expression_Obj key = parse_list();
+    ExpressionObj key = parse_list();
     List_Obj map = SASS_MEMORY_NEW(List, pstate, 0, SASS_HASH);
 
     // it's not a map so return the lexed value as a list value
@@ -943,7 +926,7 @@
       css_error("Invalid CSS", " after ", ": expected \")\", was ");
     }
 
-    Expression_Obj value = parse_space_list();
+    ExpressionObj value = parse_space_list();
 
     map->append(key);
     map->append(value);
@@ -965,14 +948,14 @@
       map->append(value);
     }
 
-    ParserState ps = map->pstate();
-    ps.offset = pstate - ps + pstate.offset;
+    SourceSpan ps = map->pstate();
+    ps.offset = pstate.position - ps.position + pstate.offset;
     map->pstate(ps);
 
     return map;
   }
 
-  Expression_Obj Parser::parse_bracket_list()
+  ExpressionObj Parser::parse_bracket_list()
   {
     NESTING_GUARD(nestings);
     // check if we have an empty list
@@ -986,7 +969,7 @@
     bool has_paren = peek_css< exactly<'('> >() != NULL;
 
     // now try to parse a space list
-    Expression_Obj list = parse_space_list();
+    ExpressionObj list = parse_space_list();
     // if it's a singleton, return it (don't wrap it)
     if (!peek_css< exactly<','> >(position)) {
       List_Obj l = Cast<List>(list);
@@ -1019,14 +1002,14 @@
   // parse list returns either a space separated list,
   // a comma separated list or any bare expression found.
   // so to speak: we unwrap items from lists if possible here!
-  Expression_Obj Parser::parse_list(bool delayed)
+  ExpressionObj Parser::parse_list(bool delayed)
   {
     NESTING_GUARD(nestings);
     return parse_comma_list(delayed);
   }
 
   // will return singletons unwrapped
-  Expression_Obj Parser::parse_comma_list(bool delayed)
+  ExpressionObj Parser::parse_comma_list(bool delayed)
   {
     NESTING_GUARD(nestings);
     // check if we have an empty list
@@ -1038,7 +1021,7 @@
     }
 
     // now try to parse a space list
-    Expression_Obj list = parse_space_list();
+    ExpressionObj list = parse_space_list();
     // if it's a singleton, return it (don't wrap it)
     if (!peek_css< exactly<','> >(position)) {
       // set_delay doesn't apply to list children
@@ -1066,10 +1049,10 @@
   // EO parse_comma_list
 
   // will return singletons unwrapped
-  Expression_Obj Parser::parse_space_list()
+  ExpressionObj Parser::parse_space_list()
   {
     NESTING_GUARD(nestings);
-    Expression_Obj disj1 = parse_disjunction();
+    ExpressionObj disj1 = parse_disjunction();
     // if it's a singleton, return it (don't wrap it)
     if (peek_css< space_list_terminator >(position)
     ) {
@@ -1091,60 +1074,60 @@
   // EO parse_space_list
 
   // parse logical OR operation
-  Expression_Obj Parser::parse_disjunction()
+  ExpressionObj Parser::parse_disjunction()
   {
     NESTING_GUARD(nestings);
     advanceToNextToken();
-    ParserState state(pstate);
+    SourceSpan state(pstate);
     // parse the left hand side conjunction
-    Expression_Obj conj = parse_conjunction();
+    ExpressionObj conj = parse_conjunction();
     // parse multiple right hand sides
-    std::vector<Expression_Obj> operands;
+    sass::vector<ExpressionObj> operands;
     while (lex_css< kwd_or >())
       operands.push_back(parse_conjunction());
     // if it's a singleton, return it directly
     if (operands.size() == 0) return conj;
     // fold all operands into one binary expression
-    Expression_Obj ex = fold_operands(conj, operands, { Sass_OP::OR });
-    state.offset = pstate - state + pstate.offset;
+    ExpressionObj ex = fold_operands(conj, operands, { Sass_OP::OR });
+    state.offset = pstate.position - state.position + pstate.offset;
     ex->pstate(state);
     return ex;
   }
   // EO parse_disjunction
 
   // parse logical AND operation
-  Expression_Obj Parser::parse_conjunction()
+  ExpressionObj Parser::parse_conjunction()
   {
     NESTING_GUARD(nestings);
     advanceToNextToken();
-    ParserState state(pstate);
+    SourceSpan state(pstate);
     // parse the left hand side relation
-    Expression_Obj rel = parse_relation();
+    ExpressionObj rel = parse_relation();
     // parse multiple right hand sides
-    std::vector<Expression_Obj> operands;
+    sass::vector<ExpressionObj> operands;
     while (lex_css< kwd_and >()) {
       operands.push_back(parse_relation());
     }
     // if it's a singleton, return it directly
     if (operands.size() == 0) return rel;
     // fold all operands into one binary expression
-    Expression_Obj ex = fold_operands(rel, operands, { Sass_OP::AND });
-    state.offset = pstate - state + pstate.offset;
+    ExpressionObj ex = fold_operands(rel, operands, { Sass_OP::AND });
+    state.offset = pstate.position - state.position + pstate.offset;
     ex->pstate(state);
     return ex;
   }
   // EO parse_conjunction
 
   // parse comparison operations
-  Expression_Obj Parser::parse_relation()
+  ExpressionObj Parser::parse_relation()
   {
     NESTING_GUARD(nestings);
     advanceToNextToken();
-    ParserState state(pstate);
+    SourceSpan state(pstate);
     // parse the left hand side expression
-    Expression_Obj lhs = parse_expression();
-    std::vector<Expression_Obj> operands;
-    std::vector<Operand> operators;
+    ExpressionObj lhs = parse_expression();
+    sass::vector<ExpressionObj> operands;
+    sass::vector<Operand> operators;
     // if it's a singleton, return it (don't wrap it)
     while (peek< alternatives <
             kwd_eq,
@@ -1177,8 +1160,8 @@
     // correctly set to zero. After folding we also unwrap
     // single nested items. So we cannot set delay on the
     // returned result here, as we have lost nestings ...
-    Expression_Obj ex = fold_operands(lhs, operands, operators);
-    state.offset = pstate - state + pstate.offset;
+    ExpressionObj ex = fold_operands(lhs, operands, operators);
+    state.offset = pstate.position - state.position + pstate.offset;
     ex->pstate(state);
     return ex;
   }
@@ -1189,15 +1172,15 @@
   // called from parse_for_directive
   // called from parse_media_expression
   // parse addition and subtraction operations
-  Expression_Obj Parser::parse_expression()
+  ExpressionObj Parser::parse_expression()
   {
     NESTING_GUARD(nestings);
     advanceToNextToken();
-    ParserState state(pstate);
+    SourceSpan state(pstate);
     // parses multiple add and subtract operations
     // NOTE: make sure that identifiers starting with
     // NOTE: dashes do NOT count as subtract operation
-    Expression_Obj lhs = parse_operators();
+    ExpressionObj lhs = parse_operators();
     // if it's a singleton, return it (don't wrap it)
     if (!(peek_css< exactly<'+'> >(position) ||
           // condition is a bit mysterious, but some combinations should not be counted as operations
@@ -1206,8 +1189,8 @@
           peek< sequence < zero_plus < exactly <'-' > >, identifier > >(position))
     { return lhs; }
 
-    std::vector<Expression_Obj> operands;
-    std::vector<Operand> operators;
+    sass::vector<ExpressionObj> operands;
+    sass::vector<Operand> operators;
     bool left_ws = peek < css_comments >() != NULL;
     while (
       lex_css< exactly<'+'> >() ||
@@ -1226,22 +1209,22 @@
     }
 
     if (operands.size() == 0) return lhs;
-    Expression_Obj ex = fold_operands(lhs, operands, operators);
-    state.offset = pstate - state + pstate.offset;
+    ExpressionObj ex = fold_operands(lhs, operands, operators);
+    state.offset = pstate.position - state.position + pstate.offset;
     ex->pstate(state);
     return ex;
   }
 
   // parse addition and subtraction operations
-  Expression_Obj Parser::parse_operators()
+  ExpressionObj Parser::parse_operators()
   {
     NESTING_GUARD(nestings);
     advanceToNextToken();
-    ParserState state(pstate);
-    Expression_Obj factor = parse_factor();
+    SourceSpan state(pstate);
+    ExpressionObj factor = parse_factor();
     // if it's a singleton, return it (don't wrap it)
-    std::vector<Expression_Obj> operands; // factors
-    std::vector<Operand> operators; // ops
+    sass::vector<ExpressionObj> operands; // factors
+    sass::vector<Operand> operators; // ops
     // lex operations to apply to lhs
     const char* left_ws = peek < css_comments >();
     while (lex_css< class_char< static_ops > >()) {
@@ -1256,8 +1239,8 @@
       left_ws = peek < css_comments >();
     }
     // operands and operators to binary expression
-    Expression_Obj ex = fold_operands(factor, operands, operators);
-    state.offset = pstate - state + pstate.offset;
+    ExpressionObj ex = fold_operands(factor, operands, operators);
+    state.offset = pstate.position - state.position + pstate.offset;
     ex->pstate(state);
     return ex;
   }
@@ -1266,13 +1249,13 @@
 
   // called from parse_operators
   // called from parse_value_schema
-  Expression_Obj Parser::parse_factor()
+  ExpressionObj Parser::parse_factor()
   {
     NESTING_GUARD(nestings);
     lex < css_comments >(false);
     if (lex_css< exactly<'('> >()) {
       // parse_map may return a list
-      Expression_Obj value = parse_map();
+      ExpressionObj value = parse_map();
       // lex the expected closing parenthesis
       if (!lex_css< exactly<')'> >()) error("unclosed parenthesis");
       // expression can be evaluated
@@ -1280,7 +1263,7 @@
     }
     else if (lex_css< exactly<'['> >()) {
       // explicit bracketed
-      Expression_Obj value = parse_bracket_list();
+      ExpressionObj value = parse_bracket_list();
       // lex the expected closing square bracket
       if (!lex_css< exactly<']'> >()) error("unclosed squared bracket");
       return value;
@@ -1342,7 +1325,7 @@
     }
   }
 
-  bool number_has_zero(const std::string& parsed)
+  bool number_has_zero(const sass::string& parsed)
   {
     size_t L = parsed.length();
     return !( (L > 0 && parsed.substr(0, 1) == ".") ||
@@ -1351,7 +1334,7 @@
               (L > 2 && parsed.substr(0, 3) == "-0.") );
   }
 
-  Number* Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
+  Number* Parser::lexed_number(const SourceSpan& pstate, const sass::string& parsed)
   {
     Number* nr = SASS_MEMORY_NEW(Number,
                                     pstate,
@@ -1363,7 +1346,7 @@
     return nr;
   }
 
-  Number* Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
+  Number* Parser::lexed_percentage(const SourceSpan& pstate, const sass::string& parsed)
   {
     Number* nr = SASS_MEMORY_NEW(Number,
                                     pstate,
@@ -1375,17 +1358,17 @@
     return nr;
   }
 
-  Number* Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
+  Number* Parser::lexed_dimension(const SourceSpan& pstate, const sass::string& parsed)
   {
     size_t L = parsed.length();
     size_t num_pos = parsed.find_first_not_of(" \n\r\t");
-    if (num_pos == std::string::npos) num_pos = L;
+    if (num_pos == sass::string::npos) num_pos = L;
     size_t unit_pos = parsed.find_first_not_of("-+0123456789.", num_pos);
     if (parsed[unit_pos] == 'e' && is_number(parsed[unit_pos+1]) ) {
       unit_pos = parsed.find_first_not_of("-+0123456789.", ++ unit_pos);
     }
-    if (unit_pos == std::string::npos) unit_pos = L;
-    const std::string& num = parsed.substr(num_pos, unit_pos - num_pos);
+    if (unit_pos == sass::string::npos) unit_pos = L;
+    const sass::string& num = parsed.substr(num_pos, unit_pos - num_pos);
     Number* nr = SASS_MEMORY_NEW(Number,
                                     pstate,
                                     sass_strtod(num.c_str()),
@@ -1396,18 +1379,18 @@
     return nr;
   }
 
-  Value* Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
+  Value* Parser::lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed)
   {
     Color_RGBA* color = NULL;
     if (parsed[0] != '#') {
       return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
     }
     // chop off the '#'
-    std::string hext(parsed.substr(1));
+    sass::string hext(parsed.substr(1));
     if (parsed.length() == 4) {
-      std::string r(2, parsed[1]);
-      std::string g(2, parsed[2]);
-      std::string b(2, parsed[3]);
+      sass::string r(2, parsed[1]);
+      sass::string g(2, parsed[2]);
+      sass::string b(2, parsed[3]);
       color = SASS_MEMORY_NEW(Color_RGBA,
                                pstate,
                                static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1417,10 +1400,10 @@
                                parsed);
     }
     else if (parsed.length() == 5) {
-      std::string r(2, parsed[1]);
-      std::string g(2, parsed[2]);
-      std::string b(2, parsed[3]);
-      std::string a(2, parsed[4]);
+      sass::string r(2, parsed[1]);
+      sass::string g(2, parsed[2]);
+      sass::string b(2, parsed[3]);
+      sass::string a(2, parsed[4]);
       color = SASS_MEMORY_NEW(Color_RGBA,
                                pstate,
                                static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1430,9 +1413,9 @@
                                parsed);
     }
     else if (parsed.length() == 7) {
-      std::string r(parsed.substr(1,2));
-      std::string g(parsed.substr(3,2));
-      std::string b(parsed.substr(5,2));
+      sass::string r(parsed.substr(1,2));
+      sass::string g(parsed.substr(3,2));
+      sass::string b(parsed.substr(5,2));
       color = SASS_MEMORY_NEW(Color_RGBA,
                                pstate,
                                static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1442,10 +1425,10 @@
                                parsed);
     }
     else if (parsed.length() == 9) {
-      std::string r(parsed.substr(1,2));
-      std::string g(parsed.substr(3,2));
-      std::string b(parsed.substr(5,2));
-      std::string a(parsed.substr(7,2));
+      sass::string r(parsed.substr(1,2));
+      sass::string g(parsed.substr(3,2));
+      sass::string b(parsed.substr(5,2));
+      sass::string a(parsed.substr(7,2));
       color = SASS_MEMORY_NEW(Color_RGBA,
                                pstate,
                                static_cast<double>(strtol(r.c_str(), NULL, 16)),
@@ -1459,7 +1442,7 @@
     return color;
   }
 
-  Value* Parser::color_or_string(const std::string& lexed) const
+  Value* Parser::color_or_string(const sass::string& lexed) const
   {
     if (auto color = name_to_color(lexed)) {
       auto c = SASS_MEMORY_NEW(Color_RGBA, color);
@@ -1473,7 +1456,7 @@
   }
 
   // parse one value for a list
-  Expression_Obj Parser::parse_value()
+  ExpressionObj Parser::parse_value()
   {
     lex< css_comments >(false);
     if (lex< ampersand >())
@@ -1560,7 +1543,7 @@
                     find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
 
     if (!p) {
-      String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end), 0, false, false, true, css);
+      String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(i, chunk.end), 0, false, false, true, css);
       if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
       return str_quoted;
     }
@@ -1573,7 +1556,7 @@
       if (p) {
         if (i < p) {
           // accumulate the preceding segment if it's nonempty
-          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p), css));
+          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p), css));
         }
         // we need to skip anything inside strings
         // create a new target in parser/prelexer
@@ -1583,7 +1566,9 @@
         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p + 2, chunk.end); // find the closing brace
         if (j) { --j;
           // parse the interpolant and accumulate it
-          Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list();
+          LocalOption<const char*> partEnd(end, j);
+          LocalOption<const char*> partBeg(position, p + 2);
+          ExpressionObj interp_node = parse_list();
           interp_node->is_interpolant(true);
           schema->append(interp_node);
           i = j;
@@ -1595,7 +1580,7 @@
       }
       else { // no interpolants left; add the last segment if nonempty
         // check if we need quotes here (was not sure after merge)
-        if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, chunk.end), css));
+        if (i < chunk.end) schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, chunk.end), css));
         break;
       }
       ++ i;
@@ -1607,7 +1592,7 @@
   String_Schema_Obj Parser::parse_css_variable_value()
   {
     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
-    std::vector<char> brackets;
+    sass::vector<char> brackets;
     while (true) {
       if (
         (brackets.empty() && lex< css_variable_top_level_value >(false)) ||
@@ -1615,7 +1600,7 @@
       ) {
         Token str(lexed);
         schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
-      } else if (Expression_Obj tok = lex_interpolation()) {
+      } else if (ExpressionObj tok = lex_interpolation()) {
         if (String_Schema* s = Cast<String_Schema>(tok)) {
           if (s->empty()) break;
           schema->concat(s);
@@ -1623,7 +1608,7 @@
           schema->append(tok);
         }
       } else if (lex< quoted_string >()) {
-        Expression_Obj tok = parse_string();
+        ExpressionObj tok = parse_string();
         if (tok.isNull()) break;
         if (String_Schema* s = Cast<String_Schema>(tok)) {
           if (s->empty()) break;
@@ -1634,18 +1619,18 @@
       } else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
         const char opening_bracket = *(position - 1);
         brackets.push_back(opening_bracket);
-        schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, opening_bracket)));
+        schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, opening_bracket)));
       } else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
         if (brackets.empty()) break;
         const char closing_bracket = *(match - 1);
         if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
-          std::string message = ": expected \"";
+          sass::string message = ": expected \"";
           message += Util::closing_bracket_for(brackets.back());
           message += "\", was ";
           css_error("Invalid CSS", " after ", message);
         }
         lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
-        schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, closing_bracket)));
+        schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(1, closing_bracket)));
         brackets.pop_back();
       } else {
         break;
@@ -1653,7 +1638,7 @@
     }
 
     if (!brackets.empty()) {
-      std::string message = ": expected \"";
+      sass::string message = ": expected \"";
       message += Util::closing_bracket_for(brackets.back());
       message += "\", was ";
       css_error("Invalid CSS", " after ", message);
@@ -1663,7 +1648,7 @@
     return schema.detach();
   }
 
-  Value_Obj Parser::parse_static_value()
+  ValueObj Parser::parse_static_value()
   {
     lex< static_value >();
     Token str(lexed);
@@ -1690,7 +1675,7 @@
     // see if there any interpolants
     const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(str.begin, str.end);
     if (!p) {
-      return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
+      return SASS_MEMORY_NEW(String_Quoted, pstate, sass::string(str.begin, str.end));
     }
 
     String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
@@ -1698,7 +1683,7 @@
       p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
       if (p) {
         if (i < p) {
-          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, p))); // accumulate the preceding segment if it's nonempty
+          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, p))); // accumulate the preceding segment if it's nonempty
         }
         if (peek < sequence < optional_spaces, exactly<rbrace> > >(p+2)) { position = p+2;
           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
@@ -1706,7 +1691,9 @@
         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, str.end); // find the closing brace
         if (j) {
           // parse the interpolant and accumulate it
-          Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list();
+          LocalOption<const char*> partEnd(end, j);
+          LocalOption<const char*> partBeg(position, p + 2);
+          ExpressionObj interp_node = parse_list();
           interp_node->is_interpolant(true);
           schema->append(interp_node);
           i = j;
@@ -1718,7 +1705,7 @@
       }
       else { // no interpolants left; add the last segment if nonempty
         if (i < str.end) {
-          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(i, str.end)));
+          schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(i, str.end)));
         }
         break;
       }
@@ -1739,7 +1726,7 @@
     kwd_arg->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
     if (peek< variable >()) kwd_arg->append(parse_list());
     else if (lex< number >()) {
-      std::string parsed(lexed);
+      sass::string parsed(lexed);
       Util::normalize_decimals(parsed);
       kwd_arg->append(lexed_number(parsed));
     }
@@ -1779,7 +1766,7 @@
         if (peek< exactly< rbrace > >()) {
           css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
         }
-        Expression_Obj ex;
+        ExpressionObj ex;
         if (lex< re_static_expression >()) {
           ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
         } else {
@@ -1815,7 +1802,7 @@
       }
       // lex (normalized) variable
       else if (lex< variable >()) {
-        std::string name(Util::normalize_underscores(lexed));
+        sass::string name(Util::normalize_underscores(lexed));
         schema->append(SASS_MEMORY_NEW(Variable, pstate, name));
       }
       // lex percentage value
@@ -1847,7 +1834,7 @@
       ++num_items;
     }
     if (position != stop) {
-      schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(position, stop)));
+      schema->append(SASS_MEMORY_NEW(String_Constant, pstate, sass::string(position, stop)));
       position = stop;
     }
     end = ee;
@@ -1863,7 +1850,7 @@
     // see if there any interpolants
     const char* p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(id.begin, id.end);
     if (!p) {
-      return SASS_MEMORY_NEW(String_Constant, pstate, std::string(id.begin, id.end));
+      return SASS_MEMORY_NEW(String_Constant, pstate, sass::string(id.begin, id.end));
     }
 
     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
@@ -1884,7 +1871,9 @@
         const char* j = skip_over_scopes< exactly<hash_lbrace>, exactly<rbrace> >(p+2, id.end); // find the closing brace
         if (j) {
           // parse the interpolant and accumulate it
-          Expression_Obj interp_node = Parser::from_token(Token(p+2, j), ctx, traces, pstate, source).parse_list(DELAYED);
+          LocalOption<const char*> partEnd(end, j);
+          LocalOption<const char*> partBeg(position, p + 2);
+          ExpressionObj interp_node = parse_list(DELAYED);
           interp_node->is_interpolant(true);
           schema->append(interp_node);
           // schema->has_interpolants(true);
@@ -1911,10 +1900,10 @@
   Function_Call_Obj Parser::parse_calc_function()
   {
     lex< identifier >();
-    std::string name(lexed);
-    ParserState call_pos = pstate;
+    sass::string name(lexed);
+    SourceSpan call_pos = pstate;
     lex< exactly<'('> >();
-    ParserState arg_pos = pstate;
+    SourceSpan arg_pos = pstate;
     const char* arg_beg = position;
     parse_list();
     const char* arg_end = position;
@@ -1931,20 +1920,20 @@
 
   String_Obj Parser::parse_url_function_string()
   {
-    std::string prefix("");
+    sass::string prefix("");
     if (lex< uri_prefix >()) {
-      prefix = std::string(lexed);
+      prefix = sass::string(lexed);
     }
 
     lex < optional_spaces >();
     String_Obj url_string = parse_url_function_argument();
 
-    std::string suffix("");
+    sass::string suffix("");
     if (lex< real_uri_suffix >()) {
-      suffix = std::string(lexed);
+      suffix = sass::string(lexed);
     }
 
-    std::string uri("");
+    sass::string uri("");
     if (url_string) {
       uri = url_string->to_string({ NESTED, 5 });
     }
@@ -1956,7 +1945,7 @@
       res->append(SASS_MEMORY_NEW(String_Constant, pstate, suffix));
       return res;
     } else {
-      std::string res = prefix + uri + suffix;
+      sass::string res = prefix + uri + suffix;
       return SASS_MEMORY_NEW(String_Constant, pstate, res);
     }
   }
@@ -1965,7 +1954,7 @@
   {
     const char* p = position;
 
-    std::string uri("");
+    sass::string uri("");
     if (lex< real_uri_value >(false)) {
       uri = lexed.to_string();
     }
@@ -1981,7 +1970,7 @@
       return parse_interpolated_chunk(Token(p, position));
     }
     else if (uri != "") {
-      std::string res = Util::rtrim(uri);
+      sass::string res = Util::rtrim(uri);
       return SASS_MEMORY_NEW(String_Constant, pstate, res);
     }
 
@@ -1991,12 +1980,12 @@
   Function_Call_Obj Parser::parse_function_call()
   {
     lex< identifier >();
-    std::string name(lexed);
+    sass::string name(lexed);
 
     if (Util::normalize_underscores(name) == "content-exists" && stack.back() != Scope::Mixin)
     { error("Cannot call content-exists() except within a mixin."); }
 
-    ParserState call_pos = pstate;
+    SourceSpan call_pos = pstate;
     Arguments_Obj args = parse_arguments();
     return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
   }
@@ -2004,7 +1993,7 @@
   Function_Call_Obj Parser::parse_function_call_schema()
   {
     String_Obj name = parse_identifier_schema();
-    ParserState source_position_of_call = pstate;
+    SourceSpan source_position_of_call = pstate;
     Arguments_Obj args = parse_arguments();
 
     return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
@@ -2012,7 +2001,7 @@
 
   Content_Obj Parser::parse_content_directive()
   {
-    ParserState call_pos = pstate;
+    SourceSpan call_pos = pstate;
     Arguments_Obj args = parse_arguments();
 
     return SASS_MEMORY_NEW(Content, call_pos, args);
@@ -2021,9 +2010,9 @@
   If_Obj Parser::parse_if_directive(bool else_if)
   {
     stack.push_back(Scope::Control);
-    ParserState if_source_position = pstate;
+    SourceSpan if_source_position = pstate;
     bool root = block_stack.back()->is_root();
-    Expression_Obj predicate = parse_list();
+    ExpressionObj predicate = parse_list();
     Block_Obj block = parse_block(root);
     Block_Obj alternative;
 
@@ -2040,23 +2029,23 @@
     return SASS_MEMORY_NEW(If, if_source_position, predicate, block, alternative);
   }
 
-  For_Obj Parser::parse_for_directive()
+  ForRuleObj Parser::parse_for_directive()
   {
     stack.push_back(Scope::Control);
-    ParserState for_source_position = pstate;
+    SourceSpan for_source_position = pstate;
     bool root = block_stack.back()->is_root();
     lex_variable();
-    std::string var(Util::normalize_underscores(lexed));
+    sass::string var(Util::normalize_underscores(lexed));
     if (!lex< kwd_from >()) error("expected 'from' keyword in @for directive");
-    Expression_Obj lower_bound = parse_expression();
+    ExpressionObj lower_bound = parse_expression();
     bool inclusive = false;
     if (lex< kwd_through >()) inclusive = true;
     else if (lex< kwd_to >()) inclusive = false;
     else                  error("expected 'through' or 'to' keyword in @for directive");
-    Expression_Obj upper_bound = parse_expression();
+    ExpressionObj upper_bound = parse_expression();
     Block_Obj body = parse_block(root);
     stack.pop_back();
-    return SASS_MEMORY_NEW(For, for_source_position, var, lower_bound, upper_bound, body, inclusive);
+    return SASS_MEMORY_NEW(ForRule, for_source_position, var, lower_bound, upper_bound, body, inclusive);
   }
 
   // helper to parse a var token
@@ -2072,7 +2061,7 @@
       css_error("Invalid CSS", " after ", ": expected identifier, was ");
     }
     // return object
-    return token;
+    return lexed;
   }
   // helper to parse identifier
   Token Parser::lex_identifier()
@@ -2082,15 +2071,15 @@
       css_error("Invalid CSS", " after ", ": expected identifier, was ");
     }
     // return object
-    return token;
+    return lexed;
   }
 
-  Each_Obj Parser::parse_each_directive()
+  EachRuleObj Parser::parse_each_directive()
   {
     stack.push_back(Scope::Control);
-    ParserState each_source_position = pstate;
+    SourceSpan each_source_position = pstate;
     bool root = block_stack.back()->is_root();
-    std::vector<std::string> vars;
+    sass::vector<sass::string> vars;
     lex_variable();
     vars.push_back(Util::normalize_underscores(lexed));
     while (lex< exactly<','> >()) {
@@ -2098,21 +2087,21 @@
       vars.push_back(Util::normalize_underscores(lexed));
     }
     if (!lex< kwd_in >()) error("expected 'in' keyword in @each directive");
-    Expression_Obj list = parse_list();
+    ExpressionObj list = parse_list();
     Block_Obj body = parse_block(root);
     stack.pop_back();
-    return SASS_MEMORY_NEW(Each, each_source_position, vars, list, body);
+    return SASS_MEMORY_NEW(EachRule, each_source_position, vars, list, body);
   }
 
   // called after parsing `kwd_while_directive`
-  While_Obj Parser::parse_while_directive()
+  WhileRuleObj Parser::parse_while_directive()
   {
     stack.push_back(Scope::Control);
     bool root = block_stack.back()->is_root();
     // create the initial while call object
-    While_Obj call = SASS_MEMORY_NEW(While, pstate, {}, {});
+    WhileRuleObj call = SASS_MEMORY_NEW(WhileRule, pstate, ExpressionObj{}, Block_Obj{});
     // parse mandatory predicate
-    Expression_Obj predicate = parse_list();
+    ExpressionObj predicate = parse_list();
     List_Obj l = Cast<List>(predicate);
     if (!predicate || (l && !l->length())) {
       css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ", false);
@@ -2127,9 +2116,9 @@
   }
 
 
-  std::vector<CssMediaQuery_Obj> Parser::parseCssMediaQueries()
+  sass::vector<CssMediaQuery_Obj> Parser::parseCssMediaQueries()
   {
-    std::vector<CssMediaQuery_Obj> result;
+    sass::vector<CssMediaQuery_Obj> result;
     do {
       if (auto query = parseCssMediaQuery()) {
         result.push_back(query);
@@ -2138,12 +2127,12 @@
     return result;
   }
 
-  std::string Parser::parseIdentifier()
+  sass::string Parser::parseIdentifier()
   {
     if (lex < identifier >(false)) {
-      return std::string(lexed);
+      return sass::string(lexed);
     }
-    return std::string();
+    return sass::string();
   }
 
   CssMediaQuery_Obj Parser::parseCssMediaQuery()
@@ -2154,14 +2143,14 @@
     // Check if any tokens are to parse
     if (!peek_css<exactly<'('>>()) {
 
-      std::string token1(parseIdentifier());
+      sass::string token1(parseIdentifier());
       lex<css_comments>(false);
 
       if (token1.empty()) {
         return {};
       }
 
-      std::string token2(parseIdentifier());
+      sass::string token2(parseIdentifier());
       lex<css_comments>(false);
 
       if (Util::equalsLiteral("and", token2)) {
@@ -2187,7 +2176,7 @@
 
     }
 
-    std::vector<std::string> queries;
+    sass::vector<sass::string> queries;
 
     do {
       lex<css_comments>(false);
@@ -2195,7 +2184,7 @@
       if (lex<exactly<'('>>()) {
         // In dart sass parser returns a pure string
         if (lex < skip_over_scopes < exactly < '(' >, exactly < ')' > > >()) {
-          std::string decl("(" + std::string(lexed));
+          sass::string decl("(" + sass::string(lexed));
           queries.push_back(decl);
         }
         // Should be: parseDeclarationValue;
@@ -2247,15 +2236,17 @@
     if (lex < kwd_not >()) { media_query->is_negated(true); lex < css_comments >(false); }
     else if (lex < kwd_only >()) { media_query->is_restricted(true); lex < css_comments >(false); }
 
-    if (lex < identifier_schema >())  media_query->media_type(parse_identifier_schema());
-    else if (lex < identifier >())    media_query->media_type(parse_interpolated_chunk(lexed));
+    if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
+    else if (lex < identifier >())   media_query->media_type(parse_interpolated_chunk(lexed));
     else                             media_query->append(parse_media_expression());
 
     while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
     if (lex < identifier_schema >()) {
-      String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
-      schema->append(media_query->media_type());
-      schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
+      String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
+      if (media_query->media_type()) {
+        schema->append(media_query->media_type());
+        schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
+      }
       schema->append(parse_identifier_schema());
       media_query->media_type(schema);
     }
@@ -2266,21 +2257,21 @@
     return media_query;
   }
 
-  Media_Query_Expression_Obj Parser::parse_media_expression()
+  Media_Query_ExpressionObj Parser::parse_media_expression()
   {
     if (lex < identifier_schema >()) {
       String_Obj ss = parse_identifier_schema();
-      return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, {}, true);
+      return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, ExpressionObj{}, true);
     }
     if (!lex_css< exactly<'('> >()) {
       error("media query expression must begin with '('");
     }
-    Expression_Obj feature;
+    ExpressionObj feature;
     if (peek_css< exactly<')'> >()) {
       error("media feature required in media query expression");
     }
     feature = parse_expression();
-    Expression_Obj expression;
+    ExpressionObj expression;
     if (lex_css< exactly<':'> >()) {
       expression = parse_list(DELAYED);
     }
@@ -2292,11 +2283,11 @@
 
   // lexed after `kwd_supports_directive`
   // these are very similar to media blocks
-  Supports_Block_Obj Parser::parse_supports_directive()
+  SupportsRuleObj Parser::parse_supports_directive()
   {
-    Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/true);
+    SupportsConditionObj cond = parse_supports_condition(/*top_level=*/true);
     // create the ast node object for the support queries
-    Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
+    SupportsRuleObj query = SASS_MEMORY_NEW(SupportsRule, pstate, cond);
     // additional block is mandatory
     // parse inner block
     query->block(parse_block());
@@ -2306,43 +2297,43 @@
 
   // parse one query operation
   // may encounter nested queries
-  Supports_Condition_Obj Parser::parse_supports_condition(bool top_level)
+  SupportsConditionObj Parser::parse_supports_condition(bool top_level)
   {
     lex < css_whitespace >();
-    Supports_Condition_Obj cond;
+    SupportsConditionObj cond;
     if ((cond = parse_supports_negation())) return cond;
     if ((cond = parse_supports_operator(top_level))) return cond;
     if ((cond = parse_supports_interpolation())) return cond;
     return cond;
   }
 
-  Supports_Condition_Obj Parser::parse_supports_negation()
+  SupportsConditionObj Parser::parse_supports_negation()
   {
     if (!lex < kwd_not >()) return {};
-    Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
-    return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
+    SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
+    return SASS_MEMORY_NEW(SupportsNegation, pstate, cond);
   }
 
-  Supports_Condition_Obj Parser::parse_supports_operator(bool top_level)
+  SupportsConditionObj Parser::parse_supports_operator(bool top_level)
   {
-    Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
+    SupportsConditionObj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
     if (cond.isNull()) return {};
 
     while (true) {
-      Supports_Operator::Operand op = Supports_Operator::OR;
-      if (lex < kwd_and >()) { op = Supports_Operator::AND; }
+      SupportsOperation::Operand op = SupportsOperation::OR;
+      if (lex < kwd_and >()) { op = SupportsOperation::AND; }
       else if(!lex < kwd_or >()) { break; }
 
       lex < css_whitespace >();
-      Supports_Condition_Obj right = parse_supports_condition_in_parens(/*parens_required=*/true);
+      SupportsConditionObj right = parse_supports_condition_in_parens(/*parens_required=*/true);
 
-      // Supports_Condition* cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition*>(cond));
-      cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op);
+      // SupportsCondition* cc = SASS_MEMORY_NEW(SupportsCondition, *static_cast<SupportsCondition*>(cond));
+      cond = SASS_MEMORY_NEW(SupportsOperation, pstate, cond, right, op);
     }
     return cond;
   }
 
-  Supports_Condition_Obj Parser::parse_supports_interpolation()
+  SupportsConditionObj Parser::parse_supports_interpolation()
   {
     if (!lex < interpolant >()) return {};
 
@@ -2354,17 +2345,17 @@
 
   // TODO: This needs some major work. Although feature conditions
   // look like declarations their semantics differ significantly
-  Supports_Condition_Obj Parser::parse_supports_declaration()
+  SupportsConditionObj Parser::parse_supports_declaration()
   {
-    Supports_Condition* cond;
+    SupportsCondition* cond;
     // parse something declaration like
-    Expression_Obj feature = parse_expression();
-    Expression_Obj expression;
+    ExpressionObj feature = parse_expression();
+    ExpressionObj expression;
     if (lex_css< exactly<':'> >()) {
       expression = parse_list(DELAYED);
     }
     if (!feature || !expression) error("@supports condition expected declaration");
-    cond = SASS_MEMORY_NEW(Supports_Declaration,
+    cond = SASS_MEMORY_NEW(SupportsDeclaration,
                      feature->pstate(),
                      feature,
                      expression);
@@ -2372,9 +2363,9 @@
     return cond;
   }
 
-  Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required)
+  SupportsConditionObj Parser::parse_supports_condition_in_parens(bool parens_required)
   {
-    Supports_Condition_Obj interp = parse_supports_interpolation();
+    SupportsConditionObj interp = parse_supports_interpolation();
     if (interp != nullptr) return interp;
 
     if (!lex < exactly <'('> >()) {
@@ -2386,7 +2377,7 @@
     }
     lex < css_whitespace >();
 
-    Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/false);
+    SupportsConditionObj cond = parse_supports_condition(/*top_level=*/false);
     if (cond.isNull()) cond = parse_supports_declaration();
     if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
 
@@ -2394,10 +2385,10 @@
     return cond;
   }
 
-  At_Root_Block_Obj Parser::parse_at_root_block()
+  AtRootRuleObj Parser::parse_at_root_block()
   {
     stack.push_back(Scope::AtRoot);
-    ParserState at_source_position = pstate;
+    SourceSpan at_source_position = pstate;
     Block_Obj body;
     At_Root_Query_Obj expr;
     Lookahead lookahead_result;
@@ -2409,11 +2400,11 @@
       body = parse_block(true);
     }
     else if ((lookahead_result = lookahead_for_selector(position)).found) {
-      Ruleset_Obj r = parse_ruleset(lookahead_result);
+      StyleRuleObj r = parse_ruleset(lookahead_result);
       body = SASS_MEMORY_NEW(Block, r->pstate(), 1, true);
       body->append(r);
     }
-    At_Root_Block_Obj at_root = SASS_MEMORY_NEW(At_Root_Block, at_source_position, body);
+    AtRootRuleObj at_root = SASS_MEMORY_NEW(AtRootRule, at_source_position, body);
     if (!expr.isNull()) at_root->expression(expr);
     stack.pop_back();
     return at_root;
@@ -2427,9 +2418,9 @@
       css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
     }
 
-    Expression_Obj feature = parse_list();
+    ExpressionObj feature = parse_list();
     if (!lex_css< exactly<':'> >()) error("style declaration must contain a value");
-    Expression_Obj expression = parse_list();
+    ExpressionObj expression = parse_list();
     List_Obj value = SASS_MEMORY_NEW(List, feature->pstate(), 1);
 
     if (expression->concrete_type() == Expression::LIST) {
@@ -2445,9 +2436,9 @@
     return cond;
   }
 
-  Directive_Obj Parser::parse_directive()
+  AtRuleObj Parser::parse_directive()
   {
-    Directive_Obj directive = SASS_MEMORY_NEW(Directive, pstate, lexed);
+    AtRuleObj directive = SASS_MEMORY_NEW(AtRule, pstate, lexed);
     String_Schema_Obj val = parse_almost_any_value();
     // strip left and right if they are of type string
     directive->value(val);
@@ -2457,7 +2448,7 @@
     return directive;
   }
 
-  Expression_Obj Parser::lex_interpolation()
+  ExpressionObj Parser::lex_interpolation()
   {
     if (lex < interpolant >(true) != NULL) {
       return parse_interpolated_chunk(lexed, true);
@@ -2465,21 +2456,21 @@
     return {};
   }
 
-  Expression_Obj Parser::lex_interp_uri()
+  ExpressionObj Parser::lex_interp_uri()
   {
     // create a string schema by lexing optional interpolations
     return lex_interp< re_string_uri_open, re_string_uri_close >();
   }
 
-  Expression_Obj Parser::lex_interp_string()
+  ExpressionObj Parser::lex_interp_string()
   {
-    Expression_Obj rv;
+    ExpressionObj rv;
     if ((rv = lex_interp< re_string_double_open, re_string_double_close >())) return rv;
     if ((rv = lex_interp< re_string_single_open, re_string_single_close >())) return rv;
     return rv;
   }
 
-  Expression_Obj Parser::lex_almost_any_value_chars()
+  ExpressionObj Parser::lex_almost_any_value_chars()
   {
     const char* match =
     lex <
@@ -2532,9 +2523,9 @@
     return {};
   }
 
-  Expression_Obj Parser::lex_almost_any_value_token()
+  ExpressionObj Parser::lex_almost_any_value_token()
   {
-    Expression_Obj rv;
+    ExpressionObj rv;
     if (*position == 0) return {};
     if ((rv = lex_almost_any_value_chars())) return rv;
     // if ((rv = lex_block_comment())) return rv;
@@ -2553,7 +2544,7 @@
     String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
     if (*position == 0) return {};
     lex < spaces >(false);
-    Expression_Obj token = lex_almost_any_value_token();
+    ExpressionObj token = lex_almost_any_value_token();
     if (!token) return {};
     schema->append(token);
     if (*position == 0) {
@@ -2572,7 +2563,7 @@
     return schema.detach();
   }
 
-  Warning_Obj Parser::parse_warning()
+  WarningRuleObj Parser::parse_warning()
   {
     if (stack.back() != Scope::Root &&
         stack.back() != Scope::Function &&
@@ -2581,10 +2572,10 @@
         stack.back() != Scope::Rules) {
       error("Illegal nesting: Only properties may be nested beneath properties.");
     }
-    return SASS_MEMORY_NEW(Warning, pstate, parse_list(DELAYED));
+    return SASS_MEMORY_NEW(WarningRule, pstate, parse_list(DELAYED));
   }
 
-  Error_Obj Parser::parse_error()
+  ErrorRuleObj Parser::parse_error()
   {
     if (stack.back() != Scope::Root &&
         stack.back() != Scope::Function &&
@@ -2593,10 +2584,10 @@
         stack.back() != Scope::Rules) {
       error("Illegal nesting: Only properties may be nested beneath properties.");
     }
-    return SASS_MEMORY_NEW(Error, pstate, parse_list(DELAYED));
+    return SASS_MEMORY_NEW(ErrorRule, pstate, parse_list(DELAYED));
   }
 
-  Debug_Obj Parser::parse_debug()
+  DebugRuleObj Parser::parse_debug()
   {
     if (stack.back() != Scope::Root &&
         stack.back() != Scope::Function &&
@@ -2605,7 +2596,7 @@
         stack.back() != Scope::Rules) {
       error("Illegal nesting: Only properties may be nested beneath properties.");
     }
-    return SASS_MEMORY_NEW(Debug, pstate, parse_list(DELAYED));
+    return SASS_MEMORY_NEW(DebugRule, pstate, parse_list(DELAYED));
   }
 
   Return_Obj Parser::parse_return_directive()
@@ -2760,53 +2751,53 @@
   void Parser::read_bom()
   {
     size_t skip = 0;
-    std::string encoding;
+    sass::string encoding;
     bool utf_8 = false;
-    switch ((unsigned char) source[0]) {
+    switch ((unsigned char)position[0]) {
     case 0xEF:
-      skip = check_bom_chars(source, end, utf_8_bom, 3);
+      skip = check_bom_chars(position, end, utf_8_bom, 3);
       encoding = "UTF-8";
       utf_8 = true;
       break;
     case 0xFE:
-      skip = check_bom_chars(source, end, utf_16_bom_be, 2);
+      skip = check_bom_chars(position, end, utf_16_bom_be, 2);
       encoding = "UTF-16 (big endian)";
       break;
     case 0xFF:
-      skip = check_bom_chars(source, end, utf_16_bom_le, 2);
-      skip += (skip ? check_bom_chars(source, end, utf_32_bom_le, 4) : 0);
+      skip = check_bom_chars(position, end, utf_16_bom_le, 2);
+      skip += (skip ? check_bom_chars(position, end, utf_32_bom_le, 4) : 0);
       encoding = (skip == 2 ? "UTF-16 (little endian)" : "UTF-32 (little endian)");
       break;
     case 0x00:
-      skip = check_bom_chars(source, end, utf_32_bom_be, 4);
+      skip = check_bom_chars(position, end, utf_32_bom_be, 4);
       encoding = "UTF-32 (big endian)";
       break;
     case 0x2B:
-      skip = check_bom_chars(source, end, utf_7_bom_1, 4)
-           | check_bom_chars(source, end, utf_7_bom_2, 4)
-           | check_bom_chars(source, end, utf_7_bom_3, 4)
-           | check_bom_chars(source, end, utf_7_bom_4, 4)
-           | check_bom_chars(source, end, utf_7_bom_5, 5);
+      skip = check_bom_chars(position, end, utf_7_bom_1, 4)
+           | check_bom_chars(position, end, utf_7_bom_2, 4)
+           | check_bom_chars(position, end, utf_7_bom_3, 4)
+           | check_bom_chars(position, end, utf_7_bom_4, 4)
+           | check_bom_chars(position, end, utf_7_bom_5, 5);
       encoding = "UTF-7";
       break;
     case 0xF7:
-      skip = check_bom_chars(source, end, utf_1_bom, 3);
+      skip = check_bom_chars(position, end, utf_1_bom, 3);
       encoding = "UTF-1";
       break;
     case 0xDD:
-      skip = check_bom_chars(source, end, utf_ebcdic_bom, 4);
+      skip = check_bom_chars(position, end, utf_ebcdic_bom, 4);
       encoding = "UTF-EBCDIC";
       break;
     case 0x0E:
-      skip = check_bom_chars(source, end, scsu_bom, 3);
+      skip = check_bom_chars(position, end, scsu_bom, 3);
       encoding = "SCSU";
       break;
     case 0xFB:
-      skip = check_bom_chars(source, end, bocu_1_bom, 3);
+      skip = check_bom_chars(position, end, bocu_1_bom, 3);
       encoding = "BOCU-1";
       break;
     case 0x84:
-      skip = check_bom_chars(source, end, gb_18030_bom, 4);
+      skip = check_bom_chars(position, end, gb_18030_bom, 4);
       encoding = "GB-18030";
       break;
     default: break;
@@ -2826,7 +2817,7 @@
   }
 
 
-  Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, Operand op)
+  ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, Operand op)
   {
     for (size_t i = 0, S = operands.size(); i < S; ++i) {
       base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), op, base, operands[i]);
@@ -2834,7 +2825,7 @@
     return base;
   }
 
-  Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
+  ExpressionObj Parser::fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, sass::vector<Operand>& ops, size_t i)
   {
     if (String_Schema* schema = Cast<String_Schema>(base)) {
       // return schema;
@@ -2850,7 +2841,7 @@
           || (ops[0].operand == Sass_OP::LTE)
           || (ops[0].operand == Sass_OP::GTE)
         )) {
-          Expression_Obj rhs = fold_operands(operands[i], operands, ops, i + 1);
+          ExpressionObj rhs = fold_operands(operands[i], operands, ops, i + 1);
           rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[0], schema, rhs);
           return rhs;
         }
@@ -2858,12 +2849,19 @@
       }
     }
 
+    if (operands.size() > Constants::MaxCallStack) {
+        // XXX: this is never hit via spec tests
+        sass::ostream stm;
+        stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
+        error(stm.str());
+    }
+
     for (size_t S = operands.size(); i < S; ++i) {
       if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
         if (schema->has_interpolants()) {
           if (i + 1 < S) {
             // this whole branch is never hit via spec tests
-            Expression_Obj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
+            ExpressionObj rhs = fold_operands(operands[i+1], operands, ops, i + 2);
             rhs = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], schema, rhs);
             base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, rhs);
             return base;
@@ -2889,28 +2887,14 @@
     return base;
   }
 
-  void Parser::error(std::string msg, Position pos)
+  void Parser::error(sass::string msg)
   {
-    Position p(pos.line ? pos : before_token);
-    ParserState pstate(path, source, p, Offset(0, 0));
-    // `pstate.src` may not outlive stack unwind so we must copy it.
-    // This is needed since we often parse dynamically generated code,
-    // e.g. for interpolations, and we normally don't want to keep this
-    // memory around after we parsed the AST tree successfully. Only on
-    // errors we want to preserve them for better error reporting.
-    char *src_copy = sass_copy_c_string(pstate.src);
-    pstate.src = src_copy;
     traces.push_back(Backtrace(pstate));
-    throw Exception::InvalidSass(pstate, traces, msg, src_copy);
-  }
-
-  void Parser::error(std::string msg)
-  {
-    error(msg, pstate);
+    throw Exception::InvalidSass(pstate, traces, msg);
   }
 
   // print a css parsing error with actual context information from parsed source
-  void Parser::css_error(const std::string& msg, const std::string& prefix, const std::string& middle, const bool trim)
+  void Parser::css_error(const sass::string& msg, const sass::string& prefix, const sass::string& middle, const bool trim)
   {
     int max_len = 18;
     const char* end = this->end;
@@ -2919,13 +2903,13 @@
     if (!pos) pos = position;
 
     const char* last_pos(pos);
-    if (last_pos > source) {
-      utf8::prior(last_pos, source);
+    if (last_pos > begin) {
+      utf8::prior(last_pos, begin);
     }
     // backup position to last significant char
-    while (trim && last_pos > source && last_pos < end) {
+    while (trim && last_pos > begin&& last_pos < end) {
       if (!Util::ascii_isspace(static_cast<unsigned char>(*last_pos))) break;
-      utf8::prior(last_pos, source);
+      utf8::prior(last_pos, begin);
     }
 
     bool ellipsis_left = false;
@@ -2934,9 +2918,9 @@
 
     if (*pos_left) utf8::next(pos_left, end);
     if (*end_left) utf8::next(end_left, end);
-    while (pos_left > source) {
+    while (pos_left > begin) {
       if (utf8::distance(pos_left, end_left) >= max_len) {
-        utf8::prior(pos_left, source);
+        utf8::prior(pos_left, begin);
         ellipsis_left = *(pos_left) != '\n' &&
                         *(pos_left) != '\r';
         utf8::next(pos_left, end);
@@ -2944,13 +2928,13 @@
       }
 
       const char* prev = pos_left;
-      utf8::prior(prev, source);
+      utf8::prior(prev, begin);
       if (*prev == '\r') break;
       if (*prev == '\n') break;
       pos_left = prev;
     }
-    if (pos_left < source) {
-      pos_left = source;
+    if (pos_left < begin) {
+      pos_left = begin;
     }
 
     bool ellipsis_right = false;
@@ -2968,14 +2952,12 @@
     }
     // if (*end_right == 0) end_right ++;
 
-    std::string left(pos_left, end_left);
-    std::string right(pos_right, end_right);
+    sass::string left(pos_left, end_left);
+    sass::string right(pos_right, end_right);
     size_t left_subpos = left.size() > 15 ? left.size() - 15 : 0;
     size_t right_subpos = right.size() > 15 ? right.size() - 15 : 0;
     if (left_subpos && ellipsis_left) left = ellipsis + left.substr(left_subpos);
     if (right_subpos && ellipsis_right) right = right.substr(right_subpos) + ellipsis;
-    // Hotfix when source is null, probably due to interpolation parsing!?
-    if (source == NULL || *source == 0) source = pstate.src;
     // now pass new message to the more generic error function
     error(msg + prefix + quote(left) + middle + quote(right));
   }
diff --git a/libsass/src/parser.hpp b/libsass/src/parser.hpp
--- a/libsass/src/parser.hpp
+++ b/libsass/src/parser.hpp
@@ -13,6 +13,7 @@
 #include "context.hpp"
 #include "position.hpp"
 #include "prelexer.hpp"
+#include "source.hpp"
 
 #ifndef MAX_NESTING
 // Note that this limit is not an exact science
@@ -34,41 +35,31 @@
 
 namespace Sass {
 
-  class Parser : public ParserState {
+  class Parser : public SourceSpan {
   public:
 
     enum Scope { Root, Mixin, Function, Media, Control, Properties, Rules, AtRoot };
 
     Context& ctx;
-    std::vector<Block_Obj> block_stack;
-    std::vector<Scope> stack;
-    const char* source;
+    sass::vector<Block_Obj> block_stack;
+    sass::vector<Scope> stack;
+    SourceDataObj source;
+    const char* begin;
     const char* position;
     const char* end;
-    Position before_token;
-    Position after_token;
-    ParserState pstate;
+    Offset before_token;
+    Offset after_token;
+    SourceSpan pstate;
     Backtraces traces;
     size_t indentation;
     size_t nestings;
     bool allow_parent;
-
     Token lexed;
 
-    Parser(Context& ctx, const ParserState& pstate, Backtraces traces, bool allow_parent = true)
-    : ParserState(pstate), ctx(ctx), block_stack(), stack(0),
-      source(0), position(0), end(0), before_token(pstate), after_token(pstate),
-      pstate(pstate), traces(traces), indentation(0), nestings(0), allow_parent(allow_parent)
-    {
-      stack.push_back(Scope::Root);
-    }
+    Parser(SourceData* source, Context& ctx, Backtraces, bool allow_parent = true);
 
-    // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
-    static Parser from_c_str(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
-    static Parser from_c_str(const char* beg, const char* end, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
-    static Parser from_token(Token t, Context& ctx, Backtraces, ParserState pstate = ParserState("[TOKEN]"), const char* source = nullptr);
     // special static parsers to convert strings into certain selectors
-    static SelectorListObj parse_selector(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[SELECTOR]"), const char* source = nullptr, bool allow_parent = true);
+    static SelectorListObj parse_selector(SourceData* source, Context& ctx, Backtraces, bool allow_parent = true);
 
 #ifdef __clang__
 
@@ -84,7 +75,7 @@
 
 
     // skip current token and next whitespace
-    // moves ParserState right before next token
+    // moves SourceSpan right before next token
     void advanceToNextToken();
 
     bool peek_newline(const char* start = 0);
@@ -189,7 +180,7 @@
       after_token.add(it_before_token, it_after_token);
 
       // ToDo: could probably do this incremental on original object (API wants offset?)
-      pstate = ParserState(path, source, lexed, before_token, after_token - before_token);
+      pstate = SourceSpan(source, before_token, after_token - before_token);
 
       // advance internal char iterator
       return position = it_after_token;
@@ -206,9 +197,9 @@
       Token prev = lexed;
       // store previous pointer
       const char* oldpos = position;
-      Position bt = before_token;
-      Position at = after_token;
-      ParserState op = pstate;
+      Offset bt = before_token;
+      Offset at = after_token;
+      SourceSpan op = pstate;
       // throw away comments
       // update srcmap position
       lex < Prelexer::css_comments >();
@@ -240,13 +231,12 @@
 
 #endif
 
-    void error(std::string msg);
-    void error(std::string msg, Position pos);
+    void error(sass::string msg);
     // generate message with given and expected sample
     // text before and in the middle are configurable
-    void css_error(const std::string& msg,
-                   const std::string& prefix = " after ",
-                   const std::string& middle = ", was: ",
+    void css_error(const sass::string& msg,
+                   const sass::string& prefix = " after ",
+                   const sass::string& middle = ", was: ",
                    const bool trim = true);
     void read_bom();
 
@@ -259,34 +249,34 @@
     Arguments_Obj parse_arguments();
     Argument_Obj parse_argument();
     Assignment_Obj parse_assignment();
-    Ruleset_Obj parse_ruleset(Lookahead lookahead);
+    StyleRuleObj parse_ruleset(Lookahead lookahead);
     SelectorListObj parseSelectorList(bool chroot);
     ComplexSelectorObj parseComplexSelector(bool chroot);
     Selector_Schema_Obj parse_selector_schema(const char* end_of_selector, bool chroot);
     CompoundSelectorObj parseCompoundSelector();
     SimpleSelectorObj parse_simple_selector();
-    Pseudo_Selector_Obj parse_negated_selector2();
+    PseudoSelectorObj parse_negated_selector2();
     Expression* parse_binominal();
     SimpleSelectorObj parse_pseudo_selector();
-    Attribute_Selector_Obj parse_attribute_selector();
+    AttributeSelectorObj parse_attribute_selector();
     Block_Obj parse_block(bool is_root = false);
     Block_Obj parse_css_block(bool is_root = false);
     bool parse_block_nodes(bool is_root = false);
     bool parse_block_node(bool is_root = false);
 
     Declaration_Obj parse_declaration();
-    Expression_Obj parse_map();
-    Expression_Obj parse_bracket_list();
-    Expression_Obj parse_list(bool delayed = false);
-    Expression_Obj parse_comma_list(bool delayed = false);
-    Expression_Obj parse_space_list();
-    Expression_Obj parse_disjunction();
-    Expression_Obj parse_conjunction();
-    Expression_Obj parse_relation();
-    Expression_Obj parse_expression();
-    Expression_Obj parse_operators();
-    Expression_Obj parse_factor();
-    Expression_Obj parse_value();
+    ExpressionObj parse_map();
+    ExpressionObj parse_bracket_list();
+    ExpressionObj parse_list(bool delayed = false);
+    ExpressionObj parse_comma_list(bool delayed = false);
+    ExpressionObj parse_space_list();
+    ExpressionObj parse_disjunction();
+    ExpressionObj parse_conjunction();
+    ExpressionObj parse_relation();
+    ExpressionObj parse_expression();
+    ExpressionObj parse_operators();
+    ExpressionObj parse_factor();
+    ExpressionObj parse_value();
     Function_Call_Obj parse_calc_function();
     Function_Call_Obj parse_function_call();
     Function_Call_Obj parse_function_call_schema();
@@ -294,49 +284,49 @@
     String_Obj parse_url_function_argument();
     String_Obj parse_interpolated_chunk(Token, bool constant = false, bool css = true);
     String_Obj parse_string();
-    Value_Obj parse_static_value();
+    ValueObj parse_static_value();
     String_Schema_Obj parse_css_variable_value();
     String_Obj parse_ie_property();
     String_Obj parse_ie_keyword_arg();
     String_Schema_Obj parse_value_schema(const char* stop);
     String_Obj parse_identifier_schema();
     If_Obj parse_if_directive(bool else_if = false);
-    For_Obj parse_for_directive();
-    Each_Obj parse_each_directive();
-    While_Obj parse_while_directive();
+    ForRuleObj parse_for_directive();
+    EachRuleObj parse_each_directive();
+    WhileRuleObj parse_while_directive();
     MediaRule_Obj parseMediaRule();
-    std::vector<CssMediaQuery_Obj> parseCssMediaQueries();
-    std::string parseIdentifier();
+    sass::vector<CssMediaQuery_Obj> parseCssMediaQueries();
+    sass::string parseIdentifier();
     CssMediaQuery_Obj parseCssMediaQuery();
     Return_Obj parse_return_directive();
     Content_Obj parse_content_directive();
     void parse_charset_directive();
     List_Obj parse_media_queries();
     Media_Query_Obj parse_media_query();
-    Media_Query_Expression_Obj parse_media_expression();
-    Supports_Block_Obj parse_supports_directive();
-    Supports_Condition_Obj parse_supports_condition(bool top_level);
-    Supports_Condition_Obj parse_supports_negation();
-    Supports_Condition_Obj parse_supports_operator(bool top_level);
-    Supports_Condition_Obj parse_supports_interpolation();
-    Supports_Condition_Obj parse_supports_declaration();
-    Supports_Condition_Obj parse_supports_condition_in_parens(bool parens_required);
-    At_Root_Block_Obj parse_at_root_block();
+    Media_Query_ExpressionObj parse_media_expression();
+    SupportsRuleObj parse_supports_directive();
+    SupportsConditionObj parse_supports_condition(bool top_level);
+    SupportsConditionObj parse_supports_negation();
+    SupportsConditionObj parse_supports_operator(bool top_level);
+    SupportsConditionObj parse_supports_interpolation();
+    SupportsConditionObj parse_supports_declaration();
+    SupportsConditionObj parse_supports_condition_in_parens(bool parens_required);
+    AtRootRuleObj parse_at_root_block();
     At_Root_Query_Obj parse_at_root_query();
     String_Schema_Obj parse_almost_any_value();
-    Directive_Obj parse_directive();
-    Warning_Obj parse_warning();
-    Error_Obj parse_error();
-    Debug_Obj parse_debug();
+    AtRuleObj parse_directive();
+    WarningRuleObj parse_warning();
+    ErrorRuleObj parse_error();
+    DebugRuleObj parse_debug();
 
-    Value* color_or_string(const std::string& lexed) const;
+    Value* color_or_string(const sass::string& lexed) const;
 
     // be more like ruby sass
-    Expression_Obj lex_almost_any_value_token();
-    Expression_Obj lex_almost_any_value_chars();
-    Expression_Obj lex_interp_string();
-    Expression_Obj lex_interp_uri();
-    Expression_Obj lex_interpolation();
+    ExpressionObj lex_almost_any_value_token();
+    ExpressionObj lex_almost_any_value_chars();
+    ExpressionObj lex_interp_string();
+    ExpressionObj lex_interp_uri();
+    ExpressionObj lex_interpolation();
 
     // these will throw errors
     Token lex_variable();
@@ -348,28 +338,28 @@
     Lookahead lookahead_for_selector(const char* start = 0);
     Lookahead lookahead_for_include(const char* start = 0);
 
-    Expression_Obj fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, Operand op);
-    Expression_Obj fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i = 0);
+    ExpressionObj fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, Operand op);
+    ExpressionObj fold_operands(ExpressionObj base, sass::vector<ExpressionObj>& operands, sass::vector<Operand>& ops, size_t i = 0);
 
-    void throw_syntax_error(std::string message, size_t ln = 0);
-    void throw_read_error(std::string message, size_t ln = 0);
+    void throw_syntax_error(sass::string message, size_t ln = 0);
+    void throw_read_error(sass::string message, size_t ln = 0);
 
 
     template <Prelexer::prelexer open, Prelexer::prelexer close>
-    Expression_Obj lex_interp()
+    ExpressionObj lex_interp()
     {
       if (lex < open >(false)) {
         String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
-        // std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
+        // std::cerr << "LEX [[" << sass::string(lexed) << "]]\n";
         schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
         if (position[0] == '#' && position[1] == '{') {
-          Expression_Obj itpl = lex_interpolation();
+          ExpressionObj itpl = lex_interpolation();
           if (!itpl.isNull()) schema->append(itpl);
           while (lex < close >(false)) {
-            // std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
+            // std::cerr << "LEX [[" << sass::string(lexed) << "]]\n";
             schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
             if (position[0] == '#' && position[1] == '{') {
-              Expression_Obj itpl = lex_interpolation();
+              ExpressionObj itpl = lex_interpolation();
               if (!itpl.isNull()) schema->append(itpl);
             } else {
               return schema;
@@ -383,15 +373,15 @@
     }
 
   public:
-    static Number* lexed_number(const ParserState& pstate, const std::string& parsed);
-    static Number* lexed_dimension(const ParserState& pstate, const std::string& parsed);
-    static Number* lexed_percentage(const ParserState& pstate, const std::string& parsed);
-    static Value* lexed_hex_color(const ParserState& pstate, const std::string& parsed);
+    static Number* lexed_number(const SourceSpan& pstate, const sass::string& parsed);
+    static Number* lexed_dimension(const SourceSpan& pstate, const sass::string& parsed);
+    static Number* lexed_percentage(const SourceSpan& pstate, const sass::string& parsed);
+    static Value* lexed_hex_color(const SourceSpan& pstate, const sass::string& parsed);
   private:
-    Number* lexed_number(const std::string& parsed) { return lexed_number(pstate, parsed); };
-    Number* lexed_dimension(const std::string& parsed) { return lexed_dimension(pstate, parsed); };
-    Number* lexed_percentage(const std::string& parsed) { return lexed_percentage(pstate, parsed); };
-    Value* lexed_hex_color(const std::string& parsed) { return lexed_hex_color(pstate, parsed); };
+    Number* lexed_number(const sass::string& parsed) { return lexed_number(pstate, parsed); };
+    Number* lexed_dimension(const sass::string& parsed) { return lexed_dimension(pstate, parsed); };
+    Number* lexed_percentage(const sass::string& parsed) { return lexed_percentage(pstate, parsed); };
+    Value* lexed_hex_color(const sass::string& parsed) { return lexed_hex_color(pstate, parsed); };
 
     static const char* re_attr_sensitive_close(const char* src);
     static const char* re_attr_insensitive_close(const char* src);
diff --git a/libsass/src/parser_selectors.cpp b/libsass/src/parser_selectors.cpp
--- a/libsass/src/parser_selectors.cpp
+++ b/libsass/src/parser_selectors.cpp
@@ -139,16 +139,16 @@
       {
         // parent selector only allowed at start
         // upcoming Sass may allow also trailing
-        ParserState state(pstate);
-        std::string found("&");
+        SourceSpan state(pstate);
+        sass::string found("&");
         if (lex < identifier >()) {
-          found += std::string(lexed);
+          found += sass::string(lexed);
         }
-        std::string sel(seq->hasRealParent() ? "&" : "");
+        sass::string sel(seq->hasRealParent() ? "&" : "");
         if (!seq->empty()) { sel = seq->last()->to_string({ NESTED, 5 }); }
         // ToDo: parser should throw parser exceptions
         error("Invalid CSS after \"" + sel + "\": expected \"{\", was \"" + found + "\"\n\n"
-          "\"" + found + "\" may only be used at the beginning of a compound selector.", state);
+          "\"" + found + "\" may only be used at the beginning of a compound selector.");
       }
       // parse functional
       else if (match < re_functional >())
@@ -159,7 +159,7 @@
       // parse type selector
       else if (lex< re_type_selector >(false))
       {
-        seq->append(SASS_MEMORY_NEW(Type_Selector, pstate, lexed));
+        seq->append(SASS_MEMORY_NEW(TypeSelector, pstate, lexed));
       }
       // peek for abort conditions
       else if (peek< spaces >()) break;
diff --git a/libsass/src/permutate.hpp b/libsass/src/permutate.hpp
--- a/libsass/src/permutate.hpp
+++ b/libsass/src/permutate.hpp
@@ -7,37 +7,42 @@
 
   // Returns a list of all possible paths through the given lists.
   //
-  // For example, given `[[1, 2], [3, 4], [5]]`, this returns:
+  // For example, given `[[1, 2], [3, 4], [5, 6]]`, this returns:
   //
   // ```
   // [[1, 3, 5],
   //  [2, 3, 5],
   //  [1, 4, 5],
-  //  [2, 4, 5]]
+  //  [2, 4, 5],
+  //  [1, 3, 6],
+  //  [2, 3, 6],
+  //  [1, 4, 6],
+  //  [2, 4, 6]]
   // ```
   // 
   // Note: called `paths` in dart-sass
   template <class T>
-  std::vector<std::vector<T>> permutate(
-    const std::vector<std::vector<T>>& in)
+  sass::vector<sass::vector<T>> permutate(
+    const sass::vector<sass::vector<T>>& in)
   {
 
     size_t L = in.size(), n = 0;
 
+    if (L == 0) return {};
     // Exit early if any entry is empty
     for (size_t i = 0; i < L; i += 1) {
       if (in[i].size() == 0) return {};
     }
 
     size_t* state = new size_t[L + 1];
-    std::vector<std::vector<T>> out;
+    sass::vector<sass::vector<T>> out;
 
     // First initialize all states for every permutation group
     for (size_t i = 0; i < L; i += 1) {
       state[i] = in[i].size() - 1;
     }
     while (true) {
-      std::vector<T> perm;
+      sass::vector<T> perm;
       // Create one permutation for state
       for (size_t i = 0; i < L; i += 1) {
         perm.push_back(in.at(i).at(in[i].size() - state[i] - 1));
@@ -73,19 +78,40 @@
   }
   // EO permutate
 
-  // ToDo: this variant is used in resolve_parent_refs
+  // ToDo: this variant is used in resolveParentSelectors
+  // Returns a list of all possible paths through the given lists.
+  //
+  // For example, given `[[1, 2], [3, 4], [5, 6]]`, this returns:
+  //
+  // ```
+  // [[1, 3, 5],
+  //  [1, 3, 6],
+  //  [1, 4, 5],
+  //  [1, 4, 6],
+  //  [2, 3, 5],
+  //  [2, 3, 6],
+  //  [2, 4, 5],
+  //  [2, 4, 6]]
+  // ```
+  // 
   template <class T>
-  std::vector<std::vector<T>>
-    permutateAlt(const std::vector<std::vector<T>>& in) {
+  sass::vector<sass::vector<T>>
+    permutateAlt(const sass::vector<sass::vector<T>>& in) {
 
     size_t L = in.size();
     size_t n = in.size() - 1;
+
+    if (L == 0) return {};
+    // Exit early if any entry is empty
+    for (size_t i = 0; i < L; i += 1) {
+      if (in[i].size() == 0) return {};
+    }
+
     size_t* state = new size_t[L];
-    std::vector< std::vector<T>> out;
+    sass::vector<sass::vector<T>> out;
 
     // First initialize all states for every permutation group
     for (size_t i = 0; i < L; i += 1) {
-      if (in[i].size() == 0) return {};
       state[i] = in[i].size() - 1;
     }
 
@@ -96,7 +122,7 @@
       { // std::cerr << state[p] << " "; }
       // std::cerr << "\n";
       */
-      std::vector<T> perm;
+      sass::vector<T> perm;
       // Create one permutation for state
       for (size_t i = 0; i < L; i += 1) {
         perm.push_back(in.at(i).at(in[i].size() - state[i] - 1));
@@ -104,10 +130,8 @@
       // Current group finished
       if (state[n] == 0) {
         // Find position of next decrement
-        while (n > 0 && state[--n] == 0)
-        {
+        while (n > 0 && state[--n] == 0) {}
 
-        }
         // Check for end condition
         if (state[n] != 0) {
           // Decrease next on the left side
diff --git a/libsass/src/plugins.cpp b/libsass/src/plugins.cpp
--- a/libsass/src/plugins.cpp
+++ b/libsass/src/plugins.cpp
@@ -44,18 +44,18 @@
     if (!strcmp(our_version, "[na]")) return false;
 
     // find the position of the second dot
-    size_t pos = std::string(our_version).find('.', 0);
-    if (pos != std::string::npos) pos = std::string(our_version).find('.', pos + 1);
+    size_t pos = sass::string(our_version).find('.', 0);
+    if (pos != sass::string::npos) pos = sass::string(our_version).find('.', pos + 1);
 
     // if we do not have two dots we fallback to compare complete string
-    if (pos == std::string::npos) { return strcmp(their_version, our_version) ? 0 : 1; }
+    if (pos == sass::string::npos) { return strcmp(their_version, our_version) ? 0 : 1; }
     // otherwise only compare up to the second dot (major versions)
     else { return strncmp(their_version, our_version, pos) ? 0 : 1; }
 
   }
 
   // load one specific plugin
-  bool Plugins::load_plugin (const std::string& path)
+  bool Plugins::load_plugin (const sass::string& path)
   {
 
     typedef const char* (*__plugin_version__)(void);
@@ -112,7 +112,7 @@
 
   }
 
-  size_t Plugins::load_plugins(const std::string& path)
+  size_t Plugins::load_plugins(const sass::string& path)
   {
 
     // count plugins
@@ -126,7 +126,7 @@
         // use wchar (utf16)
         WIN32_FIND_DATAW data;
         // trailing slash is guaranteed
-        std::string globsrch(path + "*.dll");
+        sass::string globsrch(path + "*.dll");
         // convert to wide chars (utf16) for system call
         std::wstring wglobsrch(UTF_8::convert_to_utf16(globsrch));
         HANDLE hFile = FindFirstFileW(wglobsrch.c_str(), &data);
@@ -140,7 +140,7 @@
           try
           {
             // the system will report the filenames with wide chars (utf16)
-            std::string entry = UTF_8::convert_from_utf16(data.cFileName);
+            sass::string entry = UTF_8::convert_from_utf16(data.cFileName);
             // check if file ending matches exactly
             if (!ends_with(entry, ".dll")) continue;
             // load the plugin and increase counter
diff --git a/libsass/src/plugins.hpp b/libsass/src/plugins.hpp
--- a/libsass/src/plugins.hpp
+++ b/libsass/src/plugins.hpp
@@ -36,19 +36,19 @@
 
     public: // methods
       // load one specific plugin
-      bool load_plugin(const std::string& path);
+      bool load_plugin(const sass::string& path);
       // load all plugins from a directory
-      size_t load_plugins(const std::string& path);
+      size_t load_plugins(const sass::string& path);
 
     public: // public accessors
-      const std::vector<Sass_Importer_Entry> get_headers(void) { return headers; }
-      const std::vector<Sass_Importer_Entry> get_importers(void) { return importers; }
-      const std::vector<Sass_Function_Entry> get_functions(void) { return functions; }
+      const sass::vector<Sass_Importer_Entry> get_headers(void) { return headers; }
+      const sass::vector<Sass_Importer_Entry> get_importers(void) { return importers; }
+      const sass::vector<Sass_Function_Entry> get_functions(void) { return functions; }
 
     private: // private vars
-      std::vector<Sass_Importer_Entry> headers;
-      std::vector<Sass_Importer_Entry> importers;
-      std::vector<Sass_Function_Entry> functions;
+      sass::vector<Sass_Importer_Entry> headers;
+      sass::vector<Sass_Importer_Entry> importers;
+      sass::vector<Sass_Function_Entry> functions;
 
   };
 
diff --git a/libsass/src/position.cpp b/libsass/src/position.cpp
--- a/libsass/src/position.cpp
+++ b/libsass/src/position.cpp
@@ -3,6 +3,7 @@
 #include "sass.hpp"
 
 #include "position.hpp"
+#include "source.hpp"
 
 namespace Sass {
 
@@ -18,7 +19,7 @@
     *this = inc(string, string + strlen(string));
   }
 
-  Offset::Offset(const std::string& text)
+  Offset::Offset(const sass::string& text)
   : line(0), column(0)
   {
     *this = inc(text.c_str(), text.c_str() + text.size());
@@ -56,7 +57,7 @@
         // skip over 10xxxxxx
         // is 1st bit not set
         if ((chr & 128) == 0) {
-          // regular ascii char
+          // regular ASCII char
           column += 1;
         }
         // is 2nd bit not set
@@ -117,14 +118,11 @@
   : Offset(line, column), file(file) { }
 
 
-  ParserState::ParserState(const char* path, const char* src, const size_t file)
-  : Position(file, 0, 0), path(path), src(src), offset(0, 0), token() { }
-
-  ParserState::ParserState(const char* path, const char* src, const Position& position, Offset offset)
-  : Position(position), path(path), src(src), offset(offset), token() { }
+  SourceSpan::SourceSpan(const char* path)
+  : source(SASS_MEMORY_NEW(SynthFile, path)), position(0, 0), offset(0, 0) { }
 
-  ParserState::ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset)
-  : Position(position), path(path), src(src), offset(offset), token(token) { }
+  SourceSpan::SourceSpan(SourceDataObj source, const Offset& position, const Offset& offset)
+    : source(source), position(position), offset(offset) { }
 
   Position Position::add(const char* begin, const char* end)
   {
@@ -163,22 +161,5 @@
   {
     return Offset(line - off.line, off.line == line ? column - off.column : column);
   }
-
-  /* not used anymore - remove?
-  std::ostream& operator<<(std::ostream& strm, const Offset& off)
-  {
-    if (off.line == string::npos) strm << "-1:"; else strm << off.line << ":";
-    if (off.column == string::npos) strm << "-1"; else strm << off.column;
-    return strm;
-  } */
-
-  /* not used anymore - remove?
-  std::ostream& operator<<(std::ostream& strm, const Position& pos)
-  {
-    if (pos.file != string::npos) strm << pos.file << ":";
-    if (pos.line == string::npos) strm << "-1:"; else strm << pos.line << ":";
-    if (pos.column == string::npos) strm << "-1"; else strm << pos.column;
-    return strm;
-  } */
 
 }
diff --git a/libsass/src/position.hpp b/libsass/src/position.hpp
--- a/libsass/src/position.hpp
+++ b/libsass/src/position.hpp
@@ -3,7 +3,8 @@
 
 #include <string>
 #include <cstring>
-// #include <iostream>
+#include "source_data.hpp"
+#include "ast_fwd_decl.hpp"
 
 namespace Sass {
 
@@ -13,7 +14,7 @@
     public: // c-tor
       Offset(const char chr);
       Offset(const char* string);
-      Offset(const std::string& text);
+      Offset(const sass::string& text);
       Offset(const size_t line, const size_t column);
 
       // return new position, incremented by the given string
@@ -85,37 +86,59 @@
     : prefix(p), begin(b), end(e) { }
 
     size_t length()    const { return end - begin; }
-    std::string ws_before() const { return std::string(prefix, begin); }
-    std::string to_string() const { return std::string(begin, end); }
-    std::string time_wspace() const {
-      std::string str(to_string());
-      std::string whitespaces(" \t\f\v\n\r");
+    sass::string ws_before() const { return sass::string(prefix, begin); }
+    sass::string to_string() const { return sass::string(begin, end); }
+    sass::string time_wspace() const {
+      sass::string str(to_string());
+      sass::string whitespaces(" \t\f\v\n\r");
       return str.erase(str.find_last_not_of(whitespaces)+1);
     }
 
     operator bool()        { return begin && end && begin >= end; }
-    operator std::string() { return to_string(); }
+    operator sass::string() { return to_string(); }
 
     bool operator==(Token t)  { return to_string() == t.to_string(); }
   };
 
-  class ParserState : public Position {
+  class SourceSpan {
 
-    public: // c-tor
-      ParserState(const char* path, const char* src = 0, const size_t file = std::string::npos);
-      ParserState(const char* path, const char* src, const Position& position, Offset offset = Offset(0, 0));
-      ParserState(const char* path, const char* src, const Token& token, const Position& position, Offset offset = Offset(0, 0));
+    public:
 
-    public: // down casts
-      Offset off() { return *this; }
-      Position pos() { return *this; }
-      ParserState pstate() { return *this; }
+      SourceSpan(const char* path);
 
-    public:
-      const char* path;
-      const char* src;
+      SourceSpan(SourceDataObj source,
+        const Offset& position = Offset(0, 0),
+        const Offset& offset = Offset(0, 0));
+
+      const char* getPath() const {
+        return source->getPath();
+      }
+
+      const char* getRawData() const {
+        return source->getRawData();
+      }
+
+      Offset getPosition() const {
+        return position;
+      }
+
+      size_t getLine() const {
+        return position.line + 1;
+      }
+
+      size_t getColumn() const {
+        return position.column + 1;
+      }
+
+      size_t getSrcId() const {
+        return source == nullptr
+          ? std::string::npos
+          : source->getSrcId();
+      }
+
+      SourceDataObj source;
+      Offset position;
       Offset offset;
-      Token token;
 
   };
 
diff --git a/libsass/src/remove_placeholders.cpp b/libsass/src/remove_placeholders.cpp
--- a/libsass/src/remove_placeholders.cpp
+++ b/libsass/src/remove_placeholders.cpp
@@ -18,7 +18,7 @@
 
     void Remove_Placeholders::remove_placeholders(SimpleSelector* simple)
     {
-      if (Pseudo_Selector * pseudo = simple->getPseudoSelector()) {
+      if (PseudoSelector * pseudo = simple->getPseudoSelector()) {
         if (pseudo->selector()) remove_placeholders(pseudo->selector());
       }
     }
@@ -60,7 +60,7 @@
       if (rule->block()) operator()(rule->block());
     }
 
-    void Remove_Placeholders::operator()(Ruleset* r)
+    void Remove_Placeholders::operator()(StyleRule* r)
     {
       if (SelectorListObj sl = r->selector()) {
         // Set the new placeholder selector list
@@ -73,12 +73,12 @@
       }
     }
 
-    void Remove_Placeholders::operator()(Supports_Block* m)
+    void Remove_Placeholders::operator()(SupportsRule* m)
     {
       if (m->block()) operator()(m->block());
     }
 
-    void Remove_Placeholders::operator()(Directive* a)
+    void Remove_Placeholders::operator()(AtRule* a)
     {
       if (a->block()) a->block()->perform(this);
     }
diff --git a/libsass/src/remove_placeholders.hpp b/libsass/src/remove_placeholders.hpp
--- a/libsass/src/remove_placeholders.hpp
+++ b/libsass/src/remove_placeholders.hpp
@@ -21,10 +21,10 @@
     ~Remove_Placeholders() { }
 
     void operator()(Block*);
-    void operator()(Ruleset*);
+    void operator()(StyleRule*);
     void operator()(CssMediaRule*);
-    void operator()(Supports_Block*);
-    void operator()(Directive*);
+    void operator()(SupportsRule*);
+    void operator()(AtRule*);
 
     // ignore missed types
     template <typename U>
diff --git a/libsass/src/sass.cpp b/libsass/src/sass.cpp
--- a/libsass/src/sass.cpp
+++ b/libsass/src/sass.cpp
@@ -17,9 +17,9 @@
 namespace Sass {
 
   // helper to convert string list to vector
-  std::vector<std::string> list2vec(struct string_list* cur)
+  sass::vector<sass::string> list2vec(struct string_list* cur)
   {
-    std::vector<std::string> list;
+    sass::vector<sass::string> list;
     while (cur) {
       list.push_back(cur->string);
       cur = cur->next;
@@ -46,6 +46,7 @@
 
   char* ADDCALL sass_copy_c_string(const char* str)
   {
+    if (str == nullptr) return nullptr;
     size_t len = strlen(str) + 1;
     char* cpy = (char*) sass_alloc_memory(len);
     std::memcpy(cpy, str, len);
@@ -61,14 +62,14 @@
   // caller must free the returned memory
   char* ADDCALL sass_string_quote (const char *str, const char quote_mark)
   {
-    std::string quoted = quote(str, quote_mark);
+    sass::string quoted = quote(str, quote_mark);
     return sass_copy_c_string(quoted.c_str());
   }
 
   // caller must free the returned memory
   char* ADDCALL sass_string_unquote (const char *str)
   {
-    std::string unquoted = unquote(str);
+    sass::string unquoted = unquote(str);
     return sass_copy_c_string(unquoted.c_str());
   }
 
@@ -76,13 +77,13 @@
   {
     // get the last import entry to get current base directory
     Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
-    const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
+    const sass::vector<sass::string>& incs = compiler->cpp_ctx->include_paths;
     // create the vector with paths to lookup
-    std::vector<std::string> paths(1 + incs.size());
+    sass::vector<sass::string> paths(1 + incs.size());
     paths.push_back(File::dir_name(import->abs_path));
     paths.insert( paths.end(), incs.begin(), incs.end() );
     // now resolve the file path relative to lookup paths
-    std::string resolved(File::find_include(file, paths));
+    sass::string resolved(File::find_include(file, paths));
     return sass_copy_c_string(resolved.c_str());
   }
 
@@ -90,13 +91,13 @@
   {
     // get the last import entry to get current base directory
     Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
-    const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
+    const sass::vector<sass::string>& incs = compiler->cpp_ctx->include_paths;
     // create the vector with paths to lookup
-    std::vector<std::string> paths(1 + incs.size());
+    sass::vector<sass::string> paths(1 + incs.size());
     paths.push_back(File::dir_name(import->abs_path));
     paths.insert( paths.end(), incs.begin(), incs.end() );
     // now resolve the file path relative to lookup paths
-    std::string resolved(File::find_file(file, paths));
+    sass::string resolved(File::find_file(file, paths));
     return sass_copy_c_string(resolved.c_str());
   }
 
@@ -105,8 +106,8 @@
   // this has the original resolve logic for sass include
   char* ADDCALL sass_find_include (const char* file, struct Sass_Options* opt)
   {
-    std::vector<std::string> vec(list2vec(opt->include_paths));
-    std::string resolved(File::find_include(file, vec));
+    sass::vector<sass::string> vec(list2vec(opt->include_paths));
+    sass::string resolved(File::find_include(file, vec));
     return sass_copy_c_string(resolved.c_str());
   }
 
@@ -114,8 +115,8 @@
   // Incs array has to be null terminated!
   char* ADDCALL sass_find_file (const char* file, struct Sass_Options* opt)
   {
-    std::vector<std::string> vec(list2vec(opt->include_paths));
-    std::string resolved(File::find_file(file, vec));
+    sass::vector<sass::string> vec(list2vec(opt->include_paths));
+    sass::string resolved(File::find_file(file, vec));
     return sass_copy_c_string(resolved.c_str());
   }
 
@@ -136,7 +137,7 @@
 namespace Sass {
 
   // helper to aid dreaded MSVC debug mode
-  char* sass_copy_string(std::string str)
+  char* sass_copy_string(sass::string str)
   {
     // In MSVC the following can lead to segfault:
     // sass_copy_c_string(stream.str().c_str());
diff --git a/libsass/src/sass.hpp b/libsass/src/sass.hpp
--- a/libsass/src/sass.hpp
+++ b/libsass/src/sass.hpp
@@ -11,7 +11,7 @@
 #pragma warning(disable : 4005)
 #endif
 
-// aplies to MSVC and MinGW
+// applies to MSVC and MinGW
 #ifdef _WIN32
 // we do not want the ERROR macro
 # ifndef NOGDI
@@ -48,13 +48,17 @@
 #endif
 
 
-// include C-API header
+// Include C-API header
 #include "sass/base.h"
 
+// Include allocator
+#include "memory.hpp"
+
 // For C++ helper
 #include <string>
+#include <vector>
 
-// output behaviours
+// output behavior
 namespace Sass {
 
   // create some C++ aliases for the most used options
@@ -69,11 +73,11 @@
 
   // helper to aid dreaded MSVC debug mode
   // see implementation for more details
-  char* sass_copy_string(std::string str);
+  char* sass_copy_string(sass::string str);
 
 }
 
-// input behaviours
+// input behaviors
 enum Sass_Input_Style {
   SASS_CONTEXT_NULL,
   SASS_CONTEXT_FILE,
diff --git a/libsass/src/sass_context.cpp b/libsass/src/sass_context.cpp
--- a/libsass/src/sass_context.cpp
+++ b/libsass/src/sass_context.cpp
@@ -10,17 +10,17 @@
 
 // C++ helper
 namespace Sass {
-  // see sass_copy_c_string(std::string str)
-  static inline JsonNode* json_mkstream(const std::stringstream& stream)
+  // see sass_copy_c_string(sass::string str)
+  static inline JsonNode* json_mkstream(const sass::ostream& stream)
   {
     // hold on to string on stack!
-    std::string str(stream.str());
+    sass::string str(stream.str());
     return json_mkstring(str.c_str());
   }
 
-  static void handle_string_error(Sass_Context* c_ctx, const std::string& msg, int severety)
+  static void handle_string_error(Sass_Context* c_ctx, const sass::string& msg, int severety)
   {
-    std::stringstream msg_stream;
+    sass::ostream msg_stream;
     JsonNode* json_err = json_mkobject();
     msg_stream << "Internal Error: " << msg << std::endl;
     json_append_member(json_err, "status", json_mknumber(severety));
@@ -41,9 +41,9 @@
       throw;
     }
     catch (Exception::Base& e) {
-      std::stringstream msg_stream;
-      std::string cwd(Sass::File::get_cwd());
-      std::string msg_prefix(e.errtype());
+      sass::ostream msg_stream;
+      sass::string cwd(Sass::File::get_cwd());
+      sass::string msg_prefix(e.errtype());
       bool got_newline = false;
       msg_stream << msg_prefix << ": ";
       const char* msg = e.what();
@@ -55,7 +55,7 @@
           got_newline = true;
         }
         else if (got_newline) {
-          msg_stream << std::string(msg_prefix.size() + 2, ' ');
+          msg_stream << sass::string(msg_prefix.size() + 2, ' ');
           got_newline = false;
         }
         msg_stream << *msg;
@@ -65,24 +65,25 @@
 
       if (e.traces.empty()) {
         // we normally should have some traces, still here as a fallback
-        std::string rel_path(Sass::File::abs2rel(e.pstate.path, cwd, cwd));
-        msg_stream << std::string(msg_prefix.size() + 2, ' ');
-        msg_stream << " on line " << e.pstate.line + 1 << " of " << rel_path << "\n";
+        sass::string rel_path(Sass::File::abs2rel(e.pstate.getPath(), cwd, cwd));
+        msg_stream << sass::string(msg_prefix.size() + 2, ' ');
+        msg_stream << " on line " << e.pstate.getLine() << " of " << rel_path << "\n";
       }
       else {
-        std::string rel_path(Sass::File::abs2rel(e.pstate.path, cwd, cwd));
+        sass::string rel_path(Sass::File::abs2rel(e.pstate.getPath(), cwd, cwd));
         msg_stream << traces_to_string(e.traces, "        ");
       }
 
       // now create the code trace (ToDo: maybe have util functions?)
-      if (e.pstate.line != std::string::npos &&
-          e.pstate.column != std::string::npos &&
-          e.pstate.src != nullptr) {
-        size_t lines = e.pstate.line;
+      if (e.pstate.position.line != sass::string::npos &&
+          e.pstate.position.column != sass::string::npos &&
+          e.pstate.source != nullptr) {
+        Offset offset(e.pstate.position);
+        size_t lines = offset.line;
         // scan through src until target line
         // move line_beg pointer to line start
         const char* line_beg;
-        for (line_beg = e.pstate.src; *line_beg != '\0'; ++line_beg) {
+        for (line_beg = e.pstate.getRawData(); *line_beg != '\0'; ++line_beg) {
           if (lines == 0) break;
           if (*line_beg == '\n') --lines;
         }
@@ -96,12 +97,12 @@
         size_t move_in = 0; size_t shorten = 0;
         size_t left_chars = 42; size_t max_chars = 76;
         // reported excerpt should not exceed `max_chars` chars
-        if (e.pstate.column > line_len) left_chars = e.pstate.column;
-        if (e.pstate.column > left_chars) move_in = e.pstate.column - left_chars;
+        if (offset.column > line_len) left_chars = offset.column;
+        if (offset.column > left_chars) move_in = offset.column - left_chars;
         if (line_len > max_chars + move_in) shorten = line_len - move_in - max_chars;
         utf8::advance(line_beg, move_in, line_end);
         utf8::retreat(line_end, shorten, line_beg);
-        std::string sanitized; std::string marker(e.pstate.column - move_in, '-');
+        sass::string sanitized; sass::string marker(offset.column - move_in, '-');
         utf8::replace_invalid(line_beg, line_end, std::back_inserter(sanitized));
         msg_stream << ">> " << sanitized << "\n";
         msg_stream << "   " << marker << "^\n";
@@ -109,9 +110,9 @@
 
       JsonNode* json_err = json_mkobject();
       json_append_member(json_err, "status", json_mknumber(1));
-      json_append_member(json_err, "file", json_mkstring(e.pstate.path));
-      json_append_member(json_err, "line", json_mknumber((double)(e.pstate.line + 1)));
-      json_append_member(json_err, "column", json_mknumber((double)(e.pstate.column + 1)));
+      json_append_member(json_err, "file", json_mkstring(e.pstate.getPath()));
+      json_append_member(json_err, "line", json_mknumber((double)(e.pstate.getLine())));
+      json_append_member(json_err, "column", json_mknumber((double)(e.pstate.getColumn())));
       json_append_member(json_err, "message", json_mkstring(e.what()));
       json_append_member(json_err, "formatted", json_mkstream(msg_stream));
       try { c_ctx->error_json = json_stringify(json_err, "  "); }
@@ -119,23 +120,23 @@
       c_ctx->error_message = sass_copy_string(msg_stream.str());
       c_ctx->error_text = sass_copy_c_string(e.what());
       c_ctx->error_status = 1;
-      c_ctx->error_file = sass_copy_c_string(e.pstate.path);
-      c_ctx->error_line = e.pstate.line + 1;
-      c_ctx->error_column = e.pstate.column + 1;
-      c_ctx->error_src = sass_copy_c_string(e.pstate.src);
+      c_ctx->error_file = sass_copy_c_string(e.pstate.getPath());
+      c_ctx->error_line = e.pstate.getLine();
+      c_ctx->error_column = e.pstate.getColumn();
+      c_ctx->error_src = sass_copy_c_string(e.pstate.getRawData());
       c_ctx->output_string = 0;
       c_ctx->source_map_string = 0;
       json_delete(json_err);
     }
     catch (std::bad_alloc& ba) {
-      std::stringstream msg_stream;
+      sass::ostream msg_stream;
       msg_stream << "Unable to allocate memory: " << ba.what();
       handle_string_error(c_ctx, msg_stream.str(), 2);
     }
     catch (std::exception& e) {
       handle_string_error(c_ctx, e.what(), 3);
     }
-    catch (std::string& e) {
+    catch (sass::string& e) {
       handle_string_error(c_ctx, e, 4);
     }
     catch (const char* e) {
@@ -169,8 +170,8 @@
     try {
 
       // get input/output path from options
-      std::string input_path = safe_str(c_ctx->input_path);
-      std::string output_path = safe_str(c_ctx->output_path);
+      sass::string input_path = safe_str(c_ctx->input_path);
+      sass::string output_path = safe_str(c_ctx->output_path);
 
       // maybe skip some entries of included files
       // we do not include stdin for data contexts
@@ -279,8 +280,8 @@
       // reset error position
       c_ctx->error_file = 0;
       c_ctx->error_src = 0;
-      c_ctx->error_line = std::string::npos;
-      c_ctx->error_column = std::string::npos;
+      c_ctx->error_line = sass::string::npos;
+      c_ctx->error_column = sass::string::npos;
 
       // allocate a new compiler instance
       void* ctxmem = calloc(1, sizeof(struct Sass_Compiler));
@@ -698,6 +699,23 @@
   const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i)
   {
     struct string_list* cur = options->include_paths;
+    while (i) { i--; cur = cur->next; }
+    return cur->string;
+  }
+
+  // Push function for plugin paths (no manipulation support for now)
+  size_t ADDCALL sass_option_get_plugin_path_size(struct Sass_Options* options)
+  {
+    size_t len = 0;
+    struct string_list* cur = options->plugin_paths;
+    while (cur) { len++; cur = cur->next; }
+    return len;
+  }
+
+  // Push function for plugin paths (no manipulation support for now)
+  const char* ADDCALL sass_option_get_plugin_path(struct Sass_Options* options, size_t i)
+  {
+    struct string_list* cur = options->plugin_paths;
     while (i) { i--; cur = cur->next; }
     return cur->string;
   }
diff --git a/libsass/src/sass_values.cpp b/libsass/src/sass_values.cpp
--- a/libsass/src/sass_values.cpp
+++ b/libsass/src/sass_values.cpp
@@ -283,21 +283,21 @@
 
   union Sass_Value* ADDCALL sass_value_stringify (const union Sass_Value* v, bool compressed, int precision)
   {
-    Value_Obj val = sass_value_to_ast_node(v);
+    ValueObj val = sass_value_to_ast_node(v);
     Sass_Inspect_Options options(compressed ? COMPRESSED : NESTED, precision);
-    std::string str(val->to_string(options));
+    sass::string str(val->to_string(options));
     return sass_make_qstring(str.c_str());
   }
 
   union Sass_Value* ADDCALL sass_value_op (enum Sass_OP op, const union Sass_Value* a, const union Sass_Value* b)
   {
 
-    Sass::Value_Obj rv;
+    Sass::ValueObj rv;
 
     try {
 
-      Value_Obj lhs = sass_value_to_ast_node(a);
-      Value_Obj rhs = sass_value_to_ast_node(b);
+      ValueObj lhs = sass_value_to_ast_node(a);
+      ValueObj rhs = sass_value_to_ast_node(b);
       struct Sass_Inspect_Options options(NESTED, 5);
 
       // see if it's a relational expression
@@ -340,12 +340,10 @@
         rv = Operators::op_colors(op, *l_c, *r_c, options, l_c->pstate());
       }
       else /* convert other stuff to string and apply operation */ {
-        Value* l_v = Cast<Value>(lhs);
-        Value* r_v = Cast<Value>(rhs);
-        rv = Operators::op_strings(op, *l_v, *r_v, options, l_v->pstate());
+        rv = Operators::op_strings(op, *lhs, *rhs, options, lhs->pstate());
       }
 
-      // ToDo: maybe we should should return null value?
+      // ToDo: maybe we should return null value?
       if (!rv) return sass_make_error("invalid return value");
 
       // convert result back to ast node
@@ -356,7 +354,7 @@
     catch (Exception::InvalidSass& e) { return sass_make_error(e.what()); }
     catch (std::bad_alloc&) { return sass_make_error("memory exhausted"); }
     catch (std::exception& e) { return sass_make_error(e.what()); }
-    catch (std::string& e) { return sass_make_error(e.c_str()); }
+    catch (sass::string& e) { return sass_make_error(e.c_str()); }
     catch (const char* e) { return sass_make_error(e); }
     catch (...) { return sass_make_error("unknown"); }
   }
diff --git a/libsass/src/settings.hpp b/libsass/src/settings.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/settings.hpp
@@ -0,0 +1,19 @@
+#ifndef SASS_SETTINGS_H
+#define SASS_SETTINGS_H
+
+// Global compile time settings should go here
+
+// When enabled we use our custom memory pool allocator
+// With intense workloads this can double the performance
+// Max memory usage mostly only grows by a slight amount
+// #define SASS_CUSTOM_ALLOCATOR
+
+// How many buckets should we have for the free-list
+// Determines when allocations go directly to malloc/free
+// For maximum size of managed items multiply by alignment
+#define SassAllocatorBuckets 512
+
+// The size of the memory pool arenas in bytes.
+#define SassAllocatorArenaSize (1024 * 256)
+
+#endif
diff --git a/libsass/src/source.cpp b/libsass/src/source.cpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/source.cpp
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <string.h>
+#include "source.hpp"
+#include "utf8/checked.h"
+#include "position.hpp"
+
+namespace Sass {
+
+  SourceData::SourceData()
+    : SharedObj()
+  {
+  }
+
+  SourceFile::SourceFile(
+    const char* path,
+    const char* data,
+    size_t srcid) :
+    SourceData(),
+    path(sass_copy_c_string(path)),
+    data(sass_copy_c_string(data)),
+    length(0),
+    srcid(srcid)
+  {
+    length = strlen(data);
+  }
+
+  SourceFile::~SourceFile() {
+    sass_free_memory(path);
+    sass_free_memory(data);
+  }
+
+  const char* SourceFile::end() const
+  {
+    return data + length;
+  }
+
+  const char* SourceFile::begin() const
+  {
+    return data;
+  }
+
+  const char* SourceFile::getRawData() const
+  {
+    return data;
+  }
+
+  SourceSpan SourceFile::getSourceSpan()
+  {
+    return SourceSpan(this);
+  }
+
+  ItplFile::ItplFile(const char* data, const SourceSpan& pstate) :
+    SourceFile(pstate.getPath(),
+      data, pstate.getSrcId()),
+    pstate(pstate)
+  {}
+
+  const char* ItplFile::getRawData() const
+  {
+    return pstate.getRawData();
+  }
+
+  SourceSpan ItplFile::getSourceSpan()
+  {
+    return SourceSpan(pstate);
+  }
+
+}
+
diff --git a/libsass/src/source.hpp b/libsass/src/source.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/source.hpp
@@ -0,0 +1,95 @@
+#ifndef SASS_SOURCE_H
+#define SASS_SOURCE_H
+
+#include "sass.hpp"
+#include "memory.hpp"
+#include "position.hpp"
+#include "source_data.hpp"
+
+namespace Sass {
+
+  class SourceFile :
+    public SourceData {
+  protected:
+    char* path;
+    char* data;
+    size_t length;
+    size_t srcid;
+  public:
+
+    SourceFile(
+      const char* path,
+      const char* data,
+      size_t srcid);
+
+    ~SourceFile();
+
+    const char* end() const override final;
+    const char* begin() const override final;
+    virtual const char* getRawData() const override;
+    virtual SourceSpan getSourceSpan() override;
+
+    size_t size() const override final {
+      return length;
+    }
+
+    virtual const char* getPath() const override {
+      return path;
+    }
+
+    virtual size_t getSrcId() const override {
+      return srcid;
+    }
+
+  };
+
+  class SynthFile :
+    public SourceData {
+  protected:
+    const char* path;
+  public:
+
+    SynthFile(
+      const char* path) :
+      path(path)
+    {}
+
+    ~SynthFile() {}
+
+    const char* end() const override final { return nullptr; }
+    const char* begin() const override final { return nullptr; };
+    virtual const char* getRawData() const override { return nullptr; };
+    virtual SourceSpan getSourceSpan() override { return SourceSpan(path); };
+
+    size_t size() const override final {
+      return 0;
+    }
+
+    virtual const char* getPath() const override {
+      return path;
+    }
+
+    virtual size_t getSrcId() const override {
+      return std::string::npos;
+    }
+
+  };
+  
+
+  class ItplFile :
+    public SourceFile {
+  private:
+    SourceSpan pstate;
+  public:
+
+    ItplFile(const char* data,
+      const SourceSpan& pstate);
+
+    // Offset getPosition() const override final;
+    const char* getRawData() const override final;
+    SourceSpan getSourceSpan() override final;
+  };
+
+}
+
+#endif
diff --git a/libsass/src/source_data.hpp b/libsass/src/source_data.hpp
new file mode 100644
--- /dev/null
+++ b/libsass/src/source_data.hpp
@@ -0,0 +1,32 @@
+#ifndef SASS_SOURCE_DATA_H
+#define SASS_SOURCE_DATA_H
+
+#include "sass.hpp"
+#include "memory.hpp"
+
+namespace Sass {
+
+  class SourceSpan;
+
+  class SourceData :
+    public SharedObj {
+  public:
+    SourceData();
+    virtual size_t size() const = 0;
+    virtual size_t getSrcId() const = 0;
+    virtual const char* end() const = 0;
+    virtual const char* begin() const = 0;
+    virtual const char* getPath() const = 0;
+    // virtual Offset getPosition() const = 0;
+    virtual const char* getRawData() const = 0;
+    virtual SourceSpan getSourceSpan() = 0;
+
+    sass::string to_string() const override {
+      return sass::string{ begin(), end() };
+    }
+    ~SourceData() {}
+  };
+
+}
+
+#endif
diff --git a/libsass/src/source_map.cpp b/libsass/src/source_map.cpp
--- a/libsass/src/source_map.cpp
+++ b/libsass/src/source_map.cpp
@@ -15,13 +15,13 @@
 
 namespace Sass {
   SourceMap::SourceMap() : current_position(0, 0, 0), file("stdin") { }
-  SourceMap::SourceMap(const std::string& file) : current_position(0, 0, 0), file(file) { }
+  SourceMap::SourceMap(const sass::string& file) : current_position(0, 0, 0), file(file) { }
 
-  std::string SourceMap::render_srcmap(Context &ctx) {
+  sass::string SourceMap::render_srcmap(Context &ctx) {
 
     const bool include_sources = ctx.c_options.source_map_contents;
-    const std::vector<std::string> links = ctx.srcmap_links;
-    const std::vector<Resource>& sources(ctx.resources);
+    const sass::vector<sass::string> links = ctx.srcmap_links;
+    const sass::vector<Resource>& sources(ctx.resources);
 
     JsonNode* json_srcmap = json_mkobject();
 
@@ -39,7 +39,7 @@
 
     JsonNode *json_sources = json_mkarray();
     for (size_t i = 0; i < source_index.size(); ++i) {
-      std::string source(links[source_index[i]]);
+      sass::string source(links[source_index[i]]);
       if (ctx.c_options.source_map_file_urls) {
         source = File::rel2abs(source);
         // check for windows abs path
@@ -72,19 +72,19 @@
     // no problem as we do not alter any identifiers
     json_append_member(json_srcmap, "names", json_names);
 
-    std::string mappings = serialize_mappings();
+    sass::string mappings = serialize_mappings();
     JsonNode *json_mappings = json_mkstring(mappings.c_str());
     json_append_member(json_srcmap, "mappings", json_mappings);
 
     char *str = json_stringify(json_srcmap, "\t");
-    std::string result = std::string(str);
+    sass::string result = sass::string(str);
     free(str);
     json_delete(json_srcmap);
     return result;
   }
 
-  std::string SourceMap::serialize_mappings() {
-    std::string result = "";
+  sass::string SourceMap::serialize_mappings() {
+    sass::string result = "";
 
     size_t previous_generated_line = 0;
     size_t previous_generated_column = 0;
@@ -101,7 +101,7 @@
       if (generated_line != previous_generated_line) {
         previous_generated_column = 0;
         if (generated_line > previous_generated_line) {
-          result += std::string(generated_line - previous_generated_line, ';');
+          result += sass::string(generated_line - previous_generated_line, ';');
           previous_generated_line = generated_line;
         }
       }
@@ -175,23 +175,27 @@
 
   void SourceMap::add_open_mapping(const AST_Node* node)
   {
-    mappings.push_back(Mapping(node->pstate(), current_position));
+    const SourceSpan& span(node->pstate());
+    Position from(span.getSrcId(), span.position);
+    mappings.push_back(Mapping(from, current_position));
   }
 
   void SourceMap::add_close_mapping(const AST_Node* node)
   {
-    mappings.push_back(Mapping(node->pstate() + node->pstate().offset, current_position));
+    const SourceSpan& span(node->pstate());
+    Position to(span.getSrcId(), span.position + span.offset);
+    mappings.push_back(Mapping(to, current_position));
   }
 
-  ParserState SourceMap::remap(const ParserState& pstate) {
+  SourceSpan SourceMap::remap(const SourceSpan& pstate) {
     for (size_t i = 0; i < mappings.size(); ++i) {
       if (
-        mappings[i].generated_position.file == pstate.file &&
-        mappings[i].generated_position.line == pstate.line &&
-        mappings[i].generated_position.column == pstate.column
-      ) return ParserState(pstate.path, pstate.src, mappings[i].original_position, pstate.offset);
+        mappings[i].generated_position.file == pstate.getSrcId() &&
+        mappings[i].generated_position.line == pstate.position.line &&
+        mappings[i].generated_position.column == pstate.position.column
+      ) return SourceSpan(pstate.source, mappings[i].original_position, pstate.offset);
     }
-    return ParserState(pstate.path, pstate.src, Position(-1, -1, -1), Offset(0, 0));
+    return SourceSpan(pstate.source, Position(-1, -1, -1), Offset(0, 0));
 
   }
 
diff --git a/libsass/src/source_map.hpp b/libsass/src/source_map.hpp
--- a/libsass/src/source_map.hpp
+++ b/libsass/src/source_map.hpp
@@ -9,6 +9,9 @@
 #include "position.hpp"
 #include "mapping.hpp"
 
+#include "backtrace.hpp"
+#include "memory.hpp"
+
 #define VECTOR_PUSH(vec, ins) vec.insert(vec.end(), ins.begin(), ins.end())
 #define VECTOR_UNSHIFT(vec, ins) vec.insert(vec.begin(), ins.begin(), ins.end())
 
@@ -20,9 +23,9 @@
   class SourceMap {
 
   public:
-    std::vector<size_t> source_index;
+    sass::vector<size_t> source_index;
     SourceMap();
-    SourceMap(const std::string& file);
+    SourceMap(const sass::string& file);
 
     void append(const Offset& offset);
     void prepend(const Offset& offset);
@@ -31,17 +34,17 @@
     void add_open_mapping(const AST_Node* node);
     void add_close_mapping(const AST_Node* node);
 
-    std::string render_srcmap(Context &ctx);
-    ParserState remap(const ParserState& pstate);
+    sass::string render_srcmap(Context &ctx);
+    SourceSpan remap(const SourceSpan& pstate);
 
   private:
 
-    std::string serialize_mappings();
+    sass::string serialize_mappings();
 
-    std::vector<Mapping> mappings;
+    sass::vector<Mapping> mappings;
     Position current_position;
 public:
-    std::string file;
+    sass::string file;
 private:
     Base64VLQ base64vlq;
   };
@@ -49,11 +52,11 @@
   class OutputBuffer {
     public:
       OutputBuffer(void)
-      : buffer(""),
+      : buffer(),
         smap()
       { }
     public:
-      std::string buffer;
+      sass::string buffer;
       SourceMap smap;
   };
 
diff --git a/libsass/src/units.cpp b/libsass/src/units.cpp
--- a/libsass/src/units.cpp
+++ b/libsass/src/units.cpp
@@ -65,7 +65,7 @@
     }
   };
 
-  std::string get_unit_class(UnitType unit)
+  sass::string get_unit_class(UnitType unit)
   {
     switch (unit & 0xFF00)
     {
@@ -91,7 +91,7 @@
     }
   };
 
-  UnitType string_to_unit(const std::string& s)
+  UnitType string_to_unit(const sass::string& s)
   {
     // size units
     if      (s == "px")   return UnitType::PX;
@@ -149,7 +149,7 @@
     }
   }
 
-  std::string unit_to_class(const std::string& s)
+  sass::string unit_to_class(const sass::string& s)
   {
     if      (s == "px")   return "LENGTH";
     else if (s == "pt")   return "LENGTH";
@@ -177,7 +177,7 @@
   }
 
   // throws incompatibleUnits exceptions
-  double conversion_factor(const std::string& s1, const std::string& s2)
+  double conversion_factor(const sass::string& s1, const sass::string& s2)
   {
     // assert for same units
     if (s1 == s2) return 1;
@@ -219,7 +219,7 @@
     return 0;
   }
 
-  double convert_units(const std::string& lhs, const std::string& rhs, int& lhsexp, int& rhsexp)
+  double convert_units(const sass::string& lhs, const sass::string& rhs, int& lhsexp, int& rhsexp)
   {
     double f = 0;
     // do not convert same ones
@@ -283,7 +283,7 @@
     double factor = 1;
 
     for (size_t i = 0; i < iL; i++) {
-      std::string &lhs = numerators[i];
+      sass::string &lhs = numerators[i];
       UnitType ulhs = string_to_unit(lhs);
       if (ulhs == UNKNOWN) continue;
       UnitClass clhs = get_unit_type(ulhs);
@@ -296,7 +296,7 @@
     }
 
     for (size_t n = 0; n < nL; n++) {
-      std::string &rhs = denominators[n];
+      sass::string &rhs = denominators[n];
       UnitType urhs = string_to_unit(rhs);
       if (urhs == UNKNOWN) continue;
       UnitClass crhs = get_unit_type(urhs);
@@ -328,7 +328,7 @@
     // it seems that a map table will fit nicely to do this
     // we basically construct exponents for each unit
     // has the advantage that they will be pre-sorted
-    std::map<std::string, int> exponents;
+    std::map<sass::string, int> exponents;
 
     // initialize by summing up occurrences in unit vectors
     // this will already cancel out equivalent units (e.q. px/px)
@@ -341,7 +341,7 @@
     // convert between compatible units
     for (size_t i = 0; i < iL; i++) {
       for (size_t n = 0; n < nL; n++) {
-        std::string &lhs = numerators[i], &rhs = denominators[n];
+        sass::string &lhs = numerators[i], &rhs = denominators[n];
         int &lhsexp = exponents[lhs], &rhsexp = exponents[rhs];
         double f(convert_units(lhs, rhs, lhsexp, rhsexp));
         if (f == 0) continue;
@@ -367,9 +367,9 @@
 
   }
 
-  std::string Units::unit() const
+  sass::string Units::unit() const
   {
-    std::string u;
+    sass::string u;
     size_t iL = numerators.size();
     size_t nL = denominators.size();
     for (size_t i = 0; i < iL; i += 1) {
@@ -400,11 +400,11 @@
   double Units::convert_factor(const Units& r) const
   {
 
-    std::vector<std::string> miss_nums(0);
-    std::vector<std::string> miss_dens(0);
+    sass::vector<sass::string> miss_nums(0);
+    sass::vector<sass::string> miss_dens(0);
     // create copy since we need these for state keeping
-    std::vector<std::string> r_nums(r.numerators);
-    std::vector<std::string> r_dens(r.denominators);
+    sass::vector<sass::string> r_nums(r.numerators);
+    sass::vector<sass::string> r_dens(r.denominators);
 
     auto l_num_it = numerators.begin();
     auto l_num_end = numerators.end();
@@ -419,7 +419,7 @@
     while (l_num_it != l_num_end)
     {
       // get and increment afterwards
-      const std::string l_num = *(l_num_it ++);
+      const sass::string l_num = *(l_num_it ++);
 
       auto r_num_it = r_nums.begin(), r_num_end = r_nums.end();
 
@@ -428,7 +428,7 @@
       while (r_num_it != r_num_end)
       {
         // get and increment afterwards
-        const std::string r_num = *(r_num_it);
+        const sass::string r_num = *(r_num_it);
         // get possible conversion factor for units
         double conversion = conversion_factor(l_num, r_num);
         // skip incompatible numerator
@@ -456,7 +456,7 @@
     while (l_den_it != l_den_end)
     {
       // get and increment afterwards
-      const std::string l_den = *(l_den_it ++);
+      const sass::string l_den = *(l_den_it ++);
 
       auto r_den_it = r_dens.begin();
       auto r_den_end = r_dens.end();
@@ -466,7 +466,7 @@
       while (r_den_it != r_den_end)
       {
         // get and increment afterwards
-        const std::string r_den = *(r_den_it);
+        const sass::string r_den = *(r_den_it);
         // get possible conversion factor for units
         double conversion = conversion_factor(l_den, r_den);
         // skip incompatible denominator
diff --git a/libsass/src/units.hpp b/libsass/src/units.hpp
--- a/libsass/src/units.hpp
+++ b/libsass/src/units.hpp
@@ -55,8 +55,8 @@
 
   class Units {
   public:
-    std::vector<std::string> numerators;
-    std::vector<std::string> denominators;
+    sass::vector<sass::string> numerators;
+    sass::vector<sass::string> denominators;
   public:
     // default constructor
     Units() :
@@ -69,7 +69,7 @@
       denominators(ptr->denominators)
     { }
     // convert to string
-    std::string unit() const;
+    sass::string unit() const;
     // get if units are empty
     bool is_unitless() const;
     // return if valid for css
@@ -95,15 +95,15 @@
   extern const double resolution_conversion_factors[3][3];
 
   UnitType get_main_unit(const UnitClass unit);
-  enum Sass::UnitType string_to_unit(const std::string&);
+  enum Sass::UnitType string_to_unit(const sass::string&);
   const char* unit_to_string(Sass::UnitType unit);
   enum Sass::UnitClass get_unit_type(Sass::UnitType unit);
-  std::string get_unit_class(Sass::UnitType unit);
-  std::string unit_to_class(const std::string&);
+  sass::string get_unit_class(Sass::UnitType unit);
+  sass::string unit_to_class(const sass::string&);
   // throws incompatibleUnits exceptions
-  double conversion_factor(const std::string&, const std::string&);
+  double conversion_factor(const sass::string&, const sass::string&);
   double conversion_factor(UnitType, UnitType, UnitClass, UnitClass);
-  double convert_units(const std::string&, const std::string&, int&, int&);
+  double convert_units(const sass::string&, const sass::string&, int&, int&);
 
 }
 
diff --git a/libsass/src/utf8_string.cpp b/libsass/src/utf8_string.cpp
--- a/libsass/src/utf8_string.cpp
+++ b/libsass/src/utf8_string.cpp
@@ -11,7 +11,6 @@
 
 namespace Sass {
   namespace UTF_8 {
-    using std::string;
 
     // naming conventions:
     // offset: raw byte offset (0 based)
@@ -19,25 +18,25 @@
     // index: code point offset (1 based or negative)
 
     // function that will count the number of code points (utf-8 characters) from the given beginning to the given end
-    size_t code_point_count(const string& str, size_t start, size_t end) {
+    size_t code_point_count(const sass::string& str, size_t start, size_t end) {
       return utf8::distance(str.begin() + start, str.begin() + end);
     }
 
-    size_t code_point_count(const string& str) {
+    size_t code_point_count(const sass::string& str) {
       return utf8::distance(str.begin(), str.end());
     }
 
     // function that will return the byte offset at a code point position
-    size_t offset_at_position(const string& str, size_t position) {
-      string::const_iterator it = str.begin();
+    size_t offset_at_position(const sass::string& str, size_t position) {
+      sass::string::const_iterator it = str.begin();
       utf8::advance(it, position, str.end());
       return std::distance(str.begin(), it);
     }
 
     // function that returns number of bytes in a character at offset
-    size_t code_point_size_at_offset(const string& str, size_t offset) {
+    size_t code_point_size_at_offset(const sass::string& str, size_t offset) {
       // get iterator from string and forward by offset
-      string::const_iterator stop = str.begin() + offset;
+      sass::string::const_iterator stop = str.begin() + offset;
       // check if beyond boundary
       if (stop == str.end()) return 0;
       // advance by one code point
@@ -78,9 +77,9 @@
     using std::wstring;
 
     // convert from utf16/wide string to utf8 string
-    string convert_from_utf16(const wstring& utf16)
+    sass::string convert_from_utf16(const wstring& utf16)
     {
-      string utf8;
+      sass::string utf8;
       // pre-allocate expected memory
       utf8.reserve(sizeof(utf16)/2);
       utf8::utf16to8(utf16.begin(), utf16.end(),
@@ -89,7 +88,7 @@
     }
 
     // convert from utf8 string to utf16/wide string
-    wstring convert_to_utf16(const string& utf8)
+    wstring convert_to_utf16(const sass::string& utf8)
     {
       wstring utf16;
       // pre-allocate expected memory
diff --git a/libsass/src/utf8_string.hpp b/libsass/src/utf8_string.hpp
--- a/libsass/src/utf8_string.hpp
+++ b/libsass/src/utf8_string.hpp
@@ -3,6 +3,7 @@
 
 #include <string>
 #include "utf8.h"
+#include "memory.hpp"
 
 namespace Sass {
   namespace UTF_8 {
@@ -13,22 +14,22 @@
     // index: code point offset (1 based or negative)
 
     // function that will count the number of code points (utf-8 characters) from the beginning to the given end
-    size_t code_point_count(const std::string& str, size_t start, size_t end);
-    size_t code_point_count(const std::string& str);
+    size_t code_point_count(const sass::string& str, size_t start, size_t end);
+    size_t code_point_count(const sass::string& str);
 
     // function that will return the byte offset of a code point in a
-    size_t offset_at_position(const std::string& str, size_t position);
+    size_t offset_at_position(const sass::string& str, size_t position);
 
     // function that returns number of bytes in a character in a string
-    size_t code_point_size_at_offset(const std::string& str, size_t offset);
+    size_t code_point_size_at_offset(const sass::string& str, size_t offset);
 
     // function that will return a normalized index, given a crazy one
     size_t normalize_index(int index, size_t len);
 
     #ifdef _WIN32
     // functions to handle unicode paths on windows
-    std::string convert_from_utf16(const std::wstring& wstr);
-    std::wstring convert_to_utf16(const std::string& str);
+    sass::string convert_from_utf16(const std::wstring& wstr);
+    std::wstring convert_to_utf16(const sass::string& str);
     #endif
 
   }
diff --git a/libsass/src/util.cpp b/libsass/src/util.cpp
--- a/libsass/src/util.cpp
+++ b/libsass/src/util.cpp
@@ -76,7 +76,7 @@
     free(arr);
   }
 
-  char **copy_strings(const std::vector<std::string>& strings, char*** array, int skip) {
+  char **copy_strings(const sass::vector<sass::string>& strings, char*** array, int skip) {
     int num = static_cast<int>(strings.size()) - skip;
     char** arr = (char**) calloc(num + 1, sizeof(char*));
     if (arr == 0)
@@ -97,10 +97,10 @@
   }
 
   // read css string (handle multiline DELIM)
-  std::string read_css_string(const std::string& str, bool css)
+  sass::string read_css_string(const sass::string& str, bool css)
   {
     if (!css) return str;
-    std::string out("");
+    sass::string out("");
     bool esc = false;
     for (auto i : str) {
       if (i == '\\') {
@@ -125,9 +125,9 @@
 
   // double escape all escape sequences
   // keep unescaped quotes and backslashes
-  std::string evacuate_escapes(const std::string& str)
+  sass::string evacuate_escapes(const sass::string& str)
   {
-    std::string out("");
+    sass::string out("");
     bool esc = false;
     for (auto i : str) {
       if (i == '\\' && !esc) {
@@ -159,7 +159,7 @@
   }
 
   // bell characters are replaced with spaces
-  void newline_to_space(std::string& str)
+  void newline_to_space(sass::string& str)
   {
     std::replace(str.begin(), str.end(), '\n', ' ');
   }
@@ -168,14 +168,14 @@
   // 2. Replaces newlines with spaces.
   //
   // This method only considers LF and CRLF as newlines.
-  std::string string_to_output(const std::string& str)
+  sass::string string_to_output(const sass::string& str)
   {
-    std::string result;
+    sass::string result;
     result.reserve(str.size());
     std::size_t pos = 0;
     while (true) {
       const std::size_t newline = str.find_first_of("\n\r", pos);
-      if (newline == std::string::npos) break;
+      if (newline == sass::string::npos) break;
       result.append(str, pos, newline - pos);
       if (str[newline] == '\r') {
         if (str[newline + 1] == '\n') {
@@ -191,17 +191,17 @@
       }
       result += ' ';
       const std::size_t non_space = str.find_first_not_of(" \f\n\r\t\v", pos);
-      if (non_space != std::string::npos) {
+      if (non_space != sass::string::npos) {
         pos = non_space;
       }
     }
-    result.append(str, pos, std::string::npos);
+    result.append(str, pos, sass::string::npos);
     return result;
   }
 
-  std::string escape_string(const std::string& str)
+  sass::string escape_string(const sass::string& str)
   {
-    std::string out;
+    sass::string out;
     out.reserve(str.size());
     for (char c : str) {
       switch (c) {
@@ -221,9 +221,9 @@
     return out;
   }
 
-  std::string comment_to_compact_string(const std::string& text)
+  sass::string comment_to_compact_string(const sass::string& text)
   {
-    std::string str = "";
+    sass::string str = "";
     size_t has = 0;
     char prev = 0;
     bool clean = false;
@@ -270,10 +270,10 @@
     return quote_mark;
   }
 
-  std::string read_hex_escapes(const std::string& s)
+  sass::string read_hex_escapes(const sass::string& s)
   {
 
-    std::string result;
+    sass::string result;
     bool skipped = false;
 
     for (size_t i = 0, L = s.length(); i < L; ++i) {
@@ -339,7 +339,7 @@
 
   }
 
-  std::string unquote(const std::string& s, char* qd, bool keep_utf8_sequences, bool strict)
+  sass::string unquote(const sass::string& s, char* qd, bool keep_utf8_sequences, bool strict)
   {
 
     // not enough room for quotes
@@ -355,7 +355,7 @@
     else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
     else                                                return s;
 
-    std::string unq;
+    sass::string unq;
     unq.reserve(s.length()-2);
 
     for (size_t i = 1, L = s.length() - 1; i < L; ++i) {
@@ -414,7 +414,7 @@
       //   // don't be that strict
       //   return s;
       //   // this basically always means an internal error and not users fault
-      //   error("Unescaped delimiter in string to unquote found. [" + s + "]", ParserState("[UNQUOTE]"));
+      //   error("Unescaped delimiter in string to unquote found. [" + s + "]", SourceSpan("[UNQUOTE]"));
       // }
       else {
         if (strict && !skipped) {
@@ -431,16 +431,16 @@
 
   }
 
-  std::string quote(const std::string& s, char q)
+  sass::string quote(const sass::string& s, char q)
   {
 
     // autodetect with fallback to given quote
     q = detect_best_quotemark(s.c_str(), q);
 
     // return an empty quoted string
-    if (s.empty()) return std::string(2, q ? q : '"');
+    if (s.empty()) return sass::string(2, q ? q : '"');
 
-    std::string quoted;
+    sass::string quoted;
     quoted.reserve(s.length()+2);
     quoted.push_back(q);
 
@@ -529,7 +529,7 @@
 
   namespace Util {
 
-    bool isPrintable(Ruleset* r, Sass_Output_Style style) {
+    bool isPrintable(StyleRule* r, Sass_Output_Style style) {
       if (r == NULL) {
         return false;
       }
@@ -547,11 +547,11 @@
       bool hasPrintableChildBlocks = false;
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         Statement_Obj stm = b->at(i);
-        if (Cast<Directive>(stm)) {
+        if (Cast<AtRule>(stm)) {
           return true;
         } else if (Declaration* d = Cast<Declaration>(stm)) {
           return isPrintable(d, style);
-        } else if (Has_Block* p = Cast<Has_Block>(stm)) {
+        } else if (ParentStatement* p = Cast<ParentStatement>(stm)) {
           Block_Obj pChildBlock = p->block();
           if (isPrintable(pChildBlock, style)) {
             hasPrintableChildBlocks = true;
@@ -589,13 +589,13 @@
 
     bool isPrintable(Declaration* d, Sass_Output_Style style)
     {
-      Expression_Obj val = d->value();
+      ExpressionObj val = d->value();
       if (String_Quoted_Obj sq = Cast<String_Quoted>(val)) return isPrintable(sq.ptr(), style);
       if (String_Constant_Obj sc = Cast<String_Constant>(val)) return isPrintable(sc.ptr(), style);
       return true;
     }
 
-    bool isPrintable(Supports_Block* f, Sass_Output_Style style) {
+    bool isPrintable(SupportsRule* f, Sass_Output_Style style) {
       if (f == NULL) {
         return false;
       }
@@ -606,10 +606,10 @@
       bool hasPrintableChildBlocks = false;
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         Statement_Obj stm = b->at(i);
-        if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
+        if (Cast<Declaration>(stm) || Cast<AtRule>(stm)) {
           hasDeclarations = true;
         }
-        else if (Has_Block* b = Cast<Has_Block>(stm)) {
+        else if (ParentStatement* b = Cast<ParentStatement>(stm)) {
           Block_Obj pChildBlock = b->block();
           if (!b->is_invisible()) {
             if (isPrintable(pChildBlock, style)) {
@@ -634,19 +634,19 @@
       if (m->empty()) return false;
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         Statement_Obj stm = b->at(i);
-        if (Cast<Directive>(stm)) return true;
+        if (Cast<AtRule>(stm)) return true;
         else if (Cast<Declaration>(stm)) return true;
         else if (Comment* c = Cast<Comment>(stm)) {
           if (isPrintable(c, style)) {
             return true;
           }
         }
-        else if (Ruleset* r = Cast<Ruleset>(stm)) {
+        else if (StyleRule* r = Cast<StyleRule>(stm)) {
           if (isPrintable(r, style)) {
             return true;
           }
         }
-        else if (Supports_Block* f = Cast<Supports_Block>(stm)) {
+        else if (SupportsRule* f = Cast<SupportsRule>(stm)) {
           if (isPrintable(f, style)) {
             return true;
           }
@@ -656,7 +656,7 @@
             return true;
           }
         }
-        else if (Has_Block* b = Cast<Has_Block>(stm)) {
+        else if (ParentStatement* b = Cast<ParentStatement>(stm)) {
           if (isPrintable(b->block(), style)) {
             return true;
           }
@@ -686,7 +686,7 @@
 
       for (size_t i = 0, L = b->length(); i < L; ++i) {
         Statement_Obj stm = b->at(i);
-        if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
+        if (Cast<Declaration>(stm) || Cast<AtRule>(stm)) {
           return true;
         }
         else if (Comment* c = Cast<Comment>(stm)) {
@@ -694,12 +694,12 @@
             return true;
           }
         }
-        else if (Ruleset* r = Cast<Ruleset>(stm)) {
+        else if (StyleRule* r = Cast<StyleRule>(stm)) {
           if (isPrintable(r, style)) {
             return true;
           }
         }
-        else if (Supports_Block* f = Cast<Supports_Block>(stm)) {
+        else if (SupportsRule* f = Cast<SupportsRule>(stm)) {
           if (isPrintable(f, style)) {
             return true;
           }
@@ -709,7 +709,7 @@
             return true;
           }
         }
-        else if (Has_Block* b = Cast<Has_Block>(stm)) {
+        else if (ParentStatement* b = Cast<ParentStatement>(stm)) {
           if (isPrintable(b->block(), style)) {
             return true;
           }
diff --git a/libsass/src/util.hpp b/libsass/src/util.hpp
--- a/libsass/src/util.hpp
+++ b/libsass/src/util.hpp
@@ -34,17 +34,17 @@
   double sass_strtod(const char* str);
   const char* safe_str(const char *, const char* = "");
   void free_string_array(char **);
-  char **copy_strings(const std::vector<std::string>&, char ***, int = 0);
-  std::string read_css_string(const std::string& str, bool css = true);
-  std::string evacuate_escapes(const std::string& str);
-  std::string string_to_output(const std::string& str);
-  std::string comment_to_compact_string(const std::string& text);
-  std::string read_hex_escapes(const std::string& str);
-  std::string escape_string(const std::string& str);
-  void newline_to_space(std::string& str);
+  char **copy_strings(const sass::vector<sass::string>&, char ***, int = 0);
+  sass::string read_css_string(const sass::string& str, bool css = true);
+  sass::string evacuate_escapes(const sass::string& str);
+  sass::string string_to_output(const sass::string& str);
+  sass::string comment_to_compact_string(const sass::string& text);
+  sass::string read_hex_escapes(const sass::string& str);
+  sass::string escape_string(const sass::string& str);
+  void newline_to_space(sass::string& str);
 
-  std::string quote(const std::string&, char q = 0);
-  std::string unquote(const std::string&, char* q = 0, bool keep_utf8_sequences = false, bool strict = true);
+  sass::string quote(const sass::string&, char q = 0);
+  sass::string unquote(const sass::string&, char* q = 0, bool keep_utf8_sequences = false, bool strict = true);
   char detect_best_quotemark(const char* s, char qm = '"');
 
   bool is_hex_doublet(double n);
@@ -63,21 +63,21 @@
 
   // C++20 `starts_with` equivalent.
   // See https://en.cppreference.com/w/cpp/string/basic_string/starts_with
-  inline bool starts_with(const std::string& str, const char* prefix, size_t prefix_len) {
+  inline bool starts_with(const sass::string& str, const char* prefix, size_t prefix_len) {
     return str.compare(0, prefix_len, prefix) == 0;
   }
 
-  inline bool starts_with(const std::string& str, const char* prefix) {
+  inline bool starts_with(const sass::string& str, const char* prefix) {
     return starts_with(str, prefix, std::strlen(prefix));
   }
 
   // C++20 `ends_with` equivalent.
   // See https://en.cppreference.com/w/cpp/string/basic_string/ends_with
-  inline bool ends_with(const std::string& str, const std::string& suffix) {
+  inline bool ends_with(const sass::string& str, const sass::string& suffix) {
     return suffix.size() <= str.size() && std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
   }
 
-  inline bool ends_with(const std::string& str, const char* suffix, size_t suffix_len) {
+  inline bool ends_with(const sass::string& str, const char* suffix, size_t suffix_len) {
     if (suffix_len > str.size()) return false;
     const char* suffix_it = suffix + suffix_len;
     const char* str_it = str.c_str() + str.size();
@@ -85,14 +85,14 @@
     return true;
   }
 
-  inline bool ends_with(const std::string& str, const char* suffix) {
+  inline bool ends_with(const sass::string& str, const char* suffix) {
     return ends_with(str, suffix, std::strlen(suffix));
   }
 
   namespace Util {
 
-    bool isPrintable(Ruleset* r, Sass_Output_Style style = NESTED);
-    bool isPrintable(Supports_Block* r, Sass_Output_Style style = NESTED);
+    bool isPrintable(StyleRule* r, Sass_Output_Style style = NESTED);
+    bool isPrintable(SupportsRule* r, Sass_Output_Style style = NESTED);
     bool isPrintable(CssMediaRule* r, Sass_Output_Style style = NESTED);
     bool isPrintable(Comment* b, Sass_Output_Style style = NESTED);
     bool isPrintable(Block_Obj b, Sass_Output_Style style = NESTED);
diff --git a/libsass/src/util_string.cpp b/libsass/src/util_string.cpp
--- a/libsass/src/util_string.cpp
+++ b/libsass/src/util_string.cpp
@@ -14,7 +14,7 @@
     // there is one edge case where this could give false positives
     // test could contain a (non-ascii) char exactly 32 below literal
     // ##########################################################################
-    bool equalsLiteral(const char* lit, const std::string& test) {
+    bool equalsLiteral(const char* lit, const sass::string& test) {
       // Work directly on characters
       const char* src = test.c_str();
       // There is a small chance that the search string
@@ -27,19 +27,19 @@
       return *lit == 0;
     }
 
-    void ascii_str_tolower(std::string* s) {
+    void ascii_str_tolower(sass::string* s) {
       for (auto& ch : *s) {
         ch = ascii_tolower(static_cast<unsigned char>(ch));
       }
     }
 
-    void ascii_str_toupper(std::string* s) {
+    void ascii_str_toupper(sass::string* s) {
       for (auto& ch : *s) {
         ch = ascii_toupper(static_cast<unsigned char>(ch));
       }
     }
 
-    std::string rtrim(std::string str) {
+    sass::string rtrim(sass::string str) {
       auto it = std::find_if_not(str.rbegin(), str.rend(), ascii_isspace);
       str.erase(str.rend() - it);
       return str;
@@ -49,7 +49,7 @@
     // Returns [name] without a vendor prefix.
     // If [name] has no vendor prefix, it's returned as-is.
     // ###########################################################################
-    std::string unvendor(const std::string& name)
+    sass::string unvendor(const sass::string& name)
     {
       if (name.size() < 2) return name;
       if (name[0] != '-') return name;
@@ -61,13 +61,13 @@
     }
     // EO unvendor
 
-    std::string normalize_newlines(const std::string& str) {
-      std::string result;
+    sass::string normalize_newlines(const sass::string& str) {
+      sass::string result;
       result.reserve(str.size());
       std::size_t pos = 0;
       while (true) {
         const std::size_t newline = str.find_first_of("\n\f\r", pos);
-        if (newline == std::string::npos) break;
+        if (newline == sass::string::npos) break;
         result.append(str, pos, newline - pos);
         result += '\n';
         if (str[newline] == '\r' && str[newline + 1] == '\n') {
@@ -77,18 +77,18 @@
           pos = newline + 1;
         }
       }
-      result.append(str, pos, std::string::npos);
+      result.append(str, pos, sass::string::npos);
       return result;
     }
 
-    std::string normalize_underscores(const std::string& str) {
-      std::string normalized = str;
+    sass::string normalize_underscores(const sass::string& str) {
+      sass::string normalized = str;
       std::replace(normalized.begin(), normalized.end(), '_', '-');
       return normalized;
     }
 
-    std::string normalize_decimals(const std::string& str) {
-      std::string normalized;
+    sass::string normalize_decimals(const sass::string& str) {
+      sass::string normalized;
       if (!str.empty() && str[0] == '.') {
         normalized.reserve(str.size() + 1);
         normalized += '0';
diff --git a/libsass/src/util_string.hpp b/libsass/src/util_string.hpp
--- a/libsass/src/util_string.hpp
+++ b/libsass/src/util_string.hpp
@@ -1,6 +1,7 @@
 #ifndef SASS_UTIL_STRING_H
 #define SASS_UTIL_STRING_H
 
+#include "sass.hpp"
 #include <string>
 
 namespace Sass {
@@ -14,18 +15,18 @@
     // there is one edge case where this could give false positives
     // test could contain a (non-ascii) char exactly 32 below literal
     // ##########################################################################
-    bool equalsLiteral(const char* lit, const std::string& test);
+    bool equalsLiteral(const char* lit, const sass::string& test);
 
     // ###########################################################################
     // Returns [name] without a vendor prefix.
     // If [name] has no vendor prefix, it's returned as-is.
     // ###########################################################################
-    std::string unvendor(const std::string& name);
+    sass::string unvendor(const sass::string& name);
 
-    std::string rtrim(std::string str);
-    std::string normalize_newlines(const std::string& str);
-    std::string normalize_underscores(const std::string& str);
-    std::string normalize_decimals(const std::string& str);
+    sass::string rtrim(sass::string str);
+    sass::string normalize_newlines(const sass::string& str);
+    sass::string normalize_underscores(const sass::string& str);
+    sass::string normalize_decimals(const sass::string& str);
     char opening_bracket_for(char closing_bracket);
     char closing_bracket_for(char opening_bracket);
 
@@ -58,14 +59,14 @@
       return c;
     }
 
-    void ascii_str_tolower(std::string* s);
+    void ascii_str_tolower(sass::string* s);
 
     inline char ascii_toupper(unsigned char c) {
       if (c >= 'a' && c <= 'z') return c - 32;
       return c;
     }
 
-    void ascii_str_toupper(std::string* s);
+    void ascii_str_toupper(sass::string* s);
 
   }  // namespace Sass
 }  // namespace Util
diff --git a/libsass/src/values.cpp b/libsass/src/values.cpp
--- a/libsass/src/values.cpp
+++ b/libsass/src/values.cpp
@@ -32,7 +32,7 @@
       const List* l = Cast<List>(val);
       union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed());
       for (size_t i = 0, L = l->length(); i < L; ++i) {
-        Expression_Obj obj = l->at(i);
+        ExpressionObj obj = l->at(i);
         auto val = ast_node_to_sass_value(obj);
         sass_list_set_value(list, i, val);
       }
@@ -42,7 +42,7 @@
     {
       const Map* m = Cast<Map>(val);
       union Sass_Value* map = sass_make_map(m->length());
-      size_t i = 0; for (Expression_Obj key : m->keys()) {
+      size_t i = 0; for (ExpressionObj key : m->keys()) {
         sass_map_set_key(map, i, ast_node_to_sass_value(key));
         sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
         ++ i;
@@ -78,17 +78,17 @@
     switch (sass_value_get_tag(val)) {
       case SASS_NUMBER:
         return SASS_MEMORY_NEW(Number,
-                               ParserState("[C-VALUE]"),
+                               SourceSpan("[C-VALUE]"),
                                sass_number_get_value(val),
                                sass_number_get_unit(val));
       case SASS_BOOLEAN:
         return SASS_MEMORY_NEW(Boolean,
-                               ParserState("[C-VALUE]"),
+                               SourceSpan("[C-VALUE]"),
                                sass_boolean_get_value(val));
       case SASS_COLOR:
         // ToDo: allow to also use HSLA colors!!
         return SASS_MEMORY_NEW(Color_RGBA,
-                               ParserState("[C-VALUE]"),
+                               SourceSpan("[C-VALUE]"),
                                sass_color_get_r(val),
                                sass_color_get_g(val),
                                sass_color_get_b(val),
@@ -96,15 +96,15 @@
       case SASS_STRING:
         if (sass_string_is_quoted(val)) {
           return SASS_MEMORY_NEW(String_Quoted,
-                                 ParserState("[C-VALUE]"),
+                                 SourceSpan("[C-VALUE]"),
                                  sass_string_get_value(val));
         }
         return SASS_MEMORY_NEW(String_Constant,
-                                 ParserState("[C-VALUE]"),
+                                 SourceSpan("[C-VALUE]"),
                                  sass_string_get_value(val));
       case SASS_LIST: {
         List* l = SASS_MEMORY_NEW(List,
-                                  ParserState("[C-VALUE]"),
+                                  SourceSpan("[C-VALUE]"),
                                   sass_list_get_length(val),
                                   sass_list_get_separator(val));
         for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
@@ -114,7 +114,7 @@
         return l;
       }
       case SASS_MAP: {
-        Map* m = SASS_MEMORY_NEW(Map, ParserState("[C-VALUE]"));
+        Map* m = SASS_MEMORY_NEW(Map, SourceSpan("[C-VALUE]"));
         for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) {
           *m << std::make_pair(
             sass_value_to_ast_node(sass_map_get_key(val, i)),
@@ -123,14 +123,14 @@
         return m;
       }
       case SASS_NULL:
-        return SASS_MEMORY_NEW(Null, ParserState("[C-VALUE]"));
+        return SASS_MEMORY_NEW(Null, SourceSpan("[C-VALUE]"));
       case SASS_ERROR:
         return SASS_MEMORY_NEW(Custom_Error,
-                               ParserState("[C-VALUE]"),
+                               SourceSpan("[C-VALUE]"),
                                sass_error_get_message(val));
       case SASS_WARNING:
         return SASS_MEMORY_NEW(Custom_Warning,
-                               ParserState("[C-VALUE]"),
+                               SourceSpan("[C-VALUE]"),
                                sass_warning_get_message(val));
       default: break;
     }
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -35,7 +35,7 @@
 #ifndef EXTERNAL_LIBSASS
     it "should report correct version" $ do
         str <- peekCString libsass_version
-        str `shouldBe` "3.6.3"
+        str `shouldBe` "3.6.4"
 #endif
 
     it "should support quoted strings" $ withCString "sample" $ \cstr -> do
