Preprocessor update from ANGLE

- Updated preprocessor code from Angle revision
  9fc8733187c02470a9eadb6d295348b6d37a2004
- Reran generate_parser.sh (flex 2.6.4, bison (GNU Bison) 3.0.4)
- Made a few trivial changes in src/OpenGL/compiler in order to
  adapt to the new preprocessor code.

Fixes all 24 failures in:
dEQP-GLES3.functional.shaders.preprocessor.*

Change-Id: I00d0b511d617ab81a0f57310174e1ba8bf7c22e5
Reviewed-on: https://swiftshader-review.googlesource.com/15109
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/Diagnostics.h b/src/OpenGL/compiler/Diagnostics.h
index 35983ac..43ee573 100644
--- a/src/OpenGL/compiler/Diagnostics.h
+++ b/src/OpenGL/compiler/Diagnostics.h
@@ -15,7 +15,7 @@
 #ifndef COMPILER_DIAGNOSTICS_H_
 #define COMPILER_DIAGNOSTICS_H_
 
-#include "preprocessor/Diagnostics.h"
+#include "preprocessor/DiagnosticsBase.h"
 
 class TInfoSink;
 
diff --git a/src/OpenGL/compiler/DirectiveHandler.cpp b/src/OpenGL/compiler/DirectiveHandler.cpp
index 2391d35..ef61d47 100644
--- a/src/OpenGL/compiler/DirectiveHandler.cpp
+++ b/src/OpenGL/compiler/DirectiveHandler.cpp
@@ -54,7 +54,8 @@
 
 void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
                                      const std::string& name,
-                                     const std::string& value)
+                                     const std::string& value,
+                                     bool stdgl)
 {
 	static const std::string kSTDGL("STDGL");
 	static const std::string kOptimize("optimize");
@@ -63,7 +64,7 @@
 	static const std::string kOff("off");
 
 	bool invalidValue = false;
-	if (name == kSTDGL)
+	if (stdgl || (name == kSTDGL))
 	{
 		// The STDGL pragma is used to reserve pragmas for use by future
 		// revisions of GLSL. Ignore it.
@@ -83,7 +84,7 @@
 	}
 	else
 	{
-		mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name);
+		mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
 		return;
 	}
 
diff --git a/src/OpenGL/compiler/DirectiveHandler.h b/src/OpenGL/compiler/DirectiveHandler.h
index f77d1f9..0538c59 100644
--- a/src/OpenGL/compiler/DirectiveHandler.h
+++ b/src/OpenGL/compiler/DirectiveHandler.h
@@ -17,7 +17,7 @@
 
 #include "ExtensionBehavior.h"
 #include "Pragma.h"
-#include "preprocessor/DirectiveHandler.h"
+#include "preprocessor/DirectiveHandlerBase.h"
 
 class TDiagnostics;
 
@@ -37,7 +37,8 @@
 
 	virtual void handlePragma(const pp::SourceLocation& loc,
 	                          const std::string& name,
-	                          const std::string& value);
+	                          const std::string& value,
+	                          bool stdgl);
 
 	virtual void handleExtension(const pp::SourceLocation& loc,
 	                             const std::string& name,
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index 8a93a28..cb513de 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -1122,10 +1122,10 @@
 	mDirectiveHandler.handleExtension(loc, extName, behavior);
 }
 
-void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value)
+void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl)
 {
 	pp::SourceLocation loc(line.first_file, line.first_line);
-	mDirectiveHandler.handlePragma(loc, name, value);
+	mDirectiveHandler.handlePragma(loc, name, value, stdgl);
 }
 
 /////////////////////////////////////////////////////////////////////////////////
diff --git a/src/OpenGL/compiler/ParseHelper.h b/src/OpenGL/compiler/ParseHelper.h
index 5a7ff88..07abf0f 100644
--- a/src/OpenGL/compiler/ParseHelper.h
+++ b/src/OpenGL/compiler/ParseHelper.h
@@ -56,7 +56,7 @@
 			mDefaultBlockStorage(EbsShared),
 			mDiagnostics(is),
 			mDirectiveHandler(ext, mDiagnostics, mShaderVersion),
-			mPreprocessor(&mDiagnostics, &mDirectiveHandler),
+			mPreprocessor(&mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
 			mScanner(nullptr),
 			mUsesFragData(false),
 			mUsesFragColor(false) {  }
@@ -148,7 +148,7 @@
 	void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior);
 
 	const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
-	void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value);
+	void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl);
 
 	bool containsSampler(TType& type);
 	const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0);
diff --git a/src/OpenGL/compiler/preprocessor/Diagnostics.cpp b/src/OpenGL/compiler/preprocessor/Diagnostics.cpp
deleted file mode 100644
index 767edd9..0000000
--- a/src/OpenGL/compiler/preprocessor/Diagnostics.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "Diagnostics.h"
-
-#include <cassert>
-
-namespace pp
-{
-
-Diagnostics::~Diagnostics()
-{
-}
-
-void Diagnostics::report(ID id,
-                         const SourceLocation& loc,
-                         const std::string& text)
-{
-	// TODO(alokp): Keep a count of errors and warnings.
-	print(id, loc, text);
-}
-
-Diagnostics::Severity Diagnostics::severity(ID id)
-{
-	if ((id > ERROR_BEGIN) && (id < ERROR_END))
-		return PP_ERROR;
-
-	if ((id > WARNING_BEGIN) && (id < WARNING_END))
-		return PP_WARNING;
-
-	assert(false);
-	return PP_ERROR;
-}
-
-std::string Diagnostics::message(ID id)
-{
-	switch (id)
-	{
-	// Errors begin.
-	case INTERNAL_ERROR:
-		  return "internal error";
-	case OUT_OF_MEMORY:
-		  return "out of memory";
-	case INVALID_CHARACTER:
-		  return "invalid character";
-	case INVALID_NUMBER:
-		  return "invalid number";
-	case INTEGER_OVERFLOW:
-		  return "integer overflow";
-	case FLOAT_OVERFLOW:
-		  return "float overflow";
-	case TOKEN_TOO_LONG:
-		  return "token too long";
-	case INVALID_EXPRESSION:
-		  return "invalid expression";
-	case DIVISION_BY_ZERO:
-		  return "division by zero";
-	case EOF_IN_COMMENT:
-		  return "unexpected end of file found in comment";
-	case UNEXPECTED_TOKEN:
-		  return "unexpected token";
-	case DIRECTIVE_INVALID_NAME:
-		  return "invalid directive name";
-	case MACRO_NAME_RESERVED:
-		  return "macro name is reserved";
-	case MACRO_REDEFINED:
-		  return "macro redefined";
-	case MACRO_PREDEFINED_REDEFINED:
-		  return "predefined macro redefined";
-	case MACRO_PREDEFINED_UNDEFINED:
-		  return "predefined macro undefined";
-	case MACRO_UNTERMINATED_INVOCATION:
-		  return "unterminated macro invocation";
-	case MACRO_TOO_FEW_ARGS:
-		  return "Not enough arguments for macro";
-	case MACRO_TOO_MANY_ARGS:
-		  return "Too many arguments for macro";
-	case MACRO_DUPLICATE_PARAMETER_NAMES:
-		  return "duplicate macro parameter name";
-	case CONDITIONAL_ENDIF_WITHOUT_IF:
-		  return "unexpected #endif found without a matching #if";
-	case CONDITIONAL_ELSE_WITHOUT_IF:
-		  return "unexpected #else found without a matching #if";
-	case CONDITIONAL_ELSE_AFTER_ELSE:
-		  return "unexpected #else found after another #else";
-	case CONDITIONAL_ELIF_WITHOUT_IF:
-		  return "unexpected #elif found without a matching #if";
-	case CONDITIONAL_ELIF_AFTER_ELSE:
-		  return "unexpected #elif found after #else";
-	case CONDITIONAL_UNTERMINATED:
-		  return "unexpected end of file found in conditional block";
-	case INVALID_EXTENSION_NAME:
-		  return "invalid extension name";
-	case INVALID_EXTENSION_BEHAVIOR:
-		  return "invalid extension behavior";
-	case INVALID_EXTENSION_DIRECTIVE:
-		  return "invalid extension directive";
-	case INVALID_VERSION_NUMBER:
-		  return "invalid version number";
-	case INVALID_VERSION_DIRECTIVE:
-		  return "invalid version directive";
-	case VERSION_NOT_FIRST_STATEMENT:
-		return "#version directive must occur before anything else, "
-		       "except for comments and white space";
-	case INVALID_LINE_NUMBER:
-		  return "invalid line number";
-	case INVALID_FILE_NUMBER:
-		  return "invalid file number";
-	case INVALID_LINE_DIRECTIVE:
-		  return "invalid line directive";
-	case UNDEFINED_IDENTIFIER:
-		  return "undefined identifier";
-	// Errors end.
-	// Warnings begin.
-	case EOF_IN_DIRECTIVE:
-		  return "unexpected end of file found in directive";
-	case CONDITIONAL_UNEXPECTED_TOKEN:
-		  return "unexpected token after conditional expression";
-	case UNRECOGNIZED_PRAGMA:
-		  return "unrecognized pragma";
-	// Warnings end.
-	default:
-		  assert(false);
-		  return "";
-	}
-}
-
-}  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Diagnostics.h b/src/OpenGL/compiler/preprocessor/Diagnostics.h
deleted file mode 100644
index 1f4cfc4..0000000
--- a/src/OpenGL/compiler/preprocessor/Diagnostics.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
-#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
-
-#include <string>
-
-namespace pp
-{
-
-struct SourceLocation;
-
-// Base class for reporting diagnostic messages.
-// Derived classes are responsible for formatting and printing the messages.
-class Diagnostics
-{
-public:
-	enum Severity
-	{
-		PP_ERROR,
-		PP_WARNING
-	};
-	enum ID
-	{
-		ERROR_BEGIN,
-		INTERNAL_ERROR,
-		OUT_OF_MEMORY,
-		INVALID_CHARACTER,
-		INVALID_NUMBER,
-		INTEGER_OVERFLOW,
-		FLOAT_OVERFLOW,
-		TOKEN_TOO_LONG,
-		INVALID_EXPRESSION,
-		DIVISION_BY_ZERO,
-		EOF_IN_COMMENT,
-		UNEXPECTED_TOKEN,
-		DIRECTIVE_INVALID_NAME,
-		MACRO_NAME_RESERVED,
-		MACRO_REDEFINED,
-		MACRO_PREDEFINED_REDEFINED,
-		MACRO_PREDEFINED_UNDEFINED,
-		MACRO_UNTERMINATED_INVOCATION,
-		MACRO_TOO_FEW_ARGS,
-		MACRO_TOO_MANY_ARGS,
-		MACRO_DUPLICATE_PARAMETER_NAMES,
-		CONDITIONAL_ENDIF_WITHOUT_IF,
-		CONDITIONAL_ELSE_WITHOUT_IF,
-		CONDITIONAL_ELSE_AFTER_ELSE,
-		CONDITIONAL_ELIF_WITHOUT_IF,
-		CONDITIONAL_ELIF_AFTER_ELSE,
-		CONDITIONAL_UNTERMINATED,
-		CONDITIONAL_UNEXPECTED_TOKEN,
-		INVALID_EXTENSION_NAME,
-		INVALID_EXTENSION_BEHAVIOR,
-		INVALID_EXTENSION_DIRECTIVE,
-		INVALID_VERSION_NUMBER,
-		INVALID_VERSION_DIRECTIVE,
-		VERSION_NOT_FIRST_STATEMENT,
-		INVALID_LINE_NUMBER,
-		INVALID_FILE_NUMBER,
-		INVALID_LINE_DIRECTIVE,
-		UNDEFINED_IDENTIFIER,
-		ERROR_END,
-
-		WARNING_BEGIN,
-		EOF_IN_DIRECTIVE,
-		UNRECOGNIZED_PRAGMA,
-		WARNING_END
-	};
-
-	virtual ~Diagnostics();
-
-	void report(ID id, const SourceLocation& loc, const std::string& text);
-
-protected:
-	Severity severity(ID id);
-	std::string message(ID id);
-
-	virtual void print(ID id,
-	                   const SourceLocation& loc,
-	                   const std::string& text) = 0;
-};
-
-}  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
diff --git a/src/OpenGL/compiler/preprocessor/DiagnosticsBase.cpp b/src/OpenGL/compiler/preprocessor/DiagnosticsBase.cpp
new file mode 100644
index 0000000..0cea776
--- /dev/null
+++ b/src/OpenGL/compiler/preprocessor/DiagnosticsBase.cpp
@@ -0,0 +1,163 @@
+// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "DiagnosticsBase.h"
+
+#include <cassert>
+
+namespace pp
+{
+
+Diagnostics::~Diagnostics()
+{
+}
+
+void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text)
+{
+	print(id, loc, text);
+}
+
+bool Diagnostics::isError(ID id)
+{
+	if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
+		return true;
+
+	if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
+		return false;
+
+	assert(false);
+	return true;
+}
+
+Diagnostics::Severity Diagnostics::severity(ID id)
+{
+	if((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
+		return PP_ERROR;
+
+	if((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
+		return PP_WARNING;
+
+	assert(false);
+	return PP_ERROR;
+}
+
+const char *Diagnostics::message(ID id)
+{
+	switch (id)
+	{
+	// Errors begin.
+	case PP_INTERNAL_ERROR:
+		return "internal error";
+	case PP_OUT_OF_MEMORY:
+		return "out of memory";
+	case PP_INVALID_CHARACTER:
+		return "invalid character";
+	case PP_INVALID_NUMBER:
+		return "invalid number";
+	case PP_INTEGER_OVERFLOW:
+		return "integer overflow";
+	case PP_FLOAT_OVERFLOW:
+		return "float overflow";
+	case PP_TOKEN_TOO_LONG:
+		return "token too long";
+	case PP_INVALID_EXPRESSION:
+		return "invalid expression";
+	case PP_DIVISION_BY_ZERO:
+		return "division by zero";
+	case PP_EOF_IN_COMMENT:
+		return "unexpected end of file found in comment";
+	case PP_UNEXPECTED_TOKEN:
+		return "unexpected token";
+	case PP_DIRECTIVE_INVALID_NAME:
+		return "invalid directive name";
+	case PP_MACRO_NAME_RESERVED:
+		return "macro name is reserved";
+	case PP_MACRO_REDEFINED:
+		return "macro redefined";
+	case PP_MACRO_PREDEFINED_REDEFINED:
+		return "predefined macro redefined";
+	case PP_MACRO_PREDEFINED_UNDEFINED:
+		return "predefined macro undefined";
+	case PP_MACRO_UNTERMINATED_INVOCATION:
+		return "unterminated macro invocation";
+	case PP_MACRO_UNDEFINED_WHILE_INVOKED:
+		return "macro undefined while being invoked";
+	case PP_MACRO_TOO_FEW_ARGS:
+		return "Not enough arguments for macro";
+	case PP_MACRO_TOO_MANY_ARGS:
+		return "Too many arguments for macro";
+	case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
+		return "duplicate macro parameter name";
+	case PP_MACRO_INVOCATION_CHAIN_TOO_DEEP:
+		return "macro invocation chain too deep";
+	case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
+		return "unexpected #endif found without a matching #if";
+	case PP_CONDITIONAL_ELSE_WITHOUT_IF:
+		return "unexpected #else found without a matching #if";
+	case PP_CONDITIONAL_ELSE_AFTER_ELSE:
+		return "unexpected #else found after another #else";
+	case PP_CONDITIONAL_ELIF_WITHOUT_IF:
+		return "unexpected #elif found without a matching #if";
+	case PP_CONDITIONAL_ELIF_AFTER_ELSE:
+		return "unexpected #elif found after #else";
+	case PP_CONDITIONAL_UNTERMINATED:
+		return "unexpected end of file found in conditional block";
+	case PP_INVALID_EXTENSION_NAME:
+		return "invalid extension name";
+	case PP_INVALID_EXTENSION_BEHAVIOR:
+		return "invalid extension behavior";
+	case PP_INVALID_EXTENSION_DIRECTIVE:
+		return "invalid extension directive";
+	case PP_INVALID_VERSION_NUMBER:
+		return "invalid version number";
+	case PP_INVALID_VERSION_DIRECTIVE:
+		return "invalid version directive";
+	case PP_VERSION_NOT_FIRST_STATEMENT:
+		return "#version directive must occur before anything else, "
+		       "except for comments and white space";
+	case PP_VERSION_NOT_FIRST_LINE_ESSL3:
+		return "#version directive must occur on the first line of the shader";
+	case PP_INVALID_LINE_NUMBER:
+		return "invalid line number";
+	case PP_INVALID_FILE_NUMBER:
+		return "invalid file number";
+	case PP_INVALID_LINE_DIRECTIVE:
+		return "invalid line directive";
+	case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
+		return "extension directive must occur before any non-preprocessor tokens in ESSL3";
+	case PP_UNDEFINED_SHIFT:
+		return "shift exponent is negative or undefined";
+	case PP_TOKENIZER_ERROR:
+		return "internal tokenizer error";
+	// Errors end.
+	// Warnings begin.
+	case PP_EOF_IN_DIRECTIVE:
+		return "unexpected end of file found in directive";
+	case PP_CONDITIONAL_UNEXPECTED_TOKEN:
+		return "unexpected token after conditional expression";
+	case PP_UNRECOGNIZED_PRAGMA:
+		return "unrecognized pragma";
+	case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
+		return "extension directive should occur before any non-preprocessor tokens";
+	case PP_WARNING_MACRO_NAME_RESERVED:
+		return "macro name with a double underscore is reserved - unintented behavior is "
+		       "possible";
+	// Warnings end.
+	default:
+		assert(false);
+		return "";
+	}
+}
+
+}  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/DiagnosticsBase.h b/src/OpenGL/compiler/preprocessor/DiagnosticsBase.h
new file mode 100644
index 0000000..16e6881
--- /dev/null
+++ b/src/OpenGL/compiler/preprocessor/DiagnosticsBase.h
@@ -0,0 +1,106 @@
+// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
+#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
+
+#include <string>
+
+namespace pp
+{
+
+struct SourceLocation;
+
+// Base class for reporting diagnostic messages.
+// Derived classes are responsible for formatting and printing the messages.
+class Diagnostics
+{
+public:
+	// Severity is used to classify info log messages.
+	enum Severity
+	{
+		PP_WARNING,
+		PP_ERROR
+	};
+
+	enum ID
+	{
+		PP_ERROR_BEGIN,
+		PP_INTERNAL_ERROR,
+		PP_OUT_OF_MEMORY,
+		PP_INVALID_CHARACTER,
+		PP_INVALID_NUMBER,
+		PP_INTEGER_OVERFLOW,
+		PP_FLOAT_OVERFLOW,
+		PP_TOKEN_TOO_LONG,
+		PP_INVALID_EXPRESSION,
+		PP_DIVISION_BY_ZERO,
+		PP_EOF_IN_COMMENT,
+		PP_UNEXPECTED_TOKEN,
+		PP_DIRECTIVE_INVALID_NAME,
+		PP_MACRO_NAME_RESERVED,
+		PP_MACRO_REDEFINED,
+		PP_MACRO_PREDEFINED_REDEFINED,
+		PP_MACRO_PREDEFINED_UNDEFINED,
+		PP_MACRO_UNTERMINATED_INVOCATION,
+		PP_MACRO_UNDEFINED_WHILE_INVOKED,
+		PP_MACRO_TOO_FEW_ARGS,
+		PP_MACRO_TOO_MANY_ARGS,
+		PP_MACRO_DUPLICATE_PARAMETER_NAMES,
+		PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
+		PP_CONDITIONAL_ENDIF_WITHOUT_IF,
+		PP_CONDITIONAL_ELSE_WITHOUT_IF,
+		PP_CONDITIONAL_ELSE_AFTER_ELSE,
+		PP_CONDITIONAL_ELIF_WITHOUT_IF,
+		PP_CONDITIONAL_ELIF_AFTER_ELSE,
+		PP_CONDITIONAL_UNTERMINATED,
+		PP_CONDITIONAL_UNEXPECTED_TOKEN,
+		PP_INVALID_EXTENSION_NAME,
+		PP_INVALID_EXTENSION_BEHAVIOR,
+		PP_INVALID_EXTENSION_DIRECTIVE,
+		PP_INVALID_VERSION_NUMBER,
+		PP_INVALID_VERSION_DIRECTIVE,
+		PP_VERSION_NOT_FIRST_STATEMENT,
+		PP_VERSION_NOT_FIRST_LINE_ESSL3,
+		PP_INVALID_LINE_NUMBER,
+		PP_INVALID_FILE_NUMBER,
+		PP_INVALID_LINE_DIRECTIVE,
+		PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+		PP_UNDEFINED_SHIFT,
+		PP_TOKENIZER_ERROR,
+		PP_ERROR_END,
+
+		PP_WARNING_BEGIN,
+		PP_EOF_IN_DIRECTIVE,
+		PP_UNRECOGNIZED_PRAGMA,
+		PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
+		PP_WARNING_MACRO_NAME_RESERVED,
+		PP_WARNING_END
+	};
+
+	virtual ~Diagnostics();
+
+	void report(ID id, const SourceLocation &loc, const std::string &text);
+
+protected:
+	bool isError(ID id);
+	const char *message(ID id);
+	Severity severity(ID id);
+
+	virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0;
+};
+
+}  // namespace pp
+
+#endif  // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveHandler.h b/src/OpenGL/compiler/preprocessor/DirectiveHandler.h
deleted file mode 100644
index f7b3784..0000000
--- a/src/OpenGL/compiler/preprocessor/DirectiveHandler.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
-#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
-
-#include <string>
-
-namespace pp
-{
-
-struct SourceLocation;
-
-// Base class for handling directives.
-// Preprocessor uses this class to notify the clients about certain
-// preprocessor directives. Derived classes are responsible for
-// handling them in an appropriate manner.
-class DirectiveHandler
-{
-public:
-	virtual ~DirectiveHandler();
-
-	virtual void handleError(const SourceLocation& loc,
-	                         const std::string& msg) = 0;
-
-	// Handle pragma of form: #pragma name[(value)]
-	virtual void handlePragma(const SourceLocation& loc,
-	                          const std::string& name,
-	                          const std::string& value) = 0;
-
-	virtual void handleExtension(const SourceLocation& loc,
-	                             const std::string& name,
-	                             const std::string& behavior) = 0;
-
-	virtual void handleVersion(const SourceLocation& loc,
-	                           int version) = 0;
-};
-
-}  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp b/src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.cpp
similarity index 86%
rename from src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp
rename to src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.cpp
index ac26c83..e1f1015 100644
--- a/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp
+++ b/src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "DirectiveHandler.h"
+#include "DirectiveHandlerBase.h"
 
 namespace pp
 {
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.h b/src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.h
new file mode 100644
index 0000000..54ddc9d
--- /dev/null
+++ b/src/OpenGL/compiler/preprocessor/DirectiveHandlerBase.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
+
+#include <string>
+
+namespace pp
+{
+
+struct SourceLocation;
+
+// Base class for handling directives.
+// Preprocessor uses this class to notify the clients about certain
+// preprocessor directives. Derived classes are responsible for
+// handling them in an appropriate manner.
+class DirectiveHandler
+{
+  public:
+	virtual ~DirectiveHandler();
+
+	virtual void handleError(const SourceLocation &loc, const std::string &msg) = 0;
+
+	// Handle pragma of form: #pragma name[(value)]
+	virtual void handlePragma(const SourceLocation &loc,
+	                          const std::string &name,
+	                          const std::string &value,
+	                          bool stdgl) = 0;
+
+	virtual void handleExtension(const SourceLocation &loc,
+	                             const std::string &name,
+	                             const std::string &behavior) = 0;
+
+	virtual void handleVersion(const SourceLocation &loc, int version) = 0;
+};
+
+}  // namespace pp
+
+#endif  // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp b/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp
index ec77c21..9eb044e 100644
--- a/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp
@@ -14,12 +14,13 @@
 
 #include "DirectiveParser.h"
 
+#include <algorithm>
 #include <cassert>
 #include <cstdlib>
 #include <sstream>
 
-#include "Diagnostics.h"
-#include "DirectiveHandler.h"
+#include "DiagnosticsBase.h"
+#include "DirectiveHandlerBase.h"
 #include "ExpressionParser.h"
 #include "MacroExpander.h"
 #include "Token.h"
@@ -45,7 +46,7 @@
 };
 }  // namespace
 
-static DirectiveType getDirective(const pp::Token* token)
+static DirectiveType getDirective(const pp::Token *token)
 {
 	static const std::string kDirectiveDefine("define");
 	static const std::string kDirectiveUndef("undef");
@@ -111,12 +112,12 @@
 }
 
 // Returns true if the token represents End Of Directive.
-static bool isEOD(const pp::Token* token)
+static bool isEOD(const pp::Token *token)
 {
 	return (token->type == '\n') || (token->type == pp::Token::LAST);
 }
 
-static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token)
+static void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
 {
 	while(!isEOD(token))
 	{
@@ -127,39 +128,105 @@
 static bool isMacroNameReserved(const std::string& name)
 {
 	// Names prefixed with "GL_" are reserved.
-	if (name.substr(0, 3) == "GL_")
-		return true;
+	return (name.substr(0, 3) == "GL_");
+}
 
-	// Names containing two consecutive underscores are reserved.
-	if (name.find("__") != std::string::npos)
-		return true;
-
-	return false;
+bool hasDoubleUnderscores(const std::string &name)
+{
+	return (name.find("__") != std::string::npos);
 }
 
 static bool isMacroPredefined(const std::string& name,
                               const pp::MacroSet& macroSet)
 {
 	pp::MacroSet::const_iterator iter = macroSet.find(name);
-	return iter != macroSet.end() ? iter->second.predefined : false;
+	return iter != macroSet.end() ? iter->second->predefined : false;
 }
 
 namespace pp
 {
 
-DirectiveParser::DirectiveParser(Tokenizer* tokenizer,
-                                 MacroSet* macroSet,
-                                 Diagnostics* diagnostics,
-                                 DirectiveHandler* directiveHandler) :
-	mPastFirstStatement(false),
-	mTokenizer(tokenizer),
-	mMacroSet(macroSet),
-	mDiagnostics(diagnostics),
-	mDirectiveHandler(directiveHandler)
+class DefinedParser : public Lexer
+{
+public:
+	DefinedParser(Lexer *lexer, const MacroSet *macroSet, Diagnostics *diagnostics)
+		: mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
+	{
+	}
+
+protected:
+	void lex(Token *token) override
+	{
+		const char kDefined[] = "defined";
+
+		mLexer->lex(token);
+		if (token->type != Token::IDENTIFIER)
+			return;
+		if (token->text != kDefined)
+			return;
+
+		bool paren = false;
+		mLexer->lex(token);
+		if (token->type == '(')
+		{
+			paren = true;
+			mLexer->lex(token);
+		}
+
+		if (token->type != Token::IDENTIFIER)
+		{
+			mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
+			skipUntilEOD(mLexer, token);
+			return;
+		}
+		MacroSet::const_iterator iter = mMacroSet->find(token->text);
+		std::string expression = iter != mMacroSet->end() ? "1" : "0";
+
+		if (paren)
+		{
+			mLexer->lex(token);
+			if (token->type != ')')
+			{
+				mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
+				                     token->location, token->text);
+				skipUntilEOD(mLexer, token);
+				return;
+			}
+		}
+
+		// We have a valid defined operator.
+		// Convert the current token into a CONST_INT token.
+		token->type = Token::CONST_INT;
+		token->text = expression;
+	}
+
+private:
+	Lexer *mLexer;
+	const MacroSet *mMacroSet;
+	Diagnostics *mDiagnostics;
+};
+
+DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
+                                 MacroSet *macroSet,
+                                 Diagnostics *diagnostics,
+                                 DirectiveHandler *directiveHandler,
+                                 int maxMacroExpansionDepth)
+    : mPastFirstStatement(false),
+      mSeenNonPreprocessorToken(false),
+      mTokenizer(tokenizer),
+      mMacroSet(macroSet),
+      mDiagnostics(diagnostics),
+      mDirectiveHandler(directiveHandler),
+      mShaderVersion(100),
+      mMaxMacroExpansionDepth(maxMacroExpansionDepth)
 {
 }
 
-void DirectiveParser::lex(Token* token)
+DirectiveParser::~DirectiveParser()
+{
+}
+
+void DirectiveParser::lex(Token *token)
 {
 	do
 	{
@@ -170,13 +237,17 @@
 			parseDirective(token);
 			mPastFirstStatement = true;
 		}
+		else if (!isEOD(token))
+		{
+			mSeenNonPreprocessorToken = true;
+		}
 
 		if (token->type == Token::LAST)
 		{
 			if (!mConditionalStack.empty())
 			{
-				const ConditionalBlock& block = mConditionalStack.back();
-				mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED,
+				const ConditionalBlock &block = mConditionalStack.back();
+				mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED,
 				                     block.location, block.type);
 			}
 			break;
@@ -187,7 +258,7 @@
 	mPastFirstStatement = true;
 }
 
-void DirectiveParser::parseDirective(Token* token)
+void DirectiveParser::parseDirective(Token *token)
 {
 	assert(token->type == Token::PP_HASH);
 
@@ -211,7 +282,7 @@
 	switch(directive)
 	{
 	case DIRECTIVE_NONE:
-		mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME,
+		mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		break;
@@ -262,64 +333,74 @@
 	skipUntilEOD(mTokenizer, token);
 	if (token->type == Token::LAST)
 	{
-		mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE,
+		mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE,
 		                     token->location, token->text);
 	}
 }
 
-void DirectiveParser::parseDefine(Token* token)
+void DirectiveParser::parseDefine(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_DEFINE);
 
 	mTokenizer->lex(token);
 	if (token->type != Token::IDENTIFIER)
 	{
-		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		return;
 	}
 	if (isMacroPredefined(token->text, *mMacroSet))
 	{
-		mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED,
+		mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
 		                     token->location, token->text);
 		return;
 	}
 	if (isMacroNameReserved(token->text))
 	{
-		mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED,
+		mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
 		                     token->location, token->text);
 		return;
 	}
