Skip to main content

16. Construct a Shift Reduce Parser for a given language.


Constructing a Shift-Reduce Parser involves implementing a parsing algorithm that shifts tokens onto a stack and then reduces them using production rules. Since a full implementation can be quite extensive, I'll provide you with a basic example in Python and explain each line of code. Note that this example will use a simple grammar for illustration purposes.


**Example Grammar**:

```

E -> E + T | T

T -> T * F | F

F -> ( E ) | id

```


**Python Shift-Reduce Parser Example**:


```python

# Input string to be parsed

input_string = "id + id * id"


# Define grammar rules as a dictionary

grammar = {

    "E": [["E", "+", "T"], ["T"]],

    "T": [["T", "*", "F"], ["F"]],

    "F": [["(", "E", ")"], ["id"]]

}


# Define terminals and non-terminals

terminals = set(["+", "*", "(", ")", "id"])

non_terminals = set(["E", "T", "F"])


# Initialize the stack and add the starting symbol

stack = ["$"]  # $ is the end-marker

stack.append("E")


# Initialize the input pointer

input_ptr = 0


# Parsing algorithm

while len(stack) > 0:

    top = stack[-1]

    current_token = input_string[input_ptr]


    if top in terminals:

        if top == current_token:

            stack.pop()

            input_ptr += 1

        else:

            print("Error: Unexpected token")

            break

    elif top in non_terminals:

        if current_token in terminals:

            production_found = False

            for production in grammar[top]:

                if production[0] == current_token:

                    stack.pop()

                    for symbol in reversed(production[1:]):

                        if symbol != "ε":  # ε is epsilon, representing an empty string

                            stack.append(symbol)

                    production_found = True

                    break

            if not production_found:

                print("Error: No production found")

                break

        else:

            print("Error: Unexpected token")

            break

    else:

        print("Error: Invalid symbol")

        break


if len(stack) == 0 and input_ptr == len(input_string):

    print("Parsing successful")

else:

    print("Parsing failed")

```


**Explanation**:


1. We start by defining the input string and the grammar rules.

2. Terminals and non-terminals are defined separately.

3. The stack is initialized with the end-marker `$` and the starting symbol `E`.

4. We start parsing using a loop that continues until the stack is empty.

5. For each iteration, we check the top of the stack and the current input token.

6. If the top is a terminal, we compare it with the current token. If they match, we pop the stack and advance the input pointer.

7. If the top is a non-terminal and the current token is a terminal, we find a production that matches and replace the non-terminal with the right-hand side of the production.

8. If the top is a non-terminal and the current token is not a terminal, we report an error.

9. If the top is not a terminal or a non-terminal, we report an error.

10. After the loop, we check if both the stack is empty and the input pointer has reached the end of the input string to determine parsing success or failure.


Please note that this is a simplified example. Real-world parsers would involve error handling, precedence rules, and more complex grammars.


Comments

Popular posts from this blog

6. Generate a YACC specification to recognize a valid arithmetic expression that uses operators +, – , *,/ and parenthesis.

Below is a YACC specification for recognizing valid arithmetic expressions that involve operators (+, -, *, /) and parentheses. I'll explain each line of the code afterward: ```yacc %{ #include <stdio.h> %} %token NUMBER %left '+' '-' %left '*' '/' %% expression: expression '+' expression            | expression '-' expression            | expression '*' expression            | expression '/' expression            | '(' expression ')'            | NUMBER            ; %% int yylex() {     // Code for tokenizing input and returning tokens } void yyerror(const char *s) {     fprintf(stderr, "Error: %s\n", s); } int main() {     yyparse();     return 0; } ``` Now, let's break down the YACC specification line by line: 1. `%{` ... `%}`: This is the C code section where y...

ktu 2019 Cse Complier programing Lab Syllabus

 1Design and implement a lexical analyzer using C language to recognize all valid tokens  in the input program. The lexical analyzer should ignore redundant spaces, tabs and  newlines. It should also ignore comments. 2. Implement a Lexical Analyzer for a given program using Lex Tool. 3. Write a lex program to display the number of lines, words and characters in an input text. 4. Write a LEX Program to convert the substring abc to ABC from the given input string. 5. Write a lex program to find out the total number of vowels and consonants from the given  input string. 6. Generate a YACC specification to recognize a valid arithmetic expression that uses  operators +, – , *,/ and parenthesis. 7. Generate a YACC specification to recognize a valid identifier which starts with a letter  followed by any number of letters or digits.   8. Implementation of Calculator using LEX and YACC  9. Convert the BNF rules into YACC form and write code to generat...

1, Design and implement a lexical analyzer using C language to recognize all valid tokens in the input program. The lexical analyzer should ignore redundant spaces, tabs and newlines. It should also ignore comments

#include <stdio.h> #include <ctype.h> int main() {     char c;     while ((c = getchar()) != EOF) {         if (isspace(c)) {             // Ignore whitespace, tabs, and newlines             continue;         }         if (c == '/') {             // Check for comments             char nextChar = getchar();             if (nextChar == '/') {                 while ((nextChar = getchar()) != '\n');         ...