[Tool/Web/Other] Include file parser
#1

Hey,

I've gained interest in SA-MP scripting again; however, I'm a Mac user these days. In a quest to get PAWN syntax highlighting, auto-complete, etc. in TextMate (Mac text editor) I had to get information from the include files. I did manage to get all that working just great.
Anyway, at the bottom of this post is the script I ended up using. I figured someone might find it useful.

You give the function a string containing, for example, all your PAWN include files together. The function will return an array with tags, defines, and functions.

Example output: http://pastebay.com/138441

A short example of usage:
PHP Code:
<?php
    
require_once 'pawn_parser.php';
    
    function 
get_dir_contents($dir$skip = array())
    {
        
$data '';
        
$skip array_flip(array_merge($skip, array('.''..''.DS_Store''Thumbs.db')));
    
        if (!
is_dir($dir)) {
            return 
'';
        }
        if ((
$d dir($dir)) === false) {
            return 
'';
        }
    
        
$path $d->path;
    
        while (
false !== ($entry $d->read())) {
            if (isset(
$skip[$entry])) {
                continue;
            }
        
            
$entry "$path/$entry";
        
            if (
is_dir($entry)) {
                
$data .= get_dir_contents($entry$skip);
            } else if (
is_file($entry)) {
                
$data .= file_get_contents($entry) . "\n";
            }
        }
    
        
$d->close();
    
        return 
$data;
    }
    
$include_data get_dir_contents('include'); // you gotta change this
    
$include_info parse_pawn_includes($include_data);
    foreach (
$include_info->functions as $function) {
        if (
$function->type == 'forward') {
            echo 
"Callback: $function->name<br/>\n";
        }
    }
?>
The above code would output:
Code:
Callback: OnNPCModeInit
Callback: OnNPCModeExit
Callback: OnNPCConnect
Callback: OnNPCDisconnect
Callback: OnNPCSpawn
Callback: OnNPCEnterVehicle
Callback: OnNPCExitVehicle
Callback: OnClientMessage
Callback: OnPlayerDeath
Callback: OnPlayerText
Callback: OnPlayerStreamIn
Callback: OnPlayerStreamOut
Callback: OnVehicleStreamIn
Callback: OnVehicleStreamOut
Callback: OnRecordingPlaybackEnd
Callback: OnGameModeInit
Callback: OnGameModeExit
Callback: OnFilterScriptInit
Callback: OnFilterScriptExit
Callback: OnPlayerConnect
Callback: OnPlayerDisconnect
Callback: OnPlayerSpawn
Callback: OnPlayerDeath
Callback: OnVehicleSpawn
Callback: OnVehicleDeath
Callback: OnPlayerText
Callback: OnPlayerCommandText
Callback: OnPlayerRequestClass
Callback: OnPlayerEnterVehicle
Callback: OnPlayerExitVehicle
Callback: OnPlayerStateChange
Callback: OnPlayerEnterCheckpoint
Callback: OnPlayerLeaveCheckpoint
Callback: OnPlayerEnterRaceCheckpoint
Callback: OnPlayerLeaveRaceCheckpoint
Callback: OnRconCommand
Callback: OnPlayerRequestSpawn
Callback: OnObjectMoved
Callback: OnPlayerObjectMoved
Callback: OnPlayerPickUpPickup
Callback: OnVehicleMod
Callback: OnEnterExitModShop
Callback: OnVehiclePaintjob
Callback: OnVehicleRespray
Callback: OnVehicleDamageStatusUpdate
Callback: OnPlayerSelectedMenuRow
Callback: OnPlayerExitedMenu
Callback: OnPlayerInteriorChange
Callback: OnPlayerKeyStateChange
Callback: OnRconLoginAttempt
Callback: OnPlayerUpdate
Callback: OnPlayerStreamIn
Callback: OnPlayerStreamOut
Callback: OnVehicleStreamIn
Callback: OnVehicleStreamOut
Callback: OnDialogResponse
Callback: OnPlayerClickPlayer
Callback: @receivestring
Callback: @receivepacket
The script:
PHP Code:
<?php
    
function oneLineEnumerations($input)
    {
        return 
preg_replace('/\s+/'' '$input[0]);
    }
    
    function 
