Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: hknmtt 18. 01. 2023, 17:20:45

Název: Regulární výraz pro funkce a metody v Go
Přispěvatel: hknmtt 18. 01. 2023, 17:20:45
Poradite regex do Go na najdenie vsetkych funkcii, vratane "metod"?

Teda:
Kód: [Vybrat]
func (t *Time) sec() int64 {
if t.wall&hasMonotonic != 0 {
return wallToInternal + int64(t.wall<<1>>(nsecShift+1))
}
return t.ext
}

a

func Since(t Time) Duration {
var now Time
if t.wall&hasMonotonic != 0 {
// Common case optimization: if t has monotonic time, then Sub will use only it.
now = Time{hasMonotonic, runtimeNano() - startNano, nil}
} else {
now = Now()
}
return now.Sub(t)
}

Nedari sa mi matchnut telo funkcii a regex nie je moje forte. Potrebujem sa len zbavit vsetkych funkcii z vygenerovaneho kodu lebo chcem odtial dostat len structy a je toho prilis vela skratka na manualne ocistenie.
Název: Re:Regulerny vyraz na Go funkcie a metody
Přispěvatel: alex6bbc 18. 01. 2023, 18:27:36
vyhledat radky zacinajici func :-)

to je otazka zda telo jde chytit regexem, spis bych udelal skript, ktery najde func a vsecko za tim a do prvni { a pak pricitat nalezene { a odecitat } a az se dospeje k nule tak je konec funkce a to zahodit.

a nebo obdobne s type a jen co je spojeno s type a {} ponechat do vypisu.
Název: Re:Regulerny vyraz na Go funkcie a metody
Přispěvatel: Zdenek Tomes 18. 01. 2023, 18:59:27
vyhledat radky zacinajici func :-)

to je otazka zda telo jde chytit regexem, spis bych udelal skript, ktery najde func a vsecko za tim a do prvni { a pak pricitat nalezene { a odecitat } a az se dospeje k nule tak je konec funkce a to zahodit.

a nebo obdobne s type a jen co je spojeno s type a {} ponechat do vypisu.

to ti rozbije jakejkoli zakomentovanej blok nebo jakakoli { v retezci. Jedine pokud je jistota, ze zdrojaky prosly pres gofmt, pak asi hledat ^func a potom nejblizsi ^}

Jde to relativne (RELATIVNE) snadno a hlavne spravne pres AST. Nedavno o tom vysel clanek, Go ma primo v zakladni knihovne podporu pro parsing do AST a z toho uz se snadno vypraskaji ty hledane structy atd.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Filip Jirsák 18. 01. 2023, 19:14:45
Zdrojové kódy běžných programovacích jazyků (jako Go) se nedají zpracovávat regulárním výrazem. Jsou na to potřeba silnější výrazové možnosti (vyšší typ gramatiky).
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Idris 18. 01. 2023, 19:23:38
Ta gramatika bude (přinejmenším) bezkontextová. Jak je zmíněno výše, Go má ve standardní knihovně prostředky pro parsing zdrojáků a práci s AST.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: mr.rubik 18. 01. 2023, 19:29:35
Jojo, tohle je neco, co by clovek znal, kdyby chodil na VS ;) (narazim na topic https://forum.root.cz/index.php?topic=27090.165 (https://forum.root.cz/index.php?topic=27090.165))

Programovaci jazyky jsou vetsinou bezkontextove gramatiky, tj. nelze je pokryt regularnimi vyrazy (konecnym automatem), nybrz zasobnikovym automatem, tj. parsovani tak, jak to dela frontend prekladace.

Reseni pomoci AST parseru se zda byt schudne.

Co ale zkusit jednoduchy workaround... gofmt by melo snad srovnat i whitespacy, tudiz bych ocekaval, ze uzaviraci slozena zavorka bude mit pred sebou stejny pocet whitespacu, jako func. Na tom by se nejaky skript uz dal postavit.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: mr.rubik 18. 01. 2023, 19:31:22
Ta gramatika bude (přinejmenším) bezkontextová. Jak je zmíněno výše, Go má ve standardní knihovně prostředky pro parsing zdrojáků a práci s AST.

No "vic" nez bezkontextova urcite nebude, to by uz byl prirozeny jazyk :D tedy alespon dle Chomskeho hierarchie...
Název: Re:Regulerny vyraz na Go funkcie a metody
Přispěvatel: mr.rubik 18. 01. 2023, 19:38:35
vyhledat radky zacinajici func :-)

