Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
4 views

1 Introduction to Syntax Analysis

The document introduces syntax analysis, starting with examples from the English language to illustrate parsing and the identification of word categories. It then transitions to programming languages, explaining the concepts of tokens and lexemes, and the importance of syntax in distinguishing valid constructs from semantically correct ones. Additionally, it describes the functionality of the getToken() function for tokenizing input and the peek() function for looking ahead in the token stream.

Uploaded by

maherbekdash05
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

1 Introduction to Syntax Analysis

The document introduces syntax analysis, starting with examples from the English language to illustrate parsing and the identification of word categories. It then transitions to programming languages, explaining the concepts of tokens and lexemes, and the importance of syntax in distinguishing valid constructs from semantically correct ones. Additionally, it describes the functionality of the getToken() function for tokenizing input and the peek() function for looking ahead in the token stream.

Uploaded by

maherbekdash05
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 122

Introduction to

Syntax Analysis

Rida A. Bazzi

© 2018 – 2022 RIDA BAZZI This document is copyrighted by Rida Bazzi and should not be
shared or used for other than the purpose for which it was provided to you.
Syntax Analysis in the English Language
Before introducing syntax analysis for programming languages. We start with a motivating
example from the English language. The example will illustrate the various elements of syntax
analysis that are needed for parsing programs. Then after discussing the example, we will explore
syntax for programming languages.

Example text 1: The cat drank the milk.

How do we make sense of this text?

1. In the first step, we identify the sequence of words, and, for each word, we determine what
kind or category of word it is

“The” DEFINITE_ARTICLE
“cat” NOUN
“drank” VERB
”the” DEFINITE_ARTICLE
“milk” NOUN
“.” PERIOD

Note that I am treating the period as a word and the category is PERIOD and I don’t consider a
larger category of PUNCTUATION_MARKS. When we analyze an input, we should be given the
various categories of words ahead of time, so that we can properly break the input into a
sequence of words of the right categories (or kinds).

2. The second step consists of taking the sequence of word categories and determining if the
sequence is syntactically correct.

The cat drank the milk . input

“The” “cat” “drank” “the” “milk” “.”


step 1
DEFINITE_ARTICLE NOUN VERB DEFINITE_ARTICLE NOUN PERIOD

step 2

subject VERB object PERIOD

sentence valid sentence

The process of taking some text, breaking it into words, identifying the categories of words and
determining that they form a syntactically correct sequence is called PARSING!

Parsing is done according to a grammar. In the example above, I did not give the grammar
explicitly and relied on the shared knowledge you and I have of the grammar of the English
language.
Syntax in the English Language: Grammar Rules
In the example above, parsing considered the sequence of categories to determine if the
input is syntactically correct. Parsing does not look at the specific words. The next
example illustrates this point.

Example text 2: The milk drank the cat.

This is also a grammatically valid sentence because it looks the same as the previous
sentence:

DEFINITE_ARTICLE NOUN VERB DEFINITE_ARTICLE NOUN PERIOD

This is the same format (syntax) as the previous sentence.

What matters for syntax are the categories of words and not the specific words. The
sentence above has the correct look, even though it does not make sense semantically.

To summarize, parsing a sentence involves the following

1. identify the words


2. identify the kinds or categories of words
3. group together the “kinds” according to the English grammar to identify
sentence components
4. Identify the sentence by putting the components together

For a natural language like the English language, assuming language is static, (which it is
not) we can list all words and all categories in one large unabridged dictionary.

The situation is different for programming languages as we will see next.


Syntax of Programming Languages
The elements of syntax for of programming languages are similar to those of natural
languages.

For programming languages, we need to have a well-defined alphabet and a well-defined


list of categories. The categories of words in programming languages are called tokens
and the words are called lexemes (we also call them tokens for convenience). We start
by defining alphabet and strings.

Alphabet a finite set of symbols.

Example {a,b,&,1,!}
Example The alphabet of the C language =
{ a , b , ... , z , A , B , ... Z , 0 , 1 , ... 9 , < , ... }

String A string over a given alphabet is a finite sequence of symbols


from the alphabet

Example “ab” , “a&b1” , and “1!aa” are strings


over the the alphabet above

