editor icon indicating copy to clipboard operation
editor copied to clipboard

Purpose of using a BREAK in CASE structure

Open chris7380 opened this issue 2 years ago • 19 comments

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

chris7380 avatar Dec 18 '23 09:12 chris7380

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.

Coding-Cactus avatar Dec 18 '23 12:12 Coding-Cactus

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

chris7380 avatar Dec 19 '23 09:12 chris7380

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.

Coding-Cactus avatar Dec 19 '23 10:12 Coding-Cactus

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.

chris7380 avatar Dec 19 '23 12:12 chris7380

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.

chris7380 avatar Dec 20 '23 13:12 chris7380

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().

Coding-Cactus avatar Dec 20 '23 19:12 Coding-Cactus

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

chris7380 avatar Dec 21 '23 11:12 chris7380

You need to add a bit which looks ahead for the start of the next case branch.

Coding-Cactus avatar Dec 21 '23 14:12 Coding-Cactus

can you give me more details plaese

chris7380 avatar Dec 22 '23 06:12 chris7380

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.

Coding-Cactus avatar Dec 22 '23 10:12 Coding-Cactus

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.

chris7380 avatar Dec 24 '23 08:12 chris7380

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

Coding-Cactus avatar Jan 03 '24 12:01 Coding-Cactus

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]

chris7380 avatar Jan 04 '24 07:01 chris7380

I don't think input directly into an array is mentioned in the pseudocode guide.

Coding-Cactus avatar Jan 04 '24 07:01 Coding-Cactus

it was given in many mark schemes

chris7380 avatar Jan 04 '24 08:01 chris7380

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

chris7380 avatar Jan 04 '24 08:01 chris7380

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

chris7380 avatar Jan 06 '24 11:01 chris7380

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

chris7380 avatar Jan 06 '24 11:01 chris7380

See https://github.com/PseudocodeEditor/editor/blob/main/CONTRIBUTING.md

Coding-Cactus avatar Jan 07 '24 17:01 Coding-Cactus