提交 a4059496 编写于 作者: T tschw

GLSL/JSON live editing via Codemirror.

上级 6f9dc56b
......@@ -40,8 +40,12 @@
<link rel="stylesheet" href="js/libs/codemirror/codemirror.css">
<link rel="stylesheet" href="js/libs/codemirror/theme/monokai.css">
<script src="js/libs/codemirror/codemirror.js"></script>
<script src="js/libs/codemirror/mode/javascript.js"></script>
<script src="js/libs/esprima.js"></script>
<script src="js/libs/jsonlint.js"></script>
<script src="js/libs/codemirror/mode/glsl.js"></script>
<script src="js/libs/jszip.min.js"></script>
<script src="js/libs/sortable.min.js"></script>
......
......@@ -43,7 +43,9 @@ var Script = function ( editor ) {
header.add( close );
var delay;
var currentMode;
var currentScript;
var currentObject;
var codemirror = CodeMirror( container.dom, {
value: '',
......@@ -61,14 +63,40 @@ var Script = function ( editor ) {
var value = codemirror.getValue();
if ( validate( value ) ) {
if ( ! validate( value ) ) return;
if ( typeof( currentScript ) === 'object' ) {
currentScript.source = value;
signals.scriptChanged.dispatch( currentScript );
return;
}
switch ( currentScript ) {
case 'vertexShader':
currentObject.vertexShader = value;
break;
case 'fragmentShader':
currentObject.fragmentShader = value;
break;
case 'programInfo':
var json = JSON.parse( value );
currentObject.defines = json.defines;
currentObject.uniforms = json.uniforms;
currentObject.attributes = json.attributes;
}
}, 300 );
currentObject.needsUpdate = true;
signals.materialChanged.dispatch( currentObject );
}, 200 );
});
......@@ -79,7 +107,7 @@ var Script = function ( editor ) {
var validate = function ( string ) {
var syntax, errors;
var errors;
return codemirror.operation( function () {
......@@ -97,48 +125,84 @@ var Script = function ( editor ) {
//
try {
switch ( currentMode ) {
case 'javascript':
try {
var syntax = esprima.parse( string, { tolerant: true } );
errors = syntax.errors;
} catch ( error ) {
errors = [
{ lineNumber: error.lineNumber,message: error.message }
];
}
for ( var i = 0; i < errors.length; i ++ ) {
var error = errors[ i ];
error.message = error.message.replace(/Line [0-9]+: /, '');
}
break;
case 'json':
errors = [];
jsonlint.parseError = function ( message, info ) {
syntax = esprima.parse( string, { tolerant: true } );
errors = syntax.errors;
message = message.split('\n')[3];
for ( var i = 0; i < errors.length; i ++ ) {
errors.push({
lineNumber: info.loc.first_line,
message: message
});
var error = errors[ i ];
};
var message = document.createElement( 'div' );
message.className = 'esprima-error';
message.textContent = error.message.replace(/Line [0-9]+: /, '');
try {
var lineNumber = error.lineNumber - 1;
errorLines.push( lineNumber );
jsonlint.parse( string );
codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
} catch ( error ) {
var widget = codemirror.addLineWidget(
lineNumber,
message
);
// ignore failed error recovery
widgets.push( widget );
}
}
break;
} catch ( error ) {
case 'glsl':
// TODO validate GLSL (compiling shader?)
default:
errors = [];
}
for ( var i = 0; i < errors.length; i ++ ) {
var error = errors[ i ];
var message = document.createElement( 'div' );
message.className = 'esprima-error';
message.textContent = error.message.replace(/Line [0-9]+: /, '');
message.textContent = error.message;
var lineNumber = error.lineNumber - 1;
errorLines.push( lineNumber );
codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
var widget = codemirror.addLineWidget(
lineNumber,
message
);
var widget = codemirror.addLineWidget( lineNumber, message );
widgets.push( widget );
......@@ -160,12 +224,58 @@ var Script = function ( editor ) {
signals.editScript.add( function ( object, script ) {
container.setDisplay( '' );
var mode, name, source;
if ( typeof( script ) === 'object' ) {
mode = 'javascript';
name = script.name;
source = script.source;
} else {
switch ( script ) {
case 'vertexShader':
mode = 'glsl';
name = 'Vertex Shader';
source = object.vertexShader || "";
break;
case 'fragmentShader':
mode = 'glsl';
name = 'Fragment Shader';
source = object.fragmentShader || "";
break;
case 'programInfo':
mode = 'json';
name = 'Program Properties';
var json = {
defines: object.defines,
uniforms: object.uniforms,
attributes: object.attributes
};
source = JSON.stringify( json, null, '\t' );
}
}
currentMode = mode;
currentScript = script;
currentObject = object;
title.setValue( object.name + ' / ' + script.name );
codemirror.setValue( script.source );
title.setValue( object.name + ' / ' + name );
container.setDisplay( '' );
codemirror.setValue( source );
if (mode === 'json' ) mode = { name: 'javascript', json: true };
codemirror.setOption( 'mode', mode );
} );
......
......@@ -5,6 +5,7 @@
Sidebar.Material = function ( editor ) {
var signals = editor.signals;
var currentObject;
var container = new UI.CollapsiblePanel();
container.setCollapsed( editor.config.getKey( 'ui/sidebar/material/collapsed' ) );
......@@ -112,39 +113,6 @@ Sidebar.Material = function ( editor ) {
container.add( materialShininessRow );
// uniforms
var materialUniformsRow = new UI.Panel();
var materialUniforms = new UI.TextArea().setWidth( '150px' ).setHeight( '80px' );
materialUniforms.setValue( '{\n "uColor": {\n "type": "3f",\n "value": [1, 0, 0]\n }\n}' ).onChange( update );
materialUniformsRow.add( new UI.Text( 'Uniforms' ).setWidth( '90px' ) );
materialUniformsRow.add( materialUniforms );
container.add( materialUniformsRow );
// vertex shader
var materialVertexShaderRow = new UI.Panel();
var materialVertexShader = new UI.TextArea().setWidth( '150px' ).setHeight( '80px' );
materialVertexShader.setValue( 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}' ).onChange( update );
materialVertexShaderRow.add( new UI.Text( 'Vertex Shader' ).setWidth( '90px' ) );
materialVertexShaderRow.add( materialVertexShader );
container.add( materialVertexShaderRow );
// fragment shader
var materialFragmentShaderRow = new UI.Panel();
var materialFragmentShader = new UI.TextArea().setWidth( '150px' ).setHeight( '80px' );
materialFragmentShader.setValue( 'uniform vec3 uColor;\n\nvoid main() {\n\tgl_FragColor = vec4( uColor, 1.0 );\n}' ).onChange( update );
materialFragmentShaderRow.add( new UI.Text( 'Fragment Shader' ).setWidth( '90px' ) );
materialFragmentShaderRow.add( materialFragmentShader );
container.add( materialFragmentShaderRow );
// vertex colors
var materialVertexColorsRow = new UI.Panel();
......@@ -356,11 +324,60 @@ Sidebar.Material = function ( editor ) {
container.add( materialWireframeRow );
// program info (defines, uniforms, attributes)
var materialProgramInfoRow = new UI.Panel();
var edit = new UI.Button( 'Edit' );
edit.setMarginLeft( '4px' );
edit.onClick( function () {
signals.editScript.dispatch( currentObject.material, 'programInfo' );
} );
materialProgramInfoRow.add( new UI.Text( 'Program Info' ).setWidth( '130px' ) );
materialProgramInfoRow.add( edit );
container.add( materialProgramInfoRow );
// vertex shader
var materialVertexShaderRow = new UI.Panel();
var edit = new UI.Button( 'Edit' );
edit.setMarginLeft( '4px' );
edit.onClick( function () {
signals.editScript.dispatch( currentObject.material, 'vertexShader' );
} );
materialVertexShaderRow.add( new UI.Text( 'Vertex Shader' ).setWidth( '130px' ) );
materialVertexShaderRow.add( edit );
container.add( materialVertexShaderRow );
// fragment shader
var materialFragmentShaderRow = new UI.Panel();
var edit = new UI.Button( 'Edit' );
edit.setMarginLeft( '4px' );
edit.onClick( function () {
signals.editScript.dispatch( currentObject.material, 'fragmentShader' );
} );
materialFragmentShaderRow.add( new UI.Text( 'Fragment Shader' ).setWidth( '130px' ) );
materialFragmentShaderRow.add( edit );
container.add( materialFragmentShaderRow );
//
function update() {
var object = editor.selected;
var object = currentObject;
var geometry = object.geometry;
var material = object.material;
......@@ -383,7 +400,13 @@ Sidebar.Material = function ( editor ) {
if ( material instanceof THREE[ materialClass.getValue() ] === false ) {
material = new THREE[ materialClass.getValue() ]();
object.material = material;
// TODO Copy other references in the scene graph
// keeping name and UUID then.
// Also there should be means to create a unique
// copy for the current object explicitly and to
// attach the current material to other objects.
}
......@@ -411,24 +434,6 @@ Sidebar.Material = function ( editor ) {
}
if ( material.uniforms !== undefined ) {
material.uniforms = JSON.parse( materialUniforms.getValue() );
}
if ( material.vertexShader !== undefined ) {
material.vertexShader = materialVertexShader.getValue();
}
if ( material.fragmentShader !== undefined ) {
material.fragmentShader = materialFragmentShader.getValue();
}
if ( material.vertexColors !== undefined ) {
var vertexColors = parseInt( materialVertexColors.getValue() );
......@@ -585,6 +590,7 @@ Sidebar.Material = function ( editor ) {
}
}
if ( material.side !== undefined ) {
material.side = parseInt( materialSide.getValue() );
......@@ -627,7 +633,7 @@ Sidebar.Material = function ( editor ) {
}
updateRows();
refreshUi();
signals.materialChanged.dispatch( material );
......@@ -641,7 +647,9 @@ Sidebar.Material = function ( editor ) {
};
function updateRows() {
//
function setRowVisibility() {
var properties = {
'name': materialNameRow,
......@@ -649,7 +657,7 @@ Sidebar.Material = function ( editor ) {
'emissive': materialEmissiveRow,
'specular': materialSpecularRow,
'shininess': materialShininessRow,
'uniforms': materialUniformsRow,
'uniforms': materialProgramInfoRow,
'vertexShader': materialVertexShaderRow,
'fragmentShader': materialFragmentShaderRow,
'vertexColors': materialVertexColorsRow,
......@@ -670,7 +678,7 @@ Sidebar.Material = function ( editor ) {
'wireframe': materialWireframeRow
};
var material = editor.selected.material;
var material = currentObject.material;
for ( var property in properties ) {
......@@ -680,189 +688,179 @@ Sidebar.Material = function ( editor ) {
};
// events
signals.objectSelected.add( function ( object ) {
if ( object && object.material ) {
container.setDisplay( '' );
function refreshUi() {
var material = object.material;
var material = currentObject.material;
if ( material.uuid !== undefined ) {
if ( material.uuid !== undefined ) {
materialUUID.setValue( material.uuid );
materialUUID.setValue( material.uuid );
}
if ( material.name !== undefined ) {
materialName.setValue( material.name );
}
materialClass.setValue( material.type );
}
if ( material.color !== undefined ) {
if ( material.name !== undefined ) {
materialColor.setHexValue( material.color.getHexString() );
materialName.setValue( material.name );
}
}
if ( material.emissive !== undefined ) {
materialClass.setValue( material.type );
materialEmissive.setHexValue( material.emissive.getHexString() );
if ( material.color !== undefined ) {
}
materialColor.setHexValue( material.color.getHexString() );
if ( material.specular !== undefined ) {
}
materialSpecular.setHexValue( material.specular.getHexString() );
if ( material.emissive !== undefined ) {
}
materialEmissive.setHexValue( material.emissive.getHexString() );
if ( material.shininess !== undefined ) {
}
materialShininess.setValue( material.shininess );
if ( material.specular !== undefined ) {
}
materialSpecular.setHexValue( material.specular.getHexString() );
if ( material.uniforms !== undefined ) {
}
materialUniforms.setValue( JSON.stringify( material.uniforms, null, ' ' ) );
if ( material.shininess !== undefined ) {
}
materialShininess.setValue( material.shininess );
if ( material.vertexShader !== undefined ) {
}
materialVertexShader.setValue( material.vertexShader );
if ( material.vertexColors !== undefined ) {
}
materialVertexColors.setValue( material.vertexColors );
if ( material.fragmentShader !== undefined ) {
}
materialFragmentShader.setValue( material.fragmentShader );
if ( material.skinning !== undefined ) {
}
materialSkinning.setValue( material.skinning );
if ( material.vertexColors !== undefined ) {
}
materialVertexColors.setValue( material.vertexColors );
if ( material.map !== undefined ) {
}
materialMapEnabled.setValue( material.map !== null );
materialMap.setValue( material.map );
if ( material.skinning !== undefined ) {
}
materialSkinning.setValue( material.skinning );
if ( material.alphaMap !== undefined ) {
}
materialAlphaMapEnabled.setValue( material.alphaMap !== null );
materialAlphaMap.setValue( material.alphaMap );
if ( material.map !== undefined ) {
}
materialMapEnabled.setValue( material.map !== null );
materialMap.setValue( material.map );
if ( material.bumpMap !== undefined ) {
}
materialBumpMapEnabled.setValue( material.bumpMap !== null );
materialBumpMap.setValue( material.bumpMap );
materialBumpScale.setValue( material.bumpScale );
if ( material.alphaMap !== undefined ) {
}
materialAlphaMapEnabled.setValue( material.alphaMap !== null );
materialAlphaMap.setValue( material.alphaMap );
if ( material.normalMap !== undefined ) {
}
materialNormalMapEnabled.setValue( material.normalMap !== null );
materialNormalMap.setValue( material.normalMap );
if ( material.bumpMap !== undefined ) {
}
materialBumpMapEnabled.setValue( material.bumpMap !== null );
materialBumpMap.setValue( material.bumpMap );
materialBumpScale.setValue( material.bumpScale );
if ( material.specularMap !== undefined ) {
}
materialSpecularMapEnabled.setValue( material.specularMap !== null );
materialSpecularMap.setValue( material.specularMap );
if ( material.normalMap !== undefined ) {
}
materialNormalMapEnabled.setValue( material.normalMap !== null );
materialNormalMap.setValue( material.normalMap );
if ( material.envMap !== undefined ) {
}
materialEnvMapEnabled.setValue( material.envMap !== null );
materialEnvMap.setValue( material.envMap );
materialReflectivity.setValue( material.reflectivity );
if ( material.specularMap !== undefined ) {
}
materialSpecularMapEnabled.setValue( material.specularMap !== null );
materialSpecularMap.setValue( material.specularMap );
if ( material.lightMap !== undefined ) {
}
materialLightMapEnabled.setValue( material.lightMap !== null );
materialLightMap.setValue( material.lightMap );
if ( material.envMap !== undefined ) {
}
materialEnvMapEnabled.setValue( material.envMap !== null );
materialEnvMap.setValue( material.envMap );
materialReflectivity.setValue( material.reflectivity );
if ( material.aoMap !== undefined ) {
}
materialAOMapEnabled.setValue( material.aoMap !== null );
materialAOMap.setValue( material.aoMap );
materialAOScale.setValue( material.aoMapIntensity );
if ( material.lightMap !== undefined ) {
}
materialLightMapEnabled.setValue( material.lightMap !== null );
materialLightMap.setValue( material.lightMap );
if ( material.side !== undefined ) {
}
materialSide.setValue( material.side );
if ( material.aoMap !== undefined ) {
}
materialAOMapEnabled.setValue( material.aoMap !== null );
materialAOMap.setValue( material.aoMap );
materialAOScale.setValue( material.aoMapIntensity );
if ( material.shading !== undefined ) {
}
materialShading.setValue( material.shading );
if ( material.side !== undefined ) {
}
materialSide.setValue( material.side );
if ( material.blending !== undefined ) {
}
materialBlending.setValue( material.blending );
if ( material.shading !== undefined ) {
}
materialShading.setValue( material.shading );
if ( material.opacity !== undefined ) {
}
materialOpacity.setValue( material.opacity );
if ( material.blending !== undefined ) {
}
materialBlending.setValue( material.blending );
if ( material.transparent !== undefined ) {
}
materialTransparent.setValue( material.transparent );
if ( material.opacity !== undefined ) {
}
materialOpacity.setValue( material.opacity );
if ( material.wireframe !== undefined ) {
}
materialWireframe.setValue( material.wireframe );
if ( material.transparent !== undefined ) {
}
materialTransparent.setValue( material.transparent );
if ( material.wireframeLinewidth !== undefined ) {
}
materialWireframeLinewidth.setValue( material.wireframeLinewidth );
if ( material.wireframe !== undefined ) {
}
materialWireframe.setValue( material.wireframe );
setRowVisibility();
}
}
if ( material.wireframeLinewidth !== undefined ) {
// events
materialWireframeLinewidth.setValue( material.wireframeLinewidth );
signals.objectSelected.add( function ( object ) {
}
if ( object && object.material ) {
updateRows();
currentObject = object;
refreshUi();
container.setDisplay( '' );
} else {
currentObject = null;
container.setDisplay( 'none' );
}
......
// Full source:
//
// https://github.com/hughsk/glsl-editor
//
// (C) Copyright Hugh Kennedy
//
// This software is released under the MIT license:
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL-
// INGS IN THE SOFTWARE.
// The original source code has been slightly modified for the purpose of
// integration (tschw).
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("glsl", function(config, parserConfig) {
var indentUnit = config.indentUnit,
keywords = parserConfig.keywords || words(glslKeywords),
builtins = parserConfig.builtins || words(glslBuiltins),
blockKeywords = parserConfig.blockKeywords || words("case do else for if switch while struct"),
atoms = parserConfig.atoms || words("null"),
hooks = parserConfig.hooks || {},
multiLineStrings = parserConfig.multiLineStrings;
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
var curPunc;
function tokenBase(stream, state) {
var ch = stream.next();
if (hooks[ch]) {
var result = hooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return "bracket";
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
}
if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
}
if (ch == "#") {
stream.eatWhile(/[\S]+/);
stream.eatWhile(/[\s]+/);
stream.eatWhile(/[\S]+/);
stream.eatWhile(/[\s]+/);
return "comment";
}
if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return "operator";
}
stream.eatWhile(/[\w\$_]/);
var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
return "keyword";
}
if (builtins.propertyIsEnumerable(cur)) {
return "builtin";
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
return "word";
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {end = true; break;}
escaped = !escaped && next == "\\";
}
if (end || !(escaped || multiLineStrings))
state.tokenize = tokenBase;
return "string";
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
}
// Interface
return {
startState: function(basecolumn) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
indented: 0,
startOfLine: true
};
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
curPunc = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == "}") {
while (ctx.type == "statement") ctx = popContext(state);
if (ctx.type == "}") ctx = popContext(state);
while (ctx.type == "statement") ctx = popContext(state);
}
else if (curPunc == ctx.type) popContext(state);
else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
return style;
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null) return 0;
var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type;
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
else if (ctx.align) return ctx.column + (closing ? 0 : 1);
else return ctx.indented + (closing ? 0 : indentUnit);
},
electricChars: "{}"
};
});
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var glslKeywords = "attribute const uniform varying break continue " +
"do for while if else in out inout float int void bool true false " +
"lowp mediump highp precision invariant discard return mat2 mat3 " +
"mat4 vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 sampler2D " +
"samplerCube struct gl_FragCoord gl_FragColor";
var glslBuiltins = "radians degrees sin cos tan asin acos atan pow " +
"exp log exp2 log2 sqrt inversesqrt abs sign floor ceil fract mod " +
"min max clamp mix step smoothstep length distance dot cross " +
"normalize faceforward reflect refract matrixCompMult lessThan " +
"lessThanEqual greaterThan greaterThanEqual equal notEqual any all " +
"not dFdx dFdy fwidth texture2D texture2DProj texture2DLod " +
"texture2DProjLod textureCube textureCubeLod require export";
function cppHook(stream, state) {
if (!state.startOfLine) return false;
stream.skipToEnd();
return "meta";
}
;(function() {
// C#-style strings where "" escapes a quote.
function tokenAtString(stream, state) {
var next;
while ((next = stream.next()) != null) {
if (next == '"' && !stream.eat('"')) {
state.tokenize = null;
break;
}
}
return "string";
}
CodeMirror.defineMIME("text/x-glsl", {
name: "glsl",
keywords: words(glslKeywords),
builtins: words(glslBuiltins),
blockKeywords: words("case do else for if switch while struct"),
atoms: words("null"),
hooks: {"#": cppHook}
});
}());
});
// Full source:
//
// https://github.com/zaach/jsonlint
//
// Copyright (C) 2012 Zachary Carter
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL-
// INGS IN THE SOFTWARE.
/* Jison generated parser */
var jsonlint = (function(){
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
var $0 = $$.length - 1;
switch (yystate) {
case 1: // replace escaped characters with actual character
this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
.replace(/\\n/g,'\n')
.replace(/\\r/g,'\r')
.replace(/\\t/g,'\t')
.replace(/\\v/g,'\v')
.replace(/\\f/g,'\f')
.replace(/\\b/g,'\b');
break;
case 2:this.$ = Number(yytext);
break;
case 3:this.$ = null;
break;
case 4:this.$ = true;
break;
case 5:this.$ = false;
break;
case 6:return this.$ = $$[$0-1];
break;
case 13:this.$ = {};
break;
case 14:this.$ = $$[$0-1];
break;
case 15:this.$ = [$$[$0-2], $$[$0]];
break;
case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
break;
case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];
break;
case 18:this.$ = [];
break;
case 19:this.$ = $$[$0-1];
break;
case 20:this.$ = [$$[$0]];
break;
case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
break;
}
},
table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],
defaultActions: {16:[2,6]},
parseError: function parseError(str, hash) {
throw new Error(str);
},
parse: function parse(input) {
var self = this,
stack = [0],
vstack = [null], // semantic value stack
lstack = [], // location stack
table = this.table,
yytext = '',
yylineno = 0,
yyleng = 0,
recovering = 0,
TERROR = 2,
EOF = 1;
//this.reductionCount = this.shiftCount = 0;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
if (typeof this.lexer.yylloc == 'undefined')
this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
if (typeof this.yy.parseError === 'function')
this.parseError = this.yy.parseError;
function popStack (n) {
stack.length = stack.length - 2*n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || 1; // $end = 1
// if token isn't its numeric value, convert
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
while (true) {
// retreive state number from top of stack
state = stack[stack.length-1];
// use default actions if available
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol == null)
symbol = lex();
// read action for current state and first input
action = table[state] && table[state][symbol];
}
// handle parse error
_handle_error:
if (typeof action === 'undefined' || !action.length || !action[0]) {
if (!recovering) {
// Report error
expected = [];
for (p in table[state]) if (this.terminals_[p] && p > 2) {
expected.push("'"+this.terminals_[p]+"'");
}
var errStr = '';
if (this.lexer.showPosition) {
errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
} else {
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
(symbol == 1 /*EOF*/ ? "end of input" :
("'"+(this.terminals_[symbol] || symbol)+"'"));
}
this.parseError(errStr,
{text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
}
// just recovered from another error
if (recovering == 3) {
if (symbol == EOF) {
throw new Error(errStr || 'Parsing halted.');
}
// discard current lookahead and grab another
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
symbol = lex();
}
// try to recover from error
while (1) {
// check for error recovery rule in this state
if ((TERROR.toString()) in table[state]) {
break;
}
if (state == 0) {
throw new Error(errStr || 'Parsing halted.');
}
popStack(1);
state = stack[stack.length-1];
}
preErrorSymbol = symbol; // save the lookahead token
symbol = TERROR; // insert generic error symbol as new lookahead
state = stack[stack.length-1];
action = table[state] && table[state][TERROR];
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
}
// this shouldn't happen, unless resolve defaults are off
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
}
switch (action[0]) {
case 1: // shift
//this.shiftCount++;
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]); // push state
symbol = null;
if (!preErrorSymbol) { // normal execution/no error
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0)
recovering--;
} else { // error just occurred, resume old lookahead f/ before error
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2: // reduce
//this.reductionCount++;
len = this.productions_[action[1]][1];
// perform semantic action
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
// default location, uses first token for firsts, last for lasts
yyval._$ = {
first_line: lstack[lstack.length-(len||1)].first_line,
last_line: lstack[lstack.length-1].last_line,
first_column: lstack[lstack.length-(len||1)].first_column,
last_column: lstack[lstack.length-1].last_column
};
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
if (typeof r !== 'undefined') {
return r;
}
// pop off stack
if (len) {
stack = stack.slice(0,-1*len*2);
vstack = vstack.slice(0, -1*len);
lstack = lstack.slice(0, -1*len);
}
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
vstack.push(yyval.$);
lstack.push(yyval._$);
// goto new state = table[STATE][NONTERMINAL]
newState = table[stack[stack.length-2]][stack[stack.length-1]];
stack.push(newState);
break;
case 3: // accept
return true;
}
}
return true;
}};
/* Jison generated lexer */
var lexer = (function(){
var lexer = ({EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parseError) {
this.yy.parseError(str, hash);
} else {
throw new Error(str);
}
},
setInput:function (input) {
this._input = input;
this._more = this._less = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
return this;
},
input:function () {
var ch = this._input[0];
this.yytext+=ch;
this.yyleng++;
this.match+=ch;
this.matched+=ch;
var lines = ch.match(/\n/);
if (lines) this.yylineno++;
this._input = this._input.slice(1);
return ch;
},
unput:function (ch) {
this._input = ch + this._input;
return this;
},
more:function () {
this._more = true;
return this;
},
less:function (n) {
this._input = this.match.slice(n) + this._input;
},
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
},
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c+"^";
},
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) this.done = true;
var token,
match,
tempMatch,
index,
col,
lines;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i=0;i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (!this.options.flex) break;
}
}
if (match) {
lines = match[0].match(/\n.*/g);
if (lines) this.yylineno += lines.length;
this.yylloc = {first_line: this.yylloc.last_line,
last_line: this.yylineno+1,
first_column: this.yylloc.last_column,
last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
this.yytext += match[0];
this.match += match[0];
this.yyleng = this.yytext.length;
this._more = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
if (this.done && this._input) this.done = false;
if (token) return token;
else return;
}
if (this._input === "") {
return this.EOF;
} else {
this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
{text: "", token: null, line: this.yylineno});
}
},
lex:function lex() {
var r = this.next();
if (typeof r !== 'undefined') {
return r;
} else {
return this.lex();
}
},
begin:function begin(condition) {
this.conditionStack.push(condition);
},
popState:function popState() {
return this.conditionStack.pop();
},
_currentRules:function _currentRules() {
return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
},
topState:function () {
return this.conditionStack[this.conditionStack.length-2];
},
pushState:function begin(condition) {
this.begin(condition);
}});
lexer.options = {};
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
var YYSTATE=YY_START
switch($avoiding_name_collisions) {
case 0:/* skip whitespace */
break;
case 1:return 6
break;
case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
break;
case 3:return 17
break;
case 4:return 18
break;
case 5:return 23
break;
case 6:return 24
break;
case 7:return 22
break;
case 8:return 21
break;
case 9:return 10
break;
case 10:return 11
break;
case 11:return 8
break;
case 12:return 14
break;
case 13:return 'INVALID'
break;
}
};
lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/];
lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}};
;
return lexer;})()
parser.lexer = lexer;
return parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
exports.parser = jsonlint;
exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); }
exports.main = function commonjsMain(args) {
if (!args[1])
throw new Error('Usage: '+args[0]+' FILE');
if (typeof process !== 'undefined') {
var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
} else {
var cwd = require("file").path(require("file").cwd());
var source = cwd.join(args[1]).read({charset: "utf-8"});
}
return exports.parser.parse(source);
}
if (typeof module !== 'undefined' && require.main === module) {
exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册