+	// Using double underscores is allowed, but may result in unintended
+	// behavior, so a warning is issued. At the time of writing this was
+	// specified in ESSL 3.10, but the intent judging from Khronos
+	// discussions and dEQP tests was that double underscores should be
+	// allowed in earlier ESSL versions too.
+	if (hasDoubleUnderscores(token->text))
+	{
+		mDiagnostics->report(Diagnostics::PP_WARNING_MACRO_NAME_RESERVED, token->location,
+		                     token->text);
+	}
 
-	Macro macro;
-	macro.type = Macro::kTypeObj;
-	macro.name = token->text;
+	std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+	macro->type = Macro::kTypeObj;
+	macro->name = token->text;
 
 	mTokenizer->lex(token);
 	if (token->type == '(' && !token->hasLeadingSpace())
 	{
 		// Function-like macro. Collect arguments.
-		macro.type = Macro::kTypeFunc;
+		macro->type = Macro::kTypeFunc;
 		do {
 			mTokenizer->lex(token);
 			if (token->type != Token::IDENTIFIER)
 				break;
 
-			if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end())
+			if (std::find(macro->parameters.begin(), macro->parameters.end(), token->text) != macro->parameters.end())
 			{
-				mDiagnostics->report(Diagnostics::MACRO_DUPLICATE_PARAMETER_NAMES,
+				mDiagnostics->report(Diagnostics::PP_MACRO_DUPLICATE_PARAMETER_NAMES,
 				                     token->location, token->text);
 				return;
 			}
 
-			macro.parameters.push_back(token->text);
+			macro->parameters.push_back(token->text);
 
 			mTokenizer->lex(token);  // Get ','.
 		} while (token->type == ',');
 
 		if (token->type != ')')
 		{
-			mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+			mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
 			                     token->location,
 			                     token->text);
 			return;
@@ -333,36 +414,34 @@
 		// list. Resetting it also allows us to reuse Token::equals() to
 		// compare macros.
 		token->location = SourceLocation();
-		macro.replacements.push_back(*token);
+		macro->replacements.push_back(*token);
 		mTokenizer->lex(token);
 	}
-	if (!macro.replacements.empty())
+	if (!macro->replacements.empty())
 	{
 		// Whitespace preceding the replacement list is not considered part of
 		// the replacement list for either form of macro.
-		macro.replacements.front().setHasLeadingSpace(false);
+		macro->replacements.front().setHasLeadingSpace(false);
 	}
 
 	// Check for macro redefinition.
-	MacroSet::const_iterator iter = mMacroSet->find(macro.name);
-	if (iter != mMacroSet->end() && !macro.equals(iter->second))
+	MacroSet::const_iterator iter = mMacroSet->find(macro->name);
+	if (iter != mMacroSet->end() && !macro->equals(*iter->second))
 	{
-		mDiagnostics->report(Diagnostics::MACRO_REDEFINED,
-		                     token->location,
-		                     macro.name);
+		mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro->name);
 		return;
 	}
-	mMacroSet->insert(std::make_pair(macro.name, macro));
+	mMacroSet->insert(std::make_pair(macro->name, macro));
 }
 
-void DirectiveParser::parseUndef(Token* token)
+void DirectiveParser::parseUndef(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_UNDEF);
 
 	mTokenizer->lex(token);
 	if (token->type != Token::IDENTIFIER)
 	{
-		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		return;
 	}
@@ -370,10 +449,17 @@
 	MacroSet::iterator iter = mMacroSet->find(token->text);
 	if (iter != mMacroSet->end())
 	{
-		if (iter->second.predefined)
+		if (iter->second->predefined)
 		{
-			mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED,
+			mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
 			                     token->location, token->text);
+			return;
+		}
+		else if (iter->second->expansionCount > 0)
+		{
+			mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
+			                     token->location, token->text);
+			return;
 		}
 		else
 		{
@@ -382,39 +468,44 @@
 	}
 
 	mTokenizer->lex(token);
+	if (!isEOD(token))
+	{
+		mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
+		skipUntilEOD(mTokenizer, token);
+	}
 }
 
-void DirectiveParser::parseIf(Token* token)
+void DirectiveParser::parseIf(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_IF);
 	parseConditionalIf(token);
 }
 
-void DirectiveParser::parseIfdef(Token* token)
+void DirectiveParser::parseIfdef(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_IFDEF);
 	parseConditionalIf(token);
 }
 
-void DirectiveParser::parseIfndef(Token* token)
+void DirectiveParser::parseIfndef(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_IFNDEF);
 	parseConditionalIf(token);
 }
 
-void DirectiveParser::parseElse(Token* token)
+void DirectiveParser::parseElse(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_ELSE);
 
 	if (mConditionalStack.empty())
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
 	}
 
-	ConditionalBlock& block = mConditionalStack.back();
+	ConditionalBlock &block = mConditionalStack.back();
 	if (block.skipBlock)
 	{
 		// No diagnostics. Just skip the whole line.
@@ -423,7 +514,7 @@
 	}
 	if (block.foundElseGroup)
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
@@ -437,25 +528,25 @@
 	mTokenizer->lex(token);
 	if (!isEOD(token))
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 	}
 }
 
-void DirectiveParser::parseElif(Token* token)
+void DirectiveParser::parseElif(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_ELIF);
 
 	if (mConditionalStack.empty())
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
 	}
 
-	ConditionalBlock& block = mConditionalStack.back();
+	ConditionalBlock &block = mConditionalStack.back();
 	if (block.skipBlock)
 	{
 		// No diagnostics. Just skip the whole line.
@@ -464,7 +555,7 @@
 	}
 	if (block.foundElseGroup)
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
@@ -483,13 +574,13 @@
 	block.foundValidGroup = expression != 0;
 }
 
-void DirectiveParser::parseEndif(Token* token)
+void DirectiveParser::parseEndif(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_ENDIF);
 
 	if (mConditionalStack.empty())
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
@@ -501,13 +592,13 @@
 	mTokenizer->lex(token);
 	if (!isEOD(token))
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 	}
 }
 
-void DirectiveParser::parseError(Token* token)
+void DirectiveParser::parseError(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_ERROR);
 
@@ -522,7 +613,7 @@
 }
 
 // Parses pragma of form: #pragma name[(value)].
-void DirectiveParser::parsePragma(Token* token)
+void DirectiveParser::parsePragma(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_PRAGMA);
 
@@ -539,6 +630,11 @@
 	int state = PRAGMA_NAME;
 
 	mTokenizer->lex(token);
+	bool stdgl = token->text == "STDGL";
+	if (stdgl)
+	{
+		mTokenizer->lex(token);
+	}
 	while ((token->type != '\n') && (token->type != Token::LAST))
 	{
 		switch(state++)
@@ -569,16 +665,15 @@
 	                  (state == RIGHT_PAREN + 1));  // With value.
 	if (!valid)
 	{
-		mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA,
-		                     token->location, name);
+		mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name);
 	}
 	else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
 	{
-		mDirectiveHandler->handlePragma(token->location, name, value);
+		mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
 	}
 }
 
-void DirectiveParser::parseExtension(Token* token)
+void DirectiveParser::parseExtension(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_EXTENSION);
 
@@ -598,61 +693,77 @@
 	{
 		switch (state++)
 		{
-		case EXT_NAME:
-			if (valid && (token->type != Token::IDENTIFIER))
-			{
-				mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME,
-				                     token->location, token->text);
-				valid = false;
-			}
-			if (valid) name = token->text;
-			break;
-		case COLON:
-			if (valid && (token->type != ':'))
-			{
-				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-				                     token->location, token->text);
-				valid = false;
-			}
-			break;
-		case EXT_BEHAVIOR:
-			if (valid && (token->type != Token::IDENTIFIER))
-			{
-				mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR,
-				                     token->location, token->text);
-				valid = false;
-			}
-			if (valid) behavior = token->text;
-			break;
-		default:
-			if (valid)
-			{
-				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-				                     token->location, token->text);
-				valid = false;
-			}
-			break;
+			case EXT_NAME:
+				if (valid && (token->type != Token::IDENTIFIER))
+				{
+					mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location,
+					                     token->text);
+					valid = false;
+				}
+				if (valid)
+					name = token->text;
+				break;
+			case COLON:
+				if (valid && (token->type != ':'))
+				{
+					mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+					                     token->text);
+					valid = false;
+				}
+				break;
+			case EXT_BEHAVIOR:
+				if (valid && (token->type != Token::IDENTIFIER))
+				{
+					mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
+					                     token->location, token->text);
+					valid = false;
+				}
+				if (valid)
+					behavior = token->text;
+				break;
+			default:
+				if (valid)
+				{
+					mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+					                     token->text);
+					valid = false;
+				}
+				break;
 		}
 		mTokenizer->lex(token);
 	}
 	if (valid && (state != EXT_BEHAVIOR + 1))
 	{
-		mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE,
-		                     token->location, token->text);
+		mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location,
+		                     token->text);
 		valid = false;
 	}
+	if (valid && mSeenNonPreprocessorToken)
+	{
+		if (mShaderVersion >= 300)
+		{
+			mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+			                     token->location, token->text);
+			valid = false;
+		}
+		else
+		{
+			mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
+			                     token->location, token->text);
+		}
+	}
 	if (valid)
 		mDirectiveHandler->handleExtension(token->location, name, behavior);
 }
 
-void DirectiveParser::parseVersion(Token* token)
+void DirectiveParser::parseVersion(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_VERSION);
 
 	if (mPastFirstStatement)
 	{
-		mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT,
-		                     token->location, token->text);
+		mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location,
+		                     token->text);
 		skipUntilEOD(mTokenizer, token);
 		return;
 	}
@@ -676,13 +787,13 @@
 		case VERSION_NUMBER:
 			if (token->type != Token::CONST_INT)
 			{
-				mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,
+				mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER,
 				                     token->location, token->text);
 				valid = false;
 			}
 			if (valid && !token->iValue(&version))
 			{
-				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
+				mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
 				                     token->location, token->text);
 				valid = false;
 			}
@@ -694,14 +805,14 @@
 		case VERSION_PROFILE:
 			if (token->type != Token::IDENTIFIER || token->text != "es")
 			{
-				mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
+				mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
 				                     token->location, token->text);
 				valid = false;
 			}
 			state = VERSION_ENDLINE;
 			break;
 		default:
-			mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+			mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
 			                     token->location, token->text);
 			valid = false;
 			break;
@@ -712,99 +823,98 @@
 
 	if (valid && (state != VERSION_ENDLINE))
 	{
-		mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
+		mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
 		                     token->location, token->text);
 		valid = false;
 	}
 
+	if (valid && version >= 300 && token->location.line > 1)
+	{
+		mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3, token->location,
+		                     token->text);
+		valid = false;
+	}
+
 	if (valid)
 	{
 		mDirectiveHandler->handleVersion(token->location, version);
+		mShaderVersion = version;
+		PredefineMacro(mMacroSet, "__VERSION__", version);
 	}
 }
 
-void DirectiveParser::parseLine(Token* token)
+void DirectiveParser::parseLine(Token *token)
 {
 	assert(getDirective(token) == DIRECTIVE_LINE);
 
-	enum State
-	{
-		LINE_NUMBER,
-		FILE_NUMBER
-	};
-
 	bool valid = true;
+	bool parsedFileNumber = false;
 	int line = 0, file = 0;
-	int state = LINE_NUMBER;
 
-	MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
+	MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false, mMaxMacroExpansionDepth);
+
+	// Lex the first token after "#line" so we can check it for EOD.
 	macroExpander.lex(token);
-	while ((token->type != '\n') && (token->type != Token::LAST))
-	{
-		switch (state++)
-		{
-		case LINE_NUMBER:
-			if (valid && (token->type != Token::CONST_INT))
-			{
-				mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER,
-				                     token->location, token->text);
-				valid = false;
-			}
-			if (valid && !token->iValue(&line))
-			{
-				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-				                     token->location, token->text);
-				valid = false;
-			}
-			break;
-		case FILE_NUMBER:
-			if (valid && (token->type != Token::CONST_INT))
-			{
-				mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER,
-				                     token->location, token->text);
-				valid = false;
-			}
-			if (valid && !token->iValue(&file))
-			{
-				mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-				                     token->location, token->text);
-				valid = false;
-			}
-			break;
-		default:
-			if (valid)
-			{
-				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
-				                     token->location, token->text);
-				valid = false;
-			}
-			break;
-		}
-		macroExpander.lex(token);
-	}
 
-	if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
+	if (isEOD(token))
 	{
-		mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE,
-		                     token->location, token->text);
+		mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text);
 		valid = false;
 	}
+	else
+	{
+		ExpressionParser expressionParser(&macroExpander, mDiagnostics);
+		ExpressionParser::ErrorSettings errorSettings;
+
+		// See GLES3 section 12.42
+		errorSettings.integerLiteralsMustFit32BitSignedRange = true;
+
+		errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_LINE_NUMBER;
+		// The first token was lexed earlier to check if it was EOD. Include
+		// the token in parsing for a second time by setting the
+		// parsePresetToken flag to true.
+		expressionParser.parse(token, &line, true, errorSettings, &valid);
+		if (!isEOD(token) && valid)
+		{
+			errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_FILE_NUMBER;
+			// After parsing the line expression expressionParser has also
+			// advanced to the first token of the file expression - this is the
+			// token that makes the parser reduce the "input" rule for the line
+			// expression and stop. So we're using parsePresetToken = true here
+			// as well.
+			expressionParser.parse(token, &file, true, errorSettings, &valid);
+			parsedFileNumber = true;
+		}
+		if (!isEOD(token))
+		{
+			if (valid)
+			{
+				mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
+				                     token->location, token->text);
+				valid = false;
+			}
+			skipUntilEOD(mTokenizer, token);
+		}
+	}
+
 	if (valid)
 	{
 		mTokenizer->setLineNumber(line);
-		if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file);
+		if (parsedFileNumber)
+			mTokenizer->setFileNumber(file);
 	}
 }
 
 bool DirectiveParser::skipping() const
 {
-	if (mConditionalStack.empty()) return false;
+	if (mConditionalStack.empty())
+		return false;
 
-	const ConditionalBlock& block = mConditionalStack.back();
+	const ConditionalBlock &block = mConditionalStack.back();
 	return block.skipBlock || block.skipGroup;
 }
 
-void DirectiveParser::parseConditionalIf(Token* token)
+void DirectiveParser::parseConditionalIf(Token *token)
 {
 	ConditionalBlock block;
 	block.type = token->text;
@@ -845,22 +955,26 @@
 	mConditionalStack.push_back(block);
 }
 
-int DirectiveParser::parseExpressionIf(Token* token)
+int DirectiveParser::parseExpressionIf(Token *token)
 {
-	assert((getDirective(token) == DIRECTIVE_IF) ||
-	       (getDirective(token) == DIRECTIVE_ELIF));
+	assert((getDirective(token) == DIRECTIVE_IF) || (getDirective(token) == DIRECTIVE_ELIF));
 
-	MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
+	DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
+	MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics, true, mMaxMacroExpansionDepth);
 	ExpressionParser expressionParser(&macroExpander, mDiagnostics);
 
 	int expression = 0;
-	macroExpander.lex(token);
-	expressionParser.parse(token, &expression);
+	ExpressionParser::ErrorSettings errorSettings;
+	errorSettings.integerLiteralsMustFit32BitSignedRange = false;
+	errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
+
+	bool valid = true;
+	expressionParser.parse(token, &expression, false, errorSettings, &valid);
 
 	// Check if there are tokens after #if expression.
 	if (!isEOD(token))
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 	}
@@ -876,7 +990,7 @@
 	mTokenizer->lex(token);
 	if (token->type != Token::IDENTIFIER)
 	{
-		mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 		return 0;
@@ -889,7 +1003,7 @@
 	mTokenizer->lex(token);
 	if (!isEOD(token))
 	{
-		mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN,
+		mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
 		                     token->location, token->text);
 		skipUntilEOD(mTokenizer, token);
 	}
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveParser.h b/src/OpenGL/compiler/preprocessor/DirectiveParser.h
index b23a99e..d1e1135 100644
--- a/src/OpenGL/compiler/preprocessor/DirectiveParser.h
+++ b/src/OpenGL/compiler/preprocessor/DirectiveParser.h
@@ -30,35 +30,37 @@
 class DirectiveParser : public Lexer
 {
 public:
-	DirectiveParser(Tokenizer* tokenizer,
-	                MacroSet* macroSet,
-	                Diagnostics* diagnostics,
-	                DirectiveHandler* directiveHandler);
+	DirectiveParser(Tokenizer *tokenizer,
+	                MacroSet *macroSet,
+	                Diagnostics *diagnostics,
+	                DirectiveHandler *directiveHandler,
+	                int maxMacroExpansionDepth);
+	~DirectiveParser() override;
 
-	virtual void lex(Token* token);
+	void lex(Token *token) override;
 
 private:
 	PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
 
-	void parseDirective(Token* token);
-	void parseDefine(Token* token);
-	void parseUndef(Token* token);
-	void parseIf(Token* token);
-	void parseIfdef(Token* token);
-	void parseIfndef(Token* token);
-	void parseElse(Token* token);
-	void parseElif(Token* token);
-	void parseEndif(Token* token);
-	void parseError(Token* token);
-	void parsePragma(Token* token);
-	void parseExtension(Token* token);
-	void parseVersion(Token* token);
-	void parseLine(Token* token);
+	void parseDirective(Token *token);
+	void parseDefine(Token *token);
+	void parseUndef(Token *token);
+	void parseIf(Token *token);
+	void parseIfdef(Token *token);
+	void parseIfndef(Token *token);
+	void parseElse(Token *token);
+	void parseElif(Token *token);
+	void parseEndif(Token *token);
+	void parseError(Token *token);
+	void parsePragma(Token *token);
+	void parseExtension(Token *token);
+	void parseVersion(Token *token);
+	void parseLine(Token *token);
 
 	bool skipping() const;
-	void parseConditionalIf(Token* token);
-	int parseExpressionIf(Token* token);
-	int parseExpressionIfdef(Token* token);
+	void parseConditionalIf(Token *token);
+	int parseExpressionIf(Token *token);
+	int parseExpressionIfdef(Token *token);
 
 	struct ConditionalBlock
 	{
@@ -78,11 +80,16 @@
 		}
 	};
 	bool mPastFirstStatement;
