Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Purpose of using a BREAK in CASE structure #31

Open
chris7380 opened this issue Dec 18, 2023 · 19 comments
Open

Purpose of using a BREAK in CASE structure #31

chris7380 opened this issue Dec 18, 2023 · 19 comments

Comments

@chris7380
Copy link

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

@Coding-Cactus
Copy link
Member

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.

@chris7380
Copy link
Author

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

@Coding-Cactus
Copy link
Member

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.

@chris7380
Copy link
Author

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
Copy link
Author

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.

@Coding-Cactus
Copy link
Member

Coding-Cactus commented Dec 20, 2023

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

@chris7380
Copy link
Author

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

@Coding-Cactus
Copy link
Member

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

@chris7380
Copy link
Author

can you give me more details plaese

@Coding-Cactus
Copy link
Member

Coding-Cactus commented Dec 22, 2023

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.

@chris7380
Copy link
Author

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.

@Coding-Cactus
Copy link
Member

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

@chris7380
Copy link
Author

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]

@Coding-Cactus
Copy link
Member

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

@chris7380
Copy link
Author

it was given in many mark schemes

@chris7380
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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

@Coding-Cactus
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants