Skip to content

Instantly share code, notes, and snippets.

@MattDiesel
Created June 11, 2013 21:02
Show Gist options
  • Save MattDiesel/5760655 to your computer and use it in GitHub Desktop.
Save MattDiesel/5760655 to your computer and use it in GitHub Desktop.
Example of using AuLex to write a preprocessor. Currently supports #define #undef #ifdef #ifndef #else #endif.
#include <Array.au3>
#include "AuLex.au3"
Local $s = "TestOpt.au3"
MsgBox(0, $s, _PreProcess($s))
Func _PreProcess($sFile)
Local $aDefined[1][2] = [[0, 0]] ; NAME, VALUE
Local $l = _AuLex_StartLex($sFile, $AL_FLAG_AUTOLINECONT)
Local $sOutput = FileRead($sFile)
Local $sTok
Local $iTokType
Local $ifStack[1][2] = [[0, 0]] ; ABS, BOOLEAN VALUE
Local $iAdjust = 0
While 1
$sTok = _AuLex_NextToken($l)
$iTokType = @extended
If $iTokType = $AL_TOK_EOF Then ExitLoop
If $iTokType = $AL_TOK_WORD Then
$i = _ArraySearch($aDefined, $sTok, 1, $aDefined[0][0], 0, 0, 1, 0)
If $i > 0 Then
$iAdjust += _String_ReplaceRange($sOutput, $aDefined[$i][1], $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
EndIf
ElseIf $iTokType = $AL_TOK_PREPROC Then
$sTok = StringStripWS($sTok, 3)
$s = StringLeft($sTok, StringInStr($sTok, " ") - 1)
If Not StringInStr($sTok, " ") Then $s = $sTok
Switch $s
Case "#define"
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
; Check if this is not in a false if statement
For $i = 1 To $ifStack[0][0]
If Not $ifStack[$i][1] Then
ContinueLoop 2
EndIf
Next
$sTok = StringStripWS(StringTrimLeft($sTok, StringLen("#define")), 3)
$aDefined[0][0] += 1
ReDim $aDefined[$aDefined[0][0] + 1][2]
If StringInStr($sTok, " ") Then
$aDefined[$aDefined[0][0]][0] = StringStripWS(StringLeft($sTok, StringInStr($sTok, " ") - 1), 3)
$aDefined[$aDefined[0][0]][1] = StringStripWS(StringTrimLeft($sTok, StringInStr($sTok, " ")), 3)
Else
$aDefined[$aDefined[0][0]][0] = $sTok
EndIf
Case "#undef"
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
; Check if this is not in a false if statement
For $i = 1 To $ifStack[0][0]
If Not $ifStack[$i][1] Then
ContinueLoop 2
EndIf
Next
$sTok = StringStripWS(StringTrimLeft($sTok, StringLen("#define")), 3)
$i = _ArraySearch($aDefined, $sTok, 1, $aDefined[0][0], 0, 0, 1, 0)
If $i > 0 Then
_ArrayDelete($aDefined, $i)
$aDefined[0][0] -= 1
EndIf
Case "#ifdef"
$sTok = StringStripWS(StringTrimLeft($sTok, StringLen("#ifdef")), 3)
$ifStack[0][0] += 1
ReDim $ifStack[$ifStack[0][0] + 1][2]
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
$ifStack[$ifStack[0][0]][0] = $l[$AL_LEXI_ABS] + $iAdjust + 1
$ifStack[$ifStack[0][0]][1] = _ArraySearch($aDefined, $sTok, 1, $aDefined[0][0], 0, 0, 1, 0) > 0
Case "#ifndef"
$sTok = StringStripWS(StringTrimLeft($sTok, StringLen("#ifndef")), 3)
$ifStack[0][0] += 1
ReDim $ifStack[$ifStack[0][0] + 1][2]
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
$ifStack[$ifStack[0][0]][0] = $l[$AL_LEXI_ABS] + $iAdjust + 1
$ifStack[$ifStack[0][0]][1] = _ArraySearch($aDefined, $sTok, 1, $aDefined[0][0], 0, 0, 1, 0) < 1
Case "#else"
If $ifStack[0][0] = 0 Then ContinueLoop
If $ifStack[$ifStack[0][0]][1] Then
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
Else
$iAdjust += _String_ReplaceRange($sOutput, "", $ifStack[$ifStack[0][0]][0], $l[$AL_LEXI_ABS] + $iAdjust)
EndIf
$ifStack[$ifStack[0][0]][0] = $l[$AL_LEXI_ABS] + $iAdjust + 1
$ifStack[$ifStack[0][0]][1] = Not $ifStack[$ifStack[0][0]][1]
Case "#endif"
If $ifStack[0][0] = 0 Then ContinueLoop
If $ifStack[$ifStack[0][0]][1] Then
$iAdjust += _String_ReplaceRange($sOutput, "", $l[$AL_LEXI_LASTTOK_ABS] + $iAdjust, $l[$AL_LEXI_ABS] + $iAdjust)
Else
$iAdjust += _String_ReplaceRange($sOutput, "", $ifStack[$ifStack[0][0]][0], $l[$AL_LEXI_ABS] + $iAdjust)
EndIf
$ifStack[0][0] -= 1
EndSwitch
EndIf
WEnd
Return $sOutput
EndFunc ;==>_PreProcess
Func _String_ReplaceRange(ByRef $sString, $sNew, $iStart, $iEnd)
$sString = StringLeft($sString, $iStart - 1) & $sNew & StringMid($sString, $iEnd)
Return StringLen($sNew) - ($iEnd - $iStart)
EndFunc ;==>_String_ReplaceRange
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment