最近一段时间忽然想到用javascript理论上可以实现一个复杂的在线编辑器完全能够支持词法语法方面的功能于是试验了一下效率和简易程度还是令人吃惊的看来javascript比想象的还要强大
<html>
<head>
<title>Silverna Demo Ver </title>
<style>
diveditbox{
margin: ;
padding: ;
font:/px Arial;
border:px solid #;
}
p{
margin: ;
padding: ;
}
</style>
</head>
<body onload=editboxfocus()>
<div id=editbox class=editbox contentEditable=true onkeyDown=return KeyDown() onkeyUp=KeyUp() onclick=getCursorPosition()>
</div>
<select size= id=methods onkeydown=SelectMethod() onclick=SelMethod(this)>
</body>
</html>
</select>
<script language=JScript>
var testArray = new Array();
var testDate = new Date();
var testString = aaa;
var testVal = ;
var testObj = new myObj;
function myObj()
{
myObjprototypetestFunc = function(){};
thistestProperty = test;
}
function KeyDown()
{
//alert(eventaltKey);
if(eventkeyCode == ) //TAB 键
{
clipboardDatasetData(text );
eventsrcElementdocumentexecCommand(paste);
return false;
}
if(eventkeyCode == ) //Backspace 键
{
var oSel = documentselectioncreateRange();
var offset = eventsrcElementdocumentselectioncreateRange();
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
if(offsettextlength < ) return true;
for (var i = ; i < offsettextlength; i++)
{
if (offsettextcharAt(i) != )
{
return true;
}
}
offsetselect();
eventsrcElementdocumentexecCommand(Delete);
return false;
}
return true;
}
function KeyUp()
{
var oSel offset;
if(eventkeyCode == )
{
testStr = eventsrcElementinnerTextsubstring( getCursorPosition());
//alert(testStr);
var space = ;
for (var i = testStrlength ; i >= ; i)
{
//alert(testStrlength+:+testStrcharAt(i) + : + spacelength);
if (testStrcharAt(i) == \n) break;
if (testStrcharAt(i) == )
space += ;
else
space = ;
}
//alert(testStr);
clipboardDatasetData(textspace);
eventsrcElementdocumentexecCommand(paste);
}
oSel = documentselectioncreateRange();
var left = oSeloffsetLeft;
var top = oSeloffsetTop;
var token = getCurrentToken(eventsrcElement);
var chars = getCursorPosition();
parseSyntax(eventsrcElement);
offset = eventsrcElementdocumentselectioncreateRange();
offsetmoveToPoint(left top);
offsetselect();
if(eventkeyCode == ) //键
{
setMethods(tokenposTokslice( ));
}
}
function parseSyntax(src) //解析当前文本
{
var text = srcinnerHTML;
text = textreplace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi);
text = textreplace(/<P>/gi \xfe)replace(/<\/P>/gi \xff);
text = textreplace(/\ /gi \xfd);
text = textreplace(/\r\n/gi);
for (var i = ; i <SyntaxSetAlllength; i++)
{
var syntaxes = SyntaxSetAll[i];
for (var j = ; j < syntaxesrulesAlllength; j++)
{
syntaxesrulesAll[lor = lor;
syntaxesrulesAll[ns = ns;
text = parseRule(text syntaxesrulesAll[j]);
}
}
srcinnerHTML = textreplace(/\xfc/g)replace(/\xfe/g<P>)replace(/\xff/g</P>)replace(/\xfd/g );
}
function parseRule(text rule) //解析词法
{
//利用正则表达式
var newText = ;
var idx = textsearch(ruleexpr);
while (idx != )
{
var remark = textmatch(ruleexpr);
//alert(textsubstring( idx+remark[]length));
var subText = textsubstring( idx + remark[]length);
if(ns == null || (idx == || nstest(textcharAt(idx))) && (idx + remark[]length >= textlength || nstest(textcharAt(idx + remark[]length))))
{
//alert(remark[]);
//alert(remark[]replace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi));
subText = subTextreplace(remark[] <FONT color=\xfc+lor+\xfc> + remark[]replace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi) + </FONT>);
//alert(subText);
}
newText += subText;
text = textsubstring(idx + remark[]length);
idx = textsearch(ruleexpr);
}
newText += text;
return newText;
}
function getCurrentToken(src)
{
var oSel = documentselectioncreateRange();
var offset = srcdocumentselectioncreateRange();
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
var tokens = offsettextsplit(/[\s\+\\*\/]/); //token由连续字母数字下划线点号括号引号构成
var currentToken = tokens[tokenslength ];
var idx = offsettextlength;
var fullToken = srcinnerTextsubstring(idx);
fullToken = fullTokenreplace(/[\s\+\\*\/]/@@@@);
idx = fullTokenindexOf(@@@@);
if(idx != )
fullToken = fullTokensubstring( idx);
var token = new Array();
tokencurrentToken = currentToken + fullToken;
tokenposTok = currentToken;
return token;
}
ArrayprototypepushDistinct = function(obj)
{
for (var i = ; i < thislength; i++)
{
if (this[i] == obj)
{
return null;
}
}
thispush(obj);
return obj;
}
function putMethods(methodList obj methods) //将方法添加到方法列表
{
var list = methodssplit();
for (var i = ; i < listlength; i++)
{
if (obj[list[i]] != null)
{
methodListpushDistinct(list[i]);
}
}
}
var now = new Date(); //测试用
var a = ; //测试用
var __expr = new RegExp(tt); //测试用
function setMethods(objStr)
{
var oSel = documentselectioncreateRange();
try
{
if (objStr == alert) return;
var methodList = new Array();
var obj = eval(objStr);
if (objprototype != null)
{
methodListpushDistinct(prototype);
}
if (obj != null)
{
//基本Object方法
putMethods(methodList objconstructorhasOwnPropertyisPrototypeOfpropertyIsEnumerabletoLocaleStringtoStringvalueOf);
//基本Array方法
putMethods(methodList objconcatjoinlengthpoppushreverseshiftslicesortspliceunshift);
//基本Date方法
putMethods(methodListobjgetDategetUTCDategetDaygetUTCDaygetFullYeargetUTCFullYeargetHoursgetUTCHoursgetMillisecondsgetUTCMillisecondsgetMinutesgetUTCMinutesgetMonthgetUTCMonthgetSecondsgetUTCSecondsgetTimegetTimezoneoffsetgetYear);
putMethods(methodListobjsetDatesetUTCDatesetFullYearsetUTCFullYearsetHourssetUTCHourssetMillisecondssetUTCMillisecondssetMinutessetUTCMinutessetMonthsetUTCMonthsetSecondssetUTCSecondssetTimesetYeartoDateStringtoGMTStringtoLocaleDateStringtoLocaleTimeStringtoStringtoTimeStringtoUTCStringvalueOfparseUTC);
//基本Math方法
putMethods(methodListobjELNLNLOGELOGEPISQRT_SQRT);
putMethods(methodListobjabsacosasinatanatanceilcosexpfloorlogmaxminpowrandomroundsinsqrttan);
//基本Function方法
putMethods(methodListobjargumentscallerlengthprototypeapplycalltoString);
//基本Number方法
putMethods(methodListobjMAX_VALUEMIN_VALUENaNNEGATIVE_INFINITYPOSITIVE_INFINITY);
putMethods(methodListobjtoStringtoLocalStringtoFixedtoExponentialtoPrecision);
//基本RegExp方法
putMethods(methodListobjglobalignoreCaselastIndexmultilinesourceexectest);
//基本String方法
putMethods(methodListobjcharAtcharCodeAtcontactindexOflastIndexOfmatchreplacesearchslicesplitsubstringsubstrtoLowerCasetoStringtoUpperCasevalueOffromCharCode);
putMethods(methodListobjanchorbigblinkboldfixedfontcolorfontsizeitalicslinksmallstrikesubsup);
}
for (each in obj)
{
methodListpushDistinct(each);
}
methodListsort();
if (methodListlength > )
{
methodsoptionslength = ;
for (var i = ; i < methodListlength; i++)
{
methodsoptionsadd(new Option(methodList[i]));
}
if (methodsoptionslength > )
{
methodssize = ;
}
else
{
methodssize = methodsoptionslength;
}
methodsstyletop = oSeloffsetTop;
methodsstyleleft = oSeloffsetLeft;
methodsstyledisplay = ;
methodsoptions[]selected = true;
methodsfocus();
}
}
catch(e){}
}
function SelectMethod()
{
var src = eventsrcElement;
if(eventkeyCode == )
{
SelMethod(src);
}
if(eventkeyCode == || eventkeyCode == || eventkeyCode == )
{
srcstyledisplay = none;
editboxfocus();
}
}
function SelMethod(src)
{
clipboardDatasetData(textsrcoptions[srcselectedIndex]text);
editboxfocus();
editboxdocumentexecCommand(paste);
srcstyledisplay = none;
getCursorPosition();
}
function getPos(text) //计算行数列数
{
var rows = ;
var cols = ;
var idx = ;
var subText = text;
while((idx = subTextindexOf(\n)) != )
{
subText = subTextsubstring(idx + );
rows++;
}
return new Array(rows subTextlength + );
}
function getNullRows(srcoSel) //计算空行
{
var rows = ;
var offsetEnd = srcdocumentselectioncreateRange();
var oldTop = ;
var oldLeft = ;
while()
{
offsetEndmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetEndmoveStart(characterrows);
if (offsetEndtextlength > || offsetEndoffsetTop == oldTop && offsetEndoffsetLeft == oldLeft)
{
break;
}
rows ++;
oldTop = offsetEndoffsetTop;
oldLeft = offsetEndoffsetLeft;
}
return rows;
}
function getCursorPosition()
{
var src = eventsrcElement;
var offset = srcdocumentselectioncreateRange();
var oSel = documentselectioncreateRange();
var textLength = srcinnerTextlength;
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
//srcdocumentexecCommand(ForeColorfalse#ff);
var rowSpans = offsetgetClientRects();
var pos = getPos(offsettext);
var charCodes = offsettextlength; //字符总数
var chars = offsettextreplace(/\r\n/g)length + ; //字符
var extRows = getNullRows(srcoSel);
if(extRows > )
{
pos[] += extRows;
pos[] = ;
}
windowstatus = 行: + pos[] + 列: + pos[] + 第 + chars + 个字符 + (+ oSeloffsetTop ++
oSeloffsetLeft +);
return charCodes;
}
///词法解析过程
///
///
var SyntaxSet = new Array(); //词法规则集合
SyntaxSetAll = new Array();
SyntaxSetparse = function(token) //针对token返回rule
{
for (var i = ; i < thisAlllength; i++)
{
var syntaxes = thisAll[i];
for (var j = ; j < syntaxesrulesAlllength; j++)
{
if (syntaxesrulesAll[j]test(token))
{
syntaxesrulesAll[lor = lor;
return syntaxesrulesAll[j];
}
}
}
return null;
}
SyntaxSetadd = function(syntaxes)
{
if(this[syntaxesname] != null)
return;
this[syntaxesname] = syntaxes;
thisAllpush(syntaxes);
}
function Syntaxes(name color cons) //词法规则组(同组规则用一种颜色标记)
{
thisname = name; //规则组名称
lor = color; //标记该语法的颜色
thisrules = new Array(); //语法规则(以次序决定优先级)
thisrulesAll = new Array();
ns = cons; //边界约束
SyntaxesprototypeaddRule = function(rule)
{
if(thisrules[rulename] != null)
return;
thisrules[rulename] = rule;
thisrulesAllpush(rule);
}
}
function SyntaxRule(name regExp) //词法规则
{
thisname = name; //规则名称
thisexpr = regExp; //规则描述 (正则表达式)
SyntaxRuleprototypetest = function(token)
{
return thisexprtest(token);
}
}
function RegExprX(exprStr) //扩展正则表达式的功能支持定义嵌套
{
thisexpr = exprStr;
}
RegExprXprototypegetPattern = function(tag) //获取正则表达式对象
{
if (tag == null)
return new RegExp(thisexpr);
else
return new RegExp(thisexpr tag);
}
Rencat = function(expr rule) //连接两个正则表达式串
{
if (rule == null)
thisexpr += expr; //直接连接
else if (rule == union) //联合
thisexpr = ( + thisexpr + ) + | + ( + expr + );
else if (rule == cons) //约束
thisexpr = thisexpr + (?= + expr + );
return thisexpr;
}
//为保证正确计算偏移量需要替换回车\n\r为\xff
SyntaxSetadd(new Syntaxes(keywords #ff /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //词法?关键词?蓝色
SyntaxSet[keywords]addRule(new SyntaxRule(Function/function/));
SyntaxSet[keywords]addRule(new SyntaxRule(Variable/var/));
SyntaxSet[keywords]addRule(new SyntaxRule(Return/return/));
SyntaxSet[keywords]addRule(new SyntaxRule(Exception/(try|catch|throw)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Condition/(if|else|switch)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Cycle/(for|while|do)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Type/(int|double|float|void|char)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Right/(public|private|protected|static)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Constant/(null|undefined|NaN|Infinity)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Construct/(new|delete)/));
SyntaxSetadd(new Syntaxes(objects #FF /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //词法?对象?红色
SyntaxSet[objects]addRule(new SyntaxRule(Object/(Array|arguments|Boolean|Date|Error|Function|Object|Number|Math|RegExp|String)/));
SyntaxSetadd(new Syntaxes(global # /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //词法?系统函数?红色
SyntaxSet[global]addRule(new SyntaxRule(SystemFunc/(alert|parseFloat|parseInt|eval|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|unescape)/));
SyntaxSetadd(new Syntaxes(String #ffff /[\s\\xfe\xff\xfd\(\{\}\)\;\\+\\*\/]/)); //词法?字符串?粉色
SyntaxSet[String]addRule(new SyntaxRule(String
/(((\\\)|[^\xff\])*([^\\\]|(\\\)))|(((\\\)|[^\xff\])*([^\\\]|(\\\)))/));
SyntaxSetadd(new Syntaxes(remarks #)); //词法?注释?绿色
SyntaxSet[remarks]addRule(new SyntaxRule(ShortRemark/\/\/[^\xff]*/));
SyntaxSet[remarks]addRule(new SyntaxRule(LongRemark/\/\*((*\*\/)|(*$))/));
function Grammars() //语法规则
{
}
</script>