From 59ee138e8b854cdc8cbff03164f75a9ae050339e Mon Sep 17 00:00:00 2001 From: grammarware Date: Thu, 3 Feb 2011 15:36:31 +0000 Subject: [PATCH] unbreaking the Rascal extractor; multiple Halstead metrics git-svn-id: https://slps.svn.sourceforge.net/svnroot/slps@937 ab42f6e0-554d-0410-b580-99e487e6eeb2 --- shared/python/metrics.py | 54 ++++++++++++++++--- topics/extraction/rascal/Makefile | 6 ++- topics/extraction/rascal/extract.py | 22 +++++++- topics/extraction/rascal/horizontalize.xbgf | 57 --------------------- topics/investigation/complexity/Makefile | 6 +++ topics/investigation/complexity/hal.py | 2 +- 6 files changed, 77 insertions(+), 70 deletions(-) diff --git a/shared/python/metrics.py b/shared/python/metrics.py index 1a0bdea7..332bfd9f 100755 --- a/shared/python/metrics.py +++ b/shared/python/metrics.py @@ -248,7 +248,7 @@ def mccabe(node): elif node.__class__.__name__ in ('Terminal','Nonterminal','Epsilon','Any','Empty','Value'): return 0 elif node.__class__.__name__ == 'Choice': - return len(node.data)-1 + max(map(mccabe,node.data)) + return len(node.data)-1 + sum(map(mccabe,node.data)) elif node.__class__.__name__ == 'Sequence': return sum(map(mccabe,node.data)) else: @@ -371,12 +371,50 @@ def allOperators(node): print 'How to deal with',node.__class__.__name__,'?' return 0 -def HAL(g): +# Halstead preparations +def hal_mu1(g): + # Number of unique operators # Selectable, Marked, Plus, Star, Optional, Epsilon, Empty, Any, Choice, Sequence #mu1 = 10 - mu1 = len(allOperators(g)) - mu2 = VAR(g) + TERM(g) + VAL(g) + LAB(g) - eta1 = opr(g) - eta2 = opd(g) - hal = (mu1*eta2*(eta1+eta2)*math.log(mu1+mu2,2)) / (2*mu2) - return int(round(hal)) + return len(allOperators(g)) +def hal_mu2(g): + # Number of unique operands + return VAR(g) + TERM(g) + VAL(g) + LAB(g) +def hal_eta1(g): + # Total occurrences of operators + return opr(g) +def hal_eta2(g): + # Total occurrences of operands + return opd(g) + +# HALEN - Halstead length +def HALEN(g): + eta1 = hal_eta1(g) + eta2 = hal_eta2(g) + hal = eta1 + eta2 + return hal + +# HAVOC - Halstead vocabulary +def HAVOC(g): + mu1 = hal_mu1(g) + mu2 = hal_mu2(g) + hal = mu1 + mu2 + return hal + +# HAVOL - Halstead volume +def HAVOL(g): + hal = HALEN(g)*math.log(HAVOC(g),2) + return hal + +# HADIF - Halstead difficulty +def HADIF(g): + mu1 = hal_mu1(g) + mu2 = hal_mu2(g) + eta2 = hal_eta2(g) + hal = (mu1*eta2) / (2.0*mu2) + return hal + +# HADIF - Halstead effort +def HAEFF(g): + hal = HADIF(g)*HAVOL(g) + return hal diff --git a/topics/extraction/rascal/Makefile b/topics/extraction/rascal/Makefile index af785739..72d13303 100644 --- a/topics/extraction/rascal/Makefile +++ b/topics/extraction/rascal/Makefile @@ -2,15 +2,17 @@ all: echo 'Extracting the actual grammar...' ./extract.py RascalRascal.rsc rascal.bgf ../../../shared/tools/validate bgf rascal.bgf - ../../../shared/tools/subgrammar rascal.bgf Module rascal.true.bgf + ../../../shared/tools/subgrammar rascal.bgf Module PreModule Command rascal.true.bgf ../../../shared/tools/validate bgf rascal.true.bgf ../../../shared/tools/bgf2bnf rascal.bgf rascal.bnf ../../../shared/tools/bgf2bnf rascal.true.bgf rascal.true.bnf ../../../shared/tools/bgf2html rascal.true.bgf rascal.true.html + +hor: echo 'Recovering the horizontal grammar...' ../../../shared/tools/xbgf horizontalize.xbgf rascal.bgf rascal.hor.bgf ../../../shared/tools/validate bgf rascal.hor.bgf - ../../../shared/tools/subgrammar rascal.hor.bgf Module rascal.true.hor.bgf + ../../../shared/tools/subgrammar rascal.hor.bgf Module PreModule Command rascal.true.hor.bgf ../../../shared/tools/validate bgf rascal.true.hor.bgf ../../../shared/tools/bgf2bnf rascal.hor.bgf rascal.hor.bnf ../../../shared/tools/bgf2bnf rascal.true.hor.bgf rascal.true.hor.bnf diff --git a/topics/extraction/rascal/extract.py b/topics/extraction/rascal/extract.py index 0d5302dd..8410c0a4 100755 --- a/topics/extraction/rascal/extract.py +++ b/topics/extraction/rascal/extract.py @@ -46,6 +46,13 @@ def parseGroup(g): print '['+str(cx)+']','Found first line, but of what nonterminal?' continue tokens = line[1:].split() + if len(tokens[-1])>1 and tokens[-1][-1] == ';': + tokens[-1] = tokens[-1][:-1] + tokens.append(';') + for i in range(0,len(tokens)): + if tokens[i].find('[')>-1 and tokens[i].find(']')>-1: + # treating a parametrised nonterminal as a base nonterminal + tokens[i] = tokens[i][:tokens[i].index('[')] + tokens[i][tokens[i].index(']')+1:] grammar[nt].append(tokens) continue elif line[0] == '#': @@ -73,6 +80,9 @@ def parseGroup(g): print '['+str(cx)+']','Cannot include lexical restriction information about',nt nt = '' continue + if nt.find('[')>-1 and nt.find(']')>-1: + # treating a parametrised nonterminal as a base nonterminal + nt = nt[:nt.index('[')] + nt[nt.index(']')+1:] print '['+str(cx)+']','Starting to treat nonterminal',nt grammar[nt] = [] continue @@ -101,11 +111,19 @@ def parseGroup(g): prod.setNT(nt) while alt and alt[0] in ('bracket','left','right','non-assoc','lex','(',')'): print 'Skipped a modifier',alt[0],'at',nt - alt = alt[1:] + if alt[0] == 'lex': + alt = [] + else: + alt = alt[1:] if not alt: continue - if alt[-1] == ';': + while len(alt)>0 and alt[-1] in (';',''): alt = alt[:-1] + while len(alt)>0 and alt[0] == '': + alt = alt[1:] + #print '---',alt + if not alt: + continue if alt[0][-1] == ':': prod.setLabel(alt[0][:-1]) alt = alt[1:] diff --git a/topics/extraction/rascal/horizontalize.xbgf b/topics/extraction/rascal/horizontalize.xbgf index a127da84..ed0116e9 100644 --- a/topics/extraction/rascal/horizontalize.xbgf +++ b/topics/extraction/rascal/horizontalize.xbgf @@ -12,18 +12,12 @@ BasicType - - BooleanLiteral - Case Catch - - Char - CharClass @@ -42,27 +36,12 @@ Command - - Comment - - - CommentChar - Comprehension - - DatePart - DateTimeLiteral - - DecimalIntegerLiteral - - - DecimalLongLiteral - Declaration @@ -90,9 +69,6 @@ Kind - - LAYOUT - LanguageAction @@ -105,15 +81,6 @@ LongLiteral - - Name - - - NamedRegExp - - - OctalEscapeSequence - Parameters @@ -147,36 +114,21 @@ RascalReservedKeywords - - RealLiteral - Replacement ShellCommand - - ShortChar - Signature - - SingleQuotedStrChar - Statement - - StrChar - Strategy - - StringCharacter - StringLiteral @@ -201,18 +153,9 @@ Tag - - TagChar - Test - - TimePartNoTZ - - - TimeZonePart - Type diff --git a/topics/investigation/complexity/Makefile b/topics/investigation/complexity/Makefile index 1984db02..04915b1f 100644 --- a/topics/investigation/complexity/Makefile +++ b/topics/investigation/complexity/Makefile @@ -3,5 +3,11 @@ test: cp ../../convergence/java/snapshot/*.bgf tests/ ls -1 tests/*.bgf | xargs -n1 ./testperform +check: + bgf2bnf tests/antlr.bgf + ./mcc.py tests/antlr.bgf + xbgf horizontalize.xbgf tests/antlr.bgf antlrh.bgf + bgf2bnf antlrh.bgf + ./mcc.py antlrh.bgf clean: rm -f tests/*.bgf tests/*.out \ No newline at end of file diff --git a/topics/investigation/complexity/hal.py b/topics/investigation/complexity/hal.py index 590d9503..93b8a990 100755 --- a/topics/investigation/complexity/hal.py +++ b/topics/investigation/complexity/hal.py @@ -13,5 +13,5 @@ sys.exit(1) bgf = BGF.Grammar() bgf.parse(sys.argv[1]) - print metrics.HAL(bgf) + print int(round(metrics.HAEFF(bgf))) sys.exit(0)