36
Syntax and Semantics • Syntax form or structure of expressions or statements for a given language For instance, in Java, the form of a while loop is while(<bool_expr) <stmt> • Semantics meaning of the expressions • Language group of words that can be combined and the rules for combining those words • Sentence a legal statement in the language • Lexeme lowest level syntactic unit in the language • Token a language category for the lexemes Example (in Java): index = 2 * count + 17; Lexeme: Token: index identifier = assignment_opera 2 integer_literal * mult_operator count identifier + addition_operat 17 integer_literal ; semicolon

Syntax and Semantics

  • Upload
    etta

  • View
    69

  • Download
    0

Embed Size (px)

DESCRIPTION

Syntax form or structure of expressions or statements for a given language For instance, in Java, the form of a while loop is while(

Citation preview

Page 1: Syntax and Semantics

Syntax and Semantics• Syntax

– form or structure of expressions or statements for a given language

• For instance, in Java, the form of a while loop is

– while(<bool_expr) <stmt>

• Semantics – meaning of the expressions

• Language – group of words that can be

combined and the rules for combining those words

• Sentence – a legal statement in the language

• Lexeme – lowest level syntactic unit in the

language

• Token – a language category for the

lexemes

Example (in Java): index = 2 * count + 17;

Lexeme: Token: index identifier = assignment_operator 2 integer_literal * mult_operator count identifier + addition_operator 17 integer_literal ; semicolon

Page 2: Syntax and Semantics

Languages• Language Recognizer

– given a sentence, is it in the given language?

• Language Generator – given a language, create legal

and meaningful sentences• We can build a language

recognizer if we already have a language generator

• Grammar – a description of a language -

can be used for generation or, given the grammar, a language recognizer (known as a parser) can be created

• We classify languages into one of four categories:– Regular– Context-Free– Context-Sensitive– Recursively Enumerable

• Here, we are interested in the context-free grammar– these include those which can be

generated from a language generator

– all natural languages and programming languages fall into this category

– You will study the other languages in more detail in 485

Page 3: Syntax and Semantics

BNF (Backus Naur Form)• Equivalent to a context-free language

– BNF is a notation (or a meta-language) used to specify the grammar of a language

• The BNF can then be used for language generation or recognition• BNF uses rules to map non-terminal symbols (tokens) into other non-

terminals and terminals (lexemes)

• We define a BNF Grammar as – G={alphabet, rules, <start>}

• alphabet consists of those symbols used in the rules – both terminal symbols and non-terminal symbols, non-terminal symbols

are placed in < >• rules map from a non-terminal to other elements in the alphabet

– for instance, a rule might say <A> a<B> | b<A>– rules can be recursive as shown above where an <A> can be applied to

generate a terminal (b) and another <A>• <start> is a non-terminal which is the starting point for a language

generator and must be on at least 1 rule’s left hand side

Page 4: Syntax and Semantics

Examples of Grammar Rules<program> -> begin <stmt_list> end

Notice the use of both terminals and non-terminals on the right side

Recursion is used as necessary<ident_list> -> ident | ident, <ident_list>The | symbol means “or” so that an <ident_list> can be a single ident, or an ident, a comma, and more of an ident_list

Other examples are:<assign> -> <var> = <expression>

<if_stmt> -> if <logical_expr> then <stmt> | if <logical_expr> then <stmt> else <stmt>

Page 5: Syntax and Semantics

Example Grammar<program> -> begin <stmt_list> end<stmt_list> -> <stmt> |

<stmt> ; <stmt_list><stmt> -> <var> = <expr><var> -> a | b | c | d<expr> -> <var> + <var> |

<var> - <var> | <var>

This grammar can be used to generate a program (granted, a program that will only consist of assignment statements) or we can use the grammar to generate a recognizer to recognize if a given program is syntactically valid in this language

A derivation is a generation, starting at the <start> symbol (in this case, the start symbol is <program>) and applying rules until all non-terminal symbols have been removed from the generated sentence. Such a sentence will be a legal sentence in the language

Page 6: Syntax and Semantics

A derivation from the grammar<program> => begin <stmt_list> end => begin <stmt> ; <stmt>_list> end => begin <var> = <expression> ; <stmt_list> end => begin A = <expression> ; <stmt_list> end => begin A = <var> + <var> ; <stmt_list> end => begin A = B + <var> ; <stmt_list> end => begin A = B + C ; <stmt_list> end => begin A = B + C ; <stmt> end => begin A = B + C ; <var> = <expression> end

=> begin A = B + C ; B = <expression> end=> begin A = B + C ; B = <var> end=> begin A = B + C ; B = C end

So, the programbegin A = B + C; B = Cend

is legal

We generate a leftmost derivation, where thenext rule applied is applied to the leftmostnon-terminal symbol (which is why weworked on the first assignment statementbefore we generated the second <stmt>)

Page 7: Syntax and Semantics

Parse Trees• A hierarchical structure displaying the derivation of an

expression in some grammar• Leaf nodes are terminals, non-leaf nodes are non-

terminals• Parser

– Process which takes a sentence and breaks it into its component parts, deriving a parse tree

– If the parser cannot generate a parse tree, then the sentence is not legal

– If the parser can generate two or more parse trees for the same sentence, then the grammar is ambiguous

Page 8: Syntax and Semantics

Grammar and Parse Tree<assign> <id> = <expr><id> A | B | C<expr> <id> + <expr>

| <id> * <expr> | (<expr>)

| <id>

<assign>

<id> = <expr>

A <id> * <expr>

B ( <expr> )

<id> + <expr>

A <id>

C

Parse tree for the derivation<assign> <id> = <expr> A = <expr>

A = <id> * <expr> A = B * <expr> A = B * (<expr>) A = B * (<id> + <expr>) A = B * (A + <expr>) A = B * (A + <id> ) A = B * (A + C)

Page 9: Syntax and Semantics

An Ambiguous Grammar• <assign> <id> := <expr>• <id> A | B | C• <expr> <expr> + <expr> | <expr> *

<expr> | (<expr>) | <id>• With this grammar, the sentence

– <assign> A = B + A * C – has two distinct parse trees

• see next slide– The reason this is important is that the second parse tree

represents an interpretation of the expression where + has higher precedence than * which would give us an incorrect answer

Page 10: Syntax and Semantics

Two Parse Trees for A = B + A * C

<assign>

<id> = <expr>

A <expr> + <expr>

<id> <expr> * <expr>

B <id> <id>

A C

<assign>

<id> = <expr>

A <expr> * <expr>

<expr> + <expr> <id>

<id> <id> C

B A

The lower down the operator in the parse tree, the higher its precedenceso on the left, * has a higher precedence than + (which is as it should be)but the tree on the right is incorrect, essentially being A = (B + A) * C eventhough there are no parentheses specified to alter the precedence

Page 11: Syntax and Semantics

An Unambiguous Grammar

• <assign> <id> := <expr>• <id> A | B | C• <expr> <expr> + <term>

| <term>• <term> <term> * <factor>

| <factor>• <factor> (<expr>) | <id>

Here, we force operatorprecedence by making amultiplication occur lowerin the tree by deriving itthrough an additional rule( ) having the highestprecedence requires the most derivation to get to it

Assume we wanted to addanother operator, unary –(as in -5), how would weadd it? What about adding** (exponent)?

Page 12: Syntax and Semantics

Derivation and Parse Tree of the Unambiguous Grammar

<assign> <id> = <expr> A = <expr> A = <expr> + <term> A = <term> + <term> A = <factor> + <term> A = <id> + <term> A = B + <term> A = B + <term> * <factor> A = B + <factor> * <factor> A = B + <id> * <factor> A = B + C * <factor> A = B + C * <id> A = B + C * A

<assign>

<id> = <expr>

A <expr> + <term>

<term> <term> * <factor>

<factor> <factor> <id>

<id> <id> A

B C

Page 13: Syntax and Semantics

Associativity• We maintain operator precedence through additional rules

whereby higher precedence operators appear after the application of more rules– Should we worry about associativity? Notice that A + B + C = C

+ A + B, should we force them to generate the same parse tree?– It doesn’t seem worthwhile, and yet if A, B and C are floats

instead of ints, then A + B + C may not equal C + A + B, so associativity should be preserved

• How?– We will require that all rules in our BNF be left recursive for left

associativity and right recursive for right associativity• Left recursive means that a recursive non-terminal must appear to the left of

any other non-terminals– <expr> <expr> + <term> is left recursive and– <factor> <expr> ** <factor> is right recursive

Page 14: Syntax and Semantics

Ambiguous If-Then-Else• <if_stmt> if <logical expr> then <stmt> |

if <logical expr> then <stmt> else <stmt>• Since a <stmt> could be another <if_stmt> we

could generate– if X > 0 then if Y > 0 then X:=0 else X:=Y

• The problem is that this is ambiguous:– Is the else the alternative to the first then or the

second then (that is, which condition does the else get attached to?)

– We could use { } to remove the ambiguity but it is better to create an unambiguous grammar

Page 15: Syntax and Semantics

Unambiguous If-Then-Else• <stmt> <matched> | <unmatched>• <matched> if <logical expr> then

<matched> else <matched>| any non-if statement

• <unmatched> if <logical expr> then <stmt> | if <logical expr> then <matched>

else <unmatched>Here, an if-then with a nested if-then-else is allowed, but an if-then-else where the then-clause contains an if-then is not allowed (the then and else clauses must bematched, which means either another if-then-else, or a non-if statement

In this way, any else clause is always associated with the most recent then clauseMost languages follow this grammar, or require explicit delimiters (like { })

Page 16: Syntax and Semantics

Extended BNF Grammars• 3 common extensions to

BNF:– [ ] - used to denote optional

elements (saves some space so that we don’t have to enumerate options as separate possibilities)

– { } - used to indicate 0 or more instances

– ( ) - for a list of choices• These extensions are added

to a BNF Grammar for convenience allowing us to shorten the grammar

• BNF: <expr> <expr> + <term> | <expr> - <term> | <term> <term> <term> * <factor> | <term> / <factor> | <factor> <factor> <exp> ** <factor>

| <exp> <exp> (<expr>) | <id>• EBNF: <expr> <expr> {(+ | -) <term>} <term> <term> {(* | /) <factor>} <factor> <exp> { ** <factor>} <exp> (<expr>) | <id>

Here, we revise our <expr> portion of the grammar to illustrate how much easier it is to notate the grammar using EBNF

Page 17: Syntax and Semantics

Attribute Grammars• It is not possible to describe all aspects of a language

solely with a BNF Grammar– BNF Grammar lacks static semantics (that is, rules that the

language dictates for a program to be syntactically correct)– For example:

• Making sure that the number of parameters in a function call match the number of parameters in the function header

• Making sure in an assignment statement that the left hand side type matches (or is compatible with) the value computed by the right hand side’s expression

• Attribute grammars are added to BNF grammars to handle these gaps– We will add attributes and predicate functions to every BNF

grammar rule – the attributes will store such information as variable type or number of parameters and the predicates will test to make sure that the attributes match accordingly

Page 18: Syntax and Semantics

Attribute Grammar Features• Synthesized attributes

– information passed up the parse tree• Inherited attributes

– information passed down the parse tree• Semantic functions

– rules or predicates associated with grammar rules that compare synthesized attributes to inherited attributes

• if any predicate fails its test, then we have a syntax error

• Intrinsic attributes – leaf node attributes derived when a rule generates a terminal

• for instance, if <type> int, then the attribute for the declared variable receives its intrinsic value (whatever value we use to denote that the variable is an int)

Page 19: Syntax and Semantics

Example: Deriving Identifiers• In some languages, identifier names are limited

– Here, we look at Pascal where an identifier name must start with a letter or _, consist of _, letters and numbers, and be less than or equal to 31 characters in length

• Our BNF rule for deriving an identifier is– <identifier> _<id> | <letter><id>– <id> _ | <letter> | <digit> | _<id> | <letter><id> | <digit><id>

• We enhance our grammar with the attribute length– <identifier> _<id> | <letter><id>– <identifier>.length = 1– <id> _ | <letter> | <digit> | _<id> | <letter><id> | <digit><id>– <identifier>.length <identifer>.length + 1– Predicate: <identifer>.length <= 31

Page 20: Syntax and Semantics

Example: Assignment Stmt• Attributes:

– Actual_Type • synthesized for <var>

and <expr>, stores the type

– Expected_Type • inherited for <expr>

based on the <var> type

– LHS_Type • synthesized for

<assign>– Env

• inherited for <assign>, <expr>, <var> carrying the reference to the symbol table

• Our grammar now becomes:– 1. Syntax rule: <assign> <var> = <expr>– Semantic rule: <expr>.expected_type

<var>.actual_type– 2. Syntax rule: <expr> <var>[2] + <var>[3]– Semantic rule: <expr>.actual_type if

(<var>[2].actual_type = int) and (<var>[3].actual_type = int) then int else real

– Predicate: <expr>.actual_type = <expr>.expected_type– 3. Syntax rule: <expr> <var>– Semantic rule: <expr>.actual_type <var>.actual_type– Predicate: <expr>.actual_type = <expr>.expected_type– 4. Syntax rule: <var> A | B | C– Semantic rule: <var.actual_type look-

up(<var>.string)

Page 21: Syntax and Semantics

Example

<expr>.expected_type inherited from parent

<var>[1].actual_type lookup (A)<var>[2].actual_type lookup (B)<var>[1].actual_type =? <var>[2].actual_type

<expr>.actual_type <var>[1].actual_type<expr>.actual_type =? <expr>.expected_type

<assign>

<expr>

<var>

<var>[2] <var>[3]

A = A + B

actual_type

expected_type

actual_type actual_type

Assume A is a float and B is an int:

<var>.actual_type = float<var>[2].actual_type = float<var>[3].actual_type = int<expr>.actual_type = float (derived from var[2] and var[3] through semantic rule)<expr>.expected_type = float (inherited from <assign> which is inherited from <var>)

<expr>.expected_type = <expr>.actual_type, so predicate is satisifed, no syntax error

Page 22: Syntax and Semantics

Dynamic Semantics• Describing the meaning of a program or of a statement or

group of statements– Describing the syntax of a language or of a set of code is

relatively easy, how do we describe the meaning behind code?• We could express it in English (e.g., through comments) but this is too

informal and perhaps too incomplete/imprecise• What if we want to use the semantics to make sure that the program does

what is intended? This is known as verification. We would need more formal methods of defining semantics for this, so we turn to:

• Operational Semantics – how the statement will be executed

• Axiomatic Semantics – what results to expect from the statement

• Denotational Semantics – functional way of mapping the affects of a statement

Page 23: Syntax and Semantics

Operational Semantics• This can be thought of as

“tracing” through a program to see what affects an instruction will have

• Implemented as an interpreter or compiler or assembler – that is, how will the computer

execute this instruction?• This is simply a mechanistic

description of the statement and does not necessarily help us understand the statement

Example: C for-loop

for(expr1; expr2; expr3) stmt;

Becomes:

expr1;loop: if expr2 = 0 goto out

stmt;expr 3;goto loop

out: …

Page 24: Syntax and Semantics

Axiomatic Semantics• Used mainly to prove correctness of code

– Each statement in the language has associated assertions – what we expect to be true before and after the statement executes

– We list these assertions as pre- and post-conditions that specify how the machine changes (changes to variables)

– Given the state of the machine prior to executing a statement, we can then determine what must be true afterward

• The basic form of an axiomatic semantic is{P} S {Q}

• This is interpreted as:– if P is true before S, then Q is true after S– We must now define how to determine Q given P and S

Page 25: Syntax and Semantics

Weakest pre-condition• We will start with a given post-condition and derive the

weakest pre-condition– We work backwards mainly because we will start with an

overall goal in mind for the given statement or program– We want to derive the weakest pre-condition for a given post-

condition because this is the least restrictive pre-condition that will guarantee validity

• Weakest means most general – what is the greatest range of values for a given variable such that the result will be true?

• For example, consider the assignment statement – sum = 2*x+1;

• with post-condition {sum > 1}• Possible pre-conditions are {x > 10}, {x > 50} and {x > 1000} • But the weakest pre-condition is {x > 0}

Page 26: Syntax and Semantics

Assignment Statement Rule• We will use the following notation for an assignment

statement axiomatic rule:– {QxE} x = E {Q}

• This is read as follows:– If Q is true after the assignment, then QxE is true prior

• The notation QxE means to replace all instances of x in Q with E– Examples:

• a=b/2-1; {a < 10} – We replace a in {a < 10} with b / 2 – 1 and solve for b, thus {QxE} is {b / 2 – 1

< 10} or {b < 22}– So we have: {b < 22} a = b / 2 – 1; {a < 10} – that is, if b < 22 prior to the

assignment statement, then a will be less than 10 afterward• x = 2 * y – 3; {x > 25}

– pre-condition is {2 * y – 3 > 25} or {y > 14}• c = d * e – 4; {c > 0}

– pre-condition is {d * e – 4 > 0} or {d * e > 4}, we might want to list this as {d > 4 / e} or {e > 4 / d}, or even {d > 4 / e & d != 0 & e != 0}

Page 27: Syntax and Semantics

Sequences• In general, a series of statements S1, S2, S3, ..., Sn can

be expressed as:– {P} S1 {Q1}; {Q1} S2 {Q2} ; {Q2} S3 {Q3};

... {Qn} Sn {Q}– This can be simplified to {P} S1, S2, S3, ..., Sn{Q}– Therefore, we can combine rules to show the axiomatic

semantics of a block of code • Example:

– y = 3 * x + 1; x = y + 3;• If our post-condition is {x < 10} then our pre-condition between the

two statements is {y+3 < 10} or {y < 7} and our pre-condition before the first statement is {3 * x + 1 < 7} or {x < 2}

– If x < 2 before the first statement, then x < 10 after the second statement

Page 28: Syntax and Semantics

Rule of Consequence• In the previous example, we had a sequence of 2

assignment statements, but this works in general with any number of statements of any kind

• The rule of consequence is shown as follows:

• The rule means that if P’ implies P and Q implies Q’ and we have already proven that {P} S {Q} is true, then we can infer {P’} S {Q’} is also true– notice that P’ => P means that P is a weaker condition than P’

whereas Q => Q’ means that Q is a stronger condition than Q’• this allows us to take a proven rule and weaken its postcondition and

strengthen its precondition

}{Q' S }{P'Q' Q P, P' {Q}, S P}{

=> means “implies”

0} x{ 3 - x x 5}{x 0)(x 0) (x 3), (x 5) (x 0}, {x 3 - x x 3}x{

Page 29: Syntax and Semantics

Selection Axiomatic Semantic• Given a statement: if (B) S1; else S2; • The semantic rule is: {B & P} S1 {Q}, {(!B) & P} S2 {Q}

– if Q is our post-condition, then we have two pre-conditions, if the if statement’s condition is true (B) then B & P, and if the if statement’s condition is false (Not B) then !B & P, so we must derive P that will allow the same post-condition no matter if B or !B is true

• Example:– if (x > 0) y--; else y++;

• Suppose the post-condition is {y > 0} – the pre-condition for the if-clause is {y > 1}– the pre-condition for the else-clause is {y > -1}– the condition {y > 1} is subsumed by the condition {y > -1} (that is, if

{y > 1} is true, then {y > -1} must also be true• So, we select {y > 1} as our weakest pre-condition

– we cannot use {y > -1} because, if x > 0 and y = -1, our post-condition is not true

Page 30: Syntax and Semantics

Logical Pretest Loops• Our pre-test loop looks like this:

– while (B) S;– We must derive a pre-condition that is true prior to the loop whether it

B is true or not, but also the pre-condition must remain true if B is true and S is executed – that is, P must be true prior to each loop iteration

• To derive P, we create I, a “loop invariant” – The invariant will always be true both before and after each loop

iteration• The pre-condition must include {I} and the post-condition must

include {I and Not B}– NOTE: determine a loop invariant is difficult and does not necessarily

seem to help us understand the loop• For these reasons, we will go over an example, but not cover this in any more

detail

Page 31: Syntax and Semantics

While-Loop Example• Our loop is

– while (y != x) y++; • Our post-condition is {y = x}

– the post-condition states that the condition (y != x)is false• The pre-condition must include the condition (y!= x) and the loop

invariant– what is the invariant? We need to select something that will be true both

before and after each loop iteration• notice that y initially will not equal x and then we add 1 to x, so that y < x or y = x

after each loop iteration• we cannot have y > x before the loop because this would be an infinite loop and that

would result in the post-condition never being true – since the post-condition must be true, y > x can not be true beforehand

– either y < x or y = x will be true, our loop-invariant is {y <= x}

Page 32: Syntax and Semantics

Two More Loop Exampleswhile s > 1 do s = s / 2 end {s = 1}

What is the weakest precondition? (wp)

Let’s apply the loop one time: if s > 1 then for s = 1 afterward, we would have s = s / 2 {s = 1} our wp is {s = 2} for 2 iterations, we would then have s = s / 2 {s = 2} so our wp is {s = 4} for 3 iterations, we would then have s = s / 2 {s = 4} so our wp is {s = 8}

We can now derive the invariant as being s is a non-negative power of 2 or{s = 2n for n >= 0}

The following code computes z = x * y assuming y is positive z=0; n=y; while(n>0) { z+=x; n--; }

So, our post-condition is {z=x*y & y > 0 & n=0}where n=0 is NOT B and z=x*y is P.I, our loop invariant, is not merely y > 0 however.

If we analyze each loop iteration for z and n, we find that z=x*(y-n) and n>=0

A precondition then is {s > 1 and s = 2n} but this is not theweakest, we can make it weaker by using {s > 1}

Page 33: Syntax and Semantics

Program Proofs• As you can see by the last example, finding an invariant is not

necessarily easy– the invariant must include the loop’s terminating condition but also be

weak enough to describe what happens during each loop iteration– in using axiomatic semantics for a loop, the requirement that the invariant

include the terminating condition is often ignored• in such a case, the axiomatic description is known as offering only partial

correctness rather than total correctness if the terminating condition is met• By combining these axiomatic rules, we can prove the correctness

of an entire program– consider the example below which swaps two variable values– our precondition requires that the two variable values have in fact been

swapped, now we will prove it

{x = A AND y = B}t = x;x = y;y = t;{x = B AND y = A}

{P} t = x; x = y; y = t; {x = B AND y = A}{P} t = x; {P1}, {P1} x = y; {P2}, {P2} y = t; {x = B AND y = A}{P2} is {x = B AND t = A}{P1} is {y = B AND t = A}{P} is {y = B AND x = A}and {y = B AND x = A} => {x = A AND y = B}

The chapter offers a more complete example if you are interested

Page 34: Syntax and Semantics

Denotational Semantics• This form of semantics is a more rigorous method of

describing the meaning of a program than our previous approaches– Denotational semantics is based on recursive function theory– That is, derive a function that defines the affects of an instruction– Because the function is recursive, this tends to be a very difficult

topic, probably the hardest thing when studying programming languages

– In essence, the function will map from an instance of a mathematical object (the state of the machine) onto another mathematic object

• so this is telling us what happens to the machine after applying an instruction (or program)

– We will look at an example of a recursive function and then apply the idea to 3 types of instructions

Page 35: Syntax and Semantics

Simple Examples• We define the value of a binary number

– <bin_num> 0 | 1 | <bin_num>0 | <bin_num>1• that is, a binary number is a 0, a 1, or recursively a binary number

followed by a 0 or a binary number followed by a 1– the function must map from a binary number derived from the

above grammar rule to a mathematical object (an integer value)• Mbin(<bin_num) =

– Mbin(0) = 0– Mbin(1) = 1– Mbin(<bin_num>0)=2*Mbin(<bin_num>)– Mbin(<bin_num>1)=2*Mbin(<bin_num>) + 1

» Mbin(101) = 2*Mbin(10) + 1 = 2*(2*Mbin(1))+1 = 2*2*1+1 = 5Expressions Me (E, s)

if VARMAP(i, s) = undef for some i in E then errorelse E’, where E’ is the result of evaluating

evaluating E after setting each variable i in E to VARMAP(i, s)

Expression E, in state s, is an error if some i (variable) in E is undefined, otherwise it is E’ = value of evaluating E by applying each variable I and operator in E using VARMAP(symbol table) currently in s

Page 36: Syntax and Semantics

Assignment and LoopAssignment Statements Ma(x := E, s) if Me(E, s) = error then error else s’ = {<i1’,v1’>,<i2’,v2’>,...,<in’,vn’>}, where for j = 1, 2, ..., n, vj’ = VARMAP(ij, s) if ij <> x = Me(E, s) if ij = x

Here, the state of the machine is an error if there is an error when evaluating E in s, otherwise the state of the machine is modified where x is now equal to E, but all othervariables in s remain the same

Ml(while B do L, s) = if Mb(B, s) == undef then error else if Mb(B, s) == falsethen s else if Msl(L, s) == error then error else Ml(while B do L, Msl(L, s))

If B, when evaluating given thestate of the machine s, is undefined, then we have an error, otherwise if B evaluates to False, then the state remains s, otherwise the state becomes the state when L is executed, so the state of the machine changes to be whatever the function M(L, s) returns

Since L is some non-specified statement, we don’t know exactly what will happen