Q2 done?! maybe

This commit is contained in:
bobbert committed 2026-04-28 20:06:29 +01:00
1 parent d20c595e0f
commit c76af24421
6 files changed
+102 -41

No files matched your search

+4
View File
@@ -21,3 +21,7 @@ ID_PREFIX: '// STUDENT ID:' ;
NUMBER: [0-9]+ ; NUMBER: [0-9]+ ;
STRING: '"' .*? '"' ; STRING: '"' .*? '"' ;
WS: [ \t\r\n]+ -> skip ; WS: [ \t\r\n]+ -> skip ;
+4
View File
@@ -37,3 +37,7 @@ class RobotLangVisitorUser(RobotLangVisitor):
for stat_ctx in ctx.stat(): for stat_ctx in ctx.stat():
self.visit(stat_ctx) self.visit(stat_ctx)
return None return None
BIN
View File
Binary file not shown.
+19 -19
View File
@@ -1,12 +1,10 @@
grammar fspow; grammar fspow;
// workshop 4 version
prog: stat+ ; prog: stat+ ;
// labelling alternatives creates extra visitor methods // labelling alternatives creates extra visitor methods
// the labels migh clash with rule names, so I make them unique // the labels might clash with rule names, so I make them unique
stat: stat: assignment # statAssignment
assignment # statAssignment
| fcList # statFcList | fcList # statFcList
| fcApplySelector # statFcApplySelector | fcApplySelector # statFcApplySelector
| message # statMessage | message # statMessage
@@ -16,12 +14,9 @@ assignment :
ID '=' expression; ID '=' expression;
// when alternatives are introduced, try using labels to distinguish // when alternatives are introduced, try using labels to distinguish
expression : expression : ID # exprID
ID # exprID | selCreation # exprSelCreation
| | fcCreation # exprFcCreation
selCreation # exprSelCreation
|
fcCreation # exprFcCreation
; ;
// ------- // -------
// filecollection statements // filecollection statements
@@ -33,22 +28,28 @@ 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 ')' ; fcApplySelector: ID '.' applyName '(' expression ')' ;
applyName: 'apply' ; applyName: 'apply' ;
// ------- // -------
// print statement // print statement
// ------- // -------
fcList: ID '.' printName ; fcList: ID '.' printName ; // fc.print()
printName: 'print()' ; printName: 'print()' ;
// ------- // -------
// message statement // message statement
@@ -56,7 +57,6 @@ printName: 'print()' ;
message: 'message' STRING ; message: 'message' STRING ;
ID: [a-zA-Z][a-zA-Z0-9]* ; ID: [a-zA-Z][a-zA-Z0-9]* ;
STRING: '"'.*?'"' STRING: '"'.*?'"' {self.text = self.text[1:-1]} ;
{self.text = self.text[1:-1]} ;
WS : [ \t\r\n]+ -> skip ; WS : [ \t\r\n]+ -> skip ;
COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ; COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ;
+2 -1
View File
@@ -4,6 +4,7 @@ Parse and execute statements either in stdin or in file
""" """
import sys import sys
import os
from antlr4 import * from antlr4 import *
from fspowLexer import fspowLexer from fspowLexer import fspowLexer
@@ -11,7 +12,7 @@ from fspowParser import fspowParser
# from fspowListener import fspowListener # from fspowListener import fspowListener
# from antlr4.tree.Trees import Trees # from antlr4.tree.Trees import Trees
from TreesUser import TreesUser from TreesUser import TreesUser
from Q2.Artefacts.fspowVisitorUser import fspowVisitorUser from fspowVisitorUser import fspowVisitorUser
def main(argv): def main(argv):
+73 -21
View File
@@ -1,36 +1,88 @@
# Generated from fspow.g4 by ANTLR
from antlr4 import * 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 from fspowParser import fspowParser
# superclass
from fspowVisitor import fspowVisitor from fspowVisitor import fspowVisitor
# our own imports: from repertoire.FileCollection import FileCollection
from repertoire.FileCollection import * from repertoire.Selector import Selector
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): class fspowVisitorUser(fspowVisitor):
def __init__(self):
# Dictionary to track assigned variables during the AST walk
self.variablesTable = {}
# where all the variables reside def visitMessage(self, ctx):
variablesTable = defaultdict() # 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)
# just write methods to be overridden def visitRootSpecifier(self, ctx):
# in future, may want to implement multiple subclasses return ctx.STRING().getText()
# but for now, I'd copy the ones I need to override here to implement them
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")
del fspowParser 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()}