diff --git a/Acknowledgement of GAI Contribution.docx b/Acknowledgement of GAI Contribution.docx new file mode 100644 index 0000000..6e77115 Binary files /dev/null and b/Acknowledgement of GAI Contribution.docx differ diff --git a/Q1/Artefacts/antlr4_parse_tree.png b/Q1/Artefacts/images_of_tree/antlr4_parse_tree.png similarity index 100% rename from Q1/Artefacts/antlr4_parse_tree.png rename to Q1/Artefacts/images_of_tree/antlr4_parse_tree.png diff --git a/Q1/Artefacts/antlr4_parse_tree.svg b/Q1/Artefacts/images_of_tree/antlr4_parse_tree.svg similarity index 100% rename from Q1/Artefacts/antlr4_parse_tree.svg rename to Q1/Artefacts/images_of_tree/antlr4_parse_tree.svg diff --git a/Q1/Q1.docx b/Q1/Q1.docx index c2e49ec..ac13580 100644 Binary files a/Q1/Q1.docx and b/Q1/Q1.docx differ diff --git a/Q2/Artefacts/TreesUser.py b/Q2/Artefacts/TreesUser.py new file mode 100644 index 0000000..20b0c79 --- /dev/null +++ b/Q2/Artefacts/TreesUser.py @@ -0,0 +1,27 @@ +from antlr4.Utils import escapeWhitespace +from antlr4.tree.Tree import Tree +from antlr4.tree.Trees import Trees + +# need forward declaration +Parser = None + +class TreesUser(Trees): + + # Print out a whole tree in prettier form + # Based on Trees.toStringTree() + # indent is the number of indents to use in the display + @classmethod + def PrettyPrint(cls, t:Tree, ruleNames:list=None, recog:Parser=None, indent:int=0): + # indentation is the indent to actually display + indentation = '' + for n in range(indent): + indentation += ' ' + if recog is not None: + ruleNames = recog.ruleNames + s = escapeWhitespace(cls.getNodeText(t, ruleNames), False) + retval = indentation + s + "\n" + if t.getChildCount()>0: + # we have children to deal with + for i in range(0, t.getChildCount()): + retval += cls.PrettyPrint(t.getChild(i), ruleNames, indent=indent+1) + return retval diff --git a/Q2/Artefacts/fspow.g4 b/Q2/Artefacts/fspow.g4 new file mode 100644 index 0000000..04d8936 --- /dev/null +++ b/Q2/Artefacts/fspow.g4 @@ -0,0 +1,62 @@ +grammar fspow; +// workshop 4 version + +prog: stat+ ; + +// labelling alternatives creates extra visitor methods +// the labels migh clash with rule names, so I make them unique +stat: + assignment # statAssignment + | fcList # statFcList + | fcApplySelector # statFcApplySelector + | message # statMessage + ; + +assignment : + ID '=' expression ; + +// when alternatives are introduced, try using labels to distinguish +expression : + ID # exprID + | + selCreation # exprSelCreation + | + fcCreation # exprFcCreation + ; +// ------- +// filecollection statements +// ------- +fcCreation: fcCreationName '(' rootSpecifier ')' ; + +fcCreationName: 'FileCollection' ; +rootSpecifier: STRING ; +// ------- +// selector statements +// ------- +selCreation : selCreationName '(' filterSpecifier ')' ; + +selCreationName: 'Selector' ; +filterSpecifier: selfilter '(' STRING ')' ; +selfilter: 'name' ; +// ------- +// apply statement +// ------- +fcApplySelector: ID '.' applyName '(' expression ')' ; + +applyName: 'apply' ; +// ------- +// print statement +// ------- +fcList: ID '.' printName ; + +printName: 'print()' ; +// ------- +// message statement +// ------- +message: 'message' STRING ; + +ID: [a-zA-Z][a-zA-Z0-9]* ; +STRING: '"'.*?'"' + {self.text = self.text[1:-1]} ; +WS : [ \t\r\n]+ -> skip ; +COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ; diff --git a/Q2/Artefacts/fspow.py b/Q2/Artefacts/fspow.py new file mode 100644 index 0000000..6e77c62 --- /dev/null +++ b/Q2/Artefacts/fspow.py @@ -0,0 +1,64 @@ +# main.py +""" +Parse and execute statements either in stdin or in file +""" + +import sys + +from antlr4 import * +from fspowLexer import fspowLexer +from fspowParser import fspowParser +# from fspowListener import fspowListener +# from antlr4.tree.Trees import Trees +from TreesUser import TreesUser +from Q2.Artefacts.fspowVisitorUser import fspowVisitorUser + + +def main(argv): + # argv[1] s/be name of source file + # if missing, use stdin + if len(argv) == 1: + # StdinStream is a standard ANTLR class read by the lexer + # (It is not a file descriptor) + inpstream = StdinStream() + else: + inpname = argv[1] + # FileStream is a standard ANTLR class read by the lexer + # (It is not a file descriptor) + inpstream = FileStream(inpname) + + + + # The lexer analyses the characters on inpstream and produces tokens + lexer = fspowLexer(inpstream) + # .. on the token stream (belonging to a standard ANTLR class) + tokstream = CommonTokenStream(lexer) + + # The parser produces an abstract syntax tree + parser = fspowParser(tokstream) + # When we execute the parse, we need to give it the starting rule of our grammar, + # which in our case is 'start' (as defined in fspow.g4), + # so here we invoke the method named after this rule: start() + tree = parser.prog() + + # print the parse tree + #print(TreesUser.toStringTree(tree, None, parser)) + print(TreesUser.PrettyPrint(tree, None, parser)) + + visitor = fspowVisitorUser() + visitor.visit(tree) + + # The listener defines the actions to take upon entering an exiting nodes for + # specific tokens on the AST + # listener = fspowListener() + + # A ParseTreeWalker is annother standard ANTLR class, that performs a walk on the AST + # walker = ParseTreeWalker() + + # Get the tree walker to perform a walk on the AST, getting the listener to perform + # the appropriate actions + # walker.walk~(listener, tree) + + +if __name__ == '__main__': + main(sys.argv) diff --git a/Q2/Artefacts/fspowVisitorUser.py b/Q2/Artefacts/fspowVisitorUser.py new file mode 100644 index 0000000..d53345d --- /dev/null +++ b/Q2/Artefacts/fspowVisitorUser.py @@ -0,0 +1,36 @@ +# Generated from fspow.g4 by ANTLR +from antlr4 import * +#from idlelib.idle_test.test_configdialog import root +if __name__ is not None and "." in __name__: + from .fspowParser import fspowParser +else: + from fspowParser import fspowParser + +# superclass +from fspowVisitor import fspowVisitor + +# our own imports: +from repertoire.FileCollection import * +from repertoire.Selector import * +from repertoire.FSObject import * + +# for symbol table +from collections import defaultdict + +# This class defines a complete specific visitor for a parse tree produced by fspowParser. + +class fspowVisitorUser(fspowVisitor): + + # where all the variables reside + variablesTable = defaultdict() + + + # just write methods to be overridden + # in future, may want to implement multiple subclasses + # but for now, I'd copy the ones I need to override here to implement them + + + +del fspowParser + + diff --git a/Q2/Artefacts/mincommands.txt b/Q2/Artefacts/mincommands.txt new file mode 100644 index 0000000..b003d11 --- /dev/null +++ b/Q2/Artefacts/mincommands.txt @@ -0,0 +1,15 @@ +message "Hello world!" +// wombats = FileCollection("wombats") +// wombats.print() +// hairies = Selector(name("hairy")) +// wombats.apply(hairies) +// the following not yet implemented +// wombats.apply(Selector(name(""))) +// wombats.print() +// marsupials = FileCollection("marsupials") +// marsupials.print() + + + + + diff --git a/Q2/Q2.docx b/Q2/Q2.docx index cdbbd6e..d0b040a 100644 Binary files a/Q2/Q2.docx and b/Q2/Q2.docx differ