to je otazka zda telo jde chytit regexem, spis bych udelal skript, ktery najde func a vsecko za tim a do prvni { a pak pricitat nalezene { a odecitat } a az se dospeje k nule tak je konec funkce a to zahodit.

a nebo obdobne s type a jen co je spojeno s type a {} ponechat do vypisu.

to ti rozbije jakejkoli zakomentovanej blok nebo jakakoli { v retezci. Jedine pokud je jistota, ze zdrojaky prosly pres gofmt, pak asi hledat ^func a potom nejblizsi ^}

Jde to relativne (RELATIVNE) snadno a hlavne spravne pres AST. Nedavno o tom vysel clanek, Go ma primo v zakladni knihovne podporu pro parsing do AST a z toho uz se snadno vypraskaji ty hledane structy atd.

Az ted jsem si vsiml, ze je to to, co jsem psal ja - sorry.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Idris 18. 01. 2023, 20:07:40
Ta gramatika bude (přinejmenším) bezkontextová. Jak je zmíněno výše, Go má ve standardní knihovně prostředky pro parsing zdrojáků a práci s AST.
No "vic" nez bezkontextova urcite nebude, to by uz byl prirozeny jazyk :D tedy alespon dle Chomskeho hierarchie...
Přirozené jazyky v Chomského hierarchii vůbec nejsou. A programovací jazyky dost často bývají context-sensitive.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: hknmtt 18. 01. 2023, 20:18:44
ok, diky za info. nenapadlo by ma ze spravit regex ktory len vyhlada funkciu ktorej telo medzi {} moze byt hocico(tzn len naparuje tu zatvorku) je taky problem.

tak som si spravil skript na to na koniec. na kolene na rychlo ale funguje:
Kód: [Vybrat]
package main

import (
"bufio"
"bytes"
"errors"
"io"
"os"
"path/filepath"
)

func main() {
args := os.Args

if len(args) != 2 {
println("missing file argument")
return
}

src, err := os.OpenFile(filepath.Clean(args[1]), os.O_RDWR, 0666)
if err != nil {
println(err.Error())
return
}

defer func() {
if err := src.Close(); err != nil && errors.Is(err, os.ErrClosed) == false {
println(err.Error())
}
}()

s := bufio.NewScanner(src)
s.Split(bufio.ScanLines)

fTok := []byte("func ")
openTok := []byte{'{'}
closeTok := []byte{'}'}
emptyTok := []byte{'{', '}'}

matches := make([][]byte, 0, 500)
var match bool
for {
if s.Scan() == false {
break
}
if match == false {
if bytes.HasPrefix(s.Bytes(), fTok) && (bytes.HasSuffix(s.Bytes(), openTok) || bytes.HasSuffix(s.Bytes(), emptyTok)) {
matches = append(matches, append(make([]byte, 0, len(s.Bytes())), s.Bytes()...))
matches[len(matches)-1] = append(matches[len(matches)-1], '\n')
match = bytes.HasSuffix(s.Bytes(), openTok)
}
} else {
matches[len(matches)-1] = append(matches[len(matches)-1], s.Bytes()...)
matches[len(matches)-1] = append(matches[len(matches)-1], '\n')
match = bytes.Equal(s.Bytes(), closeTok) == false
}
}

if len(matches) == 0 {
return
}

if _, err := src.Seek(0, io.SeekStart); err != nil {
println(err.Error())
return
}

data, err := io.ReadAll(src)
if err != nil {
println(err.Error())
return
}

for k := range matches {
data = bytes.Replace(data, matches[k], nil, 1)
}

if _, err := src.Seek(0, io.SeekStart); err != nil {
println(err.Error())
return
}

if err := src.Truncate(0); err != nil {
println(err.Error())
return
}

if _, err := src.Write(data); err != nil {
println(err.Error())
return
}
}

Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Filip Jirsák 18. 01. 2023, 20:44:36
tzn len naparuje tu zatvorku
Jednak pro regulární výrazy je problém už samotné vnořování párových závorek. Za druhé, to právě není pravda, že stačí napárovat závorky – jak už bylo řečeno, to vám rozbije závorka v textovém řetězci nebo v komentáři.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Idris 18. 01. 2023, 20:56:11
ok, diky za info. nenapadlo by ma ze spravit regex ktory len vyhlada funkciu ktorej telo medzi {} moze byt hocico(tzn len naparuje tu zatvorku) je taky problem.

tak som si spravil skript na to na koniec. na kolene na rychlo ale funguje:
Kód: [Vybrat]
package main

import (
"bufio"
"bytes"
"errors"
"io"
"os"
"path/filepath"
)

func main() {
args := os.Args

if len(args) != 2 {
println("missing file argument")
return
}

src, err := os.OpenFile(filepath.Clean(args[1]), os.O_RDWR, 0666)
if err != nil {
println(err.Error())
return
}

defer func() {
if err := src.Close(); err != nil && errors.Is(err, os.ErrClosed) == false {
println(err.Error())
}
}()

s := bufio.NewScanner(src)
s.Split(bufio.ScanLines)

fTok := []byte("func ")
openTok := []byte{'{'}
closeTok := []byte{'}'}
emptyTok := []byte{'{', '}'}

matches := make([][]byte, 0, 500)
var match bool
for {
if s.Scan() == false {
break
}
if match == false {
if bytes.HasPrefix(s.Bytes(), fTok) && (bytes.HasSuffix(s.Bytes(), openTok) || bytes.HasSuffix(s.Bytes(), emptyTok)) {
matches = append(matches, append(make([]byte, 0, len(s.Bytes())), s.Bytes()...))
matches[len(matches)-1] = append(matches[len(matches)-1], '\n')
match = bytes.HasSuffix(s.Bytes(), openTok)
}
} else {
matches[len(matches)-1] = append(matches[len(matches)-1], s.Bytes()...)
matches[len(matches)-1] = append(matches[len(matches)-1], '\n')
match = bytes.Equal(s.Bytes(), closeTok) == false
}
}

if len(matches) == 0 {
return
}

if _, err := src.Seek(0, io.SeekStart); err != nil {
println(err.Error())
return
}

data, err := io.ReadAll(src)
if err != nil {
println(err.Error())
return
}

for k := range matches {
data = bytes.Replace(data, matches[k], nil, 1)
}

if _, err := src.Seek(0, io.SeekStart); err != nil {
println(err.Error())
return
}

if err := src.Truncate(0); err != nil {
println(err.Error())
return
}

if _, err := src.Write(data); err != nil {
println(err.Error())
return
}
}

Pozor na pumping lemma ;)
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Idris 18. 01. 2023, 20:59:30
to by uz byl prirozeny jazyk
Přirozené jazyky bývají dost často bezkontextové, hlavně ty s bohatou morfologií nebo polysyntetické. Jsou výjimky, holandština nebo švýcarská němčina mají konstrukce, které bezkontextově vyjádřit nejdou, ale to jsou spíše netypické příklady.
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Tomáš Procházka 18. 01. 2023, 22:39:11
tzn len naparuje tu zatvorku
Jednak pro regulární výrazy je problém už samotné vnořování párových závorek. Za druhé, to právě není pravda, že stačí napárovat závorky – jak už bylo řečeno, to vám rozbije závorka v textovém řetězci nebo v komentáři.