+	bool mSeenNonPreprocessorToken;  // Tracks if a non-preprocessor token has been seen yet.  Some
+	                                 // macros, such as
+	                                 // #extension must be declared before all shader code.
 	std::vector<ConditionalBlock> mConditionalStack;
-	Tokenizer* mTokenizer;
-	MacroSet* mMacroSet;
-	Diagnostics* mDiagnostics;
-	DirectiveHandler* mDirectiveHandler;
+	Tokenizer *mTokenizer;
+	MacroSet *mMacroSet;
+	Diagnostics *mDiagnostics;
+	DirectiveHandler *mDirectiveHandler;
+	int mShaderVersion;
+	int mMaxMacroExpansionDepth;
 };
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp b/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp
index b2aa9d7..ab561b8 100644
--- a/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp
+++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp
@@ -88,26 +88,37 @@
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated pplval variable.
+#if !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#else
 #pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
 #elif defined(_MSC_VER)
-#pragma warning(disable: 4065 4701)
+#pragma warning(disable: 4065 4244 4701 4702)
 #endif
 
 #include "ExpressionParser.h"
 
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+
 #include <cassert>
 #include <sstream>
+#include <stdint.h>
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
 #include "Lexer.h"
 #include "Token.h"
+#include "../../common/debug.h"
 
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif  // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
+
+#define YYENABLE_NLS 0
+#define YYLTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_DECLARED 1
 
@@ -118,7 +129,17 @@
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
-    int shortCircuited;   // Don't produce errors when > 0
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
+
+    void startIgnoreErrors() { ++ignoreErrors; }
+    void endIgnoreErrors() { --ignoreErrors; }
+
+    bool isIgnoringErrors() { return ignoreErrors > 0; }
+
+    int ignoreErrors;
 };
 }  // namespace
 
@@ -159,15 +180,16 @@
   enum yytokentype
   {
     TOK_CONST_INT = 258,
-    TOK_OP_OR = 259,
-    TOK_OP_AND = 260,
-    TOK_OP_EQ = 261,
-    TOK_OP_NE = 262,
-    TOK_OP_LE = 263,
-    TOK_OP_GE = 264,
-    TOK_OP_LEFT = 265,
-    TOK_OP_RIGHT = 266,
-    TOK_UNARY = 267
+    TOK_IDENTIFIER = 259,
+    TOK_OP_OR = 260,
+    TOK_OP_AND = 261,
+    TOK_OP_EQ = 262,
+    TOK_OP_NE = 263,
+    TOK_OP_LE = 264,
+    TOK_OP_GE = 265,
+    TOK_OP_LEFT = 266,
+    TOK_OP_RIGHT = 267,
+    TOK_UNARY = 268
   };
 #endif
 
@@ -426,23 +448,23 @@
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  14
+#define YYFINAL  15
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   178
+#define YYLAST   176
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  27
+#define YYNTOKENS  28
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  5
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  28
+#define YYNRULES  29
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  54
+#define YYNSTATES  55
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   267
+#define YYMAXUTOK   268
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -454,16 +476,16 @@
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    23,     2,     2,     2,    21,     8,     2,
-      25,    26,    19,    17,     2,    18,     2,    20,     2,     2,
+       2,     2,     2,    24,     2,     2,     2,    22,     9,     2,
+      26,    27,    20,    18,     2,    19,     2,    21,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      11,     2,    12,     2,     2,     2,     2,     2,     2,     2,
+      12,     2,    13,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     7,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     8,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     6,     2,    24,     2,     2,     2,
+       2,     2,     2,     2,     7,     2,    25,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -477,16 +499,16 @@
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     9,    10,    13,    14,    15,    16,    22
+       5,     6,    10,    11,    14,    15,    16,    17,    23
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
+static const yytype_uint16 yyrline[] =
 {
-       0,    86,    86,    93,    94,    94,   110,   110,   126,   129,
-     132,   135,   138,   141,   144,   147,   150,   153,   156,   159,
-     162,   165,   184,   203,   206,   209,   212,   215,   218
+       0,   124,   124,   131,   132,   143,   143,   164,   164,   185,
+     188,   191,   194,   197,   200,   203,   206,   209,   212,   237,
+     259,   262,   265,   291,   318,   321,   324,   327,   339,   342
 };
 #endif
 
@@ -495,11 +517,11 @@
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_OP_OR",
-  "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_EQ", "TOK_OP_NE", "'<'",
-  "'>'", "TOK_OP_LE", "TOK_OP_GE", "TOK_OP_LEFT", "TOK_OP_RIGHT", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", "')'",
-  "$accept", "input", "expression", "$@1", "$@2", YY_NULLPTR
+  "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_IDENTIFIER",
+  "TOK_OP_OR", "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_EQ", "TOK_OP_NE",
+  "'<'", "'>'", "TOK_OP_LE", "TOK_OP_GE", "TOK_OP_LEFT", "TOK_OP_RIGHT",
+  "'+'", "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('",
+  "')'", "$accept", "input", "expression", "$@1", "$@2", YY_NULLPTR
 };
 #endif
 
@@ -508,16 +530,16 @@
    (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
-       0,   256,   257,   258,   259,   260,   124,    94,    38,   261,
-     262,    60,    62,   263,   264,   265,   266,    43,    45,    42,
-      47,    37,   267,    33,   126,    40,    41
+       0,   256,   257,   258,   259,   260,   261,   124,    94,    38,
+     262,   263,    60,    62,   264,   265,   266,   267,    43,    45,
+      42,    47,    37,   268,    33,   126,    40,    41
 };
 # endif
 
-#define YYPACT_NINF -11
+#define YYPACT_NINF -12
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-11)))
+  (!!((Yystate) == (-12)))
 
 #define YYTABLE_NINF -1
 
@@ -528,12 +550,12 @@
      STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
-      49,   -11,    49,    49,    49,    49,    49,    31,    71,   -11,
-     -11,   -11,   -11,    30,   -11,   -11,   -11,    49,    49,    49,
-      49,    49,    49,    49,    49,    49,    49,    49,    49,    49,
-      49,    49,    49,   -11,    49,    49,   119,   133,   146,   157,
-     157,   -10,   -10,   -10,   -10,    40,    40,    -7,    -7,   -11,
-     -11,   -11,    88,   104
+      31,   -12,   -12,    31,    31,    31,    31,    31,    51,    76,
+     -12,   -12,   -12,   -12,    53,   -12,   -12,   -12,    31,    31,
+      31,    31,    31,    31,    31,    31,    31,    31,    31,    31,
+      31,    31,    31,    31,   -12,    31,    31,   124,   138,    26,
+     149,   149,   -11,   -11,   -11,   -11,   154,   154,    -8,    -8,
+     -12,   -12,   -12,    93,   109
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -541,24 +563,24 @@
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     3,     0,     0,     0,     0,     0,     0,     2,    27,
-      26,    24,    25,     0,     1,     4,     6,     0,     0,     0,
+       0,     3,     4,     0,     0,     0,     0,     0,     0,     2,
+      28,    27,    25,    26,     0,     1,     5,     7,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    28,     0,     0,     8,     9,    10,    12,
-      11,    16,    15,    14,    13,    18,    17,    20,    19,    23,
-      22,    21,     5,     7
+       0,     0,     0,     0,    29,     0,     0,     9,    10,    11,
+      13,    12,    17,    16,    15,    14,    19,    18,    21,    20,
+      24,    23,    22,     6,     8
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -11,   -11,    -2,   -11,   -11
+     -12,   -12,    -3,   -12,   -12
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     7,     8,    34,    35
+      -1,     8,     9,    35,    36
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -566,74 +588,74 @@
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-       9,    10,    11,    12,    13,    26,    27,    28,    29,    30,
-      31,    32,    30,    31,    32,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    14,    52,    53,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,     1,     0,     0,     0,    33,    28,    29,    30,
-      31,    32,     0,     0,     0,     0,     2,     3,     0,     0,
-       0,     0,     4,     5,     6,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    18,    19,    20,    21,
+      10,    11,    12,    13,    14,    27,    28,    29,    30,    31,
+      32,    33,    31,    32,    33,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,     0,    53,    54,     1,     2,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,     3,
+       4,    15,     0,     0,     0,     5,     6,     7,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,     0,     0,     0,     0,
+      34,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    18,    19,    20,    21,
       22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32
+      32,    33,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    29,    30,    31,    32,    33
 };
 
 static const yytype_int8 yycheck[] =
 {
-       2,     3,     4,     5,     6,    15,    16,    17,    18,    19,
-      20,    21,    19,    20,    21,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,     0,    34,    35,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,     3,    -1,    -1,    -1,    26,    17,    18,    19,
-      20,    21,    -1,    -1,    -1,    -1,    17,    18,    -1,    -1,
-      -1,    -1,    23,    24,    25,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,     5,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,     7,     8,     9,    10,
+       3,     4,     5,     6,     7,    16,    17,    18,    19,    20,
+      21,    22,    20,    21,    22,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    -1,    35,    36,     3,     4,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    18,
+      19,     0,    -1,    -1,    -1,    24,    25,    26,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    -1,    -1,    -1,    -1,
+      27,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     7,     8,     9,    10,
       11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21
+      21,    22,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    18,    19,    20,    21,    22
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    17,    18,    23,    24,    25,    28,    29,    29,
-      29,    29,    29,    29,     0,     4,     5,     6,     7,     8,
+       0,     3,     4,    18,    19,    24,    25,    26,    29,    30,
+      30,    30,    30,    30,    30,     0,     5,     6,     7,     8,
        9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    26,    30,    31,    29,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
-      29,    29,    29,    29
+      19,    20,    21,    22,    27,    31,    32,    30,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
+      30,    30,    30,    30,    30
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    27,    28,    29,    30,    29,    31,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
-      29,    29,    29,    29,    29,    29,    29,    29,    29
+       0,    28,    29,    30,    30,    31,    30,    32,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    30
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     1,     1,     0,     4,     0,     4,     3,     3,
+       0,     2,     1,     1,     1,     0,     4,     0,     4,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     2,     2,     2,     2,     3
+       3,     3,     3,     3,     3,     2,     2,     2,     2,     3
 };
 
 
@@ -1327,10 +1349,15 @@
   case 4:
 
     {
-        if ((yyvsp[-1]) != 0)
+        if (!context->isIgnoringErrors())
         {
-            context->shortCircuited++;
+            // This rule should be applied right after the token is lexed, so we can
+            // refer to context->token in the error message.
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
+                                         context->token->location, context->token->text);
+            *(context->valid) = false;
         }
+        (yyval) = (yyvsp[0]);
     }
 
     break;
