Upload
others
View
13
Download
0
Embed Size (px)
Citation preview
SVEUCILIŠTE U ZAGREBUFAKULTET ELEKTROTEHNIKE I RACUNARSTVA
ZAVRŠNI RAD br. 2372
Uporaba leksicke analize zadetekciju plagijata
Viktor Berger
Zagreb, lipanj 2012.
iii
SADRŽAJ
1. Uvod 1
2. Leksicka analiza 22.1. Uvod u leksicku analizu . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2. Zadaci leksickog analizatora . . . . . . . . . . . . . . . . . . . . . . 2
2.2.1. Citanje znakova izvornog programa . . . . . . . . . . . . . . 2
2.2.2. Odredivanje klasa leksickih jedinki . . . . . . . . . . . . . . 3
2.2.3. Razrješavanje nejednoznacnosti . . . . . . . . . . . . . . . . 3
2.3. Temeljne klase leksickih jedinki . . . . . . . . . . . . . . . . . . . . 4
2.3.1. Identifikatori . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3.2. Konstante . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3.3. Kljucne rijeci . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3.4. Operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3.5. Specijalni znakovi . . . . . . . . . . . . . . . . . . . . . . . 6
2.4. Strukture podataka . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4.1. Tablica uniformnih znakova . . . . . . . . . . . . . . . . . . 6
2.4.2. Tablica znakova . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4.3. Primjer rada leksickog analizatora . . . . . . . . . . . . . . . 8
3. Detekcija plagijata 113.1. Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2. Veza s leksickom analizom . . . . . . . . . . . . . . . . . . . . . . . 12
4. Programska implementacija 134.1. Struktura sustava . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2. Algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.1. Odredivanje klase leksicke jedinke . . . . . . . . . . . . . . . 16
4.2.2. Algoritmi za odredivanje slicnosti . . . . . . . . . . . . . . . 18
iv
4.3. Rezultati ispitivanja . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5. Dodatak A 26
6. Zakljucak 27
Literatura 28
v
1. Uvod
Jedan od problema akademskog racunarskog obrazovanja je kontrola plagiranja
izvornih tekstova programa. Taj problem se sastoji od filozofskih (odredivanje granice
slicnosti kodova koja odjeluje originale od plagijata) i tehnickih aspekata (izrada me-
toda i algoritama detekcije plagijata). U fokusu ovog rada nalazi se tehnicki aspekt
detekcije plagijata temeljen na leksickoj analizi izvornih kodova. Ta je metoda jedna
od faza rada jezicnih procesora i time zalazi u samu strukturu koda, cime omogucuje
dublju analizu slicnosti od izravne usporedbe cistog teksta programa (eng. plain text).
U nastavku rada pobliže je opisan postupak leksicke analize te nacin na koji on
doprinosi pronalaženju slicnosti izmedu kodova programa. Osim teorijskog dijela, rad
sadrži i programsku implementaciju sustava koji obnaša navedene dužnosti. Objašnjen
je i nacin na koji sustav radi te su prikazani rezultati rada. U fokusu sustava nalaze se
dva poznatija programska jezika: Java i C.
Iako je u fokusu rada leksicka analiza i usporeda tekstova programa na temelju
njenih rezultata, valja spomenuti i mogucnost nadogradnje implementiranog sustava u
vidu narednih faza rada jezicnog procesora. Sustav pruža uporište za razvoj i integra-
ciju daljnje sintaksne i semanticke analize koje ce omoguciti usporedbu kodova na još
dubljoj razini.
1
2. Leksicka analiza
2.1. Uvod u leksicku analizu
Jedno od podrucja kojima se bavi racunarska znanost je prevodenje programa.
Sustav koji je zadužen za prevodenje programa naziva se jezicni procesor. Leksicka
analiza prva je od tri faze rada jezicnog procesora. Podsustav jezicnog procesora koji
obavlja leksicku analizu programa je leksicki analizator. Faza koja neposredno slijedi
leksicku analizu je sintaksna analiza. Izlazni podaci koje generira leksicki analizator
koriste se u sintaksnoj analizi. Postoji mogucnost integracije leksicke i sintaksne ana-
lize u jednu programsku komponentu, ali fleksibilnost je veca ukoliko se one ostvare
odvojeno.
Slika 2.1: Veza leksickog i sintaksnog analizatora
2.2. Zadaci leksickog analizatora
2.2.1. Citanje znakova izvornog programa
Leksicka analiza jedina je faza rada jezicnog procesora u kojoj se izravno pris-
tupa znakovima teksta izvornog programa. Postoje dva nacina procesiranjava ulaznih
2
znakova. Prvi nacin je slijedno citanje znakova teksta izvornog programa, dok je drugi
nacin razdvajanje leksickih jedinki na temelju prekidnih znakova (bjeline, operatori,
znakovi interpunkcije). Znakovi koji nisu važni za daljnji rad jezicnog procesora poput
bjelina, tabulatora, znaka novog reda (LF), komentara, te znaka za povratak na pocetak
reda (CR), odbacuju se. Treba napomenuti kako je prvi nacin obrade opceprihvacen,
dok je drugi jednostavniji.
2.2.2. Odredivanje klasa leksickih jedinki
Središnji algoritam leksickog analizatora je algoritam odredivanja klasa leksickih
jedinki. Ukoliko je procitanom nizu znakova moguce odrediti klasu, on se grupira u
leksicku jedinku. Sve klase leksickih jedinki definirane su nizom pravila. Suština algo-
ritma odredivanja klasa leksickih jedinki je provjera tih pravila. Sintaksna pravila svih
poznatijih programskih jezika moguce je opisati regularnim izrazima. To za posljedicu
ima mogucnost izgradnje automata za provjeru pripadnosti leksickih jedinki. Leksicka
jedinka pripada onoj klasi cija pravila zadovoljava. Prilikom slijednog citanja, znakove
je moguce grupirati na razne nacine, što dovodi do nejednoznacnosti u postupku odre-
divanja klasa. Ako se nizu znakova ne može odrediti klasa, dolazi do pogreške. Jedan
od podzadataka leksickog analizatora oporavak je od takvih pogrešaka, u slucaju da je
to moguce. Nakon što su znakovi grupirani u jedinke, i klase su odredene, jedinke se
rasporeduju u pripadne tablice.
2.2.3. Razrješavanje nejednoznacnosti
Ako prilikom citanja i grupiranja znakova u leksicke jedinke dode do nejednoz-
nacnosti, odnosno, procitani niz znakova je moguce protumaciti na razlicite nacine,
analizator mora izabrati jedno od mogucih tumacenja. Nejednoznacnosti se mogu raz-
riješiti razlicitim algoritmima. Neki su: uporaba razlicitih znakova za višestruke opera-
tore, prenošenje svih mogucih interpretacija leksickih jedinki sintaksnom analizatoru,
dinamicka suradnja sintaksnog i leksickog analizatora, te ispitivanje šire okoline lek-
sicke jedinke. Posljednji nacin je i najjednostavniji. U suštini, leksicki analizator pri
tom postupku nejednoznacnost razrješava uzimanjem najduljeg moguceg podniza zna-
kova koji tvori smislenu leksicku jedinku.
3
2.3. Temeljne klase leksickih jedinki
U nastavku je prikazan kratki opis temeljnih klasa leksickih jedinki. Za svaku
leksicku jedinku izdvojeni su i pripadni primjeri u jezicima Java i C. Neke od osnovnih
klasa leksickih jedinki su:
– Identifikatori,
– Konstante,
– Kljucne rijeci,
– Operatori,
– Specijalni znakovi.
2.3.1. Identifikatori
Identifikatori su imena varijabli, polja, programa te potprograma. U svakom pro-
gramskom jeziku postoje tocno definirana pravila prema kojima se ta imena tvore.
U programskim jezicima C i Java vrijede jednaka pravila za tvorbu identifika-
tora. U njima identifikatori mogu sadržavati mala i velika slova, zamenke i podvlaku.
Na prvom mjestu mogu se nalaziti slovo ili podvlaka, ali ne i brojka, dok se na ostalim
mjestima mogu nalaziti i brojke. Oba programska jezika su osjetljiva na velicinu slova
(eng. case sensitive), tako da su primjerice nizovi znakova "VelikoSlovo" i "velikos-
lovo" tretirani kao razliciti identifikatori. U doljnjoj tablici prikazani su primjeri dobro
i loše oblikovanih identifikatora u programskim jezicima Java i C.
Tablica 2.1: Primjeri identifikatora
Dobro Loše Objašnjenje
first_instance_3 3_first_instance znamenka na prvom mjestu
_x my.variable nedopušteni znak – tocka
MyVariable my-Variable nedopušteni znak – povlaka
2.3.2. Konstante
Klasa leksickih jedinki pod imenom konstante predstavlja sve vrijednosti zapi-
sane izravno u tekstu izvornog programa. Konstante mogu biti cjelobrojne, s posmac-
4
nim zarezom, znakovne i sl.
C i java podržavaju iste vrste konstanti. Znakovne konstante oznacuju se jed-
nostrukim navodnicima. Znakovni nizovi(eng. string) oznacuju se dvostrukim navod-
nicima. Takoder, postoji i nekoliko vrsta brojevnih konstanti: cjelobrojne, brojevi s
pomicnim zarezom, heksadekadske, oktalne i binarne. Cjelobrojne konstante su naj-
jednostavnije i sastoje se iskljucivo od znamenki dekadskog sustava. Realni brojevi ili
brojevi s pomicnim zarezom osim znamenki sadrže i decimalnu tocku (zarez). Tako-
der mogu sadržavati i veliko ili malo slovo "e" nakon kojega slijedi eksponent. Oktalni
brojevi zapocinju nulom i sadrže znamenke od 0 do 8. Heksadekadski brojevi zapoci-
nju sa 0x i osim dekadskih znamenki sadrže i slova od a do f (velika ili mala). Zapis
binarnih brojeva pocinje sa 0b i sadrži znamenke 0 i 1. Primjeri svih konstanti dani su
u doljnjoj tablici.
Tablica 2.2: Primjeri konstanti
Vrsta konstante Primjeri
Znakovna ’a’, ’c’, ’?’
Znakovni niz "Što je danas lijep i suncan dan!"
Cjelobrojna 1,234,10000
Broj s pomicnom tockom 2.71, 3.14, 6.67
Oktalni broj 0332, 0773, 045
Heksadekadski broj 0x12, 0xABBA, 0x3ACDC
Binarni broj 0b110101, 0b00110011
2.3.3. Kljucne rijeci
Svaki programski jezik sadrži niz rezerviranih rijeci posebne namjene. Neke od
zadaca takvih rijeci su kontrola toka programa, oznacavanje struktura podataka, raz-
reda, alociranje memorije i sl. Skupovi kljucnih rijeci u obradenim programskim je-
zicima su razliciti. Dok se neke rijeci pojavljuju u oba programska jezika, druge su
specificne za samo jedan od ta dva jezika. Kompletni popisi kljucnih rijeci nalaze se u
dodatku A.
5
2.3.4. Operatori
Operatori predstavljaju znakove koji oznacavaju razne operacije nad varijablama
u programu. Postoji nekoliko vrsta operatora: aritmeticki, logicki i bitovni. U sljedecoj
tablici prikazani su neki od zajednickih operatora u Javi i C-u.
Tablica 2.3: Primjeri konstanti
Vrsta operatora Operatori
Aritmeticki + - ++ - - * / % += *= /= %=
Logicki && || ! < > == != >= <=
Bitovni « » & |
2.3.5. Specijalni znakovi
Znakovi koji imaju posebne zadace poput oznacavanja blokova koda, odvajanja
redaka, oznacavanja argumenata funkcija i sl. nazivaju se specijalni znakovi. Neki od
specijalnih znakova u prije spominjanim jezicima su: [ ] ( ) : . ; , ! ? itd.
2.4. Strukture podataka
Podaci koji se koriste i nastaju prilikom rada leksickog analizatora su tekst iz-
vornog programa, tablica uniformnih znakova, te tablica znakova. Tablicu znakova
efektivno se dijeli na tri manje cjeline: tablicu identifikatora, tablicu konstanti i tablicu
kljucnih rijeci, operatora i specijalnih znakova (KROS).
2.4.1. Tablica uniformnih znakova
Veza leksickog i sintaksnog analizatora ostvarena je tablicom uniformnih zna-
kova. Ta tablica sadrži uniformne znakove leksickih jedinki koje je generirao leksicki
analizator, kao i kazaljke na druge tablice . Uniformni znakovi su pohranjeni u redo-
sljedu pojavljivanja leksickih jedinki u izvornom program, cime je ocuvana struktura
programa. To je važno za ostale faze rada jezicnog procesora, pošto one nemaju direk-
tan pristup izvornom kodu programa. Postupak nastanka tablice uniformnih znakova
je sljedeci: Analizator odreduje klasu leksicke jedinke, zapisuje pripadni uniformni
znak u tablicu, te pretražuje tablice znakova kako bi mogao zabilježiti i kazaljku na tu
6
leksicku jedinku.
Za sintaksnu analizu, važno je moci razlikovati kljucne rijeci i posebne zna-
kove. S obzirom na to, postoje dva pristupa kodiranja uniformnih znakova. Prvi pristup
zahtjeva da svaki posebni znak (pod posebnim znakovima podrazumijevaju se i ope-
ratori) i kljucna rijec predstavlja sam sebe, dok drugi pristup svim posebnih zakovima
i kljucnim rijecima pridjeljuje isti mnemonik. Primjeri pristupa dani su u sljedecoj
tablici:
Tablica 2.4: Nacini zapisa uniformnih znakova
leksicka jedinka klasa leksicke jedinke 1. nacin zapisa 2. nacin zapisa
( Specijalni znak ( KROS
/= Operator /= KROS
if Kljucna rijec if KROS
else Kljucna rijec else KROS
MyInstance Identifikator ID ID
values Identifikator ID ID
3.14 Konstanta CON CON
2.4.2. Tablica znakova
Kao što je vec spomenuto, tablica znakova dijeli se na tri podtablice. Prva je
tablica identifikatora. U njoj su pohranjena sva imena varijabli, polja, programa i sl.
Struktura zapisa u tablici identifikatora prikazana je na slici ispod.
Slika 2.2: Zapis u tablici identifikatra
Iduca je tablica konstaniti. Struktura zapisa u tablici konstanti osim same kons-
tante, sadrži i dodatnu informaciju o vrsti konstante.
7
Slika 2.3: Zapis u tablici konstanti
Postoje dvije mogucnost za odabir oblika zapisa u tablici kljucnih rijeci, operatora
i specijalnih znakova. Prvi oblik je istovjetan obliku zapisa u tablici identifikatora i
sadrži konkretnu leksicku jedinku. Drugi oblik umjesto leksicke jedinke sadrži speci-
ficni uniformni znak (svojevrsno sažimanje zapisa, nije isto kao u tablici uniformnih
znakova), što rezultira složenijom izvedbom, ali i uštedom memorije.
2.4.3. Primjer rada leksickog analizatora
Iduci primjer prikazuje rezultat rada leksickog analizatora na konkretnom pro-
gramu pisanom u programskom jeziku Java. Konacni proizvod su strukture podataka
koje su opisane u prošlom odlomku.
c l a s s Razred {
p u b l i c s t a t i c vo id main ( S t r i n g a r g s [ ] ) {
i n t b r o j e v i [ ] ;
b r o j e v i = new i n t [ 1 0 ] ;
f o r ( i n t i = 0 ; i < 1 0 ; i ++){
b r o j e v i [ i ] = i +1 ;
}
}
}
Slika 2.4: Tekst primjera programa
Na slici 2.4 nalazi se izvorni tekst programa koji je predmet leksicke analize.
Zbog jednostavnosti uzet je manji program. Njegova je namjena alokacija polja od
10 cjelobrojnih vrijednosti i popunjavanje istog sa brojevima u rasponu od 1 do 10.
Slijedi prikaz tablica koje nastaju kao rezultat leksicke analize izvršene nad gornjim
programom.
8
Slika 2.5: Tablica uniformnih znakova
Na slici 2.5 je prikazana tablica uniformnih znakova. Prvi i treci stupac tablice
sadrže uniformne znakove, dok drugi i cetvrti stupac sadrže kazaljke na pozicije odgo-
varajucih znakova u drugim tablicama. Primjerice, ukoliko je uniformni znak sadržan
u prvom stupcu ID, a kazaljka u drugom stupcu broj 3, to znaci da se konkretna vrijed-
nost tog uniformnog znaka nalazi u tablici identifikatora na trecoj poziciji. Opcenito:
uniformni znak oznacuje tablicu koja se referencira, dok kazaljka pokazuje na poziciju
leksicke jedinke u toj tablici. Jednaka logika vrijedi i za preostale, uniformne znakove.
Usporedbom slike 2.4 i 2.5 zakljucuje se da je tablica uniformnih znakova popunja-
vana onim redoslijedom kojim je napisan i program. Dakle, ona sadržava informaciju
o strukturi programa koja je potrebna u daljnjim koracima rada jezicnog procesora.
9
Slika 2.6: Rašclanjena tablica znakova
Slika 2.6 prikazuje tri tablice koje sacinjavaju tablicu znakova. Lijeva gornja
tablica je tablica konstanti, ispod nje se nalazi tablica identifikatora, a s desne strane
je tablica kljucnih rijeci, operatora i specijalnih znakova (KROS). U stvarnosti, KROS
tablica je u potpunosti popunjena svim kljucnim rijecima, operatorima i specijalnim
znakovima jezika, no ovdje je prikazan samo dio koji se koristi u programu. Postupak
popunjavanja tablica je sljedeci. Leksicki analizator odreduje klasu leksicke jedinke,
pohranjuje njen uniformni znak na kraju tablice unifrmnih znakova i traži leksicku
jedinku u odgovarajucoj tablici. Ako leksicka jedinka ne postoji u odgovarajucoj ta-
blici, leksicki ju analizator dodaje u tu tablicu, te zapisuje njenu poziciju kao kazaljku
u tablici uniformnih znakova. Ukoliko leksicka jedinka postoji, u tablicu uniformnih
znakova uz pripadni uniformni znak se pohranjuje kazaljka na poziciju postojece lek-
sicke jedinke. Iz tablice uniformnih znakova i tablice znakova moguce je u potpunosti
replicirati strukturu programa.
10
3. Detekcija plagijata
3.1. Uvod
U današnje vrijeme plagiranje je postalo ozbiljan problem u procesu akademskog
racunarskog obrazovanja. Pojam plagijata oznacava rad koji je nastao ukljucivanjem
dijela ili cijelog rada druge osobe, bez navodenja originalnog autora. Ponekad je malo
teže odrediti granicu koja odjeljuje originalni rad od plagijata. Studenti se odlucuju
na plagiranje programskih kodova (prepisivanje uz odreden stupanj izmjena) iz raz-
licitih razloga, kako iz ljenosti, tako i zbog nedostatka vremena. Cilj nastavnika je
brinuti o tome da studenti steknu znanje samostalnim rješavanjem zadataka. U praksi,
taj se cilj ostvaruje provjerom slicnosti tekstova programa koja implicira na plagiranje
te odgovarajucom sankcijom kao protumjerom. Ako je broj studenata malen, rucno
odredivanje plagijata nije teško. Medutim, ako je broj studenata veci, rucno uspore-
divanje svih izvornih tekstova programa postaje znatan problem. Pošto covjek može
razmišljati apstraktno, relativno lako mu je vidjeti jesu li dva rada koje usporeduje pla-
gijati. Takav zadatak za racunala je malo teži. Razvijeni su razni algoritmi racunalne
usporedbe izvornih tekstova programa. Neki od tih algoritama se baziraju na tretiranju
izvornih tekstova programa kao obicnog teksta. Primjeri takvih algoritama su:
– K-Grami
– usporedba otisaka teksta (hash)
– Najdulji zajednicki podniz
– Najdulji zajednicki podslijed
– Racunanje udaljenosti nizova znakova
• Hammingova udaljenost
• Levensteinova udaljenost
• Damerau–Levensteinova udaljenost
11
Druga vrsta algoritama zalazi u strukturu programa na razlicitim razinama: Lek-
sickoj, sintaksnoj i semantickoj. Valja napomenuti da sve ove provjere ima smisla
provoditi samo na programima pisanim i istim programskim jezicima. U domeni pro-
grama napisanih u svrhu rješavanja akademskih zadataka, prepisivanje programa iz
jednog programskog jezika u drugi moguce je i zanemariti. Samim takvim cinom po-
drazumijeva se da student usput shvat io cemu se radi i posjeduje solidno znanje oba
programska jezika. Unatoc upitnoj moralnosti, takvi cinovi nisu u fokusu ovog rada.
3.2. Veza s leksickom analizom
Za razliku od prije navedenih algoritama koji tretiraju izvorni tekst programa kao
obican tekst, algoritam temeljen na leksickoj analizi zadire u strukturu programa. Lek-
sicka analiza omogucuje ocjenu slicnosti programa tako što stvara odredene tablice
s leksickim jedinkama. Te tablice služe kao temelj za usporedbu slicnosti programa.
Takva usporedba nosi odredenu dodatnu težinu u odnosu na tretiranje programa kao
cistog teksta. U usporedbu su implicitno ukljucene informacije o strukturi programa,
leksickim jedinkama koje su zajednicke usporedenim programima, kao i njihove klase.
12
4. Programska implementacija
Za implementaciju sustava odabran je programski jezik Java (jdk7) i korišteno je
razvojno okruženje Eclipse. U ovom poglavlju opisane su znacajke implementacije
konkretnog sustava. Objašnjen je koncept nacina rada sustava. Prikazana je struktura
sustava i dani su prijedlozi za njegovu daljnju nadogradnju.
4.1. Struktura sustava
Za bolje razumjevanje rada implementiranog sustava, dan je graficki prikaz i tek-
stualni opis.
Na slici 4.1 prikazan je dijagram sa najvažnijim razredima sustava i nekim od
njihovih metoda. Srž sustava cini razred LexicalAnalyzer. On obnaša vecinu prije
opisanih dužnosti leksickog analizatora s iznimkom ispravljanja pogrešaka. Za tom
dužnošcu nije bilo potrebe, jer se promatra samo skup funkcionalnih programa. Ne-
funkcionlani programi se uglavnom boduju s nula bodova. Prilikom instanciranja tog
razreda, na temelju ulazne datoteke s definicijom, odreduje se za koji ce programski
jezik instancirani razred biti namijenjen. Sustav u ovom stadiju namijenjen je analizi
programa pisanih u jezicima C i Java, iako je moguce analizirati i programe pisane u
jezicima sintakse slicne c-u. Glavna metoda ovog razreda je makeTokens. Njeno za-
duženje je slijedno citanje parsiranih leksickih jedinki i odredivanje njihovih razreda.
Kao ulaz ona prima izvorni tekst programa, koji potom razlaže, uklanja komentare
i razvrstava u tablicu znakova(koja se sastoji od tri prije spomenute podtablice) i ta-
blicu uniformnih znakova. U stvarnosti, tablice su izvedene kao mape oblika (leksicka
jedinka, broj pojavljivanja) s manjim varijacijama. Mapa identifikatora, mapa unifor-
mnih znakova,te mapa kljucnih rijeci, operatora i specijalnih znakova su organizirane
upravo tako. Za razliku od njih, mapa konstanti ima i dodatno polje koje sadrži infor-
maciju o vrsti konstante.
13
Slika 4.1: Dijagram razreda
Razred LexicalAnalyzer sadrži rezultate rada svoje glavne metode u inter-
nim strukturama podataka opisanim u prošlom odlomku. Radi lakše pohrane u bazu
podataka, razvijene su i metode koje prebacuju podatke u drugacije strukture i vracaju
ih kontekstu koji ih poziva. Dakle, omogucena je i trajna pohrana dobivenih rezultata,
što uklanja potrebu za opetovanom obradom jednom procesiranih tekstova programa.
Iz prijašnjih odlomaka posvecenih strukturama podataka leksickog analizatora, vid-
ljivo je da spomenute tablice imaju mogucnost proširenja u iducim koracima rada lek-
sickog analizatora. Programska implementacija ne odstupa od toga. Za pohranu redaka
tablice zadužen je razred TableRow prikazan na slici 4.2. On je svojevrstan omotac
oko polja stringova. Time omogucuje smještanje proizvoljnog broja informacija u reak
tablice. Takoder, sadrži i staticku metodu koja omogucuje spajanje tablica ucitanih iz
baze podataka u jednu kompaktnu tablicu znakova koja se koristi pri usporedbi.
14
Slika 4.2: Razred za pohranu retka tablice
Ucinkovito parsiranje izvornog teksta programskog koda izvedeno je razre-
dom Splitter. Razred LexicalAnalyzer koristi njegove usulge. Glavna metoda raz-
reda Splitter je split. Ona kao argumente prima string koji sadrži tekst programa koji
treba parsirati i string s regularnim izrazom na temelju kojega se ulazni tekst parsira.
Regularni izraz odreden je na temelju datoteke s definicijom programskog jezika (kon-
kretno, na temelju specijalnih znakova i operatora). Iz teksta programa koji je potrebno
parsirati, prije se moraju ukloniti komentari. Razred Splitter je razvijen zbog nedo-
voljnih mogucnosti zastarjelog razreda StringTokenizer.
Razred koji je zadužen za usporedbu tablica proizvedenih od strane razreda
LexicalAnalyzer je LexicalAnalysisCheck. On sadrži nekoliko metoda koje na
razlicite nacine daju ocjene slicnosti tablica leksema, odnosno, tablica uniformnih zna-
kova. Konceptualni opis implementiranih algoritama korištenih za usporedbu dan je u
iducem potpoglavlju.
Posljednji razred koji treba spomenuti je SourceCodeComparator. On ima
samo jednu staticku metodu koja je zadužena za testiranje rada razvijenih komponenti.
U suštini, implementirani sustav je zamišljen kao skup komponenti koje je moguce
ugraditi u neki veci sustav zadužen za leksicku analizu programskih kodova. Samim
time, nije razvijeno posebno korisnicko graficko sucelje. Umjesto toga testni razred
SourceCodeComparator obavlja ispis podataka na terminal.
15
4.2. Algoritmi
4.2.1. Odredivanje klase leksicke jedinke
Programski jezici Java i C sintaksno su vrlo slicni, što je omogucilo korištenje
istih automata unutar leksickog analizatora za analizu programskih kodova pisanih u
oba jezika. U nastavku su prikazani automati korišteni u sustavu.
Slika 4.3: Oktalni, heksadekadski, dekadski i binarni brojevi
Gornja slika prikazuje automate zadužene za prepoznavanje oktalnih, heksadekad-
skih, binarnih i cijelih brojeva. Najjednostavniji od njih s obzirom na broj stanja je
automat zadužen za prepoznavanje cijelih brojeva. Skup znakova koje on prihvaca sa-
drži dekadske znamenke. Automat koji prepoznaje oktalne brojeve u pocetnom stanju
prima samo znamenku 0, cime prelazi u iduce stanje. Iz srednjeg stanja u konacno sta-
nje prelazi nakon što primi znamenku iz raspona od 1 do 7. U konacnom stanju može
odmah završiti ili primati znamenke iz raspona od 0 do 7. Automat zadužen za hek-
sadekadske brojeve u pocetnom stanju prima znamenku 0, nakon toga veliko ili malo
slovo ’x’ nakon cega prihvaca sve heksadekadske znamenke (dekadske znamenke i
slova od a do f). Na slican nacin radi i automat koji prepoznaje dinarne brojeve. U
16
pocetnom stanju prihvaca samo znamenku 0, nakon toga slovo ’b’, a zatim jednu ili
više binarnih znamenki.
Slika 4.4: Brojevi s pomicnom tockom
Na gornjoj slici prikazan je automat namijenjem prepoznavanju brojeva s decimal-
nom tockom. Za razliku od prijašnjih automata, on je složeniji u smislu brojnosti
stanja i vrste automata. Prelazak iz pocetnog stanja uzrokuje primitak jedne od de-
kadskih znamenki. Nakon toga automat može prijeci u jedno od dva stanja ovisno o
iducem ulaznom znaku. Dedcimalna tocka uzrokuje prelazak u stanje q2 nakon kojeg
dekadska znamenka uzrokuje ulazak u konacno stanje. S druge strane primitak ma-
log ili velikog slova ’e’ u stanju q1 uzrokuje prijelazak u stanje q3. U njemu takoder
postoje dvije mogucnosti: predznak ili dekadska znamenka. Nakon predznaka mora
slijediti dekadska znamenka, koja vodi u konacno stanje. Nadalje, iz prvog konacnog
stanja primitkom malog ili velikog slova ’e’ prelazi se u stanje q3. U oba konacna sta-
nja automat ili završava rad odmah ili nastavlja primati dekadske znamenke. U suštini,
ovaj automat je zadužen za primanje decimalnih brojeva u zapisu sa ili bez eksponenta.
17
Slika 4.5: Znakovne konstante i znakovni nizovi
Slika prikazuje automate koji prepoznaju znakovne konstante i znakovne nizove.
Iz strukture, koja je jako slicna, vidljivo je da rade po približno istom principu. Dok
je prvi dopušteni znak automata za prepoznavanje znakovnih konstanti apostrof, kod
automata za prepoznavanje znakovnih nizova to su navodnici. Nakon toga prvi automat
prima jedan znak (dakle ne samo slova ili brojeve, nego bilo koji znak), dok drugi
prima niz znakova (jedan ili više). Oba automata rad završavaju u konacnom stanju
primitkom apostrofa, odnosno navodnika.
Slika 4.6: Identifikatori
Posljednja slika prikazuje automat za prepoznavanje identifikatora. Automat radi
prema definiciji tvorbe identifikatora u promatranim programskim jezicima. Na po-
cetku može primiti podvlaku, veliko ili malo slovo, dok u srednjem i konacnom stanju
osim toga može primati i dekadske znamenke.
4.2.2. Algoritmi za odredivanje slicnosti
U ovom potpoglavlju dana su tri prijedloga algoritama koji omogucuju usporebu
temeljenu na leksickoj analizi. Povratne vrijednosti algoritama su poopcene, odnosno,
18
svi algoritmi vracaju broj jednakih leksickih jedinki ili uniformnih znakova. Dakle,
radi se o apsolutnim ocjenama, koje u praksi nisu od prevelike koristi. Neki od pri-
jedloga za korekciju povratnih vrijednosti algoritama dani su u nastavku. Za relativnu
ocjenu slicnosti povratnu vrijednost algoritma moguce je podijeliti sa:
– brojem svih leksickih jedinki sadržanih u kracoj tablici znakova
– brojem svih leksickih jedinki sadržanih u duljoj tablici znakova
– aritmetickom sredinom broja leksickih jedinki sadržanih u obje tablice
– proizvoljnim težinskim faktorom
Takvim pristupom dobivamo odredene postotke slicnosti koji su realnija ocjena
slicnosti izvornih kodova usporedenih programa.
Usporedba tablica znakova
Ovaj algoritam radi na temelju informacija pohranjenih u tablicama koje su nas-
tale leksickom analizom izvornog teksta programa. Glavna ideja algoritma je prolazak
kroz tablice znakova dvaju procesiranih izvornih tekstova programa koji se usporeduju,
te pronalazak jednakih leksickih jedinki. U nastavku je dan sam algoritam.
Algorithm 1 Algoritam usporedbe tablica znakovaUlaz: LIST1 , LIST2 – liste koje sadrže retke tablice znakova
Izlaz: broj jednakih leksickih jedinki
m := length(LIST1)
n := length(LIST2)
similarity := 0
for (i := 0; i < m; inc(i)) dofor (j := 0; j < n; inc(j)) do
if LIST1i == LIST2j thensimilarity += min(LIST1i.occurences, LIST2j.occurences)
end ifend for
end forreturn similarity
Elementi lista koje se usporeduju su parovi oblika: (leksicka jedinka, broj pojav-
ljivanja). Svi elementi u listi su unikatni. Ideja na kojoj se temelji algoritam vrlo je
jednostavna: Uzima se prvi element prve liste i usporeduje se sa svim elementima u
19
drugoj listi, nakon toga se uzima drugi element prve liste, te se on usporeduje sa svim
elementima druge liste itd. Kada se elementi podudaraju (leksicke jedinke su jednake),
uzima se manji broj pojavljivanja elementa i dodaje se ukupnom broju jednakih lek-
sickih jedinki (similarity). Konkretna implementacija algoritma ostvarena je u metodi
checkLexemeSimilarity
Takva usporedba pronalazi iste leksicke jedinke bez obzirana njihovu stvarnu
poziciju unutar izvornih kodova programa. Dakle, ukoliko je jedan program nastao iz
drugoga samo promjenom redosljeda naredbi, sve leksicke jedinke tih dvaju programa
su ostale identicne. Usporedbom tablica znakova tih dvaju programa zakljucujemo da
su programi identicni. Ovakav slucaj može biti problematican. Iduci primjer pobliže
docarava takvu problematiku:
i n t main ( ) {
i n t a = 2 ;
i n t b = 3 ;
i n t c = 0 ;
c = a + b ;
c ∗= a ;
re turn 0 ;
}
i n t main ( ) {
i n t a = 2 ;
i n t b = 3 ;
i n t c = 0 ;
c ∗= a ;
c = a + b ;
re turn 0 ;
}
Slika 4.7: Primjer slicnih programa
Gornji primjer prikazuje kodove dvaju programa u programskom jeziku C,
cije tablice znakova sadrže identicne leksicke jedinke. Unatoc tome, zbog razlicitog
redosljeda naredbi u programima, njihovi rezultati ce biti razliciti. Prema tome, mo-
žemo zakljuciti da programi imaju razlicite zadatke, dok usporedba na temelju tablica
znakova govori kako su programi identicni. Upravo zbog toga, ovaj algoritam ne treba
uzimati kao apsolutnu ocjenu slicnosti izvornih kodova programa i programe cija je
slicnost ocijenjena velikom ocjenom, trebalo bi dodatno rucno pregledati.
Usporeba tablica uniformnih znakova
U samoj srži, ovo je primjena prijašnjeg algoritma na drugoj tablici. Ovaj algo-
ritam daje ocjenu slicnosti na temelju klasa leksickih jedinki za razliku od prijašnjeg
20
koji usporeduje konkretne leksicke jedinke. Uniformni znakovi koji se pojavljuju u
tablici su: ID, CON i KROS. Zbog cinjenice da je broj uniformnih znakova u prosjec-
nom programu mnogo veci od broja njihovih klasa, ima smisla usporedivati programe
približno jednake duljine. Ako je tekst jednog programa znatno dulji ode teksta dru-
gog, gotovo je sigurno da ce tablica uniformnih znakova kraceg programa biti podskup
tablice uniformnih znakova duljeg programa. Algoritam je implementiran metodom
checkUniformTableSimilarity. Razlike izmedu ovog i prijašnjeg algoritma su mi-
nimalne:
Algorithm 2 Algoritam usporedbe tablica uniformnih znakovaUlaz: LIST1 , LIST2 – liste koje sadrže retke tablice uniformnih znakova
Izlaz: broj jednakih uniformnih znakova
m := length(LIST1)
n := length(LIST2)
similarity := 0
for (i := 0; i < m; inc(i)) dofor (j := 0; j < n; inc(j)) do
if LIST1i == LIST2j thensimilarity += 1
del(LIST1i)
del(LIST2j)
end ifend for
end forreturn similarity
Težinska usporedba tablica znakova na temelju tablica uniformnih znakova
Ideja ovog algoritma je uzeti u obzir i strukturu programa, a ne samo konkretne
znakove koje sadrže pripadne tablice. Prednost ovog algoritma je ta što u usporedbi
koristi dodatnu informaciju o strukturi programa. Nažalost, ista stvar može biti i mana
algoritma. Ukoliko se usporeduju kopije izvornih tekstova programa, algoritam ce dati
stopostotnu slicnost. Medutim, ubaci li se u jedan od izvornih tekstova programa samo
jedan dodatni redak koda dok ostali ostaju identicni, algoritam ce dati znatno manju
ocjenu slicnosti od stvarne. Algoritam prolazi kroz uniformne tablice programa re-
ferencirajuci pripadne tablice znakova. Referencirani leksemi na istim pozicijama u
21
uniformnim tablicama se potom usporeduju. U stvarnom programskom sustavu, ta-
blica uniformnih znakova je zbog jednostavnosti izvedena kao lista koja sadrži parove
(uniformni znak, leksem), tako da je izvedba ovog algoritma trivijalna. Ovaj algoritam
implementiran je metodom checkStructureSimilarity.
Algorithm 3 Algoritam težinske usporedbe tablica uniformnih znakovaUlaz: LIST1 , LIST2 – liste koje sadrže retke tablice uniformnih znakova
Izlaz: broj jednakih uniformnih znakova
m := minlength(LIST1,LIST2)
similarity := 0
for (i := 0; i < m; inc(i)) doif LIST1i.leksem == LIST2i.leksem then
similarity += 1
end ifend forreturn similarity
4.3. Rezultati ispitivanja
U ovom potpoglavlju prikazani su i analizirani rezultati rada opisanih algoritama
na skupu izvornih tekstova programa. Fragmenti rezultata provedenih testiranja prika-
zani su slikama. Pošto se usporedba provodi na nacin da se datoteke usporeduju svaka
sa svakom, broj podataka je velik. Upravo to je razlog prikazivanja samo malog infor-
mativnog podskupa podataka. Tablice koje sadrže rezultate ispitivanja formirane su na
sljedeci nacin: prvi redak sadrži informacije vezane za izvorni tekst programa s kojim
se usporeduju svi ostali, dok su podaci dobiveni usporedbom navedeni u ostalim ret-
cima tablice. Prvi stupac tablice sadrži imena datoteka nad kojima se vrši usporedba,
iduci stupci redom sadrže: ukupne brojeve leksema, jednakih leksema, identifikatora,
konstantni, te kljucnih rijeci, operatora i specijalnih znakova. Zadnja tri stupca sadrže
informacije o slicnosti datoteka koje su dali pojedini algoritmi. Pošto se sve ostale
datoteke usporeduju datotekom u prvom retku, prvi redak ne sadrži podatke o slic-
nosti. Sve slicnosti su u rasponu od 0.00 do 1.00. Brojnost leksickih jedinki s obzirom
na njihove klase dana je radi boljeg uvida u strukturu usporedivanih izvornih tekstova
programa.
22
Pojašnjenje tablicnih oznaka algoritama dano je u nastavku:
alg1: Algoritam usporedbe tablica znakova.
alg2: Algoritam usporedbe tablica uniformnih znakova.
alg3: Algoritam težinske usporedbe tablica uniformnih znakova.
Na iducoj slici je prikazan prvi fragment rezultata ispitivanja izvršenih nad
skupom od 30 datoteka s izvornim tekstovima programa napisanih u programskom
jeziku C.
Slika 4.8: Prvi fragment ispitnih rezultata
Iz rezultata je vidljivo da postoje prilicno velike varijacije u brojevima iden-
ticnih leksema. Takvi rezultati su i ocekivani s obzirom na skup testnih podataka.
Neke datoteke su identicne, u nekima su mijenjani komentari, dok su druge razlicite
i po svim ostalim znacajkama. Unatoc tome, nemoguce je postojanje potpuno razli-
citih programa. Svaki program ima glavnu (eng. main) metodu, kao i kljucne rijeci,
23
operatore i specijalne znakove svojstvene programskom jeziku u kojemu je pisan. Da
bi prikazani rezultati bili jasniji, potrebno je detaljno razmotriti postotke slicnosti koje
su davali pojedini algoritmi s obzirom na ukupni broj leksema pojedinih programa,
te brojnosti leksema po klasama. Stvar koja je najlakša za uociti je slicnost u stupcu
alg2. To je algoritam cija je zadaca usporedba tablica uniformnih znakova pojedinih
programa. Vidljivo je da su apsolutno sve slicnosti jednake 1. Razlog tome je sljedeci:
manje tablice uniformnih znakova sadrže podskupove uniformnih znakova sadržanih u
vecim tablicama. Iz toga proizlazi da algoritam ne daje korisnu informaciju o slicnosti
izvornih tekstova programa u praksi.
Iz rezultata vezanih uz datoteku pod imenom mn40240.c vidljivo je da slic-
nost dobivena prvim algoritmom (alg1) relativno velika (0.74). Prva datoteka sadrži
132 identifikatora, 50 konstanti i 328 kljucnih rijeci, operatora i specijalnih znakova,
od kojih je u drugoj datoteci identicnih 23 identifikatora, 8 konstanti i 136 kljucnih
rijeci, operatora i specijalnih znakova. Na prvi pogled, tolika slicnost djeluje kao po-
greška, no uzmemo li u obzir da se slicnost racuna na nacin da se broj istih leksema
podijeli sa ukupnim brojem leksema manje datoteke, rezultat postaje sasvim ocekivan.
Opisani rezultati vezani su uz algoritam usporedbe leksickih jedinki, koji je ujedno i
najefikasniji od ispitivanih algoritama.
Drugi redak tablice pokazuje stopostotnu slicnost datoteke ab39352_1.c s da-
totekom u prvom retku. Lako je zakljuciti da su datoteke identicne s obzirom da su
rezultati svih algoritama jednaki 1. U trecem retku dogada se nešto zanimljivo. Slic-
nost koju daje prvi algoritam izuzetno je visoka (0.99), dok je slicnost dobivena trecim
algoritmom (Algoritam težinske usporedbe tablica uniformnih znakova) drasticno pala
(0.14). Da bi rezultate bilo moguce shvatiti treba se sjetiti da je to algoritam koji u ob-
zir u odredenoj mjeri uzima i strukturu programa. On prati iste leksicke jedinke dok ne
naide na prvu razlicitu. Tada svaka slicnost prestaje. S tim znanjem lako je zakljuciti
da je datoteka u drugom retku ocito potpuno identicna prvoj datoteci, dok se u drugoj
datoteci negdje na pocetku dogodila mala promjena. Nekoliko je mogucnosti: ubacen
je potpuno novi redak, promijenjen je neki identifikator ili je zamijenjen redosljed na-
redbi. U svakom slucaju, mala strukturna promjena na pocetku datoteke uzrokovala je
drastican pad slicnosti dobivene trecim algoritmom.
24
Prethodna analiza podataka dobivenih ispitivanjem rada algoritama navodi na niz za-
kljucaka. Algoritam koji odreduje slicnost na temelju broja jednakih leksickih jedinki
je najkorisniji i ima najvecu vjerodostojnost. Drugi algoritam(alg2), koj odreduje slic-
nost na temelju broja istih uniformnih znakova je prakticki beskoristan u praksi s ob-
zirom da je slicnost koju daje cijelo vrijeme jednaka 1. Treci algoritam koji osim
broja jednakih leksickih jedinki u obzir uzima i njihov poredak, koristan je u kombi-
naciji s prvim algoritmom jer pruža dodatnu informaciju o nacinu na koji je došlo do
eventualnog plagiranja bez da se mora gledati sam tekst izvornog programa. Unatoc
tome, trecem algoritmu kao samostalnom ne bi trebalo davati veliku vjerodostojnost s
obzirom na nacin na koji odreduje slicnost.
25
5. Dodatak A
Kljucne rijeci programskog jezika java:
– abstract
– boolean
– break
– byte
– case
– catch
– char
– class
– const
– continue
– default
– do
– double
– else
– extends
– false
– final
– finally
– float
– for
– goto
– if
– implements
– import
– instanceof
– int
– interface
– long
– native
– new
– null
– package
– private
– protected
– public
– return
– short
– static
– super
– switch
– synchronized
– this
– throw
– throws
– transient
– true
– try
– void
– volatile
– while
Kljucne rijeci programskog jezika c:
– auto
– break
– case
– char
– const
– continue
– default
– do
– double
– else
– enum
– extern
– float
– for
– goto
– if
– int
– long
– register
– return
– short
– signed
– sizeof
– static
– struct
– switch
– typedef
– union
– unsigned
– void
– volatile
– while
26
6. Zakljucak
Detekcija plagijata programskih kodova u današnje je vrijeme prijeko potrebna. Kako se
razmjer tog problema povecava ocita je potreba za kvalitetnom automatizacijom tog zadatka u
vidu programske podrške. Algoritmi zaduženi za pronalazak slicnosti izvornih tekstova pro-
grama su raznoliki i pokrivaju razne poglede na programski kod. Neki ga uzimaju kao cisti
tekst i manipuliraju njime na razini znakova i nizova znakova, dok drugi zalaze u njegovu
strukturu. Naravno, rezultati razlicitih algoritama imaju razlicite važnosti. Neki su znacajniji
od drugih.
Iako algoritam temeljen na leksickoj analizi zalazi u strukturu programskog koda, što bi
naznacavalo vecu važnost, rezultate koje on daje ne bi trebalo uzimati kao apsolutno ispravnu
ocjenu slicnosti. Umjesto toga, Rezultati algoritma temeljenog na leksickoj analizi bolje je
koristiti u vecim sustavima za detekciju plagijata kao jednu od komponenti ukupne ocjene
slicnosti. Mogucnosti uporabe ovakve metode detekcije plagijata su velike. Osim što sama daje
rezultate odredene vjerodostojnosti, ona služi i kao temelj za analizu programa na još dubljim
razinama – sintaktickoj i semantickoj. Takvim nadogradnjama sustavi koji koriste spomenutu
metodu postaju još mocniji u svojoj namjeni. Dakle, leksicka analiza je dobar izbor i temelj za
kvalitetan sustav za detekciju plagijata izvornih tekstova programa.
27
LITERATURA
A. Baotic. Otkrivanje slicnosti u izvornim tekstovima programa. diplomski rad, Sveucilište u
Zagrebu, Fakultet elektrotehnike i racunarstva, rujan 2011.
X. Chen, B. Francia, M. Li, B. McKinnon, i Seker A. Shared information and program plagi-
arism detection. IEEE Transactions on Information Theory, 50(7), srpanj 2004.
K. Cooper i L. Torczon. Engineering a Compiler. Morgan Kaufmann, 2003.
M. Johnson, J. Zelenski. Lexical analysis, lipanj 2008. URL dragonbook.stanford.
edu/lecture-notes/Stanford-CS143/03-Lexical-Analysis.pdf.
B. Karthikeyan, V. Vaithiyanathan, i Lavanya C.V. Similarity detection in source code using
data mining techniques. European Journal of Scientific Research, (4), 2011.
S. Srbljic. Prevodenje programskih jezika, svezak I. Element Zagreb, 2009.
28
Uporaba leksicke analize za detekciju plagijata
Sažetak
U radu je obradena ideja uporabe leksicke analize u detekciji plagijata izvornih kodova
programa. U kratkim crtama je objašnjen nacin rada leksickog analizatora. Prikazana je veza
izmedu leksicke analize i detekcije plagijata. Dani su prijedlozi algoritama koji pronalaze
slicnosti programskih kodova na temelju rezultata rada leksickog analizatora. Na kraju je dana i
implementacija sustava zaduženog za leksicku analizu i usporedbu izvornih tekstova programa.
Sustav je implementiran u programskom jeziku java, a namijenjen je leksickoj analizi programa
pisanih u Javi i C-u. Nad sustavom su obavljeni testovi, od kojih je manji podskup prikazan i
analiziran u radu.
Kljucne rijeci: Plagijati, detekcija plagijata, leksicka analiza, java, c, usporedba, izvorni tekst
programa, slicnost kodova
Lexical Analysis in Plagiarism Detection
Abstract
This paper covers the idea on the use of lexical analysis in detection of plagiarised pro-
gram source code. It briefly illustrates the lexical analyser’s method of operating and shows
the connection between lexical analysis and plagiarism detection. Important part of this pa-
per are suggestions for algorithms that would be able to detect similarities between program
source codes based on the results of the lexical analyser’s work. At the end it also shows the
implementation of the system that is in charge of the lexical analysis and comparison of the
program’s source codes. The system is implemented in Java programming language and is in-
tended for lexical analysis of programs written in Java and C. The system has been put through
several tests of which a small subset is illustrated and analysed in the paper.
Keywords: Plagiarism, lexical analysis, java, c, comparison, source code, code similarity,
similarity detection