mirror of
https://github.com/mudabbir-ahmad/UNI-PROG3-CW2-DYOPL.git
synced 2026-10-07 20:00:20 +00:00
Q2 done?! maybe
This commit is contained in:
1 parent
d20c595e0f
commit
c76af24421
6 files changed
+116
-55
No files matched your search
@@ -20,4 +20,8 @@ repeatStat: 'REPEAT' NUMBER '{' stat+ '}' ;
|
||||
ID_PREFIX: '// STUDENT ID:' ;
|
||||
NUMBER: [0-9]+ ;
|
||||
STRING: '"' .*? '"' ;
|
||||
WS: [ \t\r\n]+ -> skip ;
|
||||
WS: [ \t\r\n]+ -> skip ;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,4 +36,8 @@ class RobotLangVisitorUser(RobotLangVisitor):
|
||||
for _ in range(times):
|
||||
for stat_ctx in ctx.stat():
|
||||
self.visit(stat_ctx)
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Binary file not shown.
+27
-27
@@ -1,62 +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
|
||||
// the labels might clash with rule names, so I make them unique
|
||||
stat: assignment # statAssignment
|
||||
| fcList # statFcList
|
||||
| fcApplySelector # statFcApplySelector
|
||||
| message # statMessage
|
||||
;
|
||||
|
||||
assignment :
|
||||
ID '=' expression ;
|
||||
|
||||
ID '=' expression;
|
||||
|
||||
// when alternatives are introduced, try using labels to distinguish
|
||||
expression :
|
||||
ID # exprID
|
||||
|
|
||||
selCreation # exprSelCreation
|
||||
|
|
||||
fcCreation # exprFcCreation
|
||||
expression : ID # exprID
|
||||
| selCreation # exprSelCreation
|
||||
| fcCreation # exprFcCreation
|
||||
;
|
||||
// -------
|
||||
// filecollection statements
|
||||
// filecollection statements
|
||||
// -------
|
||||
fcCreation: fcCreationName '(' rootSpecifier ')' ;
|
||||
|
||||
fcCreationName: 'FileCollection' ;
|
||||
rootSpecifier: STRING ;
|
||||
// -------
|
||||
// selector statements
|
||||
// selector statements
|
||||
// -------
|
||||
selCreation : selCreationName '(' filterSpecifier ')' ;
|
||||
selCreation : selCreationName '(' testexpression ')' ;
|
||||
selCreationName: 'Selector' ;
|
||||
|
||||
selCreationName: 'Selector' ;
|
||||
filterSpecifier: selfilter '(' STRING ')' ;
|
||||
selfilter: 'name' ;
|
||||
testexpression : testunit (testoperator testunit)* ;
|
||||
|
||||
testoperator: 'intersect' #testoperatorIntersect ;
|
||||
|
||||
testunit: 'name' '(' STRING ')' #testunitname
|
||||
| 'size' '(' STRING ')' #testunitsize
|
||||
| 'type' '(' STRING ')' #testunittype
|
||||
| 'date' '(' STRING ')' #testunitdate
|
||||
| '(' testexpression ')' #testunittestexpression
|
||||
| 'not' '(' testexpression ')' #testunitnottestexpression ;
|
||||
// -------
|
||||
// apply statement
|
||||
// apply statement
|
||||
// -------
|
||||
fcApplySelector: ID '.' applyName '(' expression ')' ;
|
||||
|
||||
applyName: 'apply' ;
|
||||
// -------
|
||||
// print statement
|
||||
// print statement
|
||||
// -------
|
||||
fcList: ID '.' printName ;
|
||||
|
||||
fcList: ID '.' printName ; // fc.print()
|
||||
printName: 'print()' ;
|
||||
// -------
|
||||
// message statement
|
||||
// message statement
|
||||
// -------
|
||||
message: 'message' STRING ;
|
||||
|
||||
ID: [a-zA-Z][a-zA-Z0-9]* ;
|
||||
STRING: '"'.*?'"'
|
||||
{self.text = self.text[1:-1]} ;
|
||||
STRING: '"'.*?'"' {self.text = self.text[1:-1]} ;
|
||||
WS : [ \t\r\n]+ -> skip ;
|
||||
COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ;
|
||||
COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ;
|
||||
@@ -4,6 +4,7 @@ Parse and execute statements either in stdin or in file
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from antlr4 import *
|
||||
from fspowLexer import fspowLexer
|
||||
@@ -11,7 +12,7 @@ from fspowParser import fspowParser
|
||||
# from fspowListener import fspowListener
|
||||
# from antlr4.tree.Trees import Trees
|
||||
from TreesUser import TreesUser
|
||||
from Q2.Artefacts.fspowVisitorUser import fspowVisitorUser
|
||||
from fspowVisitorUser import fspowVisitorUser
|
||||
|
||||
|
||||
def main(argv):
|
||||
|
||||
@@ -1,36 +1,88 @@
|
||||
# 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 fspowParser import fspowParser
|
||||
from fspowVisitor import fspowVisitor
|
||||
|
||||
# our own imports:
|
||||
from repertoire.FileCollection import *
|
||||
from repertoire.Selector import *
|
||||
from repertoire.FSObject import *
|
||||
from repertoire.FileCollection import FileCollection
|
||||
from repertoire.Selector import Selector
|
||||
|
||||
# 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()
|
||||
def __init__(self):
|
||||
# Dictionary to track assigned variables during the AST walk
|
||||
self.variablesTable = {}
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
def visitMessage(self, ctx):
|
||||
# Quotes are already stripped by the inline lexer action
|
||||
print(ctx.STRING().getText())
|
||||
return self.visitChildren(ctx)
|
||||
|
||||
def visitFcCreation(self, ctx):
|
||||
root_name = self.visit(ctx.rootSpecifier())
|
||||
return FileCollection(root_name)
|
||||
|
||||
del fspowParser
|
||||
def visitRootSpecifier(self, ctx):
|
||||
return ctx.STRING().getText()
|
||||
|
||||
def visitAssignment(self, ctx):
|
||||
# Maps string identifiers to their evaluated backend objects
|
||||
var_id = ctx.ID().getText()
|
||||
self.variablesTable[var_id] = self.visit(ctx.expression())
|
||||
return True
|
||||
|
||||
def visitFcList(self, ctx):
|
||||
var_id = ctx.getChild(0).getText()
|
||||
if var_id in self.variablesTable:
|
||||
print(self.variablesTable[var_id].list())
|
||||
else:
|
||||
print(f"File collection {var_id} not found")
|
||||
|
||||
def visitFcApplySelector(self, ctx):
|
||||
fc_id = ctx.ID().getText()
|
||||
if fc_id in self.variablesTable:
|
||||
sel_id = ctx.expression().getText()
|
||||
if sel_id in self.variablesTable:
|
||||
self.variablesTable[fc_id].apply(self.variablesTable[sel_id])
|
||||
else:
|
||||
print(f"Selector {sel_id} not found")
|
||||
else:
|
||||
print(f"File collection {fc_id} not found")
|
||||
|
||||
def visitSelCreation(self, ctx):
|
||||
# Triggers the AST walk to process the complex filter expression
|
||||
return self.visit(ctx.testexpression())
|
||||
|
||||
def visitExprID(self, ctx):
|
||||
var_id = ctx.ID().getText()
|
||||
return self.variablesTable.get(var_id)
|
||||
|
||||
# --- Filter List ---
|
||||
|
||||
def visitTestexpression(self, ctx):
|
||||
# Dynamically builds the recursive list, encoding 'intersect' as 1
|
||||
expr_list = []
|
||||
for i in range(ctx.getChildCount()):
|
||||
child = ctx.getChild(i)
|
||||
if child.getText() == 'intersect':
|
||||
expr_list.append(1)
|
||||
else:
|
||||
expr_list.append(self.visit(child))
|
||||
return expr_list
|
||||
|
||||
def visitTestunitnottestexpression(self, ctx):
|
||||
# Appends -1 to mathematically encode the 'not' inversion
|
||||
return [-1, self.visit(ctx.testexpression())]
|
||||
|
||||
def visitTestunittestexpression(self, ctx):
|
||||
return self.visit(ctx.testexpression())
|
||||
|
||||
def visitTestunitname(self, ctx):
|
||||
return {"name": ctx.STRING().getText()}
|
||||
|
||||
def visitTestunitsize(self, ctx):
|
||||
return {"size": ctx.STRING().getText()}
|
||||
|
||||
def visitTestunittype(self, ctx):
|
||||
return {"type": ctx.STRING().getText()}
|
||||
|
||||
def visitTestunitdate(self, ctx):
|
||||
return {"date": ctx.STRING().getText()}
|
||||
Reference in new issue
Block a user