@@ -1338,10 +1365,26 @@
   case 5:
 
     {
+        if ((yyvsp[-1]) != 0)
+        {
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
+        }
+    }
+
+    break;
+
+  case 6:
+
+    {
         if ((yyvsp[-3]) != 0)
         {
-            context->shortCircuited--;
-            (yyval) = 1;
+            context->endIgnoreErrors();
+            (yyval) = static_cast<YYSTYPE>(1);
         }
         else
         {
@@ -1351,24 +1394,29 @@
 
     break;
 
-  case 6:
+  case 7:
 
     {
         if ((yyvsp[-1]) == 0)
         {
-            context->shortCircuited++;
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
         }
     }
 
     break;
 
-  case 7:
+  case 8:
 
     {
         if ((yyvsp[-3]) == 0)
         {
-            context->shortCircuited--;
-            (yyval) = 0;
+            context->endIgnoreErrors();
+            (yyval) = static_cast<YYSTYPE>(0);
         }
         else
         {
@@ -1378,7 +1426,7 @@
 
     break;
 
-  case 8:
+  case 9:
 
     {
         (yyval) = (yyvsp[-2]) | (yyvsp[0]);
@@ -1386,7 +1434,7 @@
 
     break;
 
-  case 9:
+  case 10:
 
     {
         (yyval) = (yyvsp[-2]) ^ (yyvsp[0]);
@@ -1394,7 +1442,7 @@
 
     break;
 
-  case 10:
+  case 11:
 
     {
         (yyval) = (yyvsp[-2]) & (yyvsp[0]);
@@ -1402,7 +1450,7 @@
 
     break;
 
-  case 11:
+  case 12:
 
     {
         (yyval) = (yyvsp[-2]) != (yyvsp[0]);
@@ -1410,7 +1458,7 @@
 
     break;
 
-  case 12:
+  case 13:
 
     {
         (yyval) = (yyvsp[-2]) == (yyvsp[0]);
@@ -1418,7 +1466,7 @@
 
     break;
 
-  case 13:
+  case 14:
 
     {
         (yyval) = (yyvsp[-2]) >= (yyvsp[0]);
@@ -1426,7 +1474,7 @@
 
     break;
 
-  case 14:
+  case 15:
 
     {
         (yyval) = (yyvsp[-2]) <= (yyvsp[0]);
@@ -1434,7 +1482,7 @@
 
     break;
 
-  case 15:
+  case 16:
 
     {
         (yyval) = (yyvsp[-2]) > (yyvsp[0]);
@@ -1442,7 +1490,7 @@
 
     break;
 
-  case 16:
+  case 17:
 
     {
         (yyval) = (yyvsp[-2]) < (yyvsp[0]);
@@ -1450,18 +1498,32 @@
 
     break;
 
-  case 17:
-
-    {
-        (yyval) = (yyvsp[-2]) >> (yyvsp[0]);
-    }
-
-    break;
-
   case 18:
 
     {
-        (yyval) = (yyvsp[-2]) << (yyvsp[0]);
+        if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " >> " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if ((yyvsp[-2]) < 0)
+        {
+            // Logical shift right.
+            (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) >> (yyvsp[0]));
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) >> (yyvsp[0]);
+        }
     }
 
     break;
@@ -1469,7 +1531,26 @@
   case 19:
 
     {
-        (yyval) = (yyvsp[-2]) - (yyvsp[0]);
+        if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " << " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else
+        {
+            // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer
+            // overflow, which some tools treat as an error.
+            (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0]));
+        }
     }
 
     break;
@@ -1477,7 +1558,7 @@
   case 20:
 
     {
-        (yyval) = (yyvsp[-2]) + (yyvsp[0]);
+        (yyval) = (yyvsp[-2]) - (yyvsp[0]);
     }
 
     break;
@@ -1485,23 +1566,7 @@
   case 21:
 
     {
-        if ((yyvsp[0]) == 0)
-        {
-            if (!context->shortCircuited)
-            {
-                context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                             context->token->location, "");
-                YYABORT;
-            }
-            else
-            {
-                (yyval) = 0;
-            }
-        }
-        else
-        {
-            (yyval) = (yyvsp[-2]) % (yyvsp[0]);
-        }
+        (yyval) = (yyvsp[-2]) + (yyvsp[0]);
     }
 
     break;
@@ -1511,16 +1576,55 @@
     {
         if ((yyvsp[0]) == 0)
         {
-            if (!context->shortCircuited)
+            if (!context->isIgnoringErrors())
             {
-                context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                             context->token->location, "");
-                YYABORT;
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " % " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
             }
-            else
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this has undefined results.
+            (yyval) = 0;
+        }
+        else
+        {
+            (yyval) = (yyvsp[-2]) % (yyvsp[0]);
+        }
+    }
+
+    break;
+
+  case 23:
+
+    {
+        if ((yyvsp[0]) == 0)
+        {
+            if (!context->isIgnoringErrors())
             {
-                (yyval) = 0;
+                std::ostringstream stream;
+                stream << (yyvsp[-2]) << " / " << (yyvsp[0]);
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                            context->token->location,
+                                            text.c_str());
+                *(context->valid) = false;
             }
+            (yyval) = static_cast<YYSTYPE>(0);
+        }
+        else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this leads to integer overflow in C++, which
+            // has undefined results.
+            (yyval) = std::numeric_limits<YYSTYPE>::max();
         }
         else
         {
@@ -1530,7 +1634,7 @@
 
     break;
 
-  case 23:
+  case 24:
 
     {
         (yyval) = (yyvsp[-2]) * (yyvsp[0]);
@@ -1538,7 +1642,7 @@
 
     break;
 
-  case 24:
+  case 25:
 
     {
         (yyval) = ! (yyvsp[0]);
@@ -1546,7 +1650,7 @@
 
     break;
 
-  case 25:
+  case 26:
 
     {
         (yyval) = ~ (yyvsp[0]);
@@ -1554,15 +1658,24 @@
 
     break;
 
-  case 26:
+  case 27:
 
     {
-        (yyval) = - (yyvsp[0]);
+        // Check for negation of minimum representable integer to prevent undefined signed int
+        // overflow.
+        if ((yyvsp[0]) == std::numeric_limits<YYSTYPE>::min())
+        {
+            (yyval) = std::numeric_limits<YYSTYPE>::min();
+        }
+        else
+        {
+            (yyval) = -(yyvsp[0]);
+        }
     }
 
     break;
 
-  case 27:
+  case 28:
 
     {
         (yyval) = + (yyvsp[0]);
@@ -1570,7 +1683,7 @@
 
     break;
 
-  case 28:
+  case 29:
 
     {
         (yyval) = (yyvsp[-1]);
@@ -1810,93 +1923,115 @@
 
 
 
-int yylex(YYSTYPE* lvalp, Context* context)
+int yylex(YYSTYPE *lvalp, Context *context)
 {
+    pp::Token *token = context->token;
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
+
     int type = 0;
 
-    pp::Token* token = context->token;
     switch (token->type)
     {
-      case pp::Token::CONST_INT:
-      {
+      case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
-            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
+            context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
       case pp::Token::IDENTIFIER:
-        if (!context->shortCircuited)
-        {
-            // Defined identifiers should have been expanded already.
-            // Unlike the C/C++ preprocessor, it does not default to 0.
-            // Use of such identifiers causes an error.
-            context->diagnostics->report(pp::Diagnostics::UNDEFINED_IDENTIFIER,
-                                         token->location, token->text);
-        }
-
-        *lvalp = 0;
-        type = TOK_CONST_INT;
+        *lvalp = static_cast<YYSTYPE>(-1);
+        type = TOK_IDENTIFIER;
         break;
-      case pp::Token::OP_OR: type = TOK_OP_OR; break;
-      case pp::Token::OP_AND: type = TOK_OP_AND; break;
-      case pp::Token::OP_NE: type = TOK_OP_NE; break;
-      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
-      case pp::Token::OP_GE: type = TOK_OP_GE; break;
-      case pp::Token::OP_LE: type = TOK_OP_LE; break;
-      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
-      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
-      case '|': type = '|'; break;
-      case '^': type = '^'; break;
-      case '&': type = '&'; break;
-      case '>': type = '>'; break;
-      case '<': type = '<'; break;
-      case '-': type = '-'; break;
-      case '+': type = '+'; break;
-      case '%': type = '%'; break;
-      case '/': type = '/'; break;
-      case '*': type = '*'; break;
-      case '!': type = '!'; break;
-      case '~': type = '~'; break;
-      case '(': type = '('; break;
-      case ')': type = ')'; break;
+      case pp::Token::OP_OR:
+        type = TOK_OP_OR;
+        break;
+      case pp::Token::OP_AND:
+        type = TOK_OP_AND;
+        break;
+      case pp::Token::OP_NE:
+        type = TOK_OP_NE;
+        break;
+      case pp::Token::OP_EQ:
+        type = TOK_OP_EQ;
+        break;
+      case pp::Token::OP_GE:
+        type = TOK_OP_GE;
+        break;
+      case pp::Token::OP_LE:
+        type = TOK_OP_LE;
+        break;
+      case pp::Token::OP_RIGHT:
+        type = TOK_OP_RIGHT;
+        break;
+      case pp::Token::OP_LEFT:
+        type = TOK_OP_LEFT;
+        break;
+      case '|':
+      case '^':
+      case '&':
+      case '>':
+      case '<':
+      case '-':
+      case '+':
+      case '%':
+      case '/':
+      case '*':
+      case '!':
+      case '~':
+      case '(':
+      case ')':
+        type = token->type;
+        break;
 
-      default: break;
+      default:
+        break;
     }
 
-    // Advance to the next token if the current one is valid.
-    if (type != 0) context->lexer->lex(token);
-
     return type;
 }
 
-void yyerror(Context* context, const char* reason)
+void yyerror(Context *context, const char *reason)
 {
-    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
+    context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
                                  context->token->location,
                                  reason);
 }
 
 namespace pp {
 
-ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
-    mLexer(lexer),
-    mDiagnostics(diagnostics)
+ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
+    : mLexer(lexer),
+      mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token* token, int* result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
-    context.shortCircuited = 0;
+    context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
@@ -1905,12 +2040,12 @@
         break;
 
       case 2:
-        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
         break;
 
       default:
         assert(false);
-        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
         break;
     }
 
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.h b/src/OpenGL/compiler/preprocessor/ExpressionParser.h
index c28f4bb..47bd477 100644
--- a/src/OpenGL/compiler/preprocessor/ExpressionParser.h
+++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.h
@@ -15,27 +15,34 @@
 #ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
 #define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
 
-#include "pp_utils.h"
+#include "DiagnosticsBase.h"
 
 namespace pp
 {
 
-class Diagnostics;
 class Lexer;
 struct Token;
 
 class ExpressionParser
 {
 public:
-	ExpressionParser(Lexer* lexer, Diagnostics* diagnostics);
+	struct ErrorSettings
+	{
+		Diagnostics::ID unexpectedIdentifier;
+		bool integerLiteralsMustFit32BitSignedRange;
+	};
 
-	bool parse(Token* token, int* result);
+	ExpressionParser(Lexer *lexer, Diagnostics *diagnostics);
+
+	bool parse(Token *token,
+	           int *result,
+	           bool parsePresetToken,
+	           const ErrorSettings &errorSettings,
+	           bool *valid);
 
 private:
-	PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
-
-	Lexer* mLexer;
-	Diagnostics* mDiagnostics;
+	Lexer *mLexer;
+	Diagnostics *mDiagnostics;
 };
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.y b/src/OpenGL/compiler/preprocessor/ExpressionParser.y
index 09e86aa..af5abd8 100644
--- a/src/OpenGL/compiler/preprocessor/ExpressionParser.y
+++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.y
@@ -38,26 +38,37 @@
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated pplval variable.
+#if !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#else
 #pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
 #elif defined(_MSC_VER)
-#pragma warning(disable: 4065 4701)
+#pragma warning(disable: 4065 4244 4701 4702)
 #endif
 
 #include "ExpressionParser.h"
 
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+
 #include <cassert>
 #include <sstream>
+#include <stdint.h>
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
 #include "Lexer.h"
 #include "Token.h"
+#include "../../common/debug.h"
 
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif  // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
+
+#define YYENABLE_NLS 0
+#define YYLTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_TRIVIAL 1
 #define YYSTYPE_IS_DECLARED 1
 
@@ -68,7 +79,17 @@
     pp::Lexer* lexer;
     pp::Token* token;
     int* result;
-    int shortCircuited;   // Don't produce errors when > 0
+    bool parsePresetToken;
+
+    pp::ExpressionParser::ErrorSettings errorSettings;
+    bool *valid;
+
+    void startIgnoreErrors() { ++ignoreErrors; }
+    void endIgnoreErrors() { --ignoreErrors; }
+
+    bool isIgnoringErrors() { return ignoreErrors > 0; }
+
+    int ignoreErrors;
 };
 }  // namespace
 %}
@@ -84,6 +105,7 @@
 %}
 
 %token TOK_CONST_INT
+%token TOK_IDENTIFIER
 %left TOK_OP_OR
 %left TOK_OP_AND
 %left '|'
@@ -107,16 +129,32 @@
 
 expression
     : TOK_CONST_INT
+    | TOK_IDENTIFIER {
+        if (!context->isIgnoringErrors())
+        {
+            // This rule should be applied right after the token is lexed, so we can
+            // refer to context->token in the error message.
+            context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
+                                         context->token->location, context->token->text);
+            *(context->valid) = false;
+        }
+        $$ = $1;
+    }
     | expression TOK_OP_OR {
         if ($1 != 0)
         {
-            context->shortCircuited++;
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
         }
     } expression {
         if ($1 != 0)
         {
-            context->shortCircuited--;
-            $$ = 1;
+            context->endIgnoreErrors();
+            $$ = static_cast<YYSTYPE>(1);
         }
         else
         {
@@ -126,13 +164,18 @@
     | expression TOK_OP_AND {
         if ($1 == 0)
         {
-            context->shortCircuited++;
+            // Ignore errors in the short-circuited part of the expression.
+            // ESSL3.00 section 3.4:
+            // If an operand is not evaluated, the presence of undefined identifiers
+            // in the operand will not cause an error.
+            // Unevaluated division by zero should not cause an error either.
+            context->startIgnoreErrors();
         }
     } expression {
         if ($1 == 0)
         {
-            context->shortCircuited--;
-            $$ = 0;
+            context->endIgnoreErrors();
+            $$ = static_cast<YYSTYPE>(0);
         }
         else
         {
@@ -167,10 +210,51 @@
         $$ = $1 < $3;
     }
     | expression TOK_OP_RIGHT expression {
-        $$ = $1 >> $3;
+        if ($3 < 0 || $3 > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " >> " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if ($1 < 0)
+        {
+            // Logical shift right.
+            $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3);
+        }
+        else
+        {
+            $$ = $1 >> $3;
+        }
     }
     | expression TOK_OP_LEFT expression {
-        $$ = $1 << $3;
+        if ($3 < 0 || $3 > 31)
+        {
+            if (!context->isIgnoringErrors())
+            {
+                std::ostringstream stream;
+                stream << $1 << " << " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
+            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else
+        {
+            // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer
+            // overflow, which some tools treat as an error.
+            $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
+        }
     }
     | expression '-' expression {
         $$ = $1 - $3;
@@ -181,16 +265,23 @@
     | expression '%' expression {
         if ($3 == 0)
         {
-            if (!context->shortCircuited)
+            if (!context->isIgnoringErrors())
             {
-                context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                             context->token->location, "");
-                YYABORT;
+                std::ostringstream stream;
+                stream << $1 << " % " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                             context->token->location,
+                                             text.c_str());
+                *(context->valid) = false;
             }
-            else
-            {
-                $$ = 0;
-            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this has undefined results.
+            $$ = 0;
         }
         else
         {
@@ -200,16 +291,24 @@
     | expression '/' expression {
         if ($3 == 0)
         {
-            if (!context->shortCircuited)
+            if (!context->isIgnoringErrors())
             {
-                context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
-                                             context->token->location, "");
-                YYABORT;
+                std::ostringstream stream;
+                stream << $1 << " / " << $3;
+                std::string text = stream.str();
+                context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
+                                            context->token->location,
+                                            text.c_str());
+                *(context->valid) = false;
             }
-            else
-            {
-                $$ = 0;
-            }
+            $$ = static_cast<YYSTYPE>(0);
+        }
+        else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+        {
+            // Check for the special case where the minimum representable number is
+            // divided by -1. If left alone this leads to integer overflow in C++, which
+            // has undefined results.
+            $$ = std::numeric_limits<YYSTYPE>::max();
         }
         else
         {
@@ -226,7 +325,16 @@
         $$ = ~ $2;
     }
     | '-' expression %prec TOK_UNARY {
-        $$ = - $2;
+        // Check for negation of minimum representable integer to prevent undefined signed int
+        // overflow.
+        if ($2 == std::numeric_limits<YYSTYPE>::min())
+        {
+            $$ = std::numeric_limits<YYSTYPE>::min();
+        }
+        else
+        {
+            $$ = -$2;
+        }
     }
     | '+' expression %prec TOK_UNARY {
         $$ = + $2;
@@ -238,93 +346,115 @@
 
 %%
 
-int yylex(YYSTYPE* lvalp, Context* context)
+int yylex(YYSTYPE *lvalp, Context *context)
 {
+    pp::Token *token = context->token;
+    if (!context->parsePresetToken)
+    {
+        context->lexer->lex(token);
+    }
+    context->parsePresetToken = false;
+
     int type = 0;
 
-    pp::Token* token = context->token;
     switch (token->type)
     {
-      case pp::Token::CONST_INT:
-      {
+      case pp::Token::CONST_INT: {
         unsigned int val = 0;
-        if (!token->uValue(&val))
+        int testVal = 0;
+        if (!token->uValue(&val) || (!token->iValue(&testVal) &&
+                                     context->errorSettings.integerLiteralsMustFit32BitSignedRange))
         {
-            context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
+            context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
                                          token->location, token->text);
+            *(context->valid) = false;
         }
         *lvalp = static_cast<YYSTYPE>(val);
         type = TOK_CONST_INT;
         break;
       }
       case pp::Token::IDENTIFIER:
-        if (!context->shortCircuited)
-        {
-            // Defined identifiers should have been expanded already.
-            // Unlike the C/C++ preprocessor, it does not default to 0.
-            // Use of such identifiers causes an error.
-            context->diagnostics->report(pp::Diagnostics::UNDEFINED_IDENTIFIER,
-                                         token->location, token->text);
-        }
-
-        *lvalp = 0;
-        type = TOK_CONST_INT;
+        *lvalp = static_cast<YYSTYPE>(-1);
+        type = TOK_IDENTIFIER;
         break;
-      case pp::Token::OP_OR: type = TOK_OP_OR; break;
-      case pp::Token::OP_AND: type = TOK_OP_AND; break;
-      case pp::Token::OP_NE: type = TOK_OP_NE; break;
-      case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
-      case pp::Token::OP_GE: type = TOK_OP_GE; break;
-      case pp::Token::OP_LE: type = TOK_OP_LE; break;
-      case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
-      case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
-      case '|': type = '|'; break;
-      case '^': type = '^'; break;
-      case '&': type = '&'; break;
-      case '>': type = '>'; break;
-      case '<': type = '<'; break;
-      case '-': type = '-'; break;
-      case '+': type = '+'; break;
-      case '%': type = '%'; break;
-      case '/': type = '/'; break;
-      case '*': type = '*'; break;
-      case '!': type = '!'; break;
-      case '~': type = '~'; break;
-      case '(': type = '('; break;
-      case ')': type = ')'; break;
+      case pp::Token::OP_OR:
+        type = TOK_OP_OR;
+        break;
+      case pp::Token::OP_AND:
+        type = TOK_OP_AND;
+        break;
+      case pp::Token::OP_NE:
+        type = TOK_OP_NE;
+        break;
+      case pp::Token::OP_EQ:
+        type = TOK_OP_EQ;
+        break;
+      case pp::Token::OP_GE:
+        type = TOK_OP_GE;
+        break;
+      case pp::Token::OP_LE:
+        type = TOK_OP_LE;
+        break;
+      case pp::Token::OP_RIGHT:
+        type = TOK_OP_RIGHT;
+        break;
+      case pp::Token::OP_LEFT:
+        type = TOK_OP_LEFT;
+        break;
+      case '|':
+      case '^':
+      case '&':
+      case '>':
+      case '<':
+      case '-':
+      case '+':
+      case '%':
+      case '/':
+      case '*':
+      case '!':
+      case '~':
+      case '(':
+      case ')':
+        type = token->type;
+        break;
 
-      default: break;
+      default:
+        break;
     }
 
-    // Advance to the next token if the current one is valid.
-    if (type != 0) context->lexer->lex(token);
-
     return type;
 }
 
-void yyerror(Context* context, const char* reason)
+void yyerror(Context *context, const char *reason)
 {
-    context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
+    context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
                                  context->token->location,
                                  reason);
 }
 
 namespace pp {
 
-ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
-    mLexer(lexer),
-    mDiagnostics(diagnostics)
+ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
+    : mLexer(lexer),
+      mDiagnostics(diagnostics)
 {
 }
 
-bool ExpressionParser::parse(Token* token, int* result)
+bool ExpressionParser::parse(Token *token,
+                             int *result,
+                             bool parsePresetToken,
+                             const ErrorSettings &errorSettings,
+                             bool *valid)
 {
     Context context;
     context.diagnostics = mDiagnostics;
     context.lexer = mLexer;
     context.token = token;
     context.result = result;
-    context.shortCircuited = 0;
+    context.ignoreErrors = 0;
+    context.parsePresetToken = parsePresetToken;
+    context.errorSettings    = errorSettings;
+    context.valid            = valid;
     int ret = yyparse(&context);
     switch (ret)
     {
@@ -333,12 +463,12 @@
         break;
 
       case 2:
-        mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
         break;
 
       default:
         assert(false);
-        mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
+        mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
         break;
     }
 
diff --git a/src/OpenGL/compiler/preprocessor/Input.cpp b/src/OpenGL/compiler/preprocessor/Input.cpp
index c22622a..0626af7 100644
--- a/src/OpenGL/compiler/preprocessor/Input.cpp
+++ b/src/OpenGL/compiler/preprocessor/Input.cpp
@@ -25,27 +25,101 @@
 {
 }
 
-Input::Input(int count, const char* const string[], const int length[]) :
-	mCount(count),
-	mString(string)
+Input::~Input()
 {
-	assert(mCount >= 0);
+}
+
+Input::Input(size_t count, const char *const string[], const int length[])
+	: mCount(count), mString(string)
+{
 	mLength.reserve(mCount);
-	for (int i = 0; i < mCount; ++i)
+	for (size_t i = 0; i < mCount; ++i)
 	{
 		int len = length ? length[i] : -1;
-		mLength.push_back(len < 0 ? strlen(mString[i]) : len);
+		mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
 	}
 }
 
-int Input::read(char* buf, int maxSize)
+const char *Input::skipChar()
 {
-	int nRead = 0;
-	while ((nRead < maxSize) && (mReadLoc.sIndex < mCount))
+	// This function should only be called when there is a character to skip.
+	assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
+	++mReadLoc.cIndex;
+	if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
 	{
-		int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
-		size = std::min(size, maxSize);
-		memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
+		++mReadLoc.sIndex;
+		mReadLoc.cIndex = 0;
+	}
+	if (mReadLoc.sIndex >= mCount)
+	{
+		return nullptr;
+	}
+	return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
+}
+
+size_t Input::read(char *buf, size_t maxSize, int *lineNo)
+{
+	size_t nRead = 0;
+	// The previous call to read might have stopped copying the string when encountering a line
+	// continuation. Check for this possibility first.
+	if (mReadLoc.sIndex < mCount && maxSize > 0)
+	{
+		const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
+		if ((*c) == '\\')
+		{
+			c = skipChar();
+			if (c != nullptr && (*c) == '\n')
+			{
+				// Line continuation of backslash + newline.
+				skipChar();
+				// Fake an EOF if the line number would overflow.
+				if (*lineNo == INT_MAX)
+				{
+					return 0;
+				}
+				++(*lineNo);
+			}
+			else if (c != nullptr && (*c) == '\r')
+			{
+				// Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
+				c = skipChar();
+				if (c != nullptr && (*c) == '\n')
+				{
+					skipChar();
+				}
+				// Fake an EOF if the line number would overflow.
+				if (*lineNo == INT_MAX)
+				{
+					return 0;
+				}
+				++(*lineNo);
+			}
+			else
+			{
+				// Not line continuation, so write the skipped backslash to buf.
+				*buf = '\\';
+				++nRead;
+			}
+		}
+	}
+
+	size_t maxRead = maxSize;
+	while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
+	{
+		size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
+		size		= std::min(size, maxSize);
+		for (size_t i = 0; i < size; ++i)
+		{
+			// Stop if a possible line continuation is encountered.
+			// It will be processed on the next call on input, which skips it
+			// and increments line number if necessary.
+			if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
+			{
+				size	= i;
+				maxRead = nRead + size;  // Stop reading right before the backslash.
+			}
+		}
+		std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
 		nRead += size;
 		mReadLoc.cIndex += size;
 
diff --git a/src/OpenGL/compiler/preprocessor/Input.h b/src/OpenGL/compiler/preprocessor/Input.h
index 35776e7..dd85f4a 100644
--- a/src/OpenGL/compiler/preprocessor/Input.h
+++ b/src/OpenGL/compiler/preprocessor/Input.h
@@ -15,6 +15,7 @@
 #ifndef COMPILER_PREPROCESSOR_INPUT_H_
 #define COMPILER_PREPROCESSOR_INPUT_H_
 
+#include <cstddef>
 #include <vector>
 
 namespace pp
@@ -25,28 +26,33 @@
 {
 public:
 	Input();
-	Input(int count, const char* const string[], const int length[]);
+	~Input();
+	Input(size_t count, const char *const string[], const int length[]);
 
-	int count() const { return mCount; }
-	const char* string(int index) const { return mString[index]; }
-	int length(int index) const { return mLength[index]; }
+	size_t count() const { return mCount; }
+	const char *string(size_t index) const { return mString[index]; }
+	size_t length(size_t index) const { return mLength[index]; }
 
-	int read(char* buf, int maxSize);
+	size_t read(char *buf, size_t maxSize, int *lineNo);
 
 	struct Location
 	{
-		int sIndex;  // String index;
-		int cIndex;  // Char index.
+		size_t sIndex;  // String index;
+		size_t cIndex;  // Char index.
 
-		Location() : sIndex(0), cIndex(0) { }
+		Location() : sIndex(0), cIndex(0) {}
 	};
-	const Location& readLoc() const { return mReadLoc; }
+	const Location &readLoc() const { return mReadLoc; }
 
 private:
+	// Skip a character and return the next character after the one that was skipped.
+	// Return nullptr if data runs out.
+	const char *skipChar();
+
 	// Input.
-	int mCount;
-	const char* const* mString;
-	std::vector<int> mLength;
+	size_t mCount;
+	const char *const *mString;
+	std::vector<size_t> mLength;
 
 	Location mReadLoc;
 };
diff --git a/src/OpenGL/compiler/preprocessor/Lexer.h b/src/OpenGL/compiler/preprocessor/Lexer.h
index 558fc98..54de516 100644
--- a/src/OpenGL/compiler/preprocessor/Lexer.h
+++ b/src/OpenGL/compiler/preprocessor/Lexer.h
@@ -25,7 +25,7 @@
 public:
 	virtual ~Lexer();
 
-	virtual void lex(Token* token) = 0;
+	virtual void lex(Token *token) = 0;
 };
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Macro.cpp b/src/OpenGL/compiler/preprocessor/Macro.cpp
index 9024f8a..d3b419c 100644
--- a/src/OpenGL/compiler/preprocessor/Macro.cpp
+++ b/src/OpenGL/compiler/preprocessor/Macro.cpp
@@ -19,12 +19,33 @@
 namespace pp
 {
 
-bool Macro::equals(const Macro& other) const
+Macro::Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj)
 {
-    return (type == other.type) &&
-           (name == other.name) &&
-           (parameters == other.parameters) &&
-           (replacements == other.replacements);
+}
+
+Macro::~Macro()
+{
+}
+
+bool Macro::equals(const Macro &other) const
+{
+	return (type == other.type) && (name == other.name) && (parameters == other.parameters) &&
+	       (replacements == other.replacements);
+}
+
+void PredefineMacro(MacroSet *macroSet, const char *name, int value)
+{
+	Token token;
+	token.type = Token::CONST_INT;
+	token.text = std::to_string(value);
+
+	std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+	macro->predefined = true;
+	macro->type = Macro::kTypeObj;
+	macro->name = name;
+	macro->replacements.push_back(token);
+
+	(*macroSet)[name] = macro;
 }
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Macro.h b/src/OpenGL/compiler/preprocessor/Macro.h
index bad8db3..c2daeca 100644
--- a/src/OpenGL/compiler/preprocessor/Macro.h
+++ b/src/OpenGL/compiler/preprocessor/Macro.h
@@ -16,6 +16,7 @@
 #define COMPILER_PREPROCESSOR_MACRO_H_
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -34,11 +35,13 @@
     typedef std::vector<std::string> Parameters;
     typedef std::vector<Token> Replacements;
 
-    Macro() : predefined(false), disabled(false), type(kTypeObj) { }
-    bool equals(const Macro& other) const;
+    Macro();
+    ~Macro();
+    bool equals(const Macro &other) const;
 
     bool predefined;
     mutable bool disabled;
+    mutable int expansionCount;
 
     Type type;
     std::string name;
@@ -46,7 +49,9 @@
     Replacements replacements;
 };
 
-typedef std::map<std::string, Macro> MacroSet;
+typedef std::map<std::string, std::shared_ptr<Macro>> MacroSet;
+
+void PredefineMacro(MacroSet *macroSet, const char *name, int value);
 
 }  // namespace pp
 #endif  // COMPILER_PREPROCESSOR_MACRO_H_
diff --git a/src/OpenGL/compiler/preprocessor/MacroExpander.cpp b/src/OpenGL/compiler/preprocessor/MacroExpander.cpp
index df0e495..9be3d46 100644
--- a/src/OpenGL/compiler/preprocessor/MacroExpander.cpp
+++ b/src/OpenGL/compiler/preprocessor/MacroExpander.cpp
@@ -15,26 +15,32 @@
 #include "MacroExpander.h"
 
 #include <algorithm>
-#include <sstream>
+#include <cassert>
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
+#include "pp_utils.h"
 #include "Token.h"
 
 namespace pp
 {
 
+namespace
+{
+
+const size_t kMaxContextTokens = 10000;
+
 class TokenLexer : public Lexer
 {
  public:
 	typedef std::vector<Token> TokenVector;
 
-	TokenLexer(TokenVector* tokens)
+	TokenLexer(TokenVector *tokens)
 	{
 		tokens->swap(mTokens);
 		mIter = mTokens.begin();
 	}
 
-	virtual void lex(Token* token)
+	void lex(Token *token) override
 	{
 		if (mIter == mTokens.end())
 		{
@@ -54,26 +60,64 @@
 	TokenVector::const_iterator mIter;
 };
 
-MacroExpander::MacroExpander(Lexer* lexer,
-                             MacroSet* macroSet,
-                             Diagnostics* diagnostics,
-                             bool parseDefined) :
-	mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)
+}  // anonymous namespace
+
+class MacroExpander::ScopedMacroReenabler final
 {
-	mReserveToken = nullptr;
+ public:
+	ScopedMacroReenabler(MacroExpander *expander);
+	~ScopedMacroReenabler();
+
+  private:
+	PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander::ScopedMacroReenabler);
+
+	MacroExpander *mExpander;
+};
+
+MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
+	: mExpander(expander)
+{
+	mExpander->mDeferReenablingMacros = true;
+}
+
+MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
+{
+	mExpander->mDeferReenablingMacros = false;
+	for (auto macro : mExpander->mMacrosToReenable)
+	{
+		// Copying the string here by using substr is a check for use-after-free. It detects
+		// use-after-free more reliably than just toggling the disabled flag.
+		assert(macro->name.substr() != "");
+		macro->disabled = false;
+	}
+	mExpander->mMacrosToReenable.clear();
+}
+
+MacroExpander::MacroExpander(Lexer *lexer,
+                             MacroSet *macroSet,
+                             Diagnostics *diagnostics,
+                             bool parseDefined,
+                             int allowedMacroExpansionDepth)
+    : mLexer(lexer),
+      mMacroSet(macroSet),
+      mDiagnostics(diagnostics),
+      mParseDefined(parseDefined),
+      mTotalTokensInContexts(0),
+      mAllowedMacroExpansionDepth(allowedMacroExpansionDepth),
+      mDeferReenablingMacros(false)
+{
 }
 
 MacroExpander::~MacroExpander()
 {
-	for (size_t i = 0; i < mContextStack.size(); ++i)
+	assert(mMacrosToReenable.empty());
+	for (MacroContext *context : mContextStack)
 	{
-		delete mContextStack[i];
+		delete context;
 	}
-
-	delete mReserveToken;
 }
 
-void MacroExpander::lex(Token* token)
+void MacroExpander::lex(Token *token)
 {
 	while (true)
 	{
@@ -98,7 +142,7 @@
 			}
 			if (token->type != Token::IDENTIFIER)
 			{
-				mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location,
+				mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
 				                     token->text);
 				break;
 			}
@@ -110,7 +154,7 @@
 				getToken(token);
 				if (token->type != ')')
 				{
-					mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location,
+					mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
 					                     token->text);
 					break;
 				}
@@ -130,17 +174,22 @@
 		if (iter == mMacroSet->end())
 			break;
 
-		const Macro& macro = iter->second;
-		if (macro.disabled)
+		std::shared_ptr<Macro> macro = iter->second;
+		if (macro->disabled)
 		{
 			// If a particular token is not expanded, it is never expanded.
 			token->setExpansionDisabled(true);
 			break;
 		}
-		if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
+
+		// Bump the expansion count before peeking if the next token is a '('
+		// otherwise there could be a #undef of the macro before the next token.
+		macro->expansionCount++;
+		if ((macro->type == Macro::kTypeFunc) && !isNextTokenLeftParen())
 		{
 			// If the token immediately after the macro name is not a '(',
 			// this macro should not be expanded.
+			macro->expansionCount--;
 			break;
 		}
 
@@ -148,13 +197,12 @@
 	}
 }
 
-void MacroExpander::getToken(Token* token)
+void MacroExpander::getToken(Token *token)
 {
-	if (mReserveToken)
+	if (mReserveToken.get())
 	{
 		*token = *mReserveToken;
-		delete mReserveToken;
-		mReserveToken = nullptr;
+		mReserveToken.reset();
 		return;
 	}
 
@@ -170,22 +218,23 @@
 	}
 	else
 	{
+		assert(mTotalTokensInContexts == 0);
 		mLexer->lex(token);
 	}
 }
 
-void MacroExpander::ungetToken(const Token& token)
+void MacroExpander::ungetToken(const Token &token)
 {
 	if (!mContextStack.empty())
 	{
-		MacroContext* context = mContextStack.back();
+		MacroContext *context = mContextStack.back();
 		context->unget();
 		assert(context->replacements[context->index] == token);
 	}
 	else
 	{
-		assert(!mReserveToken);
-		mReserveToken = new Token(token);
+		assert(!mReserveToken.get());
+		mReserveToken.reset(new Token(token));
 	}
 }
 
@@ -200,24 +249,25 @@
 	return lparen;
 }
 
-bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier)
+bool MacroExpander::pushMacro(std::shared_ptr<Macro> macro, const Token &identifier)
 {
-	assert(!macro.disabled);
+	assert(!macro->disabled);
 	assert(!identifier.expansionDisabled());
 	assert(identifier.type == Token::IDENTIFIER);
-	assert(identifier.text == macro.name);
+	assert(identifier.text == macro->name);
 
 	std::vector<Token> replacements;
-	if (!expandMacro(macro, identifier, &replacements))
+	if (!expandMacro(*macro, identifier, &replacements))
 		return false;
 
 	// Macro is disabled for expansion until it is popped off the stack.
-	macro.disabled = true;
+	macro->disabled = true;
 
-	MacroContext* context = new MacroContext;
-	context->macro = &macro;
+	MacroContext *context = new MacroContext;
+	context->macro = macro;
 	context->replacements.swap(replacements);
 	mContextStack.push_back(context);
+	mTotalTokensInContexts += context->replacements.size();
 	return true;
 }
 
@@ -225,43 +275,54 @@
 {
 	assert(!mContextStack.empty());
 
-	MacroContext* context = mContextStack.back();
+	MacroContext *context = mContextStack.back();
 	mContextStack.pop_back();
 
 	assert(context->empty());
 	assert(context->macro->disabled);
-	context->macro->disabled = false;
+	assert(context->macro->expansionCount > 0);
+	if (mDeferReenablingMacros)
+	{
+		mMacrosToReenable.push_back(context->macro);
+	}
+	else
+	{
+		context->macro->disabled = false;
+	}
+	context->macro->expansionCount--;
+	mTotalTokensInContexts -= context->replacements.size();
 	delete context;
 }
 
-bool MacroExpander::expandMacro(const Macro& macro,
-                                const Token& identifier,
-                                std::vector<Token>* replacements)
+bool MacroExpander::expandMacro(const Macro &macro,
+                                const Token &identifier,
+                                std::vector<Token> *replacements)
 {
 	replacements->clear();
+
+	// In the case of an object-like macro, the replacement list gets its location
+	// from the identifier, but in the case of a function-like macro, the replacement
+	// list gets its location from the closing parenthesis of the macro invocation.
+	// This is tested by dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.*
+	SourceLocation replacementLocation = identifier.location;
 	if (macro.type == Macro::kTypeObj)
 	{
-		replacements->assign(macro.replacements.begin(),
-		                     macro.replacements.end());
+		replacements->assign(macro.replacements.begin(), macro.replacements.end());
 
 		if (macro.predefined)
 		{
-			static const std::string kLine = "__LINE__";
-			static const std::string kFile = "__FILE__";
+			const char kLine[] = "__LINE__";
+			const char kFile[] = "__FILE__";
 
 			assert(replacements->size() == 1);
-			Token& repl = replacements->front();
+			Token &repl = replacements->front();
 			if (macro.name == kLine)
 			{
-				std::ostringstream stream;
-				stream << identifier.location.line;
-				repl.text = stream.str();
+				repl.text = std::to_string(identifier.location.line);
 			}
 			else if (macro.name == kFile)
 			{
-				std::ostringstream stream;
-				stream << identifier.location.file;
-				repl.text = stream.str();
+				repl.text = std::to_string(identifier.location.file);
 			}
 		}
 	}
@@ -270,15 +331,15 @@
 		assert(macro.type == Macro::kTypeFunc);
 		std::vector<MacroArg> args;
 		args.reserve(macro.parameters.size());
-		if (!collectMacroArgs(macro, identifier, &args))
+		if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
 			return false;
 
 		replaceMacroParams(macro, args, replacements);
 	}
 
-	for (size_t i = 0; i < replacements->size(); ++i)
+	for (std::size_t i = 0; i < replacements->size(); ++i)
 	{
-		Token& repl = replacements->at(i);
+		Token &repl = replacements->at(i);
 		if (i == 0)
 		{
 			// The first token in the replacement list inherits the padding
@@ -286,34 +347,42 @@
 			repl.setAtStartOfLine(identifier.atStartOfLine());
 			repl.setHasLeadingSpace(identifier.hasLeadingSpace());
 		}
-		repl.location = identifier.location;
+		repl.location = replacementLocation;
 	}
 	return true;
 }
 
-bool MacroExpander::collectMacroArgs(const Macro& macro,
-                                     const Token& identifier,
-                                     std::vector<MacroArg>* args)
+bool MacroExpander::collectMacroArgs(const Macro &macro,
+                                     const Token &identifier,
+                                     std::vector<MacroArg> *args,
+                                     SourceLocation *closingParenthesisLocation)
 {
 	Token token;
 	getToken(&token);
 	assert(token.type == '(');
 
 	args->push_back(MacroArg());
-	for (int openParens = 1; openParens != 0; )
+
+	// Defer reenabling macros until args collection is finished to avoid the possibility of
+	// infinite recursion. Otherwise infinite recursion might happen when expanding the args after
+	// macros have been popped from the context stack when parsing the args.
+	ScopedMacroReenabler deferReenablingMacros(this);
+
+	int openParens = 1;
+	while (openParens != 0)
 	{
 		getToken(&token);
 
 		if (token.type == Token::LAST)
 		{
-			mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION,
-			                     identifier.location, identifier.text);
+			mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location,
+			                     identifier.text);
 			// Do not lose EOF token.
 			ungetToken(token);
 			return false;
 		}
 
-		bool isArg = false; // True if token is part of the current argument.
+		bool isArg = false;  // True if token is part of the current argument.
 		switch (token.type)
 		{
 		case '(':
@@ -323,12 +392,14 @@
 		case ')':
 			--openParens;
 			isArg = openParens != 0;
+			*closingParenthesisLocation = token.location;
 			break;
 		case ',':
 			// The individual arguments are separated by comma tokens, but
 			// the comma tokens between matching inner parentheses do not
 			// seperate arguments.
-			if (openParens == 1) args->push_back(MacroArg());
+			if (openParens == 1)
+				args->push_back(MacroArg());
 			isArg = openParens != 1;
 			break;
 		default:
@@ -337,14 +408,15 @@
 		}
 		if (isArg)
 		{
-			MacroArg& arg = args->back();
+			MacroArg &arg = args->back();
 			// Initial whitespace is not part of the argument.
-			if (arg.empty()) token.setHasLeadingSpace(false);
+			if (arg.empty())
+				token.setHasLeadingSpace(false);
 			arg.push_back(token);
 		}
 	}
 
-	const Macro::Parameters& params = macro.parameters;
+	const Macro::Parameters &params = macro.parameters;
 	// If there is only one empty argument, it is equivalent to no argument.
 	if (params.empty() && (args->size() == 1) && args->front().empty())
 	{
@@ -354,8 +426,8 @@
 	if (args->size() != params.size())
 	{
 		Diagnostics::ID id = args->size() < macro.parameters.size() ?
-			Diagnostics::MACRO_TOO_FEW_ARGS :
-			Diagnostics::MACRO_TOO_MANY_ARGS;
+			Diagnostics::PP_MACRO_TOO_FEW_ARGS :
+			Diagnostics::PP_MACRO_TOO_MANY_ARGS;
 		mDiagnostics->report(id, identifier.location, identifier.text);
 		return false;
 	}
@@ -363,11 +435,17 @@
 	// Pre-expand each argument before substitution.
 	// This step expands each argument individually before they are
 	// inserted into the macro body.
-	for (size_t i = 0; i < args->size(); ++i)
+	size_t numTokens = 0;
+	for (auto &arg : *args)
 	{
-		MacroArg& arg = args->at(i);
 		TokenLexer lexer(&arg);
-		MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
+		if (mAllowedMacroExpansionDepth < 1)
+		{
+			mDiagnostics->report(Diagnostics::PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
+			                     token.location, token.text);
+			return false;
+		}
+		MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined, mAllowedMacroExpansionDepth - 1);
 
 		arg.clear();
 		expander.lex(&token);
@@ -375,18 +453,32 @@
 		{
 			arg.push_back(token);
 			expander.lex(&token);
+			numTokens++;
+			if (numTokens + mTotalTokensInContexts > kMaxContextTokens)
+			{
+				mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+				return false;
+			}
 		}
 	}
 	return true;
 }
 
-void MacroExpander::replaceMacroParams(const Macro& macro,
-                                       const std::vector<MacroArg>& args,
-                                       std::vector<Token>* replacements)
+void MacroExpander::replaceMacroParams(const Macro &macro,
+                                       const std::vector<MacroArg> &args,
+                                       std::vector<Token> *replacements)
 {
-	for (size_t i = 0; i < macro.replacements.size(); ++i)
+	for (std::size_t i = 0; i < macro.replacements.size(); ++i)
 	{
-		const Token& repl = macro.replacements[i];
+		if (!replacements->empty() &&
+			replacements->size() + mTotalTokensInContexts > kMaxContextTokens)
+		{
+			const Token &token = replacements->back();
+			mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+			return;
+		}
+
+		const Token &repl = macro.replacements[i];
 		if (repl.type != Token::IDENTIFIER)
 		{
 			replacements->push_back(repl);
@@ -396,21 +488,21 @@
 		// TODO(alokp): Optimize this.
 		// There is no need to search for macro params every time.
 		// The param index can be cached with the replacement token.
-		Macro::Parameters::const_iterator iter = std::find(
-			macro.parameters.begin(), macro.parameters.end(), repl.text);
+		Macro::Parameters::const_iterator iter =
+			std::find(macro.parameters.begin(), macro.parameters.end(), repl.text);
 		if (iter == macro.parameters.end())
 		{
 			replacements->push_back(repl);
 			continue;
 		}
 
-		size_t iArg = std::distance(macro.parameters.begin(), iter);
-		const MacroArg& arg = args[iArg];
+		std::size_t iArg = std::distance(macro.parameters.begin(), iter);
+		const MacroArg &arg = args[iArg];
 		if (arg.empty())
 		{
 			continue;
 		}
-		size_t iRepl = replacements->size();
+		std::size_t iRepl = replacements->size();
 		replacements->insert(replacements->end(), arg.begin(), arg.end());
 		// The replacement token inherits padding properties from
 		// macro replacement token.
@@ -418,5 +510,29 @@
 	}
 }
 
+MacroExpander::MacroContext::MacroContext() : macro(0), index(0)
+{
+}
+
+MacroExpander::MacroContext::~MacroContext()
+{
+}
+
+bool MacroExpander::MacroContext::empty() const
+{
+	return index == replacements.size();
+}
+
+const Token &MacroExpander::MacroContext::get()
+{
+	return replacements[index++];
+}
+
+void MacroExpander::MacroContext::unget()
+{
+	assert(index > 0);
+	--index;
+}
+
 }  // namespace pp
 
diff --git a/src/OpenGL/compiler/preprocessor/MacroExpander.h b/src/OpenGL/compiler/preprocessor/MacroExpander.h
index c8c3920..f7c1701 100644
--- a/src/OpenGL/compiler/preprocessor/MacroExpander.h
+++ b/src/OpenGL/compiler/preprocessor/MacroExpander.h
@@ -15,7 +15,6 @@
 #ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
 #define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
 
-#include <cassert>
 #include <memory>
 #include <vector>
 
@@ -27,58 +26,67 @@
 {
 
 class Diagnostics;
+struct SourceLocation;
 
 class MacroExpander : public Lexer
 {
 public:
-	MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics, bool parseDefined);
-	virtual ~MacroExpander();
+	MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics, bool parseDefined, int allowedMacroExpansionDepth);
+	~MacroExpander() override;
 
-	virtual void lex(Token* token);
+	void lex(Token *token) override;
 
 private:
 	PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
 
-	void getToken(Token* token);
-	void ungetToken(const Token& token);
+	void getToken(Token *token);
+	void ungetToken(const Token &token);
 	bool isNextTokenLeftParen();
 
-	bool pushMacro(const Macro& macro, const Token& identifier);
+	bool pushMacro(std::shared_ptr<Macro> macro, const Token &identifier);
 	void popMacro();
 
-	bool expandMacro(const Macro& macro,
-	                 const Token& identifier,
-	                 std::vector<Token>* replacements);
+	bool expandMacro(const Macro &macro, const Token &identifier, std::vector<Token> *replacements);
 
 	typedef std::vector<Token> MacroArg;
-	bool collectMacroArgs(const Macro& macro,
-	                      const Token& identifier,
-	                      std::vector<MacroArg>* args);
-	void replaceMacroParams(const Macro& macro,
-	                        const std::vector<MacroArg>& args,
-	                        std::vector<Token>* replacements);
+	bool collectMacroArgs(const Macro &macro,
+	                      const Token &identifier,
+	                      std::vector<MacroArg> *args,
+	                      SourceLocation *closingParenthesisLocation);
+	void replaceMacroParams(const Macro &macro,
+	                        const std::vector<MacroArg> &args,
+	                        std::vector<Token> *replacements);
 
 	struct MacroContext
 	{
-		const Macro* macro;
-		size_t index;
-		std::vector<Token> replacements;
+		MacroContext();
+		~MacroContext();
+		bool empty() const;
+		const Token &get();
+		void unget();
 
-		MacroContext() : macro(0), index(0) { }
-		bool empty() const { return index == replacements.size(); }
-		const Token& get() { return replacements[index++]; }
-		void unget() { assert(index > 0); --index; }
+		std::shared_ptr<Macro> macro;
+		std::size_t index;
+		std::vector<Token> replacements;
 	};
 
-	Lexer* mLexer;
-	MacroSet* mMacroSet;
-	Diagnostics* mDiagnostics;
+	Lexer *mLexer;
+	MacroSet *mMacroSet;
+	Diagnostics *mDiagnostics;
 	const bool mParseDefined;
 
-	Token* mReserveToken;
-	std::vector<MacroContext*> mContextStack;
+	std::unique_ptr<Token> mReserveToken;
+	std::vector<MacroContext *> mContextStack;
+	size_t mTotalTokensInContexts;
+
+	int mAllowedMacroExpansionDepth;
+
+	bool mDeferReenablingMacros;
+	std::vector<std::shared_ptr<Macro>> mMacrosToReenable;
+
+	class ScopedMacroReenabler;
 };
 
 }  // namespace pp
-#endif  // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+#endif  // COMPILER_PREPROCESSOR_MACROEXPANDER_H_
 
diff --git a/src/OpenGL/compiler/preprocessor/Preprocessor.cpp b/src/OpenGL/compiler/preprocessor/Preprocessor.cpp
index 4ce0bf4..e4e2b5e 100644
--- a/src/OpenGL/compiler/preprocessor/Preprocessor.cpp
+++ b/src/OpenGL/compiler/preprocessor/Preprocessor.cpp
@@ -15,9 +15,8 @@
 #include "Preprocessor.h"
 
 #include <cassert>
-#include <sstream>
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
 #include "DirectiveParser.h"
 #include "Macro.h"
 #include "MacroExpander.h"
@@ -29,25 +28,28 @@
 
 struct PreprocessorImpl
 {
-	Diagnostics* diagnostics;
+	Diagnostics *diagnostics;
 	MacroSet macroSet;
 	Tokenizer tokenizer;
 	DirectiveParser directiveParser;
 	MacroExpander macroExpander;
 
-	PreprocessorImpl(Diagnostics* diag, DirectiveHandler* directiveHandler) :
-		diagnostics(diag),
-		tokenizer(diag),
-		directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
-		macroExpander(&directiveParser, &macroSet, diag, false)
+	PreprocessorImpl(Diagnostics *diag,
+	                 DirectiveHandler *directiveHandler,
+	                 const PreprocessorSettings &settings)
+	    : diagnostics(diag),
+	      tokenizer(diag),
+	      directiveParser(&tokenizer, &macroSet, diag, directiveHandler,  settings.maxMacroExpansionDepth),
+	      macroExpander(&directiveParser, &macroSet, diag, false, settings.maxMacroExpansionDepth)
 	{
 	}
 };
 
-Preprocessor::Preprocessor(Diagnostics* diagnostics,
-                           DirectiveHandler* directiveHandler)
+Preprocessor::Preprocessor(Diagnostics *diagnostics,
+                           DirectiveHandler *directiveHandler,
+                           const PreprocessorSettings &settings)
 {
-	mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
+	mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
 }
 
 Preprocessor::~Preprocessor()
@@ -55,40 +57,25 @@
 	delete mImpl;
 }
 
-bool Preprocessor::init(int count,
-                        const char* const string[],
-                        const int length[])
+bool Preprocessor::init(size_t count, const char *const string[], const int length[])
 {
-	static const int kGLSLVersion = 100;
+	static const int kDefaultGLSLVersion = 100;
 
 	// Add standard pre-defined macros.
 	predefineMacro("__LINE__", 0);
 	predefineMacro("__FILE__", 0);
-	predefineMacro("__VERSION__", kGLSLVersion);
+	predefineMacro("__VERSION__", kDefaultGLSLVersion);
 	predefineMacro("GL_ES", 1);
 
 	return mImpl->tokenizer.init(count, string, length);
 }
 
-void Preprocessor::predefineMacro(const char* name, int value)
+void Preprocessor::predefineMacro(const char *name, int value)
 {
-	std::ostringstream stream;
-	stream << value;
-
-	Token token;
-	token.type = Token::CONST_INT;
-	token.text = stream.str();
-
-	Macro macro;
-	macro.predefined = true;
-	macro.type = Macro::kTypeObj;
-	macro.name = name;
-	macro.replacements.push_back(token);
-
-	mImpl->macroSet[name] = macro;
+	PredefineMacro(&mImpl->macroSet, name, value);
 }
 
-void Preprocessor::lex(Token* token)
+void Preprocessor::lex(Token *token)
 {
 	bool validToken = false;
 	while (!validToken)
@@ -102,40 +89,12 @@
 		case Token::PP_HASH:
 			assert(false);
 			break;
-		case Token::CONST_INT:
-		  {
-			int val = 0;
-			if (!token->iValue(&val))
-			{
-				// Do not mark the token as invalid.
-				// Just emit the diagnostic and reset value to 0.
-				mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
-				                           token->location, token->text);
-				token->text.assign("0");
-			}
-			validToken = true;
-			break;
-		  }
-		case Token::CONST_FLOAT:
-		  {
-			float val = 0;
-			if (!token->fValue(&val))
-			{
-				// Do not mark the token as invalid.
-				// Just emit the diagnostic and reset value to 0.0.
-				mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
-				                           token->location, token->text);
-				token->text.assign("0.0");
-			}
-			validToken = true;
-			break;
-		  }
 		case Token::PP_NUMBER:
-			mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
+			mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
 			                           token->location, token->text);
 			break;
 		case Token::PP_OTHER:
-			mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,
+			mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER,
 			                           token->location, token->text);
 			break;
 		default:
@@ -145,5 +104,9 @@
 	}
 }
 
