PseudocodeEditor / editor

The codemirror 6 editor for CIE spec Pseudocode
https://editor.pseudonaja.app
21 stars 2 forks source link

Purpose of using a BREAK in CASE structure #31

Open chris7380 opened 8 months ago

chris7380 commented 8 months ago

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 commented 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.

chris7380 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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

chris7380 commented 8 months ago

can you give me more details plaese

Coding-Cactus commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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

chris7380 commented 8 months ago

it was given in many mark schemes

chris7380 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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