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

1064 lines
39 KiB
Python
Raw Permalink 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
2022-08-03 12:09:42 -07:00
* @author M.H. Gholamrezei (mh@hyperdbg.org)
* @author Sina Karvandi (sina@hyperdbg.org)
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, CommonHeaderFileScala):
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
self.CommonHeaderFileScala = CommonHeaderFileScala
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
2024-03-17 18:49:51 +09:00
# Set of all terminals and noneterminals
2020-10-24 15:54:48 +03:30
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
self.SPECIAL_TOKENS = ['%', '+', '~', '!', '++', '-', '--', '->', '.', "*", "/", "=", "==", "!=", ",", ";", "(", ")", "{", "}", "|", "||", ">>", ">=", "<<", "<=", "&", "&&", "^",
2025-10-21 16:46:49 +08:00
"+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|=" , "[", "]"]
2020-10-20 19:35:15 +03:30
2020-10-24 15:54:48 +03:30
# INVALID rule indicator
self.INVALID = 0x80000000
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 = []
2024-07-25 01:52:58 +08:00
self.VariableTypeList = []
2020-12-01 22:26:46 +03:30
self.keywordList = []
2021-04-11 23:31:36 +04:30
self.SemantiRulesList = []
self.AssignmentOperator = []
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):
2024-03-17 18:49:51 +09:00
# Read grammar from input file and initialize grammar related variables
2020-12-01 22:26:46 +03:30
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
2024-03-17 18:49:51 +09:00
# Fills "Parse Table" according to calculated "Predicted Set" and print "Parse Table"
2020-10-24 15:54:48 +03:30
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")
2024-07-25 01:52:58 +08:00
self.HeaderFile.write("#define SCRIPT_VARIABLE_TYPE_LIST_LENGTH " + str(len(self.VariableTypeList))+ "\n")
self.HeaderFile.write("#define ASSIGNMENT_OPERATOR_LIST_LENGTH " + str(len(self.AssignmentOperator)) + "\n")
self.HeaderFile.write("#define SEMANTIC_RULES_MAP_LIST_LENGTH " + str(len(self.keywordList) + len(self.OperatorsOneOperand) + len(self.OperatorsTwoOperand) + len(self.SemantiRulesList) + len(self.AssignmentOperator))+ "\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()
2024-03-17 18:49:51 +09:00
# Prints Maps into output files
2020-12-02 02:32:49 +03:30
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()
2024-07-25 01:52:58 +08:00
self.WriteVariableTypeList()
2020-12-02 18:11:03 +03:30
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
# Assign top variable an invalid value
2020-10-24 15:54:48 +03:30
Top = ""
# Read input
Tokens, CurrentIn = Read(Tokens)
2024-03-17 18:49:51 +09:00
# Temporary values counter initialized with 0 value
2020-10-24 15:54:48 +03:30
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
elif L[0][1:] == "OperatorsOneOperand":
2021-04-13 22:53:02 +04:30
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
2024-07-25 01:52:58 +08:00
elif L[0][1:] == "ScriptVariableType":
self.VariableTypeList += Elements
continue
elif L[0][1:] == "AssignmentOperator":
self.AssignmentOperator += Elements
continue
2020-12-02 18:11:03 +03:30
2020-12-02 03:20:34 +03:30
self.FunctionsDict[L[0]] = Elements
2020-12-01 22:26:46 +03:30
continue
2026-07-18 22:28:45 +08:00
L = Line.split("->", 1)
2020-10-24 15:54:48 +03:30
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:
2026-07-18 22:28:45 +08:00
if X and X[0] == "." and X in self.FunctionsDict:
2020-12-01 22:26:46 +03:30
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
self.NonTerminalList = sorted(self.NonTerminalSet)
2020-12-01 22:26:46 +03:30
self.TerminalList = sorted(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):
2026-07-18 22:28:45 +08:00
# Serialized script buffers contain FUNC_* values. Keep every legacy
# value stable and append aggregate-language additions after them.
aggregate_semantics = {
"struct_forward_declaration", "struct_definition_begin",
"struct_definition_end", "struct_variable_declaration",
"struct_member_declaration", "typedef_declaration",
"struct_pointer", "struct_array_dimension",
"struct_declarator_complete", "typed_load", "typed_store",
"aggregate_copy", "aggregate_zero"
, "struct_initializer_begin", "struct_initializer_end",
"struct_pointer_cast", "member_address", "member_read",
2026-07-20 15:03:45 +08:00
"member_dot_lvalue", "member_arrow_lvalue", "member_dot_read", "member_arrow_read",
"mov_float", "neg_float", "add_float", "sub_float", "mul_float", "div_float",
"gt_float", "lt_float", "egt_float", "elt_float", "equal_float", "neq_float",
"convert_float"
2026-07-18 22:28:45 +08:00
}
aggregate_keywords = {"struct", "typedef"}
append_only_semantics = [
"cast_scalar",
"add_typed", "sub_typed", "mul_typed", "div_typed", "mod_typed",
"bitwise_and_typed", "bitwise_or_typed", "bitwise_xor_typed",
"shift_left_typed", "shift_right_typed",
"gt_typed", "lt_typed", "egt_typed", "elt_typed", "equal_typed", "neq_typed",
"neg_typed", "bitwise_not_typed", "logical_not_typed", "pointer_diff",
"push_aggregate"
]
compiler_only_semantics = {
"type_name_begin", "sizeof_begin", "sizeof_type", "sizeof_expression",
"logical_or_begin", "logical_or_end", "logical_and_begin", "logical_and_end",
"function_parameter_struct_base", "function_parameter_pointer_to_array",
"function_parameter_array_dimension", "function_parameter_empty_array_dimension",
"member_dot_array_read", "member_arrow_array_read"
}
legacy_semantics = [x for x in self.SemantiRulesList if x not in aggregate_semantics and x not in append_only_semantics and x not in compiler_only_semantics]
2026-07-18 22:28:45 +08:00
new_semantics = [x for x in self.SemantiRulesList if x in aggregate_semantics]
legacy_keywords = [x for x in self.keywordList if x not in aggregate_keywords]
new_keywords = [x for x in self.keywordList if x in aggregate_keywords]
numbered_semantics = legacy_semantics + legacy_keywords + new_semantics + new_keywords + append_only_semantics
self.CommonHeaderFileScala.write("object ScriptEvalFunc {\n object ScriptOperators extends ChiselEnum {\n val ")
Counter = 0
CheckForDuplicateList = []
2024-06-20 15:50:22 +09:00
self.CommonHeaderFile.write("#define " + "FUNC_UNDEFINED " + str(Counter) + "\n")
self.CommonHeaderFileScala.write("sFunc" + "Undefined")
Counter += 1
2021-04-13 22:53:02 +04:30
for X in self.OperatorsOneOperand:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
2024-06-20 15:50:22 +09:00
self.CommonHeaderFileScala.write(", sFunc" + X.capitalize())
CheckForDuplicateList.append(X)
Counter += 1
2021-04-13 22:53:02 +04:30
for X in self.OperatorsTwoOperand:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
self.CommonHeaderFileScala.write(", sFunc" + X.capitalize())
CheckForDuplicateList.append(X)
Counter += 1
2021-04-11 23:31:36 +04:30
2026-07-18 22:28:45 +08:00
for X in numbered_semantics:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("#define " + "FUNC_" + X.upper() + " " + str(Counter) + "\n")
self.CommonHeaderFileScala.write(", sFunc" + X.capitalize() + "")
CheckForDuplicateList.append(X)
Counter += 1
self.CommonHeaderFileScala.write(" = Value\n }\n} ")
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:
if X in compiler_only_semantics:
self.SourceFile.write("{\"@" + X.upper() + "\", FUNC_UNDEFINED},\n")
else:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
2021-04-11 23:31:36 +04:30
2020-12-02 18:11:03 +03:30
for X in self.keywordList:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper() + "},\n")
for X in self.AssignmentOperator:
self.SourceFile.write("{\"@" + X.upper() + "\", "+ "FUNC_" + X.upper().replace("_ASSIGNMENT", "") + "},\n")
2020-12-02 18:11:03 +03:30
self.SourceFile.write("};\n")
2020-12-01 22:26:46 +03:30
CheckForDuplicateList = []
self.CommonHeaderFile.write("\nstatic const char *const FunctionNames[] = {")
self.CommonHeaderFile.write("\n\"FUNC_UNDEFINED\""+ ",\n")
for X in self.OperatorsOneOperand:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n")
CheckForDuplicateList.append(X)
for X in self.OperatorsTwoOperand:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n")
CheckForDuplicateList.append(X)
2026-07-18 22:28:45 +08:00
for X in numbered_semantics:
if X not in CheckForDuplicateList:
self.CommonHeaderFile.write("\"" + "FUNC_" + X.upper() + "\"" + ",\n")
CheckForDuplicateList.append(X)
self.CommonHeaderFile.write("};\n")
2020-10-20 19:35:15 +03:30
2020-12-02 18:11:03 +03:30
def WriteRegisterMaps(self):
self.CommonHeaderFile.write("\ntypedef enum REGS_ENUM {\n")
2021-03-11 12:49:49 +03:30
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")
2024-07-25 01:52:58 +08:00
def WriteVariableTypeList(self):
self.SourceFile.write("const char* ScriptVariableTypeList[]= {\n")
self.HeaderFile.write("extern const char* ScriptVariableTypeList[];\n")
Counter = 0
for X in self.VariableTypeList:
if Counter == len(self.VariableTypeList)-1:
self.SourceFile.write("\"" + X + "\"" + "\n")
else:
self.SourceFile.write("\"" + X + "\"" + ",\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")
self.SourceFile.write("const char* AssignmentOperatorList[]= {\n")
self.HeaderFile.write("extern const char* AssignmentOperatorList[];\n")
Counter = 0
for X in self.AssignmentOperator:
if Counter == len(self.AssignmentOperator)-1:
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
self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN Lhs[RULES_COUNT]= \n{\n")
self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_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"
2026-07-20 15:03:45 +08:00
elif Var == "_float":
return "FLOAT_LITERAL"
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):
self.SourceFile.write("const struct _SCRIPT_ENGINE_TOKEN Rhs[RULES_COUNT][MAX_RHS_LEN]= \n{\n")
self.HeaderFile.write("extern const struct _SCRIPT_ENGINE_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 i ==34 and j ==3:
dccc=3
2020-10-24 15:54:48 +03:30
if self.ParseTable[i][j] == self.INVALID:
self.ParseTable[i][j] = RuleId
2020-10-20 19:35:15 +03:30
else:
print("Error! Input grammar is not LL1: " + Lhs +
" on " + Terminal + " conflicts between rules " +
str(self.ParseTable[i][j]) + " and " + str(RuleId) + ".")
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
2022-05-09 15:02:46 +09:00
while self.IsSemanticRule(Rhs[X]) and X + 1 < len(Rhs):
2020-10-24 15:54:48 +03:30
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