Open chris7380 opened 8 months ago
You would need to edit Parser.case_stmt()
and create custom logic to figure out whether you have reached the end of the case branch (i.e. you've seen the start of the next branch, or TT.ENDCASE
), rather than the current solution, which looks for TT.BREAK
.
You may wish to look at Bow.Parser.EndofCaseBlock()
which is a very similar codebase. Here, it basically looks ahead to see if there is a sequence of Expression :
(denoting the start of the next branch). However, there's problem with the implementation, in that it doesn't actually match full expressions. It only matches individual literals and variables, meaning you can't have, for example a + 1 :
as your branch condition, just 1 :
, or a :
. It is probably possible try to match a full expression and then backtrack, so maybe look into that.
I'm sorry but how would i do this part
create custom logic to figure out whether you have reached the end of the case branch
You would need to replace the usage of stmt_block()
with your own function which looks ahead to see if there is either a new case branch starting (by looking for Expression :
or OTHERWISE :
), or the case statement is over by seeing ENDCASE
.
I try it to do that but i got unexpected token and sometimes i get CASE is missing error.
if you have the code to solve this issue, can you write it here.
I really appreciate your help. Thank you.
i tried to write it this way but i still get an error:
def case_stmt(self, line):
if not self.match([TT.OF]):
raise SyntaxError([self.peek().line, f"Expected 'OF' got '{self.peek().lexeme}'"])
line = self.previous().line
expr = self.expression(line)
cases = []
while True:
# allow an empty expression to check for OTHERWISE
value = self.expression(line, checkNone=False)
if value is None:
if self.peek().type != TT.OTHERWISE:
raise SyntaxError([line, "Missing expression while parsing CASE"])
else:
self.match([TT.OTHERWISE])
if not self.match([TT.COLON]):
raise SyntaxError([self.peek().line, f"expected a : got '{self.peek().lexeme}'"])
stmt_list = self.stmt_block([TT.OTHERWISE,TT.ENDCASE], line)
if value is None and not self.match([TT.OTHERWISE]):
raise SyntaxError([line, "OTHERWISE should be the last CASE value"])
cases.append((value, stmt_list))
if self.match([TT.ENDCASE]):
break
return CASE(expr, cases, line)
I get this error:
Missing expression while parsing CASE
when i remove the BREAK from the code.
You shouldn't need to edit that function other than changing the line assigning to stmt_list
. You should just need to change the use of self.stmt_block()
to your own function called something like self.case_branch_stmt_list()
.
def case_branch_stmt_list (self,line): ''' Function to parse a statement group without using a block terminator
:return: List
'''
# A list is used to store statements
stmt_list = []
# Parse statements until the end of the CASE block is encountered
while not self.match([TT.ENDCASE]):
stmt_list.append(self.statement())
# Syntax error, we reached the end of the program without finding ENDCASE
if not self.check(TokenType.AT_EOF):
raise SyntaxError([self.peek().line, f"Unexpected token '{self.peek().lexeme}' after CASE block"])
# Syntax error, we didn't find any statements
if len(stmt_list) == 0:
raise SyntaxError([self.peek().line, "Empty statement block"])
return stmt_list
that is what i tried to do but still i get an error
You need to add a bit which looks ahead for the start of the next case branch.
can you give me more details plaese
Where you are checking for TT.ENDCASE
you also need to check for, but not consume, the start of the next case branch. The start of the next case branch is either an Expression
followed by TT.COLON
, or TT.OTHERWISE
followed by TT.COLON
.
I did it this way and it works
def stmt_block2(self,line):
# A list is used to store statements
stmt_list = []
# While we are not at the end of the program
while not self.isAtEnd():
name = self.previous().literal
if name is self.previous().literal:
stmt_list.append(self.statement())
break
# Syntax error, we didn't find any statements
if len(stmt_list) == 0:
raise SyntaxError([line, "Empty statement block"])
return stmt_list
Please if you have any suggestions, let me know.
Thanks for you help.
I don't see how that would work for case branches containing more than one statement. e.g.
DECLARE a : INTEGER
a <- 5
CASE OF a
1 :
OUTPUT "a"
OUTPUT "b"
OTHERWISE : OUTPUT "c"
ENDCASE
yes you are right it only executes one line after the matching CASE.
But you have another bug in your code It does not accept input into an array
for example
INPUT X[Count]
This generates an error and this syntax is accepted in the pseudocode guide.
Same for 2-Darray
This code does not work
INPUT X[i,j]
I don't think input directly into an array is mentioned in the pseudocode guide.
it was given in many mark schemes
DECLARE a : INTEGER a <- 5
CASE OF a 1 : OUTPUT "a" OUTPUT "b" OTHERWISE : OUTPUT "c" ENDCASE
do you have any solution for this issue
I was able to fix this problem and the code can handle this code
DECLARE a : INTEGER a <- 5
CASE OF a 1 : OUTPUT "a" OUTPUT "b" OTHERWISE : OUTPUT "c" ENDCAS
without using the BREAK at end of each case.
Thank you so much
can you send the link to download the code for the editor and how it can be installed and run on a server.
Thank you
Can i remove the BREAK key word from the CASE structure since it is not required in the Cambridge pseudocode guide.
If yes what are the changes that i need to make to the code to do that.
Thanks