-}  // namespace pp
+void Preprocessor::setMaxTokenSize(size_t maxTokenSize)
+{
+	mImpl->tokenizer.setMaxTokenSize(maxTokenSize);
+}
 
+}  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Preprocessor.h b/src/OpenGL/compiler/preprocessor/Preprocessor.h
index 62eca56..8fdb2f6 100644
--- a/src/OpenGL/compiler/preprocessor/Preprocessor.h
+++ b/src/OpenGL/compiler/preprocessor/Preprocessor.h
@@ -25,10 +25,18 @@
 struct PreprocessorImpl;
 struct Token;
 
+struct PreprocessorSettings
+{
+	PreprocessorSettings() : maxMacroExpansionDepth(1000) {}
+	int maxMacroExpansionDepth;
+};
+
 class Preprocessor
 {
 public:
-	Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler);
+	Preprocessor(Diagnostics *diagnostics,
+	             DirectiveHandler *directiveHandler,
+	             const PreprocessorSettings &settings);
 	~Preprocessor();
 
 	// count: specifies the number of elements in the string and length arrays.
@@ -40,16 +48,19 @@
 	// Each element in the length array may contain the length of the
 	// corresponding string or a value less than 0 to indicate that the string
 	// is null terminated.
-	bool init(int count, const char* const string[], const int length[]);
+	bool init(size_t count, const char *const string[], const int length[]);
 	// Adds a pre-defined macro.
-	void predefineMacro(const char* name, int value);
+	void predefineMacro(const char *name, int value);
 
-	void lex(Token* token);
+	void lex(Token *token);
+
+	// Set maximum preprocessor token size
+	void setMaxTokenSize(size_t maxTokenSize);
 
 private:
 	PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
 
-	PreprocessorImpl* mImpl;
+	PreprocessorImpl *mImpl;
 };
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/SourceLocation.h b/src/OpenGL/compiler/preprocessor/SourceLocation.h
index b01e73b..234d304 100644
--- a/src/OpenGL/compiler/preprocessor/SourceLocation.h
+++ b/src/OpenGL/compiler/preprocessor/SourceLocation.h
@@ -20,10 +20,10 @@
 
 struct SourceLocation
 {
-	SourceLocation() : file(0), line(0) { }
-	SourceLocation(int f, int l) : file(f), line(l) { }
+	SourceLocation() : file(0), line(0) {}
+	SourceLocation(int f, int l) : file(f), line(l) {}
 
-	bool equals(const SourceLocation& other) const
+	bool equals(const SourceLocation &other) const
 	{
 		return (file == other.file) && (line == other.line);
 	}
@@ -32,12 +32,12 @@
 	int line;
 };
 
-inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs)
+inline bool operator==(const SourceLocation &lhs, const SourceLocation &rhs)
 {
 	return lhs.equals(rhs);
 }
 
-inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs)
+inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs)
 {
 	return !lhs.equals(rhs);
 }
diff --git a/src/OpenGL/compiler/preprocessor/Token.cpp b/src/OpenGL/compiler/preprocessor/Token.cpp
index 28d6f8c..731a592 100644
--- a/src/OpenGL/compiler/preprocessor/Token.cpp
+++ b/src/OpenGL/compiler/preprocessor/Token.cpp
@@ -29,7 +29,7 @@
 	text.clear();
 }
 
-bool Token::equals(const Token& other) const
+bool Token::equals(const Token &other) const
 {
 	return (type == other.type) &&
 	       (flags == other.flags) &&
@@ -61,25 +61,25 @@
 		flags &= ~EXPANSION_DISABLED;
 }
 
-bool Token::iValue(int* value) const
+bool Token::iValue(int *value) const
 {
 	assert(type == CONST_INT);
 	return numeric_lex_int(text, value);
 }
 
-bool Token::uValue(unsigned int* value) const
+bool Token::uValue(unsigned int *value) const
 {
 	assert(type == CONST_INT);
 	return numeric_lex_int(text, value);
 }
 
-bool Token::fValue(float* value) const
+bool Token::fValue(float *value) const
 {
 	assert(type == CONST_FLOAT);
 	return numeric_lex_float(text, value);
 }
 
