HyperDbg/hyperdbg/script-engine/python/ll1_parser.py

938 lines
32 KiB
Python
Raw Normal View History

2020-10-24 15:54:48 +03:30
"""
2021-02-25 18:44:26 +03:30
* @file ll1_parse_table_generator.py
2020-10-24 15:54:48 +03:30
* @author M.H. Gholamrezei (gholamrezaei.mh@gmail.com)
2021-02-25 18:44:26 +03:30
* @brief Script engine LL(1) Parse table generator
* @details This program reads grammar from Greammar.txt file
2020-11-28 19:39:08 +03:30
* placed in the same directory of the program
2020-12-01 22:26:46 +03:30
* and creates parse_table.h and parse_table.c which is
* used by the parser of script engine.
2020-10-24 15:54:48 +03:30
* @version 0.1
* @date 2020-10-24
*
* @copyright This project is released under the GNU Public License v3.
"""
2021-02-25 18:44:26 +03:30
from util import *
from lalr1_parser import *
2020-10-24 15:54:48 +03:30
2021-02-25 18:44:26 +03:30
class LL1Parser:
def __init__(self, SourceFile, HeaderFile, CommonHeaderFile):
2020-12-01 22:26:46 +03:30
# The file which contains the grammar of the language
self.GrammarFile = open("Grammar.txt", "r")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# The file which is used by parser for parsing the input
2021-02-25 18:44:26 +03:30
self.SourceFile = SourceFile
self.HeaderFile = HeaderFile
self.CommonHeaderFile = CommonHeaderFile
2020-12-01 22:26:46 +03:30
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Lists which used for storing the rules:
# Right Hand Side(Rhs)
self.RhsList = []
2020-12-01 22:26:46 +03:30
2020-10-24 15:54:48 +03:30
# Left Hand Side(Lhs)
self.LhsList = []
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Set of all termials and noneterminals
self.TerminalSet = set()
self.NonTerminalSet = set()
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Start variable
self.Start = ""
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# maximum of "Right Hand Side(Rhs)" length
self.MAXIMUM_RHS_LEN = 0
2020-10-20 19:35:15 +03:30
2021-08-20 22:36:25 +04:30
self.SPECIAL_TOKENS = ['%', '+', '~', '++', '-', '--', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^"]
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# INVALID rule indicator
2021-02-25 18:44:26 +03:30
self.INVALID = -99
2020-10-20 19:35:15 +03:30
2020-12-02 03:20:34 +03:30
self.FunctionsDict = dict()
2021-04-13 22:53:02 +04:30
self.OperatorsTwoOperand = []
self.OperatorsOneOperand = []
2020-12-02 18:11:03 +03:30
self.RegistersList = []
self.PseudoRegistersList = []
2020-12-01 22:26:46 +03:30
self.keywordList = []
2021-04-11 23:31:36 +04:30
self.SemantiRulesList = []
2020-12-01 22:26:46 +03:30
2020-12-02 18:11:03 +03:30
2020-10-24 15:54:48 +03:30
# Dictionaries used for storing first and follow sets
self.FirstDict = dict()
self.FollowDict = dict()
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def Run(self):
2020-12-01 22:26:46 +03:30
# Read grammar from input file and intialize grammar related variables
self.ReadGrammar()
2020-10-24 15:54:48 +03:30
# Calculate "First Set" for all nonterminals and print it
self.FindAllFirsts()
2020-12-01 22:26:46 +03:30
# print("Firsts:")
# self.PrintFirsts()
# print("________________________________________________________________________________")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Calculate "Follow Set" for all nonterminals and print it
self.FindAllFollows()
2020-12-01 22:26:46 +03:30
# print("Follows:")
# self.PrintFollows()
# print("________________________________________________________________________________")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Calculate "Prdicted Set" for each rule and print it
self.FindAllPredicts()
2020-12-01 22:26:46 +03:30
# print("Predicts:")
# self.print_predicts()
# print("________________________________________________________________________________")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Fills "Parse Table" according to calculted "Predicted Set" and print "Parse Table"
self.FillParseTable()
2021-02-10 18:07:25 +03:30
# print("Parse Table:")
# self.PrintParseTable()
# print()
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
# Prints variables that are needed for parser for parsing into the output file
self.HeaderFile.write("#pragma once\n")
2020-12-01 22:26:46 +03:30
self.HeaderFile.write("#ifndef PARSE_TABLE_H\n")
self.HeaderFile.write("#define PARSE_TABLE_H\n")
self.HeaderFile.write("#define RULES_COUNT " + str(len(self.LhsList)) + "\n")
self.HeaderFile.write("#define TERMINAL_COUNT " + str(len(list(self.TerminalSet))) + "\n")
self.HeaderFile.write("#define NONETERMINAL_COUNT " + str(len(list(self.NonTerminalList))) + "\n")
self.HeaderFile.write("#define START_VARIABLE " + "\"" + self.Start +"\"\n")
self.HeaderFile.write("#define MAX_RHS_LEN " + str(self.MAXIMUM_RHS_LEN) +"\n")
self.HeaderFile.write("#define KEYWORD_LIST_LENGTH " + str(len(self.keywordList)) +"\n")
2021-04-13 22:53:02 +04:30
self.HeaderFile.write("#define OPERATORS_ONE_OPERAND_LIST_LENGTH " + str(len(self.OperatorsOneOperand)) + "\n")
self.HeaderFile.write("#define OPERATORS_TWO_OPERAND_LIST_LENGTH " + str(len(self.OperatorsTwoOperand)) + "\n")
2020-12-02 18:11:03 +03:30
self.HeaderFile.write("#define REGISTER_MAP_LIST_LENGTH " + str(len(self.RegistersList))+ "\n")
self.HeaderFile.write("#define PSEUDO_REGISTER_MAP_LIST_LENGTH " + str(len(self.PseudoRegistersList))+ "\n")
2021-04-13 22:53:02 +04:30
self.HeaderFile.write("#define SEMANTIC_RULES_MAP_LIST_LENGTH " + str(len(self.keywordList) + len(self.OperatorsOneOperand) + len(self.OperatorsTwoOperand) + len(self.SemantiRulesList))+ "\n")
2020-12-02 03:20:34 +03:30
for Key in self.FunctionsDict:
self.HeaderFile.write("#define "+ Key[1:].upper() + "_LENGTH "+ str(len(self.FunctionsDict[Key]))+"\n")
2020-12-01 22:26:46 +03:30
2021-06-11 12:46:41 +04:30
self.SourceFile.write("#include \"pch.h\"\n")
2020-10-24 15:54:48 +03:30
2020-12-01 22:26:46 +03:30
# Prints Rules into output files
2020-10-24 15:54:48 +03:30
self.WriteLhsList()
self.WriteRhsList()
2020-12-01 22:26:46 +03:30
# Prints size of each Rhs into output files
2020-10-24 15:54:48 +03:30
self.WriteRhsSize()
2020-12-01 22:26:46 +03:30
# Prints noneterminals and Terminal into output files
2020-10-24 15:54:48 +03:30
self.WriteNoneTermianlList()
self.WriteTerminalList()
2020-12-01 22:26:46 +03:30
# Prints "Parse Table" into output files
2020-10-24 15:54:48 +03:30
self.WriteParseTable()
2020-12-01 22:26:46 +03:30
# Prints Keywords list into output files
self.WriteKeywordList()
2020-10-24 15:54:48 +03:30
2020-12-02 03:20:34 +03:30
# Prints Operators List into output files
self.WriteOperatorsList()
2020-12-02 02:32:49 +03:30
# Prints Maps into outpu files
self.WriteMaps()
2020-12-02 03:20:34 +03:30
2020-12-02 02:32:49 +03:30
2021-02-25 18:44:26 +03:30
2020-12-02 18:11:03 +03:30
self.WriteSemanticMaps()
self.WriteRegisterMaps()
self.WritePseudoRegMaps()
2020-12-01 22:26:46 +03:30
# Closes Grammar Input File
self.GrammarFile.close()
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
def SetLalr(self, Lalr, LalrParseTable):
self.Lalr = Lalr
self.LalrParseTable = LalrParseTable
2020-10-24 15:54:48 +03:30
# This function simulates of script engine parser in ScriptEngine.C in
# order to test the generated "Parse Table"
def Parse(self, Tokens):
# Initialize Parse Stack
Stack = []
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Initialize Match Stack
MatchedStack = []
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Push the end of stack indicator into stack
Stack.append("$")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Push start variable into stack
Stack.append(self.Start)
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# Assign top variale an invalid vlaue
Top = ""
# Read input
Tokens, CurrentIn = Read(Tokens)
# Temporary vlaues counter initialized with 0 value
TempCounter = 0
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# While Stack is not empty repeat
while Top != "$":
# Read top of stack
Top = GetTop(Stack)
2021-02-25 18:44:26 +03:30
# print(Stack)
# print("Top:", Top)
# print("CurrentIn:", CurrentIn, "\n\n")
# x = input()
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
2020-10-24 15:54:48 +03:30
if self.IsNoneTerminal(Top):
2021-02-25 18:44:26 +03:30
if Top == "BOOLEAN_EXPRESSION":
print("Top == BOOLEAN_EXPRESSION:")
2021-02-25 18:44:26 +03:30
print(Stack)
print(Tokens)
print(CurrentIn)
2021-02-25 18:44:26 +03:30
print("=====================================\n\n")
Stack.pop()
2021-02-25 18:44:26 +03:30
#------------------------------------------------------
# Get BE Tokens
BETokensSize = 0
OpenParanthesesCount = 1
i = 0
while True:
TempToken = Tokens[i]
i +=1
if TempToken == '(' :
OpenParanthesesCount += 1
BETokensSize += 1
elif TempToken == ')':
OpenParanthesesCount -= 1
if OpenParanthesesCount == 0:
break
else:
BETokensSize +=1
else:
BETokensSize +=1
print("TempToken: ", end = "")
print(TempToken)
print("BETokensSize: ", end = "")
print(BETokensSize)
# BETokens.append("$end")
print("BETokensSize: ", end = "")
print(BETokensSize)
y = input()
NewTokens = [CurrentIn]
for x in Tokens:
NewTokens.append(x)
#------------------------------------------------------
Tokens = self.Lalr.Parse(NewTokens, BETokensSize + 1)
2021-02-25 18:44:26 +03:30
# x = input()
print("after lalr parsing:")
print(Stack)
print(Tokens)
print("=====================================\n\n")
2020-10-20 19:35:15 +03:30
CurrentIn = Tokens[0]
2021-02-25 18:44:26 +03:30
if (len(Tokens) > 1):
Tokens = Tokens[1:]
# x = input()
else:
Id = self.ParseTable[self.GetNoneTerminalId(Top)][self.GetTerminalId(CurrentIn)]
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
# Error Handling
if Id == -1:
print("1)Error in input!")
print(Tokens)
print(Stack)
print("Top: ", Top)
print("CurrentIn: ", CurrentIn)
print("\n\n")
exit()
2020-10-20 19:35:15 +03:30
2021-02-25 18:44:26 +03:30
Stack.pop()
Rhs = self.RhsList[Id]
if Rhs != ["eps"]:
for Symbol in reversed(Rhs):
Stack.append(Symbol)
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
elif self.IsSemanticRule(Top):
if Top == "@PUSH":
Stack.pop()
Top = GetTop(Stack)
if Top == CurrentIn:
MatchedStack.append(Top)
Tokens, CurrentIn = Read(Tokens)
2020-10-20 19:35:15 +03:30
else:
print("2)Error in input!")
2020-10-24 15:54:48 +03:30
exit()
elif Top == "@JZ":
print("JZ:")
2021-02-25 18:44:26 +03:30
print(Stack)
print(Tokens)
print("\n\n")
y = input()
2021-02-25 18:44:26 +03:30
elif Top == "@JZCMPL":
2021-04-11 18:27:23 +04:30
print("JZCOMPELETED:")
print(Stack)
print(Tokens)
print("\n\n")
y = input()
2021-02-25 18:44:26 +03:30
2020-10-20 19:35:15 +03:30
else:
2020-10-24 15:54:48 +03:30
Op0 = MatchedStack.pop()
2020-10-28 12:29:30 +03:30
if Top == "@PRINT":
print(Top,"\t", Op0 )
elif Top == "@MOV":
Op1 = MatchedStack.pop()
2020-10-24 15:54:48 +03:30
print(Top,"\t", Op1, ", ", Op0 )
2020-10-20 19:35:15 +03:30
else:
2021-02-25 18:44:26 +03:30
pass
2020-10-28 12:29:30 +03:30
Op1 = MatchedStack.pop()
2020-10-24 15:54:48 +03:30
MatchedStack.append("t" + str(TempCounter))
print(Top, "\t", "t"+ str(TempCounter), ", ", Op1, ",", Op0 )
TempCounter += 1
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
Stack.pop()
2020-10-20 19:35:15 +03:30
else: # Terminal
2021-02-25 18:44:26 +03:30
2020-10-24 15:54:48 +03:30
CurrentIn = Tokens[0]
if (len(Tokens) > 1):
Tokens = Tokens[1:]
Stack.pop()
return MatchedStack
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
def ReadGrammar(self):
2020-10-24 15:54:48 +03:30
Flag = 1
2020-12-01 22:26:46 +03:30
Counter = -1
for Line in self.GrammarFile:
Counter += 1
2020-10-24 15:54:48 +03:30
Line = Line.strip()
if Line == "" or Line[0] == "#":
2020-10-20 19:35:15 +03:30
continue
2020-12-01 22:26:46 +03:30
elif Line[0] == ".":
L = Line.split("->")
Elements = L[1].split(" ")
2021-04-13 22:53:02 +04:30
if L[0][1:] == "OperatorsTwoOperand":
self.OperatorsTwoOperand += Elements
continue
if L[0][1:] == "OperatorsOneOperand":
self.OperatorsOneOperand += Elements
2020-12-02 18:11:03 +03:30
continue
2021-04-11 23:31:36 +04:30
elif L[0][1:] == "SemantiRules":
self.SemantiRulesList += Elements
continue
2020-12-02 18:11:03 +03:30
elif L[0][1:] == "Registers":
self.RegistersList += Elements
continue
elif L[0][1:] == "PseudoRegisters":
self.PseudoRegistersList += Elements
continue
2020-12-02 03:20:34 +03:30
self.FunctionsDict[L[0]] = Elements
2020-12-01 22:26:46 +03:30
continue
2020-10-24 15:54:48 +03:30
L = Line.split("->")
Lhs = L[0]
Rhs = L[1].split(" ")
2020-12-01 22:26:46 +03:30
HasMapKeyword = False
MapKeywordIdx1 = 0
MapKeywordIdx2 = 0
Idx = 0
2020-10-24 15:54:48 +03:30
for X in Rhs:
2020-12-01 22:26:46 +03:30
if X[0] == ".":
HasMapKeyword = True
MapKeywordIdx1 = Idx
elif X[0] == "@":
if X[1] == ".":
MapKeywordIdx2 = Idx
2021-04-11 18:27:23 +04:30
2020-12-01 22:26:46 +03:30
Idx += 1
if not HasMapKeyword:
self.NonTerminalSet.add(Lhs)
self.LhsList.append(Lhs)
self.RhsList.append(Rhs)
for X in Rhs:
if not self.IsNoneTerminal(X) and not self.IsSemanticRule(X) and not X=="eps":
self.TerminalSet.add(X)
2021-04-11 23:31:36 +04:30
if self.IsSemanticRule(X):
pass
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
else:
2020-12-02 03:20:34 +03:30
for value in self.FunctionsDict[Rhs[MapKeywordIdx1]]:
2020-12-01 22:26:46 +03:30
RhsTemp =list(Rhs)
RhsTemp[MapKeywordIdx1] = value
RhsTemp[MapKeywordIdx2] = "@" + value.upper()
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
self.keywordList.append(value)
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
self.NonTerminalSet.add(Lhs)
self.LhsList.append(Lhs)
self.RhsList.append(RhsTemp)
for X in RhsTemp:
if not self.IsNoneTerminal(X) and not self.IsSemanticRule(X) and not X=="eps":
self.TerminalSet.add(X)
2020-10-24 15:54:48 +03:30
if Flag:
Flag = 0
self.Start = Lhs
self.MAXIMUM_RHS_LEN = max(self.MAXIMUM_RHS_LEN, len(Rhs))
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
self.TerminalSet.add("$")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
self.NonTerminalList = list(self.NonTerminalSet)
2020-12-01 22:26:46 +03:30
2020-10-24 15:54:48 +03:30
self.TerminalList = list(self.TerminalSet)
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
2020-12-02 18:11:03 +03:30
def WriteSemanticMaps(self):
Counter = 0
2021-04-13 22:53:02 +04:30
for X in self.OperatorsOneOperand:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
Counter += 1
for X in self.OperatorsTwoOperand:
2020-12-02 18:11:03 +03:30
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
Counter += 1
2021-04-11 23:31:36 +04:30
for X in self.SemantiRulesList:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
Counter += 1
2020-12-02 18:11:03 +03:30
for X in self.keywordList:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
Counter += 1
2021-02-25 19:09:13 +03:30
2020-12-02 18:11:03 +03:30
self.SourceFile.write("const SYMBOL_MAP SemanticRulesMapList[]= {\n")
self.HeaderFile.write("extern const SYMBOL_MAP SemanticRulesMapList[];\n")
2021-04-13 22:53:02 +04:30
for X in self.OperatorsOneOperand:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
for X in self.OperatorsTwoOperand:
2020-12-02 18:11:03 +03:30
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
2021-04-11 23:31:36 +04:30
for X in self.SemantiRulesList:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
2020-12-02 18:11:03 +03:30
for X in self.keywordList:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
self.SourceFile.write("};\n")
2020-12-01 22:26:46 +03:30
2020-10-20 19:35:15 +03:30
2020-12-02 18:11:03 +03:30
def WriteRegisterMaps(self):
2021-03-11 12:49:49 +03:30
self.CommonHeaderFile.write("typedef enum REGS_ENUM {\n")
Counter = 0
for X in self.RegistersList:
2021-03-11 15:48:34 +03:30
if Counter == len(self.RegistersList)-1:
self.CommonHeaderFile.write("\t" + "REGISTER_" + X.upper() + " = " + str(Counter) + "\n")
else:
2021-03-11 12:49:49 +03:30
self.CommonHeaderFile.write("\t" + "REGISTER_" + X.upper() + " = " + str(Counter) + ",\n")
2021-03-11 15:48:34 +03:30
Counter += 1
self.CommonHeaderFile.write("\n} REGS_ENUM;\n\n")
self.CommonHeaderFile.write("static const char *const RegistersNames[] = {\n")
Counter = 0
for X in self.RegistersList:
if Counter == len(self.RegistersList)-1:
self.CommonHeaderFile.write("\t" + "\"" + X + "\"")
2021-03-11 12:49:49 +03:30
else:
2021-03-11 15:48:34 +03:30
if (Counter + 1) % 8 == 0:
self.CommonHeaderFile.write("" + "\"" + X + "\",\n")
2021-03-11 15:48:34 +03:30
else:
self.CommonHeaderFile.write("" + "\"" + X + "\", ")
2021-03-11 15:48:34 +03:30
2021-03-11 12:49:49 +03:30
Counter += 1
2021-03-11 15:48:34 +03:30
self.CommonHeaderFile.write("\n};\n\n")
2020-12-02 18:11:03 +03:30
self.SourceFile.write("const SYMBOL_MAP RegisterMapList[]= {\n")
self.HeaderFile.write("extern const SYMBOL_MAP RegisterMapList[];\n")
Counter = 0
for X in self.RegistersList:
if Counter == len(self.RegistersList)-1:
self.SourceFile.write("{\"" + X + "\", "+ "REGISTER_" + X.upper() + "}\n")
else:
self.SourceFile.write("{\"" + X + "\", "+ "REGISTER_" + X.upper() + "},\n")
Counter +=1
self.SourceFile.write("};\n")
def WritePseudoRegMaps(self):
Counter = 0
for X in self.PseudoRegistersList:
self.CommonHeaderFile.write("#define " + "PSEUDO_REGISTER_" + X.upper() + " " + str(Counter) + "\n")
Counter += 1
self.CommonHeaderFile.write("\n")
self.SourceFile.write("const SYMBOL_MAP PseudoRegisterMapList[]= {\n")
self.HeaderFile.write("extern const SYMBOL_MAP PseudoRegisterMapList[];\n")
Counter = 0
for X in self.PseudoRegistersList:
if Counter == len(self.PseudoRegistersList)-1:
self.SourceFile.write("{\"" + X + "\", "+ "PSEUDO_REGISTER_" + X.upper() + "}\n")
else:
self.SourceFile.write("{\"" + X + "\", "+ "PSEUDO_REGISTER_" + X.upper() + "},\n")
Counter +=1
self.SourceFile.write("};\n")
2020-12-01 22:26:46 +03:30
def WriteKeywordList(self):
self.SourceFile.write("const char* KeywordList[]= {\n")
self.HeaderFile.write("extern const char* KeywordList[];\n")
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
Counter = 0
for X in self.keywordList:
if Counter == len(self.keywordList)-1:
self.SourceFile.write("\"" + X + "\"" + "\n")
else:
self.SourceFile.write("\"" + X + "\"" + ",\n")
Counter +=1
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-12-02 03:20:34 +03:30
def WriteOperatorsList(self):
2021-04-13 22:53:02 +04:30
self.SourceFile.write("const char* OperatorsTwoOperandList[]= {\n")
self.HeaderFile.write("extern const char* OperatorsTwoOperandList[];\n")
Counter = 0
for X in self.OperatorsTwoOperand:
if Counter == len(self.OperatorsTwoOperand)-1:
self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + "\n")
else:
self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + ",\n")
Counter +=1
self.SourceFile.write("};\n")
self.SourceFile.write("const char* OperatorsOneOperandList[]= {\n")
self.HeaderFile.write("extern const char* OperatorsOneOperandList[];\n")
2020-12-02 03:20:34 +03:30
Counter = 0
2021-04-13 22:53:02 +04:30
for X in self.OperatorsOneOperand:
if Counter == len(self.OperatorsOneOperand)-1:
2020-12-02 03:20:34 +03:30
self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + "\n")
else:
self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + ",\n")
Counter +=1
self.SourceFile.write("};\n")
2020-12-02 02:32:49 +03:30
def WriteMaps(self):
2020-12-02 03:20:34 +03:30
for Key in self.FunctionsDict:
2021-02-25 18:44:26 +03:30
print(Key)
2020-12-02 02:32:49 +03:30
self.HeaderFile.write("extern const char* "+ Key[1:]+ "[];\n")
self.SourceFile.write("const char* "+ Key[1:]+ "[] = {\n")
Counter = 0
2020-12-02 03:20:34 +03:30
for X in self.FunctionsDict[Key]:
if Counter == len(self.FunctionsDict[Key])-1:
2020-12-02 02:32:49 +03:30
self.SourceFile.write("\"" + "@"+ X.upper() + "\"" + "\n")
else:
self.SourceFile.write("\"" +"@"+ X.upper() + "\"" + ",\n")
Counter +=1
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def WriteLhsList(self):
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const struct _TOKEN Lhs[RULES_COUNT]= \n{\n")
self.HeaderFile.write("extern const struct _TOKEN Lhs[RULES_COUNT];\n")
2020-10-24 15:54:48 +03:30
Counter = 0
for Lhs in self.LhsList:
if Counter == len(self.LhsList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + "\n")
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t{NON_TERMINAL, " + "\"" + Lhs + "\"}" + ",\n")
2020-10-24 15:54:48 +03:30
Counter +=1
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def GetType(self,Var):
if self.IsNoneTerminal(Var):
2020-10-20 19:35:15 +03:30
return "NON_TERMINAL"
2020-10-24 15:54:48 +03:30
elif self.IsSemanticRule(Var):
2020-10-20 19:35:15 +03:30
return "SEMANTIC_RULE"
2020-10-24 15:54:48 +03:30
elif Var == "eps":
2020-10-20 19:35:15 +03:30
return "EPSILON"
2020-10-24 15:54:48 +03:30
elif Var in self.SPECIAL_TOKENS:
2020-10-20 19:35:15 +03:30
return "SPECIAL_TOKEN"
2020-10-24 15:54:48 +03:30
elif Var[0] == "_":
return Var[1:].upper()
2020-10-20 19:35:15 +03:30
else:
return "KEYWORD"
2020-10-24 15:54:48 +03:30
def WriteRhsList(self):
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n")
self.HeaderFile.write("extern const struct _TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN];\n")
2020-10-24 15:54:48 +03:30
Counter =0
for Rhs in self.RhsList:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t{")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
C = 0
for Var in Rhs:
if C == len(Rhs) -1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}" )
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("{"+self.GetType(Var) +", "+"\"" + Var + "\"}," )
2020-10-24 15:54:48 +03:30
C += 1
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if Counter == len(self.RhsList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("}\n")
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("},\n")
2020-10-24 15:54:48 +03:30
Counter+= 1
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def WriteRhsSize(self):
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const unsigned int RhsSize[RULES_COUNT]= \n{\n")
self.HeaderFile.write("extern const unsigned int RhsSize[RULES_COUNT];\n")
2020-10-24 15:54:48 +03:30
Counter =0
for Rhs in self.RhsList:
if Counter == len(self.RhsList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write( str(len(Rhs)) + "\n" )
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write( str(len(Rhs)) + ",\n" )
2020-10-24 15:54:48 +03:30
Counter+= 1
2020-10-20 19:35:15 +03:30
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def WriteTerminalList(self):
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const char* TerminalMap[TERMINAL_COUNT]= \n{\n")
2020-12-02 02:32:49 +03:30
self.HeaderFile.write("extern const char* TerminalMap[TERMINAL_COUNT];\n")
2020-10-24 15:54:48 +03:30
Counter = 0
for X in self.TerminalList:
if Counter == len(self.TerminalList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\"" + X + "\"" + "\n")
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\"" + X + "\"" + ",\n")
2020-10-24 15:54:48 +03:30
Counter +=1
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-24 15:54:48 +03:30
def WriteNoneTermianlList(self):
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const char* NoneTerminalMap[NONETERMINAL_COUNT]= \n{\n")
2020-12-02 02:32:49 +03:30
self.HeaderFile.write("extern const char* NoneTerminalMap[NONETERMINAL_COUNT];\n")
2020-10-24 15:54:48 +03:30
Counter = 0
for X in self.NonTerminalList:
if Counter == len(self.NonTerminalList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\"" + X + "\"" + "\n")
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\"" + X + "\"" + ",\n")
2020-10-24 15:54:48 +03:30
Counter +=1
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def WriteParseTable(self):
2020-12-01 22:26:46 +03:30
self.SourceFile.write("const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT]= \n{\n")
2020-12-02 02:32:49 +03:30
self.HeaderFile.write("extern const int ParseTable[NONETERMINAL_COUNT][TERMINAL_COUNT];\n")
2020-10-20 19:35:15 +03:30
i = 0
2020-10-24 15:54:48 +03:30
for X in self.NonTerminalList:
2020-10-20 19:35:15 +03:30
j = 0
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t{")
2020-10-24 15:54:48 +03:30
for y in self.TerminalList:
2020-12-01 22:26:46 +03:30
self.SourceFile.write(str(self.ParseTable[i][j]))
2020-10-24 15:54:48 +03:30
if j != len(self.TerminalList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t\t,")
2020-10-20 19:35:15 +03:30
j += 1
2020-10-24 15:54:48 +03:30
if i == len(self.NonTerminalList)-1:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t}\n")
2020-10-20 19:35:15 +03:30
else:
2020-12-01 22:26:46 +03:30
self.SourceFile.write("\t},\n")
2020-10-20 19:35:15 +03:30
i +=1
2020-12-01 22:26:46 +03:30
self.SourceFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def FindAllFirsts(self):
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
self.FirstDict = {}
for Symbol in self.NonTerminalList:
self.FirstDict[Symbol] = set()
2020-10-20 19:35:15 +03:30
t = 0
while True:
2020-10-24 15:54:48 +03:30
Updated = False
2020-10-20 19:35:15 +03:30
i = 0
2020-10-24 15:54:48 +03:30
for Lhs in self.LhsList:
Rhs = self.RhsList[i]
Temp = set(self.FirstDict[Lhs])
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if Rhs[0] == "eps":
2020-10-20 19:35:15 +03:30
pass
2020-10-24 15:54:48 +03:30
elif self.IsNoneTerminal(Rhs[0]):
self.FirstDict[Lhs] = self.FirstDict[Lhs].union(self.FirstDict[Rhs[0]])
2020-10-20 19:35:15 +03:30
p = 0
2020-10-24 15:54:48 +03:30
while self.IsNullable(Rhs[p]):
self.FirstDict[Lhs] = self.FirstDict[Lhs].union(self.FirstDict[Rhs[p+1]])
2020-10-20 19:35:15 +03:30
p += 1
2020-10-24 15:54:48 +03:30
elif self.IsSemanticRule(Rhs[0]):
if self.IsNoneTerminal(Rhs[0]):
self.FirstDict[Lhs] = self.FirstDict[Lhs].union(self.FirstDict[Rhs[1]])
2020-10-20 19:35:15 +03:30
else:
2020-10-24 15:54:48 +03:30
self.FirstDict[Lhs].add(Rhs[1])
2020-10-20 19:35:15 +03:30
else:
2020-10-24 15:54:48 +03:30
self.FirstDict[Lhs].add(Rhs[0])
2020-10-20 19:35:15 +03:30
i += 1
2020-10-24 15:54:48 +03:30
if Temp != self.FirstDict[Lhs]:
Updated = True
2020-10-20 19:35:15 +03:30
p += 1
2020-10-24 15:54:48 +03:30
if not Updated:
2020-10-20 19:35:15 +03:30
break;
2020-10-24 15:54:48 +03:30
def PrintFirsts(self):
for Id in self.FirstDict:
print(Id, end=": ")
for X in self.FirstDict[Id]:
print(X,end = " ")
2020-10-20 19:35:15 +03:30
print()
2020-10-24 15:54:48 +03:30
def GetNoneTerminalId(self, nonterminal):
for i in range(len(self.NonTerminalList)):
if nonterminal == self.NonTerminalList[i]:
2020-10-20 19:35:15 +03:30
return i
return -1
2020-12-02 18:11:03 +03:30
2020-10-24 15:54:48 +03:30
def GetTerminalId(self, Terminal):
for i in range(len(self.TerminalList)):
if Terminal == self.TerminalList[i]:
2020-10-20 19:35:15 +03:30
return i
return -1
2020-10-24 15:54:48 +03:30
def FillParseTable(self):
self.ParseTable = [[self.INVALID for y in range(len(self.TerminalList))] for X in range(len(self.NonTerminalList))]
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
RuleId = 0
for Lhs in self.LhsList:
i = self.GetNoneTerminalId(Lhs)
2020-10-20 19:35:15 +03:30
j = 0
2020-10-24 15:54:48 +03:30
for Terminal in self.TerminalList:
if Terminal in self.PredictDict[RuleId]:
if self.ParseTable[i][j] == self.INVALID:
self.ParseTable[i][j] = RuleId
2020-10-20 19:35:15 +03:30
else:
2021-02-25 18:44:26 +03:30
2020-12-01 22:26:46 +03:30
print("Error! Input grammar is not LL1.")
2020-10-20 19:35:15 +03:30
exit()
j += 1
2020-10-24 15:54:48 +03:30
RuleId += 1
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def PrintParseTable(self):
2020-10-20 19:35:15 +03:30
print("\t", end = "")
2020-10-24 15:54:48 +03:30
for j in range(len(self.TerminalList)):
2021-02-07 15:14:26 +03:30
print(self.TerminalList[j], end= "\t")
2020-10-20 19:35:15 +03:30
print()
2020-10-24 15:54:48 +03:30
for i in range(len(self.NonTerminalList)):
print(self.NonTerminalList[i], end= "\t")
for j in range(len(self.TerminalList)):
if self.ParseTable[i][j] == self.INVALID:
2021-02-07 15:14:26 +03:30
print(".", end= "\t")
2020-10-20 19:35:15 +03:30
else:
2021-02-07 15:14:26 +03:30
print(self.ParseTable[i][j], end= "\t")
2020-10-20 19:35:15 +03:30
print()
2020-10-24 15:54:48 +03:30
def FindAllPredicts(self):
self.PredictDict = {}
for i in range(len(self.LhsList)):
self.PredictDict[i] = set()
2020-10-20 19:35:15 +03:30
i = 0
2020-10-24 15:54:48 +03:30
for Lhs in self.LhsList:
Rhs = self.RhsList[i]
IsRightNullable = True
for Symbol in Rhs:
if self.IsSemanticRule(Symbol):
2020-10-20 19:35:15 +03:30
pass
2020-10-24 15:54:48 +03:30
elif Symbol == "eps":
IsRightNullable = True
2020-10-20 19:35:15 +03:30
break
2020-10-24 15:54:48 +03:30
elif self.IsNoneTerminal(Symbol):
self.PredictDict[i] |= self.FirstDict[Symbol]
if not self.IsNullable(Symbol):
IsRightNullable = False
2020-10-20 19:35:15 +03:30
break
else:
2020-10-24 15:54:48 +03:30
self.PredictDict[i].add(Symbol)
IsRightNullable = False
2020-10-20 19:35:15 +03:30
break
2020-10-24 15:54:48 +03:30
if IsRightNullable:
self.PredictDict[i] |= self.FollowDict[Lhs]
2020-10-20 19:35:15 +03:30
i += 1
def print_predicts(self):
2020-10-24 15:54:48 +03:30
for Key in self.PredictDict:
print(Key, end=": ")
for X in self.PredictDict[Key]:
print(X,end = " ")
2020-10-20 19:35:15 +03:30
print()
2020-10-24 15:54:48 +03:30
def FindAllFollows(self):
self.FollowDict = {}
for Symbol in self.NonTerminalList:
self.FollowDict[Symbol] = set()
if Symbol == self.Start:
self.FollowDict[Symbol].add('$')
2020-10-20 19:35:15 +03:30
t = 0
while True:
2020-10-24 15:54:48 +03:30
Updated = False
2020-10-20 19:35:15 +03:30
i = 0
2020-10-24 15:54:48 +03:30
for Lhs in self.LhsList:
Rhs = self.RhsList[i]
2020-10-20 19:35:15 +03:30
p = 0
2020-10-24 15:54:48 +03:30
for Symbol in Rhs:
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if self.IsNoneTerminal(Symbol):
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
Temp = set(self.FollowDict[Symbol])
if p == len(Rhs)-1:
self.FollowDict[Symbol] = self.FollowDict[Symbol].union(self.FollowDict[Lhs])
2020-10-20 19:35:15 +03:30
else:
2020-10-24 15:54:48 +03:30
NextVar = self.GetNextVar(Rhs, p)
if self.IsNoneTerminal(NextVar):
self.FollowDict[Symbol] = self.FollowDict[Symbol].union(self.FirstDict[NextVar])
if self.IsNullable(NextVar):
self.FollowDict[Symbol] = self.FollowDict[Symbol].union(self.FollowDict[NextVar])
elif self.IsSemanticRule(NextVar):
2020-10-20 19:35:15 +03:30
pass
else:
2020-10-24 15:54:48 +03:30
self.FollowDict[Symbol].add(NextVar)
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if p == len(Rhs)-2:
NextVar = self.GetNextVar(Rhs, p)
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if self.IsNullable(NextVar):
self.FollowDict[Symbol] = self.FollowDict[Symbol].union(self.FollowDict[Lhs])
self.FollowDict[Lhs] = self.FollowDict[Lhs].union(self.FollowDict[NextVar])
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if Temp != self.FollowDict[Symbol]:
Updated = True
2020-10-20 19:35:15 +03:30
p += 1
i += 1
t += 1
2020-10-24 15:54:48 +03:30
if not Updated:
2020-10-20 19:35:15 +03:30
break
2020-10-24 15:54:48 +03:30
def GetNextVar(self, Rhs, p):
if p == len(Rhs)-1:
2020-10-20 19:35:15 +03:30
return None
2020-10-24 15:54:48 +03:30
X = p +1
while self.IsSemanticRule(Rhs[X]):
X+=1
return Rhs[X]
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
def PrintFollows(self):
for Key in self.FollowDict:
print(Key, end=": ")
for X in self.FollowDict[Key]:
print(X,end = " ")
2020-10-20 19:35:15 +03:30
print()
2020-10-24 15:54:48 +03:30
def IsNoneTerminal(self,X):
if X[0].isupper():
2020-10-20 19:35:15 +03:30
return True
else:
return False
2020-10-24 15:54:48 +03:30
def IsSemanticRule(self, X):
if X[0] == '@':
2020-10-20 19:35:15 +03:30
return True
else:
return False
2020-10-24 15:54:48 +03:30
def IsNullable(self, s):
2020-10-20 19:35:15 +03:30
if not s[0].isupper():
return False
i = 0
2020-10-24 15:54:48 +03:30
for Lhs in self.LhsList:
Rhs = self.RhsList[i]
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if Lhs == s:
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
if Rhs[0] == "eps":
2020-10-20 19:35:15 +03:30
return True
p = 0
while True:
2020-10-24 15:54:48 +03:30
if self.IsNullable(Rhs[p]):
2020-10-20 19:35:15 +03:30
return True
else:
break
p += 1
i +=1
return False