Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 13

1. What is the difference between the compilation in C++ and java?

C++ is a compiled language and compiles directly to machine code, meaning that the code is linked
directly to the hardware and will run faster than Java. Java is a bytecode language which compiles to
bytecode and runs on the JVM, meaning it is platform-independent and slower than C++.

2. Write the algorithm of predictive parsing using tables and parse x-2*y using top down

parsing based on the algorithm1

Algorithm:

1. Construct a parse table containing all possible terminal and non-terminal symbols, including the start
symbol

2. Using the parse table, form a parse tree containing all the terminal and non-terminal symbols

3. Choose any non-terminal from the root of the parse tree, enter it in the stack

4. Match the first symbol from the input string against the top of the stack

5. If the symbol is a terminal, Pop it from the stack & Match it with the same symbol from the input
string

6. If the symbol is a non-terminal, look up the corresponding productions in the parse table &

Push the symbols in the right side of the production into the stack in reverse order

7. Repeat steps 4-6 until all symbols in the stack and the input string are matched

Parse Tree Table:

Stack Input string Action

X x-2*y Pop X, push X → E

E x-2*y Pop E, push E → T + E

T + E x-2*y Pop T, push T → F

F + E x-2*y Pop F, push F → (E)

(E) + E x-2*y Pop (, Push E → T + E


E + E x-2*y Pop E , Push T → F

F + E x-2*y Pop F, push F → x

x + E x-2*y Pop x, Match with x from input string

E -2*y Pop E, Push E → T

T -2*y Pop T, Push T→ F

F -2*y Pop F, Push F → * F

*F -2*y Pop *, Match with * from input string

F -2*y Pop F, Push F → y

y -2*y Pop F, Match with y from input string

ε -2*y Pop ε, Push E → -T

-T -2*y Pop -, Match with - from input string

T 2*y Pop T, Push T → F

F 2*y Pop F, Push F → 2

2 2*y Pop 2, Match with 2 from input string

F *y Pop F, Push F → * F

*F *y Pop * , Match with * from input string

F *y Pop F, Push F → y

y *y Pop y, Match with y from input string

3. Explain how shift reduce parsing using ACTION/GOTO table is implemented using

example

2Shift-Reduce Parsing using ACTION/GOTO tables is a type of bottom-up parsing. It goes through a given
grammar and builds up the parse tree from the bottom up.

A Shift-Reduce Parser first looks at an input string and uses a set of Parser Actions to determine if the
string can be shifted (moved) to the right or reduced. When shifting, the parser moves the input string
one symbol to the right, and when reducing, the parser will try to match the symbols of the input string
with a part of the grammar and if it matches, it will replace the matched part of the input string with a
non-terminal and add to the parse tree.

For example, consider the following grammar and input string:

Grammar:

Sentence → Noun Phrase Verb Phrase

Noun Phrase → Article Noun

Verb Phrase → Verb Noun

Article → the

Noun → book

Verb → read

Input String: the book read

The ACTION/GOTO table would be represented as:

ACTION GOTO

----------------------------------------------------------------

State | the | book | read | NounPhrase | VerbPhrase | Sentence

----------------------------------------------------------------

1 S4 S5 - Goto 2 Goto 3 -

2 - S6 - - - -

3 - - S7 - - -

4 - - - - - Accept
5 - - - - - Reduce Noun

6 - - - - - Reduce Noun Phrase

7 - - - - Reduce Verb Phrase -

The parser will start in state 1. It will then take action corresponding to the symbol at the start of the
input string. In this case, the first symbol is ‘the’, and so the parser will shift to state 4. From state 4, the
parser will see the symbol ‘book’ and shift to state 5. From state 5, the parser will see the symbol ‘read’
and reduce Noun. This will replace the matched part of the input string (‘book read’) with a non-
terminal (‘NounPhrase’). The parser will then shift to state 6. From state 6, the parser will reduce Noun
Phrase and this will replace the matched part of the input string (‘the NounPhrase’) with a non-terminal
(‘VerbPhrase’). From state 3, the parser will shift to state 7 and then reduce Verb Phrase, replacing the
matched part of the input string (‘the VerbPhrase’) with the non-terminal (‘Sentence’). The parser will
then move to state 4 and accept the input string.

4. Show LALR algorithm works

4𝐌𝐀: LALR (Look-Ahead LR) is a type of bottom-up parsing algorithm that is similar to LR (Left-to-Right)
parsing, but with a smaller parsing table. LALR uses look-ahead symbols to disambiguate between
different grammar rules and reduce the size of the parsing table, making it more practical to use in real-
world applications.

Here is an outline of how the LALR algorithm works:

1. Construct a parse table from the given grammar. The parse table has two parts: a state transition
table (GOTO) and an action table. The GOTO table is used to determine which state to transition to after
shifting a symbol onto the stack, and the action table is used to determine whether to shift or reduce at
each step.

2. Initialize a stack and a current position in the input string. Push the initial state (0) onto the stack and
set the current position to the beginning of the input string.

3. Look up the current symbol in the input string and the top state on the stack in the action table.

4. If the entry in the action table is "shift X", where X is a state, push the current symbol onto the stack
and transition to state X.

5. If the entry in the action table is "reduce A -> B C", where A, B, and C are grammar symbols, pop the
top two symbols (B and C) from the stack and replace them with symbol A. Then, look up A and the new
top state on the stack in the GOTO table and push the resulting state onto the stack.
6. Repeat steps 3-5 until the input string has been fully processed and the stack contains only the initial
state and the goal non-terminal symbol.

Here is an example of how the LALR algorithm might be used to parse the input string "2 + 3 * 4":

1. Construct the parse table from the given grammar. The GOTO table might contain the following
entries:

- GOTO0, E = 6

- GOTO6, T = 7

- GOTO7, F = 8

- GOTO8, \* = 9

- GOTO9, F = 10

- GOTO6, F = 11

- GOTO7, + = 12

- GOTO12, T = 13

- GOTO13, F = 14

- GOTO14, \* = 15

- GOTO15, F = 16

And the action table might contain the following entries:

- ACTION0, 2 = shift 3

- ACTION3, + = shift 5

- ACTION5, 2 = shift 3

- ACTION3, \* = shift 6

- ACTION6, 2 = shift 3

- ACTION3, $ = reduce "E -> T"


- ACTION5, \* = shift 6

- ACTION6, 2 = shift 3

- ACTION6, + = reduce "T -> F"

- ACTION6, \* = reduce "T -> F"

- ACTION6, $ = reduce "T -> F"

- ACTION7, + = reduce "E -> E + T"

- ACTION7, \* = reduce "E -> E * T"

- ACTION7, $ = reduce "E -> E

5. Explain how item-set construction is carried out using example6

Item-set construction is a technique used in the construction of LR parsing tables. Given a context-free
grammar, the goal of item-set construction is to create a set of "items" that represent the possible steps
of a parse, and to group these items into sets called "item sets".

To carry out item-set construction, you can follow these steps:

1. Begin with the set of all grammar rules, and create a single item set containing the items "A -> alpha .
B beta", where A is a non-terminal symbol, alpha is a sequence of symbols, and beta is a sequence of
symbols. These items represent the possible steps in a parse, with the "dot" symbol (.) indicating the
current position in the rule.

2. For each item set, do the following:

- For each item of the form "A -> alpha . B beta" in the item set, add the item "B -> . gamma" for each
production rule "B -> gamma" in the grammar.

- For each item of the form "A -> alpha B . beta" in the item set, add the item "B -> gamma . delta" for
each production rule "B -> gamma delta" in the grammar.

3. Repeat step 2 until no new items can be added to any item set.
Here is an example of how item-set construction might be carried out for the grammar:

E -> E + T

E -> T

T -> T * F

T -> F

F -> (E)

F -> id

1. Begin with the set of all grammar rules, and create a single item set containing the following items:

- E -> . E + T

- E -> . T

- T -> . T * F

- T -> . F

- F -> . (E)

- F -> . id

2. For each item set, do the following:

- For each item of the form "A -> alpha . B beta" in the item set, add the item "B -> . gamma" for each
production rule "B -> gamma" in the grammar.

- For each item of the form "A -> alpha B . beta" in the item set, add the item "B -> gamma . delta" for
each production rule "B -> gamma delta" in the grammar.

This results in the following item sets:

Item set 1:
- E -> . E + T

- E -> . T

- T -> . T * F

- T -> . F

- F -> . (E)

- F -> . id

- T -> T . * F

- F -> ( . E )

- E -> E . + T

Item set 2:

- T -> T * . F

- F -> . (E)

- F -> . id

- E -> T .

- T -> F .

- F -> (E) .

- F -> id .

Item set 3:

- E -> E + T .

- T -> T * F .

- F -> (E) .

- F -> id .
Item set 4:

- F -> (E) .

- F -> id .

Item set 5:

- F -> (E) .

- F -> id .

Item set 6:

- F -> (

6. Discuss how conflicts are resolved during parsing(Example: shift-reduce conflict) give

example9

During parsing, conflicts can arise when the parser has to choose between two or more options for the
next step in constructing the parse tree. One common type of conflict is a shift-reduce conflict, which
occurs when the parser has to decide whether to shift the next token onto the stack (i.e., postponing its
reduction) or to reduce the current contents of the stack (i.e., combining them into a single unit).

An example of a shift-reduce conflict is shown below:

Input: "1 + 2 * 3"

Stack: 1 + 2

Here, the parser has to choose between shifting the next token (3) onto the stack or reducing the
current stack contents (1 + 2) to a single unit. The choice depends on the operator precedence: if * has
higher precedence than +, then the parser should reduce the stack contents to a single unit before
shifting 3 onto the stack. If + has higher precedence than *, then the parser should shift 3 onto the stack
before reducing the current stack contents.
In this case, the correct choice is to reduce the stack contents to a single unit, since * has higher
precedence than +. The resulting stack would be:

Stack: (1 + 2) * 3

This conflict can be resolved using operator precedence rules, which specify the order in which
operations should be performed. However, other conflicts may require more complex resolution
strategies, such as using context-sensitive rules or consulting a parse table

9. Construct first() and follow() for

S->aBDh

B->cC

C->bC/ᵋ

D->EF

E->g/ᵋ

F->f/ᵋ10

𝐏𝐈: The first() function returns the set of terminal symbols that can begin a string derived from a given
non-terminal symbol. The follow() function returns the set of terminal symbols that can immediately
follow a given non-terminal symbol in some string derived from the grammar.

For this grammar, we can define the first() and follow() functions as follows:
first(S) = {a}

first(B) = {c}

first(C) = {b}

first(D) = {g, ε}

first(E) = {g, ε}

first(F) = {f, ε}

follow(S) = {$}

follow(B) = {h}

follow(C) = {c, h}

follow(D) = {h}

follow(E) = {f}

follow(F) = {h}

Here, $ is a special symbol that represents the end of input.

To compute these sets, we can use the following rules:

first(X) = {x} if X -> x is a production

first(X) = {first(Y) | Y appears in the right-hand side of a production of the form X -> YZ}

first(X) = {ε} if X -> ε is a production, and X does not appear in the right-hand side of any other
production

follow(X) = {follow(Y) | Y appears in the right-hand side of a production of the form YZ -> X}
follow(X) = {first(Y) - {ε} | Y appears in the right-hand side of a production of the form XY -> XZ, and ε is
in first(Y)}

follow(S) = {$}

Using these rules, we can compute the first() and follow() sets for the given grammar as follows:

first(S) = {a}

first(B) = {c}

first(C) = {b}

first(D) = {g, ε}

first(E) = {g, ε}

first(F) = {f, ε}

follow(S) = {$}

follow(B) = {h}

follow(C) = {c, h}

follow(D) = {h}

follow(E) = {f}

follow(F) = {h}

10. How to Construct LL(1) parser? Explain in detail

A LL(1) parser is an efficient predictive parser that uses a top-down approach based on a set of Left-to-
right scan of the input with a single current input symbol and a single stack symbol. It parses the input
and produces a parse tree.

Steps in constructing a LL(1) parser:


1. Building the grammar: The first step in building a LL(1) parser is to create a grammar that conforms to
the LL(1) rules. This grammar should contain all the productions and their respective first and follow
sets. The productions should be designed in such a way that the productions do not produce any left-
recursion and should not contain any multiple options.

2. Building the Parsing Table: The next step is to build the parsing table. The parsing table contains
entries which link a non-terminal symbol to a terminal symbol in the grammar. Each of these entries
contains either a production rule to be used or an error indication.

3. Traversing the Parsing Table: The parsing table is then traversed in the same way as a normal LL(1)
parser would. The parser starts at the beginning symbol of the grammar, and follows the links in the
parsing table. If the parser encounters a terminal symbol, it marks it as visited. If the parser encounters a
non-terminal symbol, it uses that symbol's row in the parsing table to determine which production rule
to use.

4. Generating the Parse Tree: Finally, the parser uses the parse tree that it created while traversing the
parsing table to generate the parse tree. The parse tree is a recursive structure which contains the
assigned meanings to the non-terminal symbols. The parse tree is then used for generating the parse
code for the given input string.

You might also like