-std::ostream& operator<<(std::ostream& out, const Token& token)
+std::ostream &operator<<(std::ostream &out, const Token &token)
 {
 	if (token.hasLeadingSpace())
 		out << " ";
diff --git a/src/OpenGL/compiler/preprocessor/Token.h b/src/OpenGL/compiler/preprocessor/Token.h
index ddd3aac..c0475a8 100644
--- a/src/OpenGL/compiler/preprocessor/Token.h
+++ b/src/OpenGL/compiler/preprocessor/Token.h
@@ -27,6 +27,8 @@
 {
 	enum Type
 	{
+		// Calling this ERROR causes a conflict with wingdi.h
+		GOT_ERROR = -1,
 		LAST = 0,  // EOF.
 
 		IDENTIFIER = 258,
@@ -70,10 +72,10 @@
 		EXPANSION_DISABLED = 1 << 2
 	};
 
-	Token() : type(0), flags(0) { }
+	Token() : type(0), flags(0) {}
 
 	void reset();
-	bool equals(const Token& other) const;
+	bool equals(const Token &other) const;
 
 	// Returns true if this is the first token on line.
 	// It disregards any leading whitespace.
@@ -88,9 +90,9 @@
 
 	// Converts text into numeric value for CONST_INT and CONST_FLOAT token.
 	// Returns false if the parsed value cannot fit into an int or float.
-	bool iValue(int* value) const;
-	bool uValue(unsigned int* value) const;
-	bool fValue(float* value) const;
+	bool iValue(int *value) const;
+	bool uValue(unsigned int *value) const;
+	bool fValue(float *value) const;
 
 	int type;
 	unsigned int flags;
@@ -98,17 +100,17 @@
 	std::string text;
 };
 
-inline bool operator==(const Token& lhs, const Token& rhs)
+inline bool operator==(const Token &lhs, const Token &rhs)
 {
 	return lhs.equals(rhs);
 }
 
-inline bool operator!=(const Token& lhs, const Token& rhs)
+inline bool operator!=(const Token &lhs, const Token &rhs)
 {
 	return !lhs.equals(rhs);
 }
 
-extern std::ostream& operator<<(std::ostream& out, const Token& token);
+std::ostream &operator<<(std::ostream &out, const Token &token);
 
 }  // namepsace pp
 #endif  // COMPILER_PREPROCESSOR_TOKEN_H_
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.cpp b/src/OpenGL/compiler/preprocessor/Tokenizer.cpp
index 39e29be..44025a9 100644
--- a/src/OpenGL/compiler/preprocessor/Tokenizer.cpp
+++ b/src/OpenGL/compiler/preprocessor/Tokenizer.cpp
@@ -1,4 +1,4 @@
-#line 16 "./Tokenizer.l"
+#line 24 "./Tokenizer.l"
 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,20 +17,330 @@
 
 
 
-#line 13 "./Tokenizer.cpp"
-
 #define  YY_INT_ALIGNED short int
 
 /* A lexical scanner generated by flex */
 
+
+
+
+
+
+
+
+
+
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 0
+#define YY_FLEX_SUBMINOR_VERSION 4
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef yy_create_buffer
+#define pp_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer pp_create_buffer
+#endif
+
+    
+#ifdef yy_delete_buffer
+#define pp_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer pp_delete_buffer
+#endif
+
+    
+#ifdef yy_scan_buffer
+#define pp_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer pp_scan_buffer
+#endif
+
+    
+#ifdef yy_scan_string
+#define pp_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string pp_scan_string
+#endif
+
+    
+#ifdef yy_scan_bytes
+#define pp_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes pp_scan_bytes
+#endif
+
+    
+#ifdef yy_init_buffer
+#define pp_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer pp_init_buffer
+#endif
+
+    
+#ifdef yy_flush_buffer
+#define pp_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer pp_flush_buffer
+#endif
+
+    
+#ifdef yy_load_buffer_state
+#define pp_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state pp_load_buffer_state
+#endif
+
+    
+#ifdef yy_switch_to_buffer
+#define pp_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer pp_switch_to_buffer
+#endif
+
+    
+#ifdef yypush_buffer_state
+#define pppush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state pppush_buffer_state
+#endif
+
+    
+#ifdef yypop_buffer_state
+#define pppop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state pppop_buffer_state
+#endif
+
+    
+#ifdef yyensure_buffer_stack
+#define ppensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack ppensure_buffer_stack
+#endif
+
+    
+#ifdef yylex
+#define pplex_ALREADY_DEFINED
+#else
+#define yylex pplex
+#endif
+
+    
+#ifdef yyrestart
+#define pprestart_ALREADY_DEFINED
+#else
+#define yyrestart pprestart
+#endif
+
+    
+#ifdef yylex_init
+#define pplex_init_ALREADY_DEFINED
+#else
+#define yylex_init pplex_init
+#endif
+
+    
+#ifdef yylex_init_extra
+#define pplex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra pplex_init_extra
+#endif
+
+    
+#ifdef yylex_destroy
+#define pplex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy pplex_destroy
+#endif
+
+    
+#ifdef yyget_debug
+#define ppget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug ppget_debug
+#endif
+
+    
+#ifdef yyset_debug
+#define ppset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug ppset_debug
+#endif
+
+    
+#ifdef yyget_extra
+#define ppget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra ppget_extra
+#endif
+
+    
+#ifdef yyset_extra
+#define ppset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra ppset_extra
+#endif
+
+    
+#ifdef yyget_in
+#define ppget_in_ALREADY_DEFINED
+#else
+#define yyget_in ppget_in
+#endif
+
+    
+#ifdef yyset_in
+#define ppset_in_ALREADY_DEFINED
+#else
+#define yyset_in ppset_in
+#endif
+
+    
+#ifdef yyget_out
+#define ppget_out_ALREADY_DEFINED
+#else
+#define yyget_out ppget_out
+#endif
+
+    
+#ifdef yyset_out
+#define ppset_out_ALREADY_DEFINED
+#else
+#define yyset_out ppset_out
+#endif
+
+    
+#ifdef yyget_leng
+#define ppget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng ppget_leng
+#endif
+
+    
+#ifdef yyget_text
+#define ppget_text_ALREADY_DEFINED
+#else
+#define yyget_text ppget_text
+#endif
+
+    
+#ifdef yyget_lineno
+#define ppget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno ppget_lineno
+#endif
+
+    
+#ifdef yyset_lineno
+#define ppset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno ppset_lineno
+#endif
+
+    
+        
+#ifdef yyget_column
+#define ppget_column_ALREADY_DEFINED
+#else
+#define yyget_column ppget_column
+#endif
+
+        
+#ifdef yyset_column
+#define ppset_column_ALREADY_DEFINED
+#else
+#define yyset_column ppset_column
+#endif
+
+    
+    
+#ifdef yywrap
+#define ppwrap_ALREADY_DEFINED
+#else
+#define yywrap ppwrap
+#endif
+
+
+
+
+    
+#ifdef yyget_lval
+#define ppget_lval_ALREADY_DEFINED
+#else
+#define yyget_lval ppget_lval
+#endif
+
+    
+#ifdef yyset_lval
+#define ppset_lval_ALREADY_DEFINED
+#else
+#define yyset_lval ppset_lval
+#endif
+
+
+
+
+    
+#ifdef yyget_lloc
+#define ppget_lloc_ALREADY_DEFINED
+#else
+#define yyget_lloc ppget_lloc
+#endif
+
+    
+#ifdef yyset_lloc
+#define ppset_lloc_ALREADY_DEFINED
+#else
+#define yyset_lloc ppset_lloc
+#endif
+
+
+
+
+#ifdef yyalloc
+#define ppalloc_ALREADY_DEFINED
+#else
+#define yyalloc ppalloc
+#endif
+
+    
+#ifdef yyrealloc
+#define pprealloc_ALREADY_DEFINED
+#else
+#define yyrealloc pprealloc
+#endif
+
+    
+#ifdef yyfree
+#define ppfree_ALREADY_DEFINED
+#else
+#define yyfree ppfree
+#endif
+
+
+
+
+
+
+
+
+
 /* First, we deal with  platform-specific or compiler-specific issues. */
 
 /* begin standard C headers. */
@@ -101,40 +411,38 @@
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
 #endif /* ! C99 */
 
 #endif /* ! FLEXINT_H */
 
-#ifdef __cplusplus
 
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
+/* begin standard C++ headers. */
 
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
 #define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
 #else
-#define yyconst
+#define yynoreturn
 #endif
 
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+
+/* Promotes a possibly negative, possibly signed char to an
+ *   integer in range [0..255] for use as an array index.
  */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+
+
+
 
 /* An opaque pointer. */
 #ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -142,6 +450,22 @@
 typedef void* yyscan_t;
 #endif
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 /* For convenience, these vars (plus the bison vars far below)
    are macros in the reentrant scanner. */
 #define yyin yyg->yyin_r
@@ -153,27 +477,36 @@
 #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
 #define yy_flex_debug yyg->yy_flex_debug_r
 
+
+
+
+
+
+
+
+
+
+
+
+
 /* Enter a start condition.  This macro really ought to take a parameter,
  * but we do it the disgusting crufty way forced on us by the ()-less
  * definition of BEGIN.
  */
 #define BEGIN yyg->yy_start = 1 + 2 *
-
 /* Translate the current start state into a value that can be later handed
  * to BEGIN to return to the state.  The YYSTATE alias is for lex
  * compatibility.
  */
 #define YY_START ((yyg->yy_start - 1) / 2)
 #define YYSTATE YY_START
-
 /* Action number for EOF rule of a given start state. */
 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
 /* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE pprestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
 #define YY_END_OF_BUFFER_CHAR 0
 
+
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
 #ifdef __ia64__
@@ -187,10 +520,13 @@
 #endif /* __ia64__ */
 #endif
 
+
 /* The state buf must be large enough to hold one state per character in the main buffer.
  */
 #define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
 
+
+
 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
 #define YY_TYPEDEF_YY_BUFFER_STATE
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -201,10 +537,13 @@
 typedef size_t yy_size_t;
 #endif
 
+
+
+
 #define EOB_ACT_CONTINUE_SCAN 0
 #define EOB_ACT_END_OF_FILE 1
 #define EOB_ACT_LAST_MATCH 2
-
+    
     #define YY_LESS_LINENO(n)
     #define YY_LINENO_REWIND_TO(ptr)
     
@@ -221,27 +560,29 @@
 		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
 		} \
 	while ( 0 )
-
 #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
 
+
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
 struct yy_buffer_state
 	{
 	FILE *yy_input_file;
 
+
+
 	char *yy_ch_buf;		/* input buffer */
 	char *yy_buf_pos;		/* current position in input buffer */
 
 	/* Size of input buffer in bytes, not including room for EOB
 	 * characters.
 	 */
-	yy_size_t yy_buf_size;
+	int yy_buf_size;
 
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	yy_size_t yy_n_chars;
+	int yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -264,7 +605,8 @@
 
     int yy_bs_lineno; /**< The line count. */
     int yy_bs_column; /**< The column count. */
-    
+
+
 	/* Whether to try to fill the input buffer when we reach the
 	 * end of it.
 	 */
@@ -281,7 +623,7 @@
 	 * possible backing-up.
 	 *
 	 * When we actually see the EOF, we change the status to "new"
-	 * (via pprestart()), so that the user can continue scanning by
+	 * (via yyrestart()), so that the user can continue scanning by
 	 * just pointing yyin at a new input file.
 	 */
 #define YY_BUFFER_EOF_PENDING 2
@@ -289,6 +631,9 @@
 	};
 #endif /* !YY_STRUCT_YY_BUFFER_STATE */
 
+
+
+
 /* We provide macros for accessing buffer states in case in the
  * future we want to put the buffer states in a more general
  * "scanner state".
@@ -298,89 +643,97 @@
 #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
                           ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
                           : NULL)
-
 /* Same as previous macro, but useful when we know that the buffer stack is not
  * NULL or when we need an lvalue. For internal use only.
  */
 #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
 
-void pprestart (FILE *input_file ,yyscan_t yyscanner );
-void pp_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE pp_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void pp_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void pp_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void pppush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void pppop_buffer_state (yyscan_t yyscanner );
 
-static void ppensure_buffer_stack (yyscan_t yyscanner );
-static void pp_load_buffer_state (yyscan_t yyscanner );
-static void pp_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
 
-#define YY_FLUSH_BUFFER pp_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
 
-YY_BUFFER_STATE pp_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE pp_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE pp_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
 
-void *ppalloc (yy_size_t ,yyscan_t yyscanner );
-void *pprealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void ppfree (void * ,yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
 
-#define yy_new_buffer pp_create_buffer
 
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
+
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
+
+
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+
+
+#define yy_new_buffer yy_create_buffer
 #define yy_set_interactive(is_interactive) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){ \
-        ppensure_buffer_stack (yyscanner); \
+        yyensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
 	}
-
 #define yy_set_bol(at_bol) \
 	{ \
 	if ( ! YY_CURRENT_BUFFER ){\
-        ppensure_buffer_stack (yyscanner); \
+        yyensure_buffer_stack (yyscanner); \
 		YY_CURRENT_BUFFER_LVALUE =    \
-            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
 	} \
 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
 	}
-
 #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
+
 /* Begin user sect3 */
 
 #define ppwrap(yyscanner) (/*CONSTCOND*/1)
 #define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
 
-typedef unsigned char YY_CHAR;
 
 typedef int yy_state_type;
 
 #define yytext_ptr yytext_r
 
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-#if defined(__GNUC__) && __GNUC__ >= 3
-__attribute__((__noreturn__))
-#endif
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+
+
+
+
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
+
+
+
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
  */
 #define YY_DO_BEFORE_ACTION \
 	yyg->yytext_ptr = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyleng = (int) (yy_cp - yy_bp); \
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 38
-#define YY_END_OF_BUFFER 39
+#define YY_NUM_RULES 37
+#define YY_END_OF_BUFFER 38
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -388,22 +741,22 @@
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[98] =
+static const flex_int16_t yy_accept[95] =
     {   0,
-        0,    0,    0,    0,   39,   37,   34,   35,   35,   33,
+        0,    0,    0,    0,   38,   36,   34,   35,   35,   33,
         7,   33,   33,   33,   33,   33,   33,   33,   33,    9,
-        9,   33,   33,   33,    8,   37,   33,   33,    3,    5,
-        5,    4,   34,   35,   19,   27,   20,   30,   25,   12,
-       23,   13,   24,   10,    2,    1,   26,   10,    9,   11,
-       11,   11,    9,   11,    9,    9,   14,   16,   18,   17,
-       15,    8,   36,   36,   31,   21,   32,   22,    3,    5,
-        6,   11,   10,   11,   10,    1,   10,   11,   10,    0,
-       10,    9,    9,    9,   28,   29,    0,   10,   10,   10,
-       10,    9,   10,   10,    9,   10,    0
+        9,   33,   33,   33,    8,   33,   33,    3,    5,    5,
+        4,   34,   35,   19,   27,   20,   30,   25,   12,   23,
+       13,   24,   10,    2,    1,   26,   10,    9,   11,   11,
+       11,    9,   11,    9,    9,   14,   16,   18,   17,   15,
+        8,   31,   21,   32,   22,    3,    5,    6,   11,   10,
+       11,   10,    1,   10,   11,   10,    0,   10,    9,    9,
+        9,   28,   29,    0,   10,   10,   10,   10,    9,   10,
+       10,    9,   10,    0
 
     } ;
 
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         2,    2,    4,    1,    1,    1,    1,    1,    1,    1,
@@ -414,11 +767,11 @@
        19,   20,    9,    1,   21,   21,   21,   21,   22,   23,
        24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
        24,   24,   24,   24,   25,   24,   24,   26,   24,   24,
-        9,   27,    9,   28,   24,    1,   21,   21,   21,   21,
+        9,    1,    9,   27,   24,    1,   21,   21,   21,   21,
 
        22,   23,   24,   24,   24,   24,   24,   24,   24,   24,
        24,   24,   24,   24,   24,   24,   25,   24,   24,   26,
-       24,   24,    9,   29,    9,    9,    1,    1,    1,    1,
+       24,   24,    9,   28,    9,    9,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -435,101 +788,99 @@
         1,    1,    1,    1,    1
     } ;
 
-static yyconst YY_CHAR yy_meta[30] =
+static const YY_CHAR yy_meta[29] =
     {   0,
         1,    1,    2,    2,    1,    1,    1,    1,    1,    3,
         1,    1,    4,    1,    5,    5,    5,    1,    1,    1,
-        5,    5,    5,    5,    5,    5,    1,    1,    1
+        5,    5,    5,    5,    5,    5,    1,    1
     } ;
 
-static yyconst flex_uint16_t yy_base[103] =
+static const flex_int16_t yy_base[100] =
     {   0,
-        0,    0,   27,   29,  137,  194,  133,  194,  117,  100,
-      194,   98,   26,  194,   94,   24,   28,   33,   32,   39,
-       51,   39,   80,   50,    0,   68,   25,   54,    0,  194,
-       88,   71,   80,  194,  194,  194,  194,  194,  194,  194,
-      194,  194,  194,   71,  194,    0,  194,   85,   55,   64,
-       99,  111,   53,  105,    0,   50,   55,  194,  194,  194,
-       40,    0,  194,   38,  194,  194,  194,  194,    0,  194,
-      194,  117,    0,  130,    0,    0,    0,  137,    0,   88,
-      113,    0,  131,    0,  194,  194,  143,  139,  152,  150,
-        0,   13,  153,  194,    0,  194,  194,  176,   31,  181,
+        0,    0,   26,   28,  133,  195,  130,  195,  128,  105,
+      195,  104,   25,  195,  100,   23,   27,   32,   31,   38,
+       50,   38,   93,   49,    0,   16,   51,    0,  195,  105,
+       87,   93,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,   67,  195,    0,  195,   81,   55,   84,   98,
+      110,   53,   61,    0,   52,   39,  195,  195,  195,   33,
+        0,  195,  195,  195,  195,    0,  195,  195,  113,    0,
+      126,    0,    0,    0,  133,    0,   56,  128,    0,  133,
+        0,  195,  195,  101,  141,  143,  145,    0,   15,  154,
+      195,    0,  195,  195,  177,   32,  182,  187,  189
 
-      186,  188
     } ;
 
-static yyconst flex_int16_t yy_def[103] =
+static const flex_int16_t yy_def[100] =
     {   0,
-       97,    1,   98,   98,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       20,   97,   97,   97,   99,   97,   97,   97,  100,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,  101,   97,   97,   20,   20,
-       50,   51,   51,  102,   21,   51,   97,   97,   97,   97,
-       97,   99,   97,   97,   97,   97,   97,   97,  100,   97,
-       97,   44,   44,   72,   72,  101,   48,   51,   51,   97,
-       52,   51,  102,   51,   97,   97,   97,   74,   78,   97,
-       51,   51,   97,   97,   51,   97,    0,   97,   97,   97,
+       94,    1,   95,   95,   94,   94,   94,   94,   94,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       20,   94,   94,   94,   96,   94,   94,   97,   94,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94,   94,   98,   94,   94,   20,   20,   49,
+       50,   50,   99,   21,   50,   94,   94,   94,   94,   94,
+       96,   94,   94,   94,   94,   97,   94,   94,   43,   43,
+       69,   69,   98,   47,   50,   50,   94,   51,   50,   99,
+       50,   94,   94,   94,   71,   75,   94,   50,   50,   94,
+       94,   50,   94,    0,   94,   94,   94,   94,   94
 
-       97,   97
     } ;
 
-static yyconst flex_uint16_t yy_nxt[224] =
+static const flex_int16_t yy_nxt[224] =
     {   0,
         6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
        16,   17,   18,   19,   20,   21,   21,   22,   23,   24,
-       25,   25,   25,   25,   25,   25,   26,   27,   28,   30,
-       31,   30,   31,   37,   40,   62,   32,   95,   32,   42,
-       63,   45,   41,   65,   38,   46,   43,   44,   44,   44,
-       47,   48,   66,   49,   49,   50,   57,   58,   86,   51,
-       52,   51,   51,   53,   54,   55,   55,   55,   60,   61,
-       63,   64,   67,   85,   84,   56,   51,   82,   50,   50,
-       51,   33,   68,   72,   71,   73,   73,   73,   51,   51,
-       70,   72,   74,   75,   72,   72,   72,   51,   59,   77,
+       25,   25,   25,   25,   25,   25,   26,   27,   29,   30,
+       29,   30,   36,   39,   62,   31,   61,   31,   41,   92,
+       44,   40,   63,   37,   45,   42,   43,   43,   43,   46,
+       47,   83,   48,   48,   49,   56,   57,   82,   50,   51,
+       50,   50,   52,   53,   54,   54,   54,   59,   60,   64,
+       87,   87,   87,   50,   55,   50,   81,   79,   65,   69,
+       50,   70,   70,   70,   50,   50,   50,   69,   71,   72,
+       69,   69,   69,   50,   32,   74,   74,   74,   49,   49,
 
-       77,   77,   90,   90,   90,   51,   78,   79,   51,   51,
-       51,   51,   39,   51,   51,   51,   36,   51,   35,   34,
-       51,   80,   80,   97,   97,   81,   81,   81,   51,   51,
-       51,   72,   72,   72,   33,   91,   97,   97,   72,   72,
-       87,   87,   97,   51,   88,   88,   88,   87,   87,   97,
-       97,   89,   89,   89,   51,   92,   51,   93,   93,   93,
-       97,   75,   97,   97,   90,   90,   90,   93,   93,   93,
-       97,   97,   94,   97,   79,   96,   29,   29,   29,   29,
-       29,   69,   97,   97,   69,   69,   76,   97,   76,   76,
-       76,   83,   83,    5,   97,   97,   97,   97,   97,   97,
+       68,   50,   75,   76,   50,   50,   50,   67,   50,   50,
+       50,   58,   50,   50,   50,   90,   90,   90,   38,   50,
+       77,   77,   35,   34,   78,   78,   78,   69,   69,   69,
+       33,   32,   94,   94,   69,   69,   84,   84,   94,   94,
+       85,   85,   85,   84,   84,   50,   94,   86,   86,   86,
+       88,   94,   94,   94,   94,   94,   50,   89,   50,   87,
+       87,   87,   94,   72,   94,   76,   94,   91,   90,   90,
+       90,   94,   94,   94,   94,   94,   93,   28,   28,   28,
+       28,   28,   66,   94,   94,   66,   66,   73,   94,   73,
+       73,   73,   80,   80,    5,   94,   94,   94,   94,   94,
 
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94
     } ;
 
-static yyconst flex_int16_t yy_chk[224] =
+static const flex_int16_t yy_chk[224] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
-        3,    4,    4,   13,   16,   99,    3,   92,    4,   17,
-       64,   19,   16,   27,   13,   19,   17,   18,   18,   18,
-       19,   20,   27,   20,   20,   20,   22,   22,   61,   20,
-       20,   20,   20,   20,   20,   21,   21,   21,   24,   24,
-       26,   26,   28,   57,   56,   21,   21,   53,   50,   50,
-       49,   33,   28,   44,   32,   44,   44,   44,   50,   50,
-       31,   44,   44,   44,   44,   44,   44,   48,   23,   48,
+        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
+        4,    4,   13,   16,   26,    3,   96,    4,   17,   89,
+       19,   16,   26,   13,   19,   17,   18,   18,   18,   19,
+       20,   60,   20,   20,   20,   22,   22,   56,   20,   20,
+       20,   20,   20,   20,   21,   21,   21,   24,   24,   27,
+       77,   77,   77,   53,   21,   21,   55,   52,   27,   43,
+       48,   43,   43,   43,   53,   53,   53,   43,   43,   43,
+       43,   43,   43,   47,   32,   47,   47,   47,   49,   49,
 
