highlighting logic needs improvement

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
logikal2
Forum Newbie
Posts: 4
Joined: Wed Jun 07, 2006 10:33 pm

highlighting logic needs improvement

Post by logikal2 »

Hey guys,

I'm new to these forums, and fairly new to PHP, so I thought maybe you all could give me a little advice to help me with this problem. I just created an actionscript syntax highlighter for this wiki i'm creating, but it's taking too long for PHP to process all the data sometimes. For example, it takes around 20 seconds to process about 1,000 lines of actionscript code.

I think the problem is that I'm searching through the entire list way too many times, but who knows. Here's what I have so far: (don't be intimidated, the first half of the code are just the KEYWORDS)

* the only variable that needs to be passed into the following function (parse_code) is $out, which is an example Actionscript string*

Inside the CSS file:
.kw1 {color:#ff6600;}
.w6c {color:#808080;}
.w6r {color:#ff0000;}
.w6n {color:#cc66cc;}
.w6s {color:#66cc66;}

PHP:

Code: Select all

<?php
function parse_code($out) {
	$as=array(
		'KEYWORDS'=>array(
			1=>array(
				'#include','for','foreach','if','elseif','else','while','do','dowhile',
				'endwhile','endif','switch','case','endswitch','return','break','continue','in'
			),
			2=>array('null','false','true','var','default','function','class','new','_global'),
			3=>array(
				'#endinitclip','#initclip','__proto__','_accProps','_alpha','_currentframe',
				'_droptarget','_focusrect','_framesloaded','_height','_highquality','_lockroot',
				'_name','_parent','_quality','_root','_rotation','_soundbuftime','_target','_totalframes',
				'_url','_visible','_width','_x','_xmouse','_xscale','_y','_ymouse','_yscale','abs',
				'Accessibility','acos','activityLevel','add','addListener','addPage','addProperty',
				'addRequestHeader','align','allowDomain','allowInsecureDomain','and','appendChild',
				'apply','Arguments','Array','asfunction','asin','atan','atan2','attachAudio','attachMovie',
				'attachSound','attachVideo','attributes','autosize','avHardwareDisable','background',
				'backgroundColor','BACKSPACE','bandwidth','beginFill','beginGradientFill','blockIndent',
				'bold','Boolean','border','borderColor','bottomScroll','bufferLength','bufferTime',
				'builtInItems','bullet','Button','bytesLoaded','bytesTotal','call','callee','caller',
				'Camera','capabilities','CAPSLOCK','caption','catch','ceil','charAt','charCodeAt',
				'childNodes','chr','clear','clearInterval','cloneNode','close','Color','concat',
				'connect','condenseWhite','constructor','contentType','ContextMenu','ContextMenuItem',
				'CONTROL','copy','cos','createElement','createEmptyMovieClip','createTextField',
				'createTextNode','currentFps','curveTo','CustomActions','customItems','data','Date',
				'deblocking','delete','DELETEKEY','docTypeDecl','domain','DOWN',
				'duplicateMovieClip','duration','dynamic','E','embedFonts','enabled',
				'END','endFill','ENTER','eq','Error','ESCAPE','escape','eval',
				'exactSettings','exp','extends','finally','findText','firstChild','floor',
				'flush','focusEnabled','font','fps','fromCharCode','fscommand',
				'gain','ge','get','getAscii','getBeginIndex','getBounds','getBytesLoaded','getBytesTotal',
				'getCaretIndex','getCode','getCount','getDate','getDay','getDepth','getEndIndex','getFocus',
				'getFontList','getFullYear','getHours','getInstanceAtDepth','getLocal','getMilliseconds',
				'getMinutes','getMonth','getNewTextFormat','getNextHighestDepth','getPan','getProgress',
				'getProperty','getRGB','getSeconds','getSelected','getSelectedText','getSize','getStyle',
				'getStyleNames','getSWFVersion','getText','getTextExtent','getTextFormat','getTextSnapshot',
				'getTime','getTimer','getTimezoneOffset','getTransform','getURL','getUTCDate','getUTCDay',
				'getUTCFullYear','getUTCHours','getUTCMilliseconds','getUTCMinutes','getUTCMonth','getUTCSeconds',
				'getVersion','getVolume','getYear','globalToLocal','goto','gotoAndPlay','gotoAndStop',
				'hasAccessibility','hasAudio','hasAudioEncoder','hasChildNodes','hasEmbeddedVideo','hasMP3',
				'hasPrinting','hasScreenBroadcast','hasScreenPlayback','hasStreamingAudio','hasStreamingVideo',
				'hasVideoEncoder','height','hide','hideBuiltInItems','hitArea','hitTest','hitTestTextNearPos',
				'HOME','hscroll','html','htmlText','ID3','ifFrameLoaded','ignoreWhite','implements',
				'import','indent','index','indexOf','Infinity','-Infinity','INSERT','insertBefore','install',
				'instanceof','int','interface','isActive','isDebugger','isDown','isFinite','isNaN','isToggled',
				'italic','join','Key','language','lastChild','lastIndexOf','le','leading','LEFT','leftMargin',
				'length','level','lineStyle','lineTo','list','LN10','LN2','load','loadClip','loaded','loadMovie',
				'loadMovieNum','loadSound','loadVariables','loadVariablesNum','LoadVars','LocalConnection',
				'localFileReadDisable','localToGlobal','log','LOG10E','LOG2E','manufacturer','Math','max',
				'MAX_VALUE','maxChars','maxhscroll','maxscroll','mbchr','mblength','mbord','mbsubstring','menu',
				'message','Microphone','min','MIN_VALUE','MMExecute','motionLevel','motionTimeOut','Mouse',
				'mouseWheelEnabled','moveTo','Movieclip','MovieClipLoader','multiline','muted','name','names','NaN',
				'ne','NEGATIVE_INFINITY','NetConnection','NetStream','newline','nextFrame',
				'nextScene','nextSibling','nodeName','nodeType','nodeValue','not','Number','Object',
				'on','onActivity','onChanged','onClipEvent','onClose','onConnect','onData','onDragOut',
				'onDragOver','onEnterFrame','onID3','onKeyDown','onKeyUp','onKillFocus','onLoad','onLoadComplete',
				'onLoadError','onLoadInit','onLoadProgress','onLoadStart','onMouseDown','onMouseMove','onMouseUp',
				'onMouseWheel','onPress','onRelease','onReleaseOutside','onResize','onRollOut','onRollOver',
				'onScroller','onSelect','onSetFocus','onSoundComplete','onStatus','onUnload','onUpdate','onXML',
				'or(logischesOR)','ord','os','parentNode','parseCSS','parseFloat','parseInt','parseXML','password',
				'pause','PGDN','PGUP','PI','pixelAspectRatio','play','playerType','pop','position',
				'POSITIVE_INFINITY','pow','prevFrame','previousSibling','prevScene','print','printAsBitmap',
				'printAsBitmapNum','PrintJob','printNum','private','prototype','public','push','quality',
				'random','rate','registerClass','removeListener','removeMovieClip','removeNode','removeTextField',
				'replaceSel','replaceText','resolutionX','resolutionY','restrict','reverse','RIGHT',
				'rightMargin','round','scaleMode','screenColor','screenDPI','screenResolutionX','screenResolutionY',
				'scroll','seek','selectable','Selection','send','sendAndLoad','separatorBefore','serverString',
				'set','setvariable','setBufferTime','setClipboard','setDate','setFocus','setFullYear','setGain',
				'setHours','setInterval','setMask','setMilliseconds','setMinutes','setMode','setMonth',
				'setMotionLevel','setNewTextFormat','setPan','setProperty','setQuality','setRate','setRGB',
				'setSeconds','setSelectColor','setSelected','setSelection','setSilenceLevel','setStyle',
				'setTextFormat','setTime','setTransform','setUseEchoSuppression','setUTCDate','setUTCFullYear',
				'setUTCHours','setUTCMilliseconds','setUTCMinutes','setUTCMonth','setUTCSeconds','setVolume',
				'setYear','SharedObject','SHIFT','shift','show','showMenu','showSettings',
				'silenceLevel','silenceTimeout','sin','size','slice','smoothing','sort','sortOn','Sound','SPACE',
				'splice','split','sqrt','SQRT1_2','SQRT2','Stage','start','startDrag','static','status','stop',
				'stopAllSounds','stopDrag','String','StyleSheet','styleSheet','substr',
				'substring','super','swapDepths','System','TAB','tabChildren','tabEnabled','tabIndex',
				'tabStops','tan','target','targetPath','tellTarget','text','textColor','TextField','TextFormat',
				'textHeight','TextSnapshot','textWidth','this','throw','time','toggleHighQuality','toLowerCase',
				'toString','toUpperCase','trace','trackAsMenu','try','type','typeof','undefined',
				'underline','unescape','uninstall','unloadClip','unloadMovie','unLoadMovieNum','unshift','unwatch',
				'UP','updateAfterEvent','updateProperties','url','useCodePage','useEchoSuppression','useHandCursor',
				'UTC','valueOf','variable','version','Video','visible','void','watch','width',
				'with','wordwrap','XML','xmlDecl','XMLNode','XMLSocket'
			)
		),'SYMBOLS'=>array('(',')','[',']','{','}','!','@','%','&','|','<','>'), # missing '/' and '*'
	);

	#numbers
	$out = ' '.trim($out).' ';
	$out = preg_replace("@([^#])([0-9]+)@", '\1:w6n:\2:end2:',$out);

	# symbols
	for($i=0; $i<count($as['SYMBOLS']); $i++) {
			$who = $as['SYMBOLS'][$i];
			$out = str_replace($who,':w6s:'.$who.':end2:',$out);
	}
	
	# spacing
	$out = str_replace(" ","&nbsp;",$out);
	
	# single-line comments
	$out = preg_replace_callback("@[^:]{1}//[\S\s]*\r@U", "fixComment", $out);

	# multi-line comments
	$out = preg_replace_callback("@/\*[\S\s]*?\*/@U", "fixComment", $out);

	# keywords
	for($i=0; $i<count($as['KEYWORDS'][3]); $i++) {
			$who = $as['KEYWORDS'][3][$i];
			$out = preg_replace("@([\W])$who([\W])@",'\1:kw3~'.$who.'::end1:\2',$out);
	}
	for($i=0; $i<count($as['KEYWORDS'][2]); $i++) {
			$who = $as['KEYWORDS'][2][$i];
			$out = preg_replace("@([\W])$who([\W])@",'\1:kw2~'.$who.'::end1:\2',$out);
	}
	for($i=0; $i<count($as['KEYWORDS'][1]); $i++) {
			$who = $as['KEYWORDS'][1][$i];
			$out = preg_replace("@([\W])$who([\W])@",'\1:kw1:'.$who.':end2:\2',$out);
	}

	# quotes
	$out = preg_replace("@\'([\S\s]*)?\'@U", ':w6r:\0:end2:', $out);
	$out = preg_replace("@\"([\S\s]*)?\"@U", ':w6r:\0:end2:', $out);

	# make substitutions
	$out = str_replace(':kw1:',"<span class='kw1'>",$out);
	$out = preg_replace("@:kw2~([\w]*)?:@","<a href='wiki.php?id=\$1'>\$1",$out);
	$out = preg_replace("@:kw3~([\w]*)?:@","<a href='wiki.php?id=\$1'>\$1",$out);
	$out = str_replace(':w6c:',"<span class='w6c'>",$out);
	$out = str_replace(':w6r:',"<span class='w6r'>",$out);
	$out = str_replace(':w6n:',"<span class='w6n'>",$out);
	$out = str_replace(':w6s:',"<span class='w6s'>",$out);
	$out = str_replace(':end2:',"</span>",$out);
	$out = str_replace(':end1:',"</a>",$out);

	# newlines and tabs
	$out = str_replace("\t","&nbsp;&nbsp;&nbsp;&nbsp;",$out);
	$out = str_replace("\r","<br />",$out);
	return $out;
}

function fixComment($m) {
  $beg = '';
	if(substr($m[0],0,2) != '/*') {
			$beg = substr($m[0],0,1);
			$m[0] = substr($m[0],1);
	}
	# remove tags from #numbers and #symbols
	$m[0] = str_replace(":w6n:","",$m[0]);
	$m[0] = str_replace(":w6s:","",$m[0]);
	$m[0] = str_replace(":end2:","",$m[0]);
	$swap = ':w6c:';
	# replace each character with its entity equivalent
	for ($i=0; $i < strlen($m[0]); $i++) {
			$swap .= '&#'.ord($m[0][$i]).';';
	}
	# reverse the important tags
	$swap = str_replace("&nbsp;","&nbsp;",$swap);
	$swap = str_replace("&","&",$swap);
	$swap = str_replace("<","<",$swap);
	$swap = str_replace(">",">",$swap);
	$swap .= ':end2:'."\r";
	return $beg.$swap;
}
?>
As you can see, I'm using preg_replace and str_replace way too many times... one time for each keyword, totalling about 600 times. When you run down 1,000 lines of code 600 times... that could take a while.

Can anyone point me in the right direction in terms of shortcuts or better logic? I used a lot of RegEx to save lines of code, so I can explain what the lines are doing if you need me to.

Thanks in advance,
Matt 8)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Have you taken a look at Geshi? It has Actionscript highlighting, along with much much more.

http://qbnz.com/highlighter/
logikal2
Forum Newbie
Posts: 4
Joined: Wed Jun 07, 2006 10:33 pm

Post by logikal2 »

yep, i was actually thinking about using GeSHi as part of my wiki. However, I want to do this as sort of a learning experience. Plus, GeSHi is built for multiple languages, and mine is strictly Actionscript (to save code). Everything else on my wiki has been made from scratch. I actually got the KEYWORDS from GeSHi (hell if i'm gonna type those all out myself) :P[/u]
logikal2
Forum Newbie
Posts: 4
Joined: Wed Jun 07, 2006 10:33 pm

Post by logikal2 »

anyone?
Post Reply