Koukám, že jdu rozbíjet hračky pozdě.
https://go.dev/play/p/pB7As-_tqmN
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: mr.rubik 18. 01. 2023, 23:40:08
Ta gramatika bude (přinejmenším) bezkontextová. Jak je zmíněno výše, Go má ve standardní knihovně prostředky pro parsing zdrojáků a práci s AST.
No "vic" nez bezkontextova urcite nebude, to by uz byl prirozeny jazyk :D tedy alespon dle Chomskeho hierarchie...
Přirozené jazyky v Chomského hierarchii vůbec nejsou. A programovací jazyky dost často bývají context-sensitive.

OK, vidim svoji chybu, uznavam, prirozene jazyky tam vubec nepatri, Chomskeho hierarchie jsou pouze formalismy, uz je to nejaky ten cas od automatu a gramatik...

Nicmene, troufam si tvrdit, ze je fer mluvit o drtive vetsine programovacich jazyku jako o bezkontextovych - parser funguje nad gramatikou a ta je IMO bezkontextova takrka vzdy. Zbytek jsou uz semanticka pravidla aplikovana v jine fazi, neni-liz pravda?
Název: Re:Regulérní výraz pro funkce a metody v Go
Přispěvatel: Idris 18. 01. 2023, 23:51:36
Ta gramatika bude (přinejmenším) bezkontextová. Jak je zmíněno výše, Go má ve standardní knihovně prostředky pro parsing zdrojáků a práci s AST.
No "vic" nez bezkontextova urcite nebude, to by uz byl prirozeny jazyk :D tedy alespon dle Chomskeho hierarchie...
Přirozené jazyky v Chomského hierarchii vůbec nejsou. A programovací jazyky dost často bývají context-sensitive.
Nicmene, troufam si tvrdit, ze je fer mluvit o drtive vetsine programovacich jazyku jako o bezkontextovych - parser funguje nad gramatikou a ta je IMO bezkontextova takrka vzdy. Zbytek jsou uz semanticka pravidla aplikovana v jine fazi, neni-liz pravda?
Zhruba řečeno ano, ale ne nutně, parserů existuje hromada a některé jsou kontextové, ještě než se začne řešit sémantika. Někdy to jsou spíše anomálie.