-       48,   48,   80,   80,   80,   48,   48,   48,   48,   48,
-       48,   51,   15,   51,   51,   51,   12,   54,   10,    9,
-       51,   52,   52,   81,   81,   52,   52,   52,   54,   54,
-       54,   72,   72,   72,    7,   81,    5,    0,   72,   72,
-       74,   74,    0,   83,   74,   74,   74,   78,   78,   88,
-       88,   78,   78,   78,   83,   83,   83,   87,   87,   87,
-        0,   88,   89,   89,   90,   90,   90,   93,   93,   93,
-        0,    0,   90,    0,   89,   93,   98,   98,   98,   98,
-       98,  100,    0,    0,  100,  100,  101,    0,  101,  101,
-      101,  102,  102,   97,   97,   97,   97,   97,   97,   97,
+       31,   47,   47,   47,   47,   47,   47,   30,   49,   49,
+       50,   23,   50,   50,   50,   84,   84,   84,   15,   50,
+       51,   51,   12,   10,   51,   51,   51,   69,   69,   69,
+        9,    7,    5,    0,   69,   69,   71,   71,   78,   78,
+       71,   71,   71,   75,   75,   80,    0,   75,   75,   75,
+       78,   85,   85,   86,   86,    0,   80,   80,   80,   87,
+       87,   87,    0,   85,    0,   86,    0,   87,   90,   90,
+       90,    0,    0,    0,    0,    0,   90,   95,   95,   95,
+       95,   95,   97,    0,    0,   97,   97,   98,    0,   98,
+       98,   98,   99,   99,   94,   94,   94,   94,   94,   94,
 
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94,   94,   94,   94,   94,   94,   94,   94,
+       94,   94,   94
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -561,14 +912,27 @@
 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
 */
 
+#if defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#endif
+
 #include "Tokenizer.h"
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
 #include "Token.h"
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated yy_fatal_error function.
 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4244)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
 #endif
 
 typedef std::string YYSTYPE;
@@ -602,13 +966,25 @@
     } while(0);
 
 #define YY_INPUT(buf, result, maxSize) \
-    result = yyextra->input.read(buf, maxSize);
+    result = yyextra->input.read(buf, maxSize, &yylineno);
+
+
+
+
 
 #define INITIAL 0
 #define COMMENT 1
 
+
+
+
+
+
 #define YY_EXTRA_TYPE pp::Tokenizer::Context*
 
+
+
+
 /* Holds the entire state of the reentrant scanner. */
 struct yyguts_t
     {
@@ -622,8 +998,8 @@
     size_t yy_buffer_stack_max; /**< capacity of stack. */
     YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
     char yy_hold_char;
-    yy_size_t yy_n_chars;
-    yy_size_t yyleng_r;
+    int yy_n_chars;
+    int yyleng_r;
     char *yy_c_buf_p;
     int yy_init;
     int yy_start;
@@ -637,78 +1013,141 @@
     int yylineno_r;
     int yy_flex_debug_r;
 
+
+
+
     char *yytext_r;
     int yy_more_flag;
     int yy_more_len;
 
+
+
     YYSTYPE * yylval_r;
 
+
+
     YYLTYPE * yylloc_r;
 
+
     }; /* end struct yyguts_t */
 
-static int yy_init_globals (yyscan_t yyscanner );
 
+
+
+static int yy_init_globals ( yyscan_t yyscanner );
+
+
+
+
+    
     /* This must go here because YYSTYPE and YYLTYPE are included
      * from bison output in section 1.*/
     #    define yylval yyg->yylval_r
     
+
+    
     #    define yylloc yyg->yylloc_r
     
-int pplex_init (yyscan_t* scanner);
 
-int pplex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
+
+
 
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
-int pplex_destroy (yyscan_t yyscanner );
 
-int ppget_debug (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
 
-void ppset_debug (int debug_flag ,yyscan_t yyscanner );
 
-YY_EXTRA_TYPE ppget_extra (yyscan_t yyscanner );
 
-void ppset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
 
-FILE *ppget_in (yyscan_t yyscanner );
 
-void ppset_in  (FILE * _in_str ,yyscan_t yyscanner );
 
-FILE *ppget_out (yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
 
-void ppset_out  (FILE * _out_str ,yyscan_t yyscanner );
 
-yy_size_t ppget_leng (yyscan_t yyscanner );
 
-char *ppget_text (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
 
-int ppget_lineno (yyscan_t yyscanner );
 
-void ppset_lineno (int _line_number ,yyscan_t yyscanner );
 
-int ppget_column  (yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
 
-void ppset_column (int _column_no ,yyscan_t yyscanner );
 
-YYSTYPE * ppget_lval (yyscan_t yyscanner );
 
-void ppset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
 
-       YYLTYPE *ppget_lloc (yyscan_t yyscanner );
+
+
+void yyset_in  ( FILE * _in_str , yyscan_t yyscanner );
+
+
+
+FILE *yyget_out ( yyscan_t yyscanner );
+
+
+
+void yyset_out  ( FILE * _out_str , yyscan_t yyscanner );
+
+
+
+			int yyget_leng ( yyscan_t yyscanner );
+
+
+
+char *yyget_text ( yyscan_t yyscanner );
+
+
+
+int yyget_lineno ( yyscan_t yyscanner );
+
+
+
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
+
+
+
+
+int yyget_column  ( yyscan_t yyscanner );
+
+
+
+
+
+void yyset_column ( int _column_no , yyscan_t yyscanner );
+
+
+
+
+YYSTYPE * yyget_lval ( yyscan_t yyscanner );
+
+
+void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
+
+
     
-        void ppset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+       YYLTYPE *yyget_lloc ( yyscan_t yyscanner );
     
+
+    
+        void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner );
+    
+
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
 
 #ifndef YY_SKIP_YYWRAP
 #ifdef __cplusplus
-extern "C" int ppwrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
 #else
-extern int ppwrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
 #endif
 #endif
 
@@ -716,24 +1155,31 @@
     
 #endif
 
+
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
 #endif
 
 #ifndef YY_NO_INPUT
-
 #ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
 #else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
 #endif
 
 #endif
 
+
+
+
+
+
+
+
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
 #ifdef __ia64__
@@ -744,14 +1190,17 @@
 #endif /* __ia64__ */
 #endif
 
+
 /* Copy whatever the last rule matched to the standard output. */
 #ifndef ECHO
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
 #endif
 
+
+
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
  * is returned in "result".
  */
@@ -760,7 +1209,7 @@
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		int n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -773,7 +1222,7 @@
 	else \
 		{ \
 		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
 			{ \
 			if( errno != EINTR) \
 				{ \
@@ -788,6 +1237,8 @@
 
 #endif
 
+
+
 /* No semi-colon after return; correct usage is to write "yyterminate();" -
  * we don't want an extra ';' after the "return" because that will cause
  * some compilers to complain about unreachable statements.
@@ -796,31 +1247,54 @@
 #define yyterminate() return YY_NULL
 #endif
 
+
 /* Number of entries by which start-condition stack grows. */
 #ifndef YY_START_STACK_INCR
 #define YY_START_STACK_INCR 25
 #endif
 
+
 /* Report a fatal error. */
 #ifndef YY_FATAL_ERROR
 #define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
 #endif
 
+
+
 /* end tables serialization structures and prototypes */
 
+
+
 /* Default declaration of generated scanner - a define so the user can
  * easily add parameters.
  */
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int pplex \
-               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
 
-#define YY_DECL int pplex \
+
+
+
+
+        
+    
+    
+
+
+
+    
+    
+    
+
+
+extern int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
                (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
 #endif /* !YY_DECL */
 
+
 /* Code executed at the beginning of each rule, after yytext and yyleng
  * have been set up.
  */
@@ -828,14 +1302,19 @@
 #define YY_USER_ACTION
 #endif
 
+
+
 /* Code executed at the end of each rule. */
 #ifndef YY_BREAK
 #define YY_BREAK /*LINTED*/break;
 #endif
 
+
+
 #define YY_RULE_SETUP \
 	YY_USER_ACTION
 
+
 /** The main scanner function which does all the work.
  */
 YY_DECL
@@ -845,10 +1324,16 @@
 	int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
+
+
+
     yylval = yylval_param;
 
+
+
     yylloc = yylloc_param;
 
+
 	if ( !yyg->yy_init )
 		{
 		yyg->yy_init = 1;
@@ -857,6 +1342,8 @@
 		YY_USER_INIT;
 #endif
 
+
+
 		if ( ! yyg->yy_start )
 			yyg->yy_start = 1;	/* first start state */
 
@@ -867,16 +1354,17 @@
 			yyout = stdout;
 
 		if ( ! YY_CURRENT_BUFFER ) {
-			ppensure_buffer_stack (yyscanner);
+			yyensure_buffer_stack (yyscanner);
 			YY_CURRENT_BUFFER_LVALUE =
-				pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+				yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
 		}
 
-		pp_load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 		}
 
 	{
 
+
     /* Line comment */
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
@@ -904,13 +1392,13 @@
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 98 )
-					yy_c = yy_meta[(unsigned int) yy_c];
+				if ( yy_current_state >= 95 )
+					yy_c = yy_meta[yy_c];
 				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 97 );
+		while ( yy_current_state != 94 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -919,8 +1407,11 @@
 
 		YY_DO_BEFORE_ACTION;
 
+
+
 do_action:	/* This label is used only to access EOF actions. */
 
+
 		switch ( yy_act )
 	{ /* beginning of action switch */
 			case 0: /* must back up */
@@ -936,7 +1427,7 @@
 	YY_BREAK
 /* Block comment */
 /* Line breaks are just counted - not returned. */
-/* The comment is replaced by a single space. */ 
+/* The comment is replaced by a single space. */
 case 2:
 YY_RULE_SETUP
 { BEGIN(COMMENT); }
@@ -952,7 +1443,14 @@
 case 5:
 /* rule 5 can match eol */
 YY_RULE_SETUP
-{ ++yylineno; }
+{
+    if (yylineno == INT_MAX)
+    {
+        *yylval = "Integer overflow on line number";
+        return pp::Token::GOT_ERROR;
+    }
+    ++yylineno;
+}
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
@@ -1161,17 +1659,17 @@
 /* rule 35 can match eol */
 YY_RULE_SETUP
 {
+    if (yylineno == INT_MAX)
+    {
+        *yylval = "Integer overflow on line number";
+        return pp::Token::GOT_ERROR;
+    }
     ++yylineno;
     yylval->assign(1, '\n');
     return '\n';
 }
 	YY_BREAK
 case 36:
-/* rule 36 can match eol */
-YY_RULE_SETUP
-{ ++yylineno; }
-	YY_BREAK
-case 37:
 YY_RULE_SETUP
 {
     yylval->assign(1, yytext[0]);
@@ -1185,28 +1683,35 @@
     // Set the location for EOF token manually.
     pp::Input* input = &yyextra->input;
     pp::Input::Location* scanLoc = &yyextra->scanLoc;
-    int sIndexMax = std::max(0, input->count() - 1);
+    yy_size_t sIndexMax = input->count() ? input->count() - 1 : 0;
     if (scanLoc->sIndex != sIndexMax)
     {
         // We can only reach here if there are empty strings at the
         // end of the input.
         scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
-        yyfileno = sIndexMax; yylineno = 1;
+        // FIXME: this is not 64-bit clean.
+        yyfileno = static_cast<int>(sIndexMax); yylineno = 1;
     }
     yylloc->file = yyfileno;
     yylloc->line = yylineno;
     yylval->clear();
 
-    if (YY_START == COMMENT)
+    // Line number overflows fake EOFs to exit early, check for this case.
+    if (yylineno == INT_MAX) {
+        yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+                pp::SourceLocation(yyfileno, yylineno),
+                "Integer overflow on line number");
+    }
+    else if (YY_START == COMMENT)
     {
-        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
+        yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
-                                     "");
+                                     "EOF while in a comment");
     }
     yyterminate();
 }
 	YY_BREAK
-case 38:
+case 37:
 YY_RULE_SETUP
 ECHO;
 	YY_BREAK
@@ -1225,7 +1730,7 @@
 			/* We're scanning a new file or input source.  It's
 			 * possible that this happened because the user
 			 * just pointed yyin at a new source and called
-			 * pplex().  If so, then we have to assure
+			 * yylex().  If so, then we have to assure
 			 * consistency between YY_CURRENT_BUFFER and our
 			 * globals.  Here is the right place to do so, because
 			 * this is the first action (other than possibly a
@@ -1286,7 +1791,7 @@
 				{
 				yyg->yy_did_buffer_switch_on_eof = 0;
 
-				if ( ppwrap(yyscanner ) )
+				if ( yywrap( yyscanner ) )
 					{
 					/* Note: because we've taken care in
 					 * yy_get_next_buffer() to have set up
@@ -1340,7 +1845,11 @@
 	} /* end of action switch */
 		} /* end of scanning one token */
 	} /* end of user's declarations */
-} /* end of pplex */
+} /* end of yylex */
+
+
+
+
 
 /* yy_get_next_buffer - try to read in a new buffer
  *
@@ -1354,7 +1863,7 @@
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
 	char *source = yyg->yytext_ptr;
-	yy_size_t number_to_move, i;
+	int number_to_move, i;
 	int ret_val;
 
 	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1383,7 +1892,7 @@
 	/* Try to read more data. */
 
 	/* First move last chars to start of buffer. */
-	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
 
 	for ( i = 0; i < number_to_move; ++i )
 		*(dest++) = *(source++);
@@ -1396,7 +1905,7 @@
 
 	else
 		{
-			yy_size_t num_to_read =
+			int num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
@@ -1410,7 +1919,7 @@
 
 			if ( b->yy_is_our_buffer )
 				{
-				yy_size_t new_size = b->yy_buf_size * 2;
+				int new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -1419,11 +1928,12 @@
 
 				b->yy_ch_buf = (char *)
 					/* Include room in for 2 EOB chars. */
-					pprealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+					yyrealloc( (void *) b->yy_ch_buf,
+							 (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
 				}
 			else
 				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
+				b->yy_ch_buf = NULL;
 
 			if ( ! b->yy_ch_buf )
 				YY_FATAL_ERROR(
@@ -1451,7 +1961,7 @@
 		if ( number_to_move == YY_MORE_ADJ )
 			{
 			ret_val = EOB_ACT_END_OF_FILE;
-			pprestart(yyin  ,yyscanner);
+			yyrestart( yyin  , yyscanner);
 			}
 
 		else
@@ -1465,12 +1975,15 @@
 	else
 		ret_val = EOB_ACT_CONTINUE_SCAN;
 
-	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+	if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
 		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pprealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+		/* "- 2" to take care of EOB's */
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
 	}
 
 	yyg->yy_n_chars += number_to_move;
@@ -1482,6 +1995,7 @@
 	return ret_val;
 }
 
+
 /* yy_get_previous_state - get the state just before the EOB char was reached */
 
     static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
@@ -1503,15 +2017,16 @@
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 98 )
-				yy_c = yy_meta[(unsigned int) yy_c];
+			if ( yy_current_state >= 95 )
+				yy_c = yy_meta[yy_c];
 			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 		}
 
 	return yy_current_state;
 }
 
+
 /* yy_try_NUL_trans - try to make a transition on the NUL character
  *
  * synopsis
@@ -1532,16 +2047,17 @@
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 98 )
-			yy_c = yy_meta[(unsigned int) yy_c];
+		if ( yy_current_state >= 95 )
+			yy_c = yy_meta[yy_c];
 		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 97);
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	yy_is_jam = (yy_current_state == 94);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
 }
 
+
 #ifndef YY_NO_UNPUT
 
 #endif
@@ -1571,7 +2087,7 @@
 
 		else
 			{ /* need more input */
-			yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
 			++yyg->yy_c_buf_p;
 
 			switch ( yy_get_next_buffer( yyscanner ) )
@@ -1588,14 +2104,14 @@
 					 */
 
 					/* Reset buffer status. */
-					pprestart(yyin ,yyscanner);
+					yyrestart( yyin , yyscanner);
 
 					/*FALLTHROUGH*/
 
 				case EOB_ACT_END_OF_FILE:
 					{
-					if ( ppwrap(yyscanner ) )
-						return EOF;
+					if ( yywrap( yyscanner ) )
+						return 0;
 
 					if ( ! yyg->yy_did_buffer_switch_on_eof )
 						YY_NEW_FILE;
@@ -1617,6 +2133,7 @@
 	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
 	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
 
+
 	return c;
 }
 #endif	/* ifndef YY_NO_INPUT */
@@ -1626,34 +2143,35 @@
  * @param yyscanner The scanner object.
  * @note This function does not reset the start condition to @c INITIAL .
  */
-    void pprestart  (FILE * input_file , yyscan_t yyscanner)
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	if ( ! YY_CURRENT_BUFFER ){
-        ppensure_buffer_stack (yyscanner);
+        yyensure_buffer_stack (yyscanner);
 		YY_CURRENT_BUFFER_LVALUE =
-            pp_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
 	}
 
-	pp_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	pp_load_buffer_state(yyscanner );
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+	yy_load_buffer_state( yyscanner );
 }
 
+
 /** Switch to a different input buffer.
  * @param new_buffer The new input buffer.
  * @param yyscanner The scanner object.
  */
-    void pp_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 	/* TODO. We should be able to replace this entire function body
 	 * with
-	 *		pppop_buffer_state();
-	 *		pppush_buffer_state(new_buffer);
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
      */
-	ppensure_buffer_stack (yyscanner);
+	yyensure_buffer_stack (yyscanner);
 	if ( YY_CURRENT_BUFFER == new_buffer )
 		return;
 
@@ -1666,17 +2184,18 @@
 		}
 
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	pp_load_buffer_state(yyscanner );
+	yy_load_buffer_state( yyscanner );
 
 	/* We don't actually know whether we did this switch during
-	 * EOF (ppwrap()) processing, but the only time this flag
-	 * is looked at is after ppwrap() is called, so it's safe
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
 	 * to go ahead and always set it.
 	 */
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
-static void pp_load_buffer_state  (yyscan_t yyscanner)
+
+static void yy_load_buffer_state  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -1691,35 +2210,36 @@
  * @param yyscanner The scanner object.
  * @return the allocated buffer state.
  */
-    YY_BUFFER_STATE pp_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
-	b = (YY_BUFFER_STATE) ppalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
 	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in pp_create_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
-	b->yy_buf_size = (yy_size_t)size;
+	b->yy_buf_size = size;
 
 	/* yy_ch_buf has to be 2 characters longer than the size given because
 	 * we need to put in 2 end-of-buffer characters.
 	 */
-	b->yy_ch_buf = (char *) ppalloc(b->yy_buf_size + 2 ,yyscanner );
+	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
 	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in pp_create_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
 	b->yy_is_our_buffer = 1;
 
-	pp_init_buffer(b,file ,yyscanner);
+	yy_init_buffer( b, file , yyscanner);
 
 	return b;
 }
 
+
 /** Destroy the buffer.
- * @param b a buffer created with pp_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
  * @param yyscanner The scanner object.
  */
-    void pp_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
@@ -1730,28 +2250,29 @@
 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
 
 	if ( b->yy_is_our_buffer )
-		ppfree((void *) b->yy_ch_buf ,yyscanner );
+		yyfree( (void *) b->yy_ch_buf , yyscanner );
 
-	ppfree((void *) b ,yyscanner );
+	yyfree( (void *) b , yyscanner );
 }
 
+
 /* Initializes or reinitializes a buffer.
  * This function is sometimes called more than once on the same buffer,
- * such as during a pprestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
  */
-    static void pp_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
 
 {
 	int oerrno = errno;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-	pp_flush_buffer(b ,yyscanner);
+	yy_flush_buffer( b , yyscanner);
 
 	b->yy_input_file = file;
 	b->yy_fill_buffer = 1;
 
-    /* If b is the current buffer, then pp_init_buffer was _probably_
-     * called from pprestart() or through yy_get_next_buffer.
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
      * In that case, we don't want to reset the lineno or column.
      */
     if (b != YY_CURRENT_BUFFER){
@@ -1759,8 +2280,11 @@
         b->yy_bs_column = 0;
     }
 
+
+    
         b->yy_is_interactive = 0;
     
+
 	errno = oerrno;
 }
 
@@ -1768,7 +2292,7 @@
  * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
  * @param yyscanner The scanner object.
  */
-    void pp_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if ( ! b )
@@ -1789,7 +2313,7 @@
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
 	if ( b == YY_CURRENT_BUFFER )
-		pp_load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 }
 
 /** Pushes the new state onto the stack. The new state becomes
@@ -1798,15 +2322,15 @@
  *  @param new_buffer The new state.
  *  @param yyscanner The scanner object.
  */
-void pppush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if (new_buffer == NULL)
 		return;
 
-	ppensure_buffer_stack(yyscanner);
+	yyensure_buffer_stack(yyscanner);
 
-	/* This block is copied from pp_switch_to_buffer. */
+	/* This block is copied from yy_switch_to_buffer. */
 	if ( YY_CURRENT_BUFFER )
 		{
 		/* Flush out information for old buffer. */
@@ -1820,36 +2344,38 @@
 		yyg->yy_buffer_stack_top++;
 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
-	/* copied from pp_switch_to_buffer. */
-	pp_load_buffer_state(yyscanner );
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( yyscanner );
 	yyg->yy_did_buffer_switch_on_eof = 1;
 }
 
+
 /** Removes and deletes the top of the stack, if present.
  *  The next element becomes the new top.
  *  @param yyscanner The scanner object.
  */
-void pppop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	if (!YY_CURRENT_BUFFER)
 		return;
 
-	pp_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
 	YY_CURRENT_BUFFER_LVALUE = NULL;
 	if (yyg->yy_buffer_stack_top > 0)
 		--yyg->yy_buffer_stack_top;
 
 	if (YY_CURRENT_BUFFER) {
-		pp_load_buffer_state(yyscanner );
+		yy_load_buffer_state( yyscanner );
 		yyg->yy_did_buffer_switch_on_eof = 1;
 	}
 }
 
+
 /* Allocates the stack if it does not exist.
  *  Guarantees space for at least one push.
  */
-static void ppensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
 {
 	yy_size_t num_to_alloc;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1860,15 +2386,16 @@
 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
 		 * immediate realloc on the next call.
          */
-		num_to_alloc = 1; // After all that talk, this was set to 1 anyways...
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)ppalloc
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
 								(num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in ppensure_buffer_stack()" );
-								  
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+
 		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
+
 		yyg->yy_buffer_stack_max = num_to_alloc;
 		yyg->yy_buffer_stack_top = 0;
 		return;
@@ -1880,12 +2407,12 @@
 		yy_size_t grow_size = 8 /* arbitrary grow size */;
 
 		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)pprealloc
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
 								(yyg->yy_buffer_stack,
 								num_to_alloc * sizeof(struct yy_buffer_state*)
 								, yyscanner);
 		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in ppensure_buffer_stack()" );
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
 		/* zero only the new slots.*/
 		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1893,13 +2420,17 @@
 	}
 }
 
+
+
+
+
 /** Setup the input buffer state to scan directly from a user-specified character buffer.
  * @param base the character buffer
  * @param size the size in bytes of the character buffer
  * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
+ * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE pp_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
     
@@ -1907,69 +2438,75 @@
 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
 		/* They forgot to leave room for the EOB's. */
-		return 0;
+		return NULL;
 
-	b = (YY_BUFFER_STATE) ppalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
 	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_buffer()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
 
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */
 	b->yy_buf_pos = b->yy_ch_buf = base;
 	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
+	b->yy_input_file = NULL;
 	b->yy_n_chars = b->yy_buf_size;
 	b->yy_is_interactive = 0;
 	b->yy_at_bol = 1;
 	b->yy_fill_buffer = 0;
 	b->yy_buffer_status = YY_BUFFER_NEW;
 