Note I enclose strings between double quotation marks to emphasize that they are
strings
Note Strings are sequences of symbols, so order matter. “abc” is not equivalent
to “bac”
Note Sometime I enclose single characters in single quotation marks to indicate
that they are alphabet characters and not meta characters used in the
description. For example, I write
{ ‘,’ , ‘;’ }
for a set containing two symbols ‘,’ (comma) and ‘;’ (semicolon). The middle red
comma is used a separator in the description of the set and is not part of the
symbols of the set.
Elements of Syntax
Token A token is a set of strings. We can think of a token as the name of a set of
strings.
Every programming language has a definition of the list of tokens and the The following
are some examples.

Example 1 NUM = { “0” , “1” , “2” , ... , “9” , “10” , “11”, “12” , ... }
= strings that consist of a sequence of 1 or more digits
starting with a non-zero digit or the digit 0 by itself

Example 2 ID = set of strings consisting of 1 or more


characters and digits and starting with a
character

Example 3 DECIMAL = set of strings of the form


- NUM `.’ NUM or
- ‘.’ NUM or
- NUM ‘.’
Lexeme A lexeme of a token is a string from the set strings labeled by the token

Example 1 “123” is a lexeme of NUM


“123a” is not a lexeme of NUM
Example 2 “1.00” is a lexeme of DECIMAL
“1.” is a lexeme of DECIMAL
“0.00100” is a lexeme of DECIMAL
“0.00” is a lexeme of DECIMAL
“0.1b” is not a lexeme of DECIMAL
Example 3 “a123” is a lexeme of ID
“123a” is not a lexeme of ID

Oftentimes we abuse notation and refer to the lexeme as the token. For example, we
say “123” is a NUM token

As we stated earlier, tokens correspond to word categories (for natural languages). Each
token defines a category.

Lexemes correspond to words in a particular category.


Syntax vs. Semantics
Syntax vs. Semantics in English

As we pointed out earlier, syntax only depends on the categories of words and not on the
specific word used. Semantics do not depend just on the categories of words (NOUN,
ARTICLE, ...), but they also depend on the specific word that is used. The example

The milk drank the cat.

is syntactically correct, but it does not make sense (is not semantically correct). The
sentence does not make sense because “milk” is not a semantically meaningful subject for
the verb “drank”.

Syntax vs. Semantics in programming languages

The situation is similar for programming languages. Consider the following two program
fragment in the C language

int x; 1 int x; 2
float y; int y;

x = y; x = y;

The two fragments are syntactically correct. From a syntax point of view, they look exactly
the same:

ID ID SEMICOLON
ID ID SEMICOLON

ID EQUAL ID SEMICOLON

x = y ;

Where ID is the category that contains all valid identifiers (valid variable names as well as
type names). Even though the two fragments are syntactically correct, only 2 is valid
semantically because C does not allow a float value to be assigned to an integer variable.

The syntax of fragment 1 is correct, but the semantics are not.

In general, syntax does not care about the specific word (or lexeme) but only about its
category. When we disallow some constructs because of the specific word used, we are
dealing with semantics, but the separation is not clear-cut. One can introduce categories
that have only one word.

For now, we will concentrate on syntax and not semantics.


getToken() function

In discussing the examples above (the cat and the milk or the program fragments), we assumed
that we could take a list of categories (or tokens) and an input string and break that string into a
sequence of tokens/lexemes. When we write a parser, we need to have a function that can provide
this functionality. In this class, we use a function that I call getToken() to help us with this task.

A getToken() function works for a specific token list. It takes input from standard input. When
getToken() is called, it will consult the list of tokens and returns the next token in the input (this
will become clearer as we describe it in more details).

getToken() takes input from standard input

returns a struct that has two fields (the struct type is token a type
that I declare in the code I will provide you)

• token_type this is the category or kind (the token in our terminology)


• lexeme this is the actual part of the input that corresponds to the
token_type corresponds to the token_type identified by
getToken()1
• line_no this is the line on which the token appears. This can be useful for
error messages

Calling getToken() repeatedly will give us the sequence of tokes in the input, according to the list
of tokens. When getToken() is called, it “consumes” the part of the input that corresponds to the
lexeme of the token and, next time it is called, it starts after the token that was already
consumed.

Depending on the language, getToken() might also ignore some parts of the input, such as space
characters, which are typically treated as separators and are otherwise skipped over.

In general, we are going to assume in the examples that white space characters are ignored and
only serve as separators, but that need not be the case always. For example, in Python, the
indentation level is determined by white space.

1If the token (category) has only one possible lexeme, the implementation I will provide will have
the lexeme field equal to the empty string. The reason is that all the information you need about
getToken() function

I will give two examples to make the behavior of getToken() clearer and to further specify it

Example 1 token list:


ID
EQUAL
SEMICOLON

input:
x = y;

If we call getToken() repeatedly, we get the following

1. getToken() ⟶ ( ID, “x” )


2. getToken() ⟶ ( EQUAL, “” )
3. getToken() ⟶ ( ID , “y” )
4. getToken() ⟶ ( SEMICOLON , “” )
5. getToken() ⟶ ( EOF , “” )
6. getToken() ⟶ ( EOF , “” )

Each line above corresponds to one call of getToken(). The struct that is returned by getToken() is
represented as a pair, with the first element being the token_type and the second element being
the lexeme).

Some explanation of the returned values is needed:

1. getToken() starts reading the input from the very beginning. The first token it finds is
ID whose lexeme is “x”
2. After the first call to getToken(), the second call starts at the space after the x. In
our example, the space is ignored (as is usually the case with many programming
languages) and the next token to be returned is EQUAL. We note here that the lexeme
field is given as the empty string. In reality, the lexeme is “=“ but in my implementation
I return the empty string for the lexeme because, for the EQUAL token, all the
information about the lexeme is available in the token_type
3. the next call to getToken() starts after the =. The space is ignored, and the next token
returned is ID whose lexeme is “y”
4. The next call to getToken() returns SEMICOLON. Again, in the implementation, I have
the lexeme for SEMICOLON equal to the empty string because all the information
about the lexeme is captured by the token_type SEMICOLON.
5. The last two calls (5 and 6) are interesting. After reading the semicolon, we run out of
input. The getToken() function must have a way to indicate that there is no more input.
This is represented by returning a struct whose token_type is EOF which represents
end of input is reached. The EOF itself is not a token (or a category). It is just an
indication that the call of getToken() failed to find more input.
getToken() function

Example 2 token list:


NUM
DOT
DEC which I define to be NUM.NUM

input:
1.1..1

If we call getToken() repeatedly, we get the following :

1. getToken() ⟶ ( DEC, “1.1” )


2. getToken() ⟶ ( DOT, “” )
3. getToken() ⟶ ( DOT, “” )
4. getToken() ⟶ ( NUM, “1” )
5. getToken() ⟶ ( EOF , “” )

An explanation of the first returned value is needed. getToken() starts reading the input from the
very beginning. The question is: why DECIMAL is returned and not NUM? The reason is that
getToken() should always try to get the token with the longest possible lexeme. So, given a list of
tokens, when getToken() is called from a given point in the input, the following two rules need to
be followed:

• Longest prefix match: The token with the longest possible lexeme that matches a prefix
of rest of the input is returned (this statements needs to be read carefully!)
• Priority for tokens that are listed first in the list: If there are multiple possible tokens
with longest lexeme, then the one that is listed first in the list of tokens is returned

Example 3 reserved words and identifiers

Typically, in programming languages, lexemes for reserved words are also lexemes for identifiers
(ID). For that reason, reserved words are listed before identifiers in the list of tokens. This
ensures that when the lexeme matches a reserved word, the token for the reserved word is
returned. For example, for the following input:

if1 ifif if 1

The list of tokens is (ID, “if1”) (ID, “ifif”) (IF, “”) (NUM, “1”)

To understand why this the case, let us consider the first two calls. The first call starts at the
beginning of the input. There are two possible tokens for the first call

if1 ifif if 1
if1 ifif if 1

Since if1 is longer than if, (ID, “if1”) is returned by the first call. Note that getToken() does not
keep on going past the space, because the space cannot be part of a token, but it is a separator.
The second call starts at the space after the if1. Since the space character is ignored, we skip
ahead until the i at the beginning of ifif. Then, the second call to getToken() returns (ID, “ifif”) .
peek()
Another functions that is useful in parsing is peek() which allows us to look ahead without
consuming tokens.

To describe peek(), we assume that the input is already broken down into tokens (token and
lexemes) and that the whole list of tokens is in an array, which I will call token_array:

(tt1,lex1) (tt2,lex2) (tt3,lex3) ... (tti,lexi) (tti+1,lexi+1) ....

The i’th token is token[i]. In the description I assume that the index i starts at 1. As we
execute getToken() the index changes to reflect the fact that tokens are consumed. After
each call, if index is not larger than the number of tokens, then index points to the next
unconsumed token With this representation, the functions getToken() and peek() can be defined
as follows.

getToken() this function will simply return the next token and increments the index. It is
defined as follows

Token getToken() if index > number of tokens


return EOF
else
tok = token_array[index];
index = index + 1; // token is consumed
return tok;

peek() sometimes, we want to look at the next token or the token after the next token,
but without consuming them. The function peek() allows us to do so. The function peek() takes
an integer argument that specifies how far ahead to peek. It is defined as follows.

// Argument howfar > 0.


// Behavior is not defined if howfar ≤ 0
Token peek(int howfar) if index+howfar -1 > number of tokens
return EOF
else
return token_array[index+howfar-1]

Remember that index points to the next token that has not been yet consumed, so peek(1)
returns token_array[index+1-1] = token_array[index]. In particular getToken() and peek(1) will
both return the same token but getToken() modifies the index and peek() does not modify the
index.
Example of getToken() and Peek() together
We consider the following token list

IF = { “if”}
ID // previously defined
NUM // previously defined

We also assume that whitespace characters such as the space character, tab and newline are
separators of tokens. This means that whitespace characters cannot be part of a token and
that when a whitespace character is encountered by the function getToken(), it stops and
returns the longest matching prefix. If the next character before a call to getToken() is a
space character, the next call to getToken() will first skip the whitespace characters before
attempting to identify the next token.

Input
if1if if iff 123hello

The sequence of tokens for this example is

1 2 3 4 5
ID, “if1if” IF, “” ID, “iff” NUM, “123” ID, “hello”

initially index is 1 which means that the first token that will be read is the first token in the
array. Let us examine the behavior of getToken() and peek() through a sequence of calls.

1. getToken() will return (ID, “if1if”) and index is incremented to 2. The resulting
figure is

1 2 3 4 5
ID, “if1if” IF, “” ID, “iff” NUM, “123” ID, “hello”

notice how the arrow is pointing to the second entry (index is 2). This is the next token
to read. So, if we call peek(1) we get the token at index 2. If we call peek(2), we get
the token after that and so on. The rest of the example follows:

2. peek(1) will return (IF, “”) index is still 2


3. peek(2) will return (ID, “iff”) index is still 2
4. pek(1) will return (IF, “”) index is still 2
5. getToken() will return (IF, “”) now index is incremented to 3
6. peek(1) will return (ID, “iff”) index is still 3
7. peek(4) will return (EOF, “”) index is still 3
Syntax in Programming Languages
Now that we have covered the getToken() and peek() functions, we are ready to start
with parsing which consists of determining if the sequence of tokens (categories) is valid
according to a grammar. I will start by introducing the parsing concepts through an
example grammar for simple expressions.

Example: Simple Expressions grammar

expr ➝ term
expr ➝ term PLUS expr
term ➝ factor
term ➝ factor MULT term
factor ➝ ID
factor ➝ NUM
factor ➝ LPAREN expr RPAREN

Instead of being overly verbose, I am going to rewrite the grammar as follows

E ➝ T PLUS E OR // T + E
E ➝T // T
T ➝ F MULT T // F * T
T ➝F // F
F ➝ NUM | ID | LPAREN E RPAREN // NUM | ID | (E)

Note. The concepts of expr, term and factor are typically introduced in Algebra 1 when
you learn about operators and their precedence!

Grammar Format. A grammar consists of a set of rules. Each rule has a left-hand side
(LHS) and a right-hand side (RHS). The left-hand sides of rules must be non-terminals (NT).
Non-terminals are the symbols that appear on the LHS of rules The right-hand sides of
rules are sequences of terminals and non-terminals. Terminals are simply tokens and they
do not appear on the left-hand sides of rules. For example:

RHS is a sequence of
E ➝ T PLUS E terminals and non-terminals

LHS is a
non-terminal
NT T NT

rule
Parsing
• The goal of parsing is to determine if the input is syntactically correct
according to the grammar

• In general, the parser (the program that does the parsing) can build a parse
tree or some other representation of the program to be used by later
processing stages (expression optimization for example)

• In this set of notes, I will start by showing how a simple parser can be written
for a simple expression grammar.

• In another set of notes, we will introduce a general definition of grammars


which are called context free grammars and show how parsing can be done
efficiently for a significant subset of context free grammars
Parsing
Recursive Descent Parsing The parsers we will write are called recursive descent
parsers. These parsers are used in practice. For example, the gcc compiler is a
recursive descent parser. The parsers we will write in this class have the following
properties:

• One parsing function per non-terminal We will have one parsing function for each
“non-terminal”. These are the symbols that appear on the left side of an arrow in a
grammar rule.

• Each parsing function consumes the part of the input that corresponds to its non-
terminal
• If parse_X() is called for non-terminal X, it will either
• succeed in parsing the non-terminal by consuming the part of the input
corresponding to X (no more and no less) or
• it throws a syntax_error() which stops the whole parsing process. In
general, one can attempt to recover from syntax errors, but this is beyond
the scope of our class. This behavior is appropriate for grammars for which
no backtracking is needed, but if backtracking is needed, the function
would need to return with an indication that it could not correctly parse.
• A parse function does not consume any part of the input that is not part of the
non-terminal it is parsing.

• Recursive A parsing function will proceed by calling other parsing functions


(recursively) and the expect() and peek() functions (as we will see next)

• To consume non-terminal X, we call parse_X()


• To consume token ttype, we call expect(ttype)

• Descent Parsing is done from top to bottom. To parse a program, we start by calling
parse_program() which calls other parse functions to parse components of the
program which in turn call other functions to parse subcomponents and so on.
Simple Expression Grammar
E ➝ T PLUS E // T + E
E ➝T // T
T ➝ F MULT T // T * E
T ➝F // F
F ➝ NUM | ID | LPAREN E RPAREN // NUM | ID | (E)

void parse_input() // top level input parsing


{
parse_E(); // consume E which is
// the top level symbol
// of the grammar
t = lexer.getToken();
if (t.token_type != EOF) // input should have
syntax_error(); // nothing after E

return; // Input -> E


}

In the code, we call syntax_error() function whenever we determine that there is


a syntax_error(). We assume that the syntax_error() function will simply print a
message and exits the whole program, so there is really no attempt at recovering
from the error.

In the code, you will notice the following pattern which we will encounter often:

t = lexer.getToken();
if (t.token_type != ttype)
syntax_error();

This pattern is used whenever we want to be sure that the next token is equal to
a particular token type (ttype in the code). To simplify the code, we introduce the
expect() function to capture this pattern.

expect(ttype) ≣ t = lexer.getToken();
if (t.token_type != ttype)
syntax_error();
return t;

The expect function returns the token t if there is no syntax_error(). So, if you
call expect(ID) and the next token is an ID, the returned value is the token
structure for the ID.
Simple Expression Grammar
E ➝ T PLUS E // T + E
E ➝ T // T
T ➝ F MULT T // T * E
T ➝ F // F
F ➝ NUM | ID | LPAREN E RPAREN // NUM | ID | (E)

void parse_E() // consumes E


{
parse_T(); // consumes T
t = lexer.peek(1);
if (t.token_type == PLUS)
{
expect(PLUS); // consumes +
parse_E(); // consumes E
}
else if ( (t.token_type == EOF) |
(t.token_type == RPAREN) )
{
return;
}
else
syntax_error();
}

Here you notice that I used expect(PLUS) instead of using getToken(). We could have
used getToken(), but expect(PLUS) makes it clear when reading the code which token is
being consumed.

Also, notice how we are using peek() when there are multiple valid possibilities for the
next token. If the next token is PLUS, then we continue parsing by consuming the PLUS
and calling parse_E(). If the token is EOF or RPARAN (the tokens that can follow an E),
then we return, otherwise, we detect syntax error.
Parsing by Example
E ➝ T PLUS E // T+E
E ➝ T // T
T ➝ F MULT T // T*E
T ➝ F // F
F ➝ NUM | ID | LPAREN E RPAREN // NUM | ID | (E)

void parse_T() // consumes T


{
parse_F(); // consumes F
t = lexer.peek(1);
if (t.token_type == MULT)
{
expect(MULT); // consumes *
parse_T(); // consumes T
}
else if ( (t.token_type == EOF) |
(t.token_type == PLUS) |
(t.token_type == RPAREN))
{
return;
}
else
syntax_error();
}

void parse_F() // consumes F


{
t = lexer.peek(1);
if (t.token_type == ID)
expect(ID); // F -> ID
else if (t.token_type == NUM) )
expect(NUM) ; // F -> NUM
else if (t.token_type == LPAREN)
{
expect(LPAREN); // LPAREN
parse_E(); // E
expect(RPAREN); // RPAREN
} else
syntax_error();
}
Step-by-Step execution
In the following I show a step-by-step execution of the code we
wrote in two different format

1. Illustration of how a “parse tree” is built

2. An equivalent illustration using call sequence


SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
call parse_T() T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) returns LPAREN T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(LPAREN) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(LPAREN) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1)
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(NUM) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

peek(1) E

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION
Since the token
was +, we conclude E
that T -> F
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

peek(1) E

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

expect(PLUS) E

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1)
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(NUM)
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
since the token is
RPAREN, we conclude T
that T is only F
F

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

Since the next token is E


RPAREN, we conclude
that E is only T
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

Now, we are done E


parsing E which is T+E
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(RPAREN) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(MULT)
T

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1)
T

( E )

F * T

E F

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(NUM) T

( E )

F * T

E F

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) T

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
peek(1) T

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

E
expect(RPAREN) T

( E

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION
peek(1)
E

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION
peek(1)
E

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE
expect(EOF) Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE
Input EXECUTION

( E )

F * T

E F

( T + E ) NUM

F T

NUM F

NUM
EOF
( ( 3 + 5 ) * 8 )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
SAMPLE
Input EXECUTION

E
since the token is
RPAREN, we conclude T
that E is only T
F

( E )

F * T

( T + E )

F T

NUM F

NUM
( ( 3 + 5 ) * 8 )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN); (
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
parse_term()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN); (
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()
peek(1);expect(NUM); 3
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

F parse_factor()
peek(1);expect(NUM); 3
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

F parse_factor()
peek(1);expect(NUM); 3
peek() +
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

peek(1);expect(PLUS); +
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS); +
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()
peek(1);expect(NUM); 5
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()
F peek(1);expect(NUM); 5
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( getToken()
peek(1); expect(LPAREN);
(
(
parse_expr()
parse_term()
parse_factor()
( peek(1); expect(LPAREN); (
parse_expr()

T F
parse_term()
parse_factor()
peek(1);expect(NUM); 3
peek() +
+ peek(1);expect(PLUS); +
parse_expr()
parse_term()
F parse_factor()
peek(1);expect(NUM); 5
peek() )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
peek() )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
peek() )
peek() )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek(1) *
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T Fparse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
gexpect(MULT) *
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()
parse_factor()
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()
parse_factor()
peek(1);expect(NUM) 8
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
peek(1);expect(NUM) 8
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
peek(1);expect(NUM) 8
peek(1) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

F E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

T F E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

T F E T F E
parse_term()
parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

T F E T F E
parse_term()
E parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3
peek() +

+ peek(1);expect(PLUS);
parse_expr()
+

T F E T F E
parse_term()
E parse_factor()

T F peek(1);expect(NUM); 5
E peek() )
peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
peek(1) EOF
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3

i
peek() +

F E +
n
peek(1);expect(PLUS); +
parse_expr()

p E T F E T
parse_term()
parse_factor()

u E T F peek(1);expect(NUM); 5
peek() )
t peek() )

) expect(RPAREN) )

peek() *

*
expect(RPAREN) *
parse_term()

F
parse_factor()
T peek(1)
peek(1);expect(NUM) 8
)
peek(1) )

) expect(RPAREN) )
peek(1) EOF
peek(1) EOF
peek(1) EOF
SAMPLE EXECUTION ((3+5)*8)

parse_input()
parse_expr()
parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()
parse_factor()

( peek(1); expect(LPAREN);
parse_expr()
(

parse_term()

T F parse_factor()
peek(1);expect(NUM); 3

F E
peek() +

peek(1);expect(PLUS); +
+ parse_expr()

T F E T
parse_term()
E parse_factor()

E T F
peek(1);expect(NUM); 5
peek() )
peek() )

expect(RPAREN) )

peek()) *
expect(RPAREN) *
parse_term()

*
parse_factor()
peek(1);expect(NUM) 8

T F
peek(1) )
peek(1) )
expect(RPAREN) )

)
peek(1) EOF
peek(1) EOF
peek(1) EOF

You might also like