parse_pawn_includes($input) {
        
$input preg_replace('#/\*[\s\S]*?\*/#'''$input);
        
$input preg_replace('#//.*#'''$input);
        
$input preg_replace_callback('/enum[\s\S]*?{[\s\S]*?}/''oneLineEnumerations'$input);
        
        
$functions = array();
        
$bad_args = array();
        
$all_tags = array();
        
$constants array_flip(array('floatround_round''floatround_floor''floatround_ceil''floatround_tozero''floatround_unbiased''seek_start''seek_current''seek_end''EOS''cellbits''cellmax''cellmin''charbits''charmin''charmax''ucharmax''__Pawn''debug''overlaysize''radian''degrees''grades'));
        
        foreach (
$constants as $constant => $v) {
            
$constants[$constant] = true;
        }
        
        foreach (
explode("\n"$input) as $line) {
            
$line trim($line);
    
            if (empty(
$line)) {
                continue;
            }
    
            if (
preg_match('/^(native|forward)/'$line)) {
                if (
preg_match('/^(native|forward)\s+(?:([\S]+)\s*:\s*)?([^(]+)\s*\(\s*([^;]*)\s*\)\s*;/'$line$matches)) {
                    
$type $matches[1];
                    
$tag $matches[2];
                    
$name $matches[3];
                    
$arguments $matches[4];
                    
                    if (
preg_match('/^operator.$/'$name)) {
                        continue;
                    }
            
                    
$arguments preg_split('/\s*,(?![^{]+})\s*/'$arguments);
            
                    
$arguments_parsed = array();
            
                    foreach (
$arguments as &$argument) {
                        if (empty(
$argument)) {
                            continue;
                        }
                
                        if (
preg_match('/(const)?\s*(&)?\s*(?:([^:]+?)\s*:\s*)?(\.\.\.|\.\.|[@a-zA-Z0-9_]+)(\[.*\])?(?:.*=\s*(.+))?/'$argument$matches)) {
                            
$arguments_match = array(
                                
'line' => $matches[0],
                                
'const' => $matches[1] == 'const',
                                
'reference' => $matches[2] == '&',
                                
'tags' => $matches[3],
                                
'name' => $matches[4],
                                
'length' => @$matches[5],
                                
'default' => @$matches[6],
                            );
                    
                            if (
preg_match('/{\s*(.*)\s*}/'$arguments_match['tags'], $matches)) {
                                
$arguments_match['tags'] = preg_split('/\s*,\s*/'$matches[1]);
                        
                                foreach (
$arguments_match['tags'] as $tag) {
                                    
$all_tags[$tag] = true;
                                }
                            } else {
                                
$arguments_match['tags'] = trim($arguments_match['tags']);
                        
                                if (!empty(
$arguments_match['tags'])) {
                                    
$all_tags[$arguments_match['tags']] = true;
                            
                                    
$arguments_match['tags'] = array($arguments_match['tags']);
                                } else {
                                    
$arguments_match['tags'] = array();
                                }
                            }
                    
                            if (!empty(
$arguments_match['length'])) {
                                if (
preg_match('/\[\s*(\S+)\s*\]/'$arguments_match['length'], $matches)) {
                                    
$arguments_match['length'] = (string) $matches[1];
                                } else {
                                    
$arguments_match['length'] = true;
                                }
                            } else {
                                
$arguments_match['length'] = null;
                            }
                    
                            
$arguments_parsed[] = (object) $arguments_match;
                        } else {
                            
$bad_args[] = $line;
                        }
                    }
            
                    unset(
$argument);
            
                    
$functions[] = (object) array(
                        
'type' => $type,
                        
'tag' => $tag,
                        
'name' => $name,
                        
'arguments' => $arguments_parsed,
                    );
                } else {
                    
//echo 'ERROR: ' . $line . "\n";
                
}
            } else if (
preg_match('/^#define\s+(\S+)\s*(\S+)?\s*/i'$line$matches)) {
                
$constants[$matches[1]] = isset($matches[2]) ? $matches[2] : true;
            }
        }
        
        return array(
            
'functions' => $functions,
            
'constants' => $constants,
            
'tags' => array_keys($all_tags),
        );
    }
?>
Reply


Messages In This Thread
Include file parser - by Slice - 15.09.2011, 07:40
Re: Include file parser - by |_ⒾⓇⓄN_ⒹⓄG_| - 15.09.2011, 07:43
Re: Include file parser - by Slice - 15.09.2011, 08:03
Re: Include file parser - by |_ⒾⓇⓄN_ⒹⓄG_| - 15.09.2011, 08:05

Forum Jump:


Users browsing this thread: 1 Guest(s)