Page 2 of 2

Posted: Sun Dec 11, 2005 7:42 am
by blueznl
NOT if you want to comment on sections of code, ie. do this

Code: Select all

OpenWindow( #1, _                   ; window nr
           10,10, _                 ; x/y position
           100,100, _               ; size
           #PB_Window_SystemMenu, _ ; add a close button etc
           "test")                  ; and the title
to

Code: Select all

OpenWindow( #1, 10,10,100,100,#PB_Window_SystemMenu,"test")
i agree that you wouldn't have to do parsing if don't need that comment option

Posted: Sun Dec 11, 2005 8:37 am
by Dare2
Parsing/Tokenising is best and perhaps useful for other nifty things.

However here is a quick and dirty (and untested) way. It just makes sure the ; is not inside a string. Rules are:

Open quotes on a physical line must have matching closed quotes.
The _ must be the last character except spaces (not any whitespace)
To allow any trailing white space would need to replacestring things like chr(9) with " " first.

Code: Select all

Global ptr
Dim wk.s(3)

wk(0)="Var.s = "+Chr('"')+"This is my string"+Chr('"')+" _"
wk(1)=" + chr(13)+chr(10) _ ; COMMENTED "
wk(2)=" + "+Chr('"')+"containing these ; _"+Chr('"')+" ; REMARKABLE :)"
wk(3)="Another Line"

Procedure.s GetNextLine()
  If ptr<4                            ; Emulate read or whatever process used
    s.s=wk(ptr)                       ; to get individual lines
    ptr+1
  EndIf
  
  Debug "--> "+s
  
  If FindString(s,";",1)
    For i=1 To Len(s)
      If Mid(s,i,1)=Chr('"')
        If tf=#True
          tf=#False
        Else
          tf=#True
        EndIf
      ElseIf Mid(s,i,1)=";" And tf=#False
        s=Left(s,i-1)
        Break
      EndIf
    Next
  EndIf
  ProcedureReturn Trim(s)
EndProcedure


While ptr<4                        ; not eof emulation :)
  codeline.s=GetNextLine()
  While Right(codeline,1)="_"
    codeline = Left(codeline,Len(codeline)-1) + GetNextLine()
  Wend
  Debug codeline
Wend

Posted: Sun Dec 11, 2005 8:40 am
by PB
> NOT if you want to comment on sections of code

I know, but the concept is that space+underscore is an END OF LINE combo,
so having comments after it defeats that concept, which is my entire point.
That's the way it's always been with other apps, eg. Visual Basic.

Posted: Sun Dec 11, 2005 10:59 am
by blueznl
purebasic is not *just* another basic :-)

hmmm... well, i've added it, on my pc it's not too slow (but your mileage may vary)

it's good for educational purposes to be able to comment on parts, i'd assume :-)

perhaps i'll add an option to make it less smart but faster...

Posted: Sun Dec 11, 2005 5:27 pm
by Pupil
Ok, here's another one, as you can see i really like pointers :)
There's probably ways to improve this, but i wont do it..for now i'm just happy that it works ;)

If you have many many lines in a row with linecontinuation and really long comments you will have to enlarge the string buffer that PB uses internally. Though i doubt this will happend, if one use >64kb of comments one should consider writing a book instead ;)

Code: Select all

;
#EOL$ = Chr(13)+Chr(10)
; Init
Dim hash.b(255)

hash(' ') = 1
hash(';') = 1
hash(10) = 1
hash(13) = 1
hash('"') = 1
hash(9) = 1
hash(39) = 1

