File size: 7,577 Bytes
4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2fb8011 4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2fb8011 4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2dbf53a 4290b1a 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 2dbf53a 2fb8011 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
import streamlit as st
import numpy as np
import pandas as pd
# Function to remove left recursion
def removeLeftRecursion(rulesDiction):
store = {}
for lhs in rulesDiction:
alphaRules = []
betaRules = []
allrhs = rulesDiction[lhs]
for subrhs in allrhs:
if subrhs[0] == lhs:
alphaRules.append(subrhs[1:])
else:
betaRules.append(subrhs)
if len(alphaRules) != 0:
lhs_ = lhs + "'"
while (lhs_ in rulesDiction.keys()) or (lhs_ in store.keys()):
lhs_ += "'"
for b in range(len(betaRules)):
betaRules[b].append(lhs_)
rulesDiction[lhs] = betaRules
for a in range(len(alphaRules)):
alphaRules[a].append(lhs_)
alphaRules.append(['#'])
store[lhs_] = alphaRules
for left in store:
rulesDiction[left] = store[left]
return rulesDiction
# Function for Left Factoring
def LeftFactoring(rulesDiction):
newDict = {}
for lhs in rulesDiction:
allrhs = rulesDiction[lhs]
temp = dict()
for subrhs in allrhs:
if subrhs[0] not in temp.keys():
temp[subrhs[0]] = [subrhs]
else:
temp[subrhs[0]].append(subrhs)
new_rule = []
tempo_dict = {}
for term_key in temp:
allStartingWithTermKey = temp[term_key]
if len(allStartingWithTermKey) > 1:
lhs_ = lhs + "'"
while (lhs_ in rulesDiction.keys()) or (lhs_ in tempo_dict.keys()):
lhs_ += "'"
new_rule.append([term_key, lhs_])
ex_rules = []
for g in temp[term_key]:
ex_rules.append(g[1:])
tempo_dict[lhs_] = ex_rules
else:
new_rule.append(allStartingWithTermKey[0])
newDict[lhs] = new_rule
for key in tempo_dict:
newDict[key] = tempo_dict[key]
return newDict
# Function to compute the FIRST set
def first(symbol, grammar, first_sets):
if symbol in first_sets:
return first_sets[symbol]
first_set = set()
if symbol not in grammar:
first_set.add(symbol)
else:
for rule in grammar[symbol]:
if rule == ['#']:
first_set.add('#')
else:
for s in rule:
first_set |= first(s, grammar, first_sets)
if '#' not in first(s, grammar, first_sets):
break
first_sets[symbol] = first_set
return first_set
# Function to compute the FOLLOW set
def follow(symbol, grammar, start_symbol, follow_sets, first_sets):
if symbol in follow_sets:
return follow_sets[symbol]
follow_set = set()
if symbol == start_symbol:
follow_set.add('$')
for lhs in grammar:
for rule in grammar[lhs]:
for i, s in enumerate(rule):
if s == symbol:
if i + 1 < len(rule):
follow_set |= first(rule[i + 1], grammar, first_sets) - {'#'}
if i + 1 == len(rule) or '#' in first(rule[i + 1], grammar, first_sets):
follow_set |= follow(lhs, grammar, start_symbol, follow_sets, first_sets)
follow_sets[symbol] = follow_set
return follow_set
# Function to compute all FIRST sets
def computeAllFirsts(grammar):
first_sets = {}
for symbol in grammar:
first(symbol, grammar, first_sets)
return first_sets
# Function to compute all FOLLOW sets
def computeAllFollows(grammar, start_symbol, first_sets):
follow_sets = {}
for symbol in grammar:
follow(symbol, grammar, start_symbol, follow_sets, first_sets)
return follow_sets
# Function to create the LL(1) parsing table
def createParseTable(grammar, first_sets, follow_sets, terminals):
parse_table = {}
for lhs in grammar:
for rule in grammar[lhs]:
first_set = first(rule[0], grammar, first_sets)
for terminal in first_set - {'#'}:
if lhs not in parse_table:
parse_table[lhs] = {}
parse_table[lhs][terminal] = rule
if '#' in first_set:
for terminal in follow_sets[lhs]:
if lhs not in parse_table:
parse_table[lhs] = {}
parse_table[lhs][terminal] = rule
return parse_table
# Function to validate a string using the LL(1) parsing table
def validateStringUsingStackBuffer(parse_table, grammar_is_LL, terminals, input_string, term_userdef, start_symbol):
stack = [start_symbol]
input_string = input_string + ['$']
idx = 0
while stack:
top = stack[-1]
if top == input_string[idx]:
stack.pop()
idx += 1
elif top in parse_table and input_string[idx] in parse_table[top]:
rule = parse_table[top][input_string[idx]]
stack.pop()
if rule != ['#']:
stack.extend(reversed(rule))
else:
return "String is not valid."
if idx == len(input_string):
return "String is valid."
return "String is not valid."
# Main Streamlit App
def main():
st.title("Grammar Analyzer")
st.markdown("This app performs grammar analysis, including left recursion removal, left factoring, FIRST/FOLLOW set calculations, and LL(1) parsing.")
# Input Section
st.sidebar.header("Input Parameters")
start_symbol = st.text_input("Start Symbol (Non-terminal):", "S")
num_rules = st.number_input("Number of Grammar Rules:", min_value=1, value=4)
# Input rules dynamically based on the number of rules
grammar_rules = []
for i in range(num_rules):
rule = st.text_input(f"Rule {i + 1}:", f"S -> A k O")
grammar_rules.append(rule)
non_terminals = st.text_input("Non-Terminals (comma-separated):", "S, A, B, C")
terminals = st.text_input("Terminals (comma-separated):", "a, b, c, d, k, r, O")
# Process the inputs
if st.button("Analyze"):
# Parse the non-terminals and terminals
non_terminals_list = [nt.strip() for nt in non_terminals.split(",")]
terminals_list = [t.strip() for t in terminals.split(",")]
# Parse the grammar rules
grammar_dict = {}
for rule in grammar_rules:
lhs, rhs = rule.split("->")
rhs_options = rhs.split("|")
grammar_dict[lhs.strip()] = [option.strip().split() for option in rhs_options]
# Remove left recursion
grammar_dict = removeLeftRecursion(grammar_dict)
# Apply left factoring
grammar_dict = LeftFactoring(grammar_dict)
# Compute FIRST and FOLLOW sets
first_sets = computeAllFirsts(grammar_dict)
follow_sets = computeAllFollows(grammar_dict, start_symbol, first_sets)
# Generate parsing table
parse_table = createParseTable(grammar_dict, first_sets, follow_sets, terminals_list)
# Display the parsing table
st.subheader("Parsing Table")
st.write(parse_table)
# Validate the input string using the parsing table
input_string = st.text_input("Enter string to validate:", "a c")
validation_result = validateStringUsingStackBuffer(parse_table, True, terminals_list, input_string.split(), terminals_list, start_symbol)
st.write(validation_result)
if __name__ == "__main__":
main()
|