-	pp_switch_to_buffer(b ,yyscanner );
+	yy_switch_to_buffer( b , yyscanner );
 
 	return b;
 }
 
-/** Setup the input buffer state to scan a string. The next call to pplex() will
+
+
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
  * scan from a @e copy of @a str.
  * @param yystr a NUL-terminated string to scan
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
- *       pp_scan_bytes() instead.
+ *       yy_scan_bytes() instead.
  */
-YY_BUFFER_STATE pp_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
 {
     
-	return pp_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+	return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
 }
 
-/** Setup the input buffer state to scan the given bytes. The next call to pplex() will
+
+
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
  * @param yybytes the byte buffer to scan
  * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * @param yyscanner The scanner object.
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE pp_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
 {
 	YY_BUFFER_STATE b;
 	char *buf;
 	yy_size_t n;
-	yy_size_t i;
+	int i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) ppalloc(n ,yyscanner );
+	n = (yy_size_t) (_yybytes_len + 2);
+	buf = (char *) yyalloc( n , yyscanner );
 	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in pp_scan_bytes()" );
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
 
 	for ( i = 0; i < _yybytes_len; ++i )
 		buf[i] = yybytes[i];
 
 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
-	b = pp_scan_buffer(buf,n ,yyscanner);
+	b = yy_scan_buffer( buf, n , yyscanner);
 	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in pp_scan_bytes()" );
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
 
 	/* It's okay to grow etc. this buffer, and we should throw it
 	 * away when we're done.
@@ -1979,15 +2516,25 @@
 	return b;
 }
 
+
+
+
+
+
+
+
+
+
+
 #ifndef YY_EXIT_FAILURE
 #define YY_EXIT_FAILURE 2
 #endif
 
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
-	(void) fprintf( stderr, "%s\n", msg );
+	fprintf( stderr, "%s\n", msg );
 	exit( YY_EXIT_FAILURE );
 }
 
@@ -2008,23 +2555,29 @@
 		} \
 	while ( 0 )
 
+
+
 /* Accessor  methods (get/set functions) to struct members. */
 
+
 /** Get the user-defined data for this scanner.
  * @param yyscanner The scanner object.
  */
-YY_EXTRA_TYPE ppget_extra  (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyextra;
 }
 
+
+
 /** Get the current line number.
  * @param yyscanner The scanner object.
  */
-int ppget_lineno  (yyscan_t yyscanner)
+int yyget_lineno  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
     
         if (! YY_CURRENT_BUFFER)
             return 0;
@@ -2032,12 +2585,16 @@
     return yylineno;
 }
 
+
+
+
 /** Get the current column number.
  * @param yyscanner The scanner object.
  */
-int ppget_column  (yyscan_t yyscanner)
+int yyget_column  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
     
         if (! YY_CURRENT_BUFFER)
             return 0;
@@ -2045,155 +2602,194 @@
     return yycolumn;
 }
 
+
+
+
 /** Get the input stream.
  * @param yyscanner The scanner object.
  */
-FILE *ppget_in  (yyscan_t yyscanner)
+FILE *yyget_in  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyin;
 }
 
+
+
 /** Get the output stream.
  * @param yyscanner The scanner object.
  */
-FILE *ppget_out  (yyscan_t yyscanner)
+FILE *yyget_out  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyout;
 }
 
+
+
 /** Get the length of the current token.
  * @param yyscanner The scanner object.
  */
-yy_size_t ppget_leng  (yyscan_t yyscanner)
+int yyget_leng  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yyleng;
 }
 
+
 /** Get the current token.
  * @param yyscanner The scanner object.
  */
 
-char *ppget_text  (yyscan_t yyscanner)
+char *yyget_text  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yytext;
 }
 
+
+
 /** Set the user-defined data. This data is never touched by the scanner.
  * @param user_defined The data to be associated with this scanner.
  * @param yyscanner The scanner object.
  */
-void ppset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yyextra = user_defined ;
 }
 
+
+
 /** Set the current line number.
  * @param _line_number line number
  * @param yyscanner The scanner object.
  */
-void ppset_lineno (int  _line_number , yyscan_t yyscanner)
+void yyset_lineno (int  _line_number , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
+    
         /* lineno is only valid if an input buffer exists. */
         if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "ppset_lineno called with no buffer" );
+           YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
     
     yylineno = _line_number;
 }
 
+
+
+
 /** Set the current column.
  * @param _column_no column number
  * @param yyscanner The scanner object.
  */
-void ppset_column (int  _column_no , yyscan_t yyscanner)
+void yyset_column (int  _column_no , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
+    
         /* column is only valid if an input buffer exists. */
         if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "ppset_column called with no buffer" );
+           YY_FATAL_ERROR( "yyset_column called with no buffer" );
     
     yycolumn = _column_no;
 }
 
+
+
+
+
 /** Set the input stream. This does not discard the current
  * input buffer.
  * @param _in_str A readable stream.
  * @param yyscanner The scanner object.
- * @see pp_switch_to_buffer
+ * @see yy_switch_to_buffer
  */
-void ppset_in (FILE *  _in_str , yyscan_t yyscanner)
+void yyset_in (FILE *  _in_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yyin = _in_str ;
 }
 
-void ppset_out (FILE *  _out_str , yyscan_t yyscanner)
+
+
+void yyset_out (FILE *  _out_str , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yyout = _out_str ;
 }
 
-int ppget_debug  (yyscan_t yyscanner)
+
+
+
+int yyget_debug  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yy_flex_debug;
 }
 
-void ppset_debug (int  _bdebug , yyscan_t yyscanner)
+
+
+void yyset_debug (int  _bdebug , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yy_flex_debug = _bdebug ;
 }
 
+
 /* Accessor methods for yylval and yylloc */
 
-YYSTYPE * ppget_lval  (yyscan_t yyscanner)
+
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yylval;
 }
 
-void ppset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+
+
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yylval = yylval_param;
 }
 
-YYLTYPE *ppget_lloc  (yyscan_t yyscanner)
+
+
+    
+YYLTYPE *yyget_lloc  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     return yylloc;
 }
     
-void ppset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
+
+    
+void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     yylloc = yylloc_param;
 }
     
+
+
+
+
 /* User-visible API */
 
-/* pplex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
  * the ONLY reentrant function that doesn't take the scanner as the last argument.
  * That's why we explicitly handle the declaration, instead of using our macros.
  */
-
-int pplex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
 {
     if (ptr_yy_globals == NULL){
         errno = EINVAL;
         return 1;
     }
 
-    *ptr_yy_globals = (yyscan_t) ppalloc ( sizeof( struct yyguts_t ), NULL );
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
 
     if (*ptr_yy_globals == NULL){
         errno = ENOMEM;
@@ -2206,111 +2802,127 @@
     return yy_init_globals ( *ptr_yy_globals );
 }
 
-/* pplex_init_extra has the same functionality as pplex_init, but follows the
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
  * convention of taking the scanner as the last argument. Note however, that
  * this is a *pointer* to a scanner, as it will be allocated by this call (and
  * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to ppalloc in
+ * The user defined value in the first argument will be available to yyalloc in
  * the yyextra field.
  */
-
-int pplex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
 {
     struct yyguts_t dummy_yyguts;
 
-    ppset_extra (yy_user_defined, &dummy_yyguts);
+    yyset_extra (yy_user_defined, &dummy_yyguts);
 
     if (ptr_yy_globals == NULL){
         errno = EINVAL;
         return 1;
     }
-	
-    *ptr_yy_globals = (yyscan_t) ppalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-	
+
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
     if (*ptr_yy_globals == NULL){
         errno = ENOMEM;
         return 1;
     }
-    
+
     /* By setting to 0xAA, we expose bugs in
     yy_init_globals. Leave at 0x00 for releases. */
     memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    ppset_extra (yy_user_defined, *ptr_yy_globals);
-    
+
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
+
     return yy_init_globals ( *ptr_yy_globals );
 }
 
+
 static int yy_init_globals (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
     /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from pplex_destroy(), so don't allocate here.
+     * This function is called from yylex_destroy(), so don't allocate here.
      */
 
-    yyg->yy_buffer_stack = 0;
+
+    yyg->yy_buffer_stack = NULL;
     yyg->yy_buffer_stack_top = 0;
     yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_c_buf_p = NULL;
     yyg->yy_init = 0;
     yyg->yy_start = 0;
 
+
     yyg->yy_start_stack_ptr = 0;
     yyg->yy_start_stack_depth = 0;
     yyg->yy_start_stack =  NULL;
 
+
+
+
+
+
 /* Defined in main.c */
 #ifdef YY_STDINIT
     yyin = stdin;
     yyout = stdout;
 #else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
+    yyin = NULL;
+    yyout = NULL;
 #endif
 
     /* For future reference: Set errno on error, since we are called by
-     * pplex_init()
+     * yylex_init()
      */
     return 0;
 }
 
-/* pplex_destroy is for both reentrant and non-reentrant scanners. */
-int pplex_destroy  (yyscan_t yyscanner)
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (yyscan_t yyscanner)
 {
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
     /* Pop the buffer stack, destroying each element. */
 	while(YY_CURRENT_BUFFER){
-		pp_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
 		YY_CURRENT_BUFFER_LVALUE = NULL;
-		pppop_buffer_state(yyscanner);
+		yypop_buffer_state(yyscanner);
 	}
 
 	/* Destroy the stack itself. */
-	ppfree(yyg->yy_buffer_stack ,yyscanner);
+	yyfree(yyg->yy_buffer_stack , yyscanner);
 	yyg->yy_buffer_stack = NULL;
 
+
     /* Destroy the start condition stack. */
-        ppfree(yyg->yy_start_stack ,yyscanner );
+        yyfree( yyg->yy_start_stack , yyscanner );
         yyg->yy_start_stack = NULL;
 
+
+
+
     /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * pplex() is called, initialization will occur. */
+     * yylex() is called, initialization will occur. */
     yy_init_globals( yyscanner);
 
     /* Destroy the main struct (reentrant only). */
-    ppfree ( yyscanner , yyscanner );
+    yyfree ( yyscanner , yyscanner );
     yyscanner = NULL;
     return 0;
 }
 
+
+
 /*
  * Internal utility routines.
  */
 
+
+
 #ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
@@ -2321,8 +2933,10 @@
 }
 #endif
 
+
+
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
 {
 	int n;
 	for ( n = 0; s[n]; ++n )
@@ -2332,14 +2946,18 @@
 }
 #endif
 
-void *ppalloc (yy_size_t  size , yyscan_t yyscanner)
+
+
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
-	return (void *) malloc( size );
+	return malloc(size);
 }
 
-void *pprealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+
+
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
@@ -2351,25 +2969,31 @@
 	 * any pointer type to void*, and deal with argument conversions
 	 * as though doing an assignment.
 	 */
-	return (void *) realloc( (char *) ptr, size );
+	return realloc(ptr, size);
 }
 
-void ppfree (void * ptr , yyscan_t yyscanner)
+
+
+void yyfree (void * ptr , yyscan_t yyscanner)
 {
 	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 	(void)yyg;
-	free( (char *) ptr );	/* see pprealloc() for (char *) cast */
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
 }
 
+
 #define YYTABLES_NAME "yytables"
 
+
+
+
+
+
+
+
 namespace pp {
 
-// TODO(alokp): Maximum token length should ideally be specified by
-// the preprocessor client, i.e., the compiler.
-const size_t Tokenizer::kMaxTokenLength = 1024;
-
-Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(1024)
 {
     mContext.diagnostics = diagnostics;
 }
@@ -2379,10 +3003,10 @@
     destroyScanner();
 }
 
-bool Tokenizer::init(int count, const char* const string[], const int length[])
+bool Tokenizer::init(size_t count, const char * const string[], const int length[])
 {
-    if (count < 0) return false;
-    if ((count > 0) && (string == 0)) return false;
+    if ((count > 0) && (string == 0))
+        return false;
 
     mContext.input = Input(count, string, length);
     return initScanner();
@@ -2392,22 +3016,38 @@
 {
     // We use column number as file number.
     // See macro yyfileno.
-    ppset_column(file,mHandle);
+    yyset_column(file, mHandle);
 }
 
 void Tokenizer::setLineNumber(int line)
 {
-    ppset_lineno(line,mHandle);
+    yyset_lineno(line, mHandle);
 }
 
-void Tokenizer::lex(Token* token)
+void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
 {
-    token->type = pplex(&token->text,&token->location,mHandle);
-    if (token->text.size() > kMaxTokenLength)
+    mMaxTokenSize = maxTokenSize;
+}
+
+void Tokenizer::lex(Token *token)
+{
+    int tokenType = yylex(&token->text, &token->location, mHandle);
+
+    if (tokenType == Token::GOT_ERROR)
     {
-        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
+        mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text);
+        token->type = Token::LAST;
+    }
+    else
+    {
+        token->type = tokenType;
+    }
+
+    if (token->text.size() > mMaxTokenSize)
+    {
+        mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
                                      token->location, token->text);
-        token->text.erase(kMaxTokenLength);
+        token->text.erase(mMaxTokenSize);
     }
 
     token->flags = 0;
@@ -2421,21 +3061,22 @@
 
 bool Tokenizer::initScanner()
 {
-    if ((mHandle == NULL) && pplex_init_extra(&mContext,&mHandle))
+    if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
         return false;
 
-    pprestart(0,mHandle);
+    yyrestart(0, mHandle);
     return true;
 }
 
 void Tokenizer::destroyScanner()
 {
-    if (mHandle == NULL)
+    if (mHandle == nullptr)
         return;
 
-    pplex_destroy(mHandle);
-    mHandle = NULL;
+    yylex_destroy(mHandle);
+    mHandle = nullptr;
 }
 
 }  // namespace pp
 
+
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.h b/src/OpenGL/compiler/preprocessor/Tokenizer.h
index 3bad966..7227fe0 100644
--- a/src/OpenGL/compiler/preprocessor/Tokenizer.h
+++ b/src/OpenGL/compiler/preprocessor/Tokenizer.h
@@ -19,8 +19,6 @@
 #include "Lexer.h"
 #include "pp_utils.h"
 
-#include <algorithm>
-
 namespace pp
 {
 
@@ -31,7 +29,7 @@
 public:
 	struct Context
 	{
-		Diagnostics* diagnostics;
+		Diagnostics *diagnostics;
 
 		Input input;
 		// The location where yytext points to. Token location should track
@@ -42,25 +40,26 @@
 		bool leadingSpace;
 		bool lineStart;
 	};
-	static const size_t kMaxTokenLength;
 
-	Tokenizer(Diagnostics* diagnostics);
-	~Tokenizer();
+	Tokenizer(Diagnostics *diagnostics);
+	~Tokenizer() override;
 
-	bool init(int count, const char* const string[], const int length[]);
+	bool init(size_t count, const char *const string[], const int length[]);
 
 	void setFileNumber(int file);
 	void setLineNumber(int line);
+	void setMaxTokenSize(size_t maxTokenSize);
 
-	virtual void lex(Token* token);
+	void lex(Token *token) override;
 
 private:
 	PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
 	bool initScanner();
 	void destroyScanner();
 
-	void* mHandle;  // Scanner handle.
+	void *mHandle;  // Scanner handle.
 	Context mContext;  // Scanner extra.
+	size_t mMaxTokenSize;  // Maximum token size
 };
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.l b/src/OpenGL/compiler/preprocessor/Tokenizer.l
index 959d327..f99cfd4 100644
--- a/src/OpenGL/compiler/preprocessor/Tokenizer.l
+++ b/src/OpenGL/compiler/preprocessor/Tokenizer.l
@@ -39,14 +39,27 @@
 }
 
 %{
+#if defined(_MSC_VER)
+#pragma warning(disable: 4005)
+#endif
+
 #include "Tokenizer.h"
 
-#include "Diagnostics.h"
+#include "DiagnosticsBase.h"
 #include "Token.h"
 
 #if defined(__GNUC__)
 // Triggered by the auto-generated yy_fatal_error function.
 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4244)
+#endif
+
+// Workaround for flex using the register keyword, deprecated in C++11.
+#ifdef __cplusplus
+#if __cplusplus > 199711L
+#define register
+#endif
 #endif
 
 typedef std::string YYSTYPE;
@@ -80,7 +93,7 @@
     } while(0);
 
 #define YY_INPUT(buf, result, maxSize) \
-    result = yyextra->input.read(buf, maxSize);
+    result = yyextra->input.read(buf, maxSize, &yylineno);
 
 %}
 
@@ -109,11 +122,18 @@
 
     /* Block comment */
     /* Line breaks are just counted - not returned. */
-    /* The comment is replaced by a single space. */ 
+    /* The comment is replaced by a single space. */
 "/*" { BEGIN(COMMENT); }
 <COMMENT>[^*\r\n]+
 <COMMENT>"*"
-<COMMENT>{NEWLINE} { ++yylineno; }
+<COMMENT>{NEWLINE} {
+    if (yylineno == INT_MAX)
+    {
+        *yylval = "Integer overflow on line number";
+        return pp::Token::GOT_ERROR;
+    }
+    ++yylineno;
+}
 <COMMENT>"*/" {
     yyextra->leadingSpace = true;
     BEGIN(INITIAL);
@@ -240,13 +260,16 @@
 [ \t\v\f]+   { yyextra->leadingSpace = true; }
 
 {NEWLINE} {
+    if (yylineno == INT_MAX)
+    {
+        *yylval = "Integer overflow on line number";
+        return pp::Token::GOT_ERROR;
+    }
     ++yylineno;
     yylval->assign(1, '\n');
     return '\n';
 }
 
-\\{NEWLINE} { ++yylineno; }
-
 . {
     yylval->assign(1, yytext[0]);
     return pp::Token::PP_OTHER;
@@ -257,23 +280,30 @@
     // Set the location for EOF token manually.
     pp::Input* input = &yyextra->input;
     pp::Input::Location* scanLoc = &yyextra->scanLoc;
-    int sIndexMax = std::max(0, input->count() - 1);
+    yy_size_t sIndexMax = input->count() ? input->count() - 1 : 0;
     if (scanLoc->sIndex != sIndexMax)
     {
         // We can only reach here if there are empty strings at the
         // end of the input.
         scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
-        yyfileno = sIndexMax; yylineno = 1;
+        // FIXME: this is not 64-bit clean.
+        yyfileno = static_cast<int>(sIndexMax); yylineno = 1;
     }
     yylloc->file = yyfileno;
     yylloc->line = yylineno;
     yylval->clear();
 
-    if (YY_START == COMMENT)
+    // Line number overflows fake EOFs to exit early, check for this case.
+    if (yylineno == INT_MAX) {
+        yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+                pp::SourceLocation(yyfileno, yylineno),
+                "Integer overflow on line number");
+    }
+    else if (YY_START == COMMENT)
     {
-        yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
+        yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
-                                     "");
+                                     "EOF while in a comment");
     }
     yyterminate();
 }
@@ -282,11 +312,7 @@
 
 namespace pp {
 
-// TODO(alokp): Maximum token length should ideally be specified by
-// the preprocessor client, i.e., the compiler.
-const size_t Tokenizer::kMaxTokenLength = 1024;
-
-Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(1024)
 {
     mContext.diagnostics = diagnostics;
 }
@@ -296,10 +322,10 @@
     destroyScanner();
 }
 
-bool Tokenizer::init(int count, const char* const string[], const int length[])
+bool Tokenizer::init(size_t count, const char * const string[], const int length[])
 {
-    if (count < 0) return false;
-    if ((count > 0) && (string == 0)) return false;
+    if ((count > 0) && (string == 0))
+        return false;
 
     mContext.input = Input(count, string, length);
     return initScanner();
@@ -317,14 +343,30 @@
     yyset_lineno(line, mHandle);
 }
 
-void Tokenizer::lex(Token* token)
+void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
 {
-    token->type = yylex(&token->text, &token->location, mHandle);
-    if (token->text.size() > kMaxTokenLength)
+    mMaxTokenSize = maxTokenSize;
+}
+
+void Tokenizer::lex(Token *token)
+{
+    int tokenType = yylex(&token->text, &token->location, mHandle);
+
+    if (tokenType == Token::GOT_ERROR)
     {
-        mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
+        mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text);
+        token->type = Token::LAST;
+    }
+    else
+    {
+        token->type = tokenType;
+    }
+
+    if (token->text.size() > mMaxTokenSize)
+    {
+        mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
                                      token->location, token->text);
-        token->text.erase(kMaxTokenLength);
+        token->text.erase(mMaxTokenSize);
     }
 
     token->flags = 0;
@@ -338,7 +380,7 @@
 
 bool Tokenizer::initScanner()
 {
-    if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
+    if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
         return false;
 
     yyrestart(0, mHandle);
@@ -347,11 +389,11 @@
 
 void Tokenizer::destroyScanner()
 {
-    if (mHandle == NULL)
+    if (mHandle == nullptr)
         return;
 
     yylex_destroy(mHandle);
-    mHandle = NULL;
+    mHandle = nullptr;
 }
 
 }  // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/numeric_lex.h b/src/OpenGL/compiler/preprocessor/numeric_lex.h
index f57410c..64faa26 100644
--- a/src/OpenGL/compiler/preprocessor/numeric_lex.h
+++ b/src/OpenGL/compiler/preprocessor/numeric_lex.h
@@ -62,7 +62,7 @@
 	stream.imbue(std::locale::classic());
 
 	stream >> (*value);
-	return !stream.fail();
+	return !stream.fail() && std::isfinite(*value);
 }
 
 } // namespace pp.
diff --git a/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj b/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj
index 72a2b24..3c7a19c 100644
--- a/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj
+++ b/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj
@@ -143,8 +143,8 @@
     </Link>

   </ItemDefinitionGroup>

   <ItemGroup>

-    <ClInclude Include="Diagnostics.h" />

-    <ClInclude Include="DirectiveHandler.h" />

+    <ClInclude Include="DiagnosticsBase.h" />

+    <ClInclude Include="DirectiveHandlerBase.h" />

     <ClInclude Include="DirectiveParser.h" />

     <ClInclude Include="ExpressionParser.h" />

     <ClInclude Include="Input.h" />

@@ -160,8 +160,8 @@
     <ClInclude Include="Tokenizer.h" />

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="Diagnostics.cpp" />

-    <ClCompile Include="DirectiveHandler.cpp" />

+    <ClCompile Include="DiagnosticsBase.cpp" />

+    <ClCompile Include="DirectiveHandlerBase.cpp" />

     <ClCompile Include="DirectiveParser.cpp" />

     <ClCompile Include="ExpressionParser.cpp" />

     <ClCompile Include="Input.cpp" />

diff --git a/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj.filters b/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj.filters
index d68cbe2..02c06a0 100644
--- a/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj.filters
+++ b/src/OpenGL/compiler/preprocessor/preprocessor.vcxproj.filters
@@ -15,12 +15,6 @@
     </Filter>

   </ItemGroup>

   <ItemGroup>

-    <ClInclude Include="Diagnostics.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

-    <ClInclude Include="DirectiveHandler.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="DirectiveParser.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -60,14 +54,14 @@
     <ClInclude Include="Tokenizer.h">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="DiagnosticsBase.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="DirectiveHandlerBase.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

-    <ClCompile Include="Diagnostics.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-    <ClCompile Include="DirectiveHandler.cpp">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="DirectiveParser.cpp">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -95,9 +89,15 @@
     <ClCompile Include="Tokenizer.cpp">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="DiagnosticsBase.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="DirectiveHandlerBase.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <None Include="Tokenizer.l" />

     <None Include="ExpressionParser.y" />

   </ItemGroup>

-</Project>

+</Project>
\ No newline at end of file