Procedure ParseFile(InFile.s, OutFile.s)
DefType.s comment, commentbuffer, dbgtext
DefType.l length, char, quote, pos, posline, linecontinuation
DefType.byte *ibuffer, *obuffer, *start, *endline, *iptr, *optr, *commentstart
  If ReadFile(0, InFile)
    length = Lof()
    If length
      *ibuffer = AllocateMemory(length+10) : *obuffer = AllocateMemory(length+10)
      If *ibuffer And *obuffer
        ReadData(*ibuffer, length)
      Else
        length = 0
      EndIf
    EndIf
    CloseFile(0)
  EndIf
  
  If length = 0
    ProcedureReturn 0
  EndIf
  
  *optr = *obuffer
  *iptr = *ibuffer
  Repeat
    *start = *iptr
    Repeat
      char = *iptr\b & $ff
      If char = '"' Or char = 39 ; Single or double quote
        posline = 0
        If quote
          If quote = char ; Found matching quotes
            quote = 0
          EndIf
        Else
          quote = char
        EndIf
      ElseIf quote = 0
        If char = ' ' Or char = 9 ; white space
          If *iptr = *start And linecontinuation
            *start + 1
          EndIf 
          prevchar = ' ' : *iptr+1 : Continue
        ElseIf char = ';' ; comment to end of line
          *commentstart = *iptr
          Repeat
            ; check for EOL or EOF
            If *iptr\b = 10 Or *iptr\b = 0
              If PeekB(*iptr-1) = 13
                *endline = *iptr-1
              Else
                *endline = *iptr
              EndIf
              Break 2
            EndIf
            *iptr+1
          ForEver
        ElseIf char = '_' And prevchar = ' '
          ; Maybe it's a line continuation
          posline = *iptr
        ElseIf hash(char) = 0
          posline = 0
        EndIf
      EndIf
      
      ; check for EOL or EOF
      If char = 10 Or char = 0; End of line/file?
        If *iptr > *start And PeekB(*iptr-1) = 13
          *endline = *iptr-1
        Else
          *endline = *iptr
        EndIf
        Break
      EndIf
      
      prevchar = char
      *iptr+1
    ForEver
    
    
    
    If posline
      pos = posline
    ElseIf linecontinuation
      If *commentstart
        pos = *commentstart
      Else
        pos = *endline
      EndIf
    Else
      pos = *endline
    EndIf
    
    length = pos - *start
    CopyMemory(*start, *optr, length) : *optr + length; + 1
    
    If linecontinuation
      If *commentstart
        commentbuffer + PeekS(*commentstart, *endline-*commentstart)
      EndIf
      commentbuffer + #EOL$
      If posline = 0
        linecontinuation = 0
        length = PokeS(*optr, comment+#EOL$) : *optr + length ;+ 1
        length = PokeS(*optr, commentbuffer) : *optr + length ;+ 1
        comment = "" : commentbuffer = ""
      EndIf
    ElseIf posline
      linecontinuation = 1
      If *commentstart
        comment = PeekS(*commentstart, *endline-*commentstart)
      Else
        comment = ""
      EndIf
    ElseIf *iptr\b <> 0
      PokeS(*optr, #EOL$) : *optr+2
    EndIf
    
    quote = 0 : prevchar = 0
    posline = 0 : *endline = 0 : *commentstart = 0
    
    
    *iptr+1
    
  Until *iptr\b = 0
  
  If *optr <> *obuffer
    If CreateFile(0, OutFile)
      WriteData(*obuffer, *optr-*obuffer)
      CloseFile(0)
    EndIf
  EndIf
  FreeMemory(*ibuffer) : FreeMemory(*obuffer)
  ProcedureReturn 1
EndProcedure

file.s = OpenFileRequester("Select file", "", "All Files|*.*", 0)
If file <> ""
  t1.l = GetTickCount_()
  For i = 0 To 100
    ParseFile(file, file+"$new.pb")
  Next
  t2.l = GetTickCount_()
  MessageRequester("Time", Str(i-1)+" iterations took "+Str(t2-t1)+"ms.")
EndIf

Posted: Sun Dec 11, 2005 7:33 pm
by Trond
Here's my contribution. It's about twice as fast as the ones by blueznl and Konne.

Edit: Yes I know it generates "ugly" output, but so what, it's going through the compiler anyways!

Code: Select all

Procedure Apple(fnamein.s, fnameout.s)

ReadFile(0, fnamein)
InMem = AllocateMemory(Lof()+2)
OutMem = AllocateMemory(Lof())
Ln = Lof()
ReadData(InMem, Lof())
CloseFile(0)

I = INMem
Z = OUTMem
Ln = INMem + Ln
B = 0
CR = 0
While I < Ln
  B = PeekB(I)
  If B = '"' ;string
    PokeB(Z, B)
    Z + 1
    Repeat
      I + 1
      B = PeekB(I)
      If B = #CR ;We don't want linefeed inside string!
        ProcedureReturn 1
      EndIf
      PokeB(Z, B)
      Z + 1
    Until B = '"' ;end of string
    I + 1
    Continue
  EndIf
  If B = 39 ;single quote
    PokeB(Z, B)
    Z + 1
    Repeat
      I + 1
      B = PeekB(I)
      If B = #CR ;We don't want linefeed inside quotes!
        ProcedureReturn 2
      EndIf
      PokeB(Z, B)
      Z + 1
    Until B = 39 ;end of single quote
    I + 1
    Continue
  EndIf
  If B = ';'
    Repeat
      I + 1
      B = PeekB(I)
      If I > Ln ;In case there is only eof after comment
        Continue
      EndIf
    Until B = #CR ;Linefeed at the end of a comment
    PokeB(Z, B)
    Z + 1
    I + 1
    Continue
  EndIf
  If PeekW(I) = '_ '
    CR + 1
    I + 2
    Repeat
      B = PeekB(I)
      I + 1
      If B = ';'
        Repeat
          B = PeekB(I)
          I + 1
        Until B = #CR
      EndIf
    Until B = #CR
    I + 1
    Continue
  EndIf
  If B = #CR
    While CR
      PokeW(Z, 2573)
      Z + 2
      CR - 1
    Wend
  EndIf
  PokeB(Z, B)
  Z + 1
  I + 1
Wend

CreateFile(0, fnameout)
WriteData(OUTMem, Z-OUTMem)
CloseFile(0)

EndProcedure