Anul 3 Semestrul 1

This commit is contained in:
2025-02-06 20:33:26 +02:00
parent 0b130ee18c
commit 184f3bd92e
313 changed files with 348499 additions and 0 deletions
@@ -0,0 +1,22 @@
q0 q1 q2 q3 qf
1 2 3
q0
qf
q0 q0 1
q0 q0 2
q0 q0 3
q0 q1 1
q0 q2 2
q0 q3 3
q1 q1 1
q1 q1 2
q1 q1 3
q1 qf 1
q2 q2 1
q2 q2 2
q2 q2 3
q2 qf 2
q3 q3 1
q3 q3 2
q3 q3 3
q3 qf 3
@@ -0,0 +1,46 @@
class FiniteAutomata:
def __init__(self, file_path):
self.alphabet = set()
self.states = set()
self.transitions = {}
self.start_state = None
self.final_states = set()
self.read_fa(file_path)
def read_fa(self, file_path):
with open(file_path, "r") as file:
self.states = set(file.readline().strip().split())
self.alphabet = set(file.readline().strip().split())
self.start_state = file.readline().strip()
self.final_states = set(file.readline().strip().split())
for line in file:
state1, state2, char = line.strip().split()
if state1 not in self.transitions:
self.transitions[state1] = {}
if char not in self.transitions[state1]:
self.transitions[state1][char] = []
self.transitions[state1][char].append(state2)
def is_accepted(self, word):
current_states = [self.start_state]
for char in word:
new_states = []
for state in current_states:
if state in self.transitions and char in self.transitions[state]:
new_states.extend(self.transitions[state][char])
current_states = new_states
return any(state in self.final_states for state in current_states)
def isNFA(self):
for state in self.transitions:
for char in self.transitions[state]:
if len(self.transitions[state][char]) > 1:
return True
return False
fa = FiniteAutomata("FA.in")
print(fa.isNFA())
print(fa.is_accepted("1312"))
print(fa.is_accepted("12321"))
print(fa.is_accepted(""))
@@ -0,0 +1,161 @@
import re
from collections import defaultdict
from Parser import RecursiveDescentParser
from ParserOutput import TreeNode, ParserOutput
class Grammar:
def __init__(self):
self.nonterminals = set()
self.terminals = set()
self.productions = defaultdict(list)
self.start_symbol = None
def read_from_file(self, filename):
with open(filename, 'r') as file:
lines = file.readlines()
grammar_header = lines[0].strip()
match = re.match(r"G\s*=\s*\(\s*\{([^}]*)\}\s*,\s*\{([^}]*)\}\s*,\s*P\s*,\s*([^)]+)\s*\)", grammar_header)
if not match:
raise ValueError("Invalid grammar format in the first line.")
self.nonterminals = set([x.strip() for x in set(match.group(1).split(', '))])
self.terminals = set([x.strip() for x in set(match.group(2).split(', '))])
self.start_symbol = match.group(3)
# Parse the productions
for line in lines[1:]:
line = line.strip()
if line.startswith("P :"):
line = line[3:].strip()
if "->" in line:
lhs, rhs = line.split('->')
lhs = lhs.strip()
self.nonterminals.add(lhs)
for production in rhs.split('|'):
production = production.strip()
self.productions[lhs].append(production.strip())
def print_nonterminals(self):
print("Nonterminals:", self.nonterminals)
def print_terminals(self):
print("Terminals:", self.terminals)
def print_productions(self):
for lhs, rhs in self.productions.items():
print(f"{lhs} -> {' | '.join(rhs)}")
def get_productions_for(self, nonterminal):
return self.productions.get(nonterminal, [])
def is_cfg(self):
for lhs, rhs_list in self.productions.items():
if lhs not in self.nonterminals:
print(f"Invalid nonterminal: {lhs}")
return False
for rhs in rhs_list:
rhs_symbols = rhs.split()
for symbol in rhs_symbols:
if symbol not in self.terminals and symbol not in self.nonterminals:
print(f"Invalid symbol in RHS: {symbol}")
return False
return True
def menu():
g = Grammar()
#g.read_from_file("g2.txt")
parser = None
while True:
print("1. Read grammar from file")
print("2. Print nonterminals")
print("3. Print terminals")
print("4. Print productions")
print("5. Get productions for a nonterminal")
print("6. Check if the grammar is CFG")
print("7. Parse input string")
print("0. Exit")
input_command = input("Enter your command: ")
match input_command:
case "1":
filename = input("Enter the filename: ")
g.read_from_file(filename)
case "2":
g.print_nonterminals()
case "3":
g.print_terminals()
case "4":
g.print_productions()
case "5":
nonterminal = input("Enter the nonterminal: ")
print(g.get_productions_for(nonterminal))
case "6":
print(g.is_cfg())
case "7":
input_string = input("Enter the input string: ")
parser = RecursiveDescentParser(g, input_string)
if parser.parse():
print(parser.print_parse_tree())
parser.save_parse_tree("out1.txt")
else:
print("The input string is not in the language")
print(parser.stack)
print(parser.parsed_stack)
case "0":
return
case _:
print("Invalid command")
if __name__ == '__main__':
menu()
# g = Grammar()
# g.read_from_file("g1.txt")
# parser = RecursiveDescentParser(g, "a a b")
# parser.expand("S", 0)
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.advance()
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.expand("A", 1)
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.advance()
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.back()
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.another_try("A",1)
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.advance()
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# parser.advance()
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
# print(parser.success())
# print(parser.current_pos)
# print(parser.stack)
# print(parser.parsed_stack)
@@ -0,0 +1,78 @@
import copy
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class HashTable:
def __init__(self):
self.capacity = 2
self.noOfElements = 0
self.elementList = [None] * 2
def hash(self, value):
if isinstance(value, int):
return value % self.capacity
sum = 0
for l in value:
sum += ord(l)
return sum % self.capacity
def insert(self, key, value):
if self.noOfElements and (self.capacity // self.noOfElements < 2):
self.resizeAndRehash()
hash_key = self.hash(key)
element = self.elementList[hash_key]
if element is None:
self.elementList[hash_key] = Node(key, value)
self.noOfElements += 1
return
while element.next is not None:
element = element.next
element.next = Node(key, value)
self.noOfElements += 1
def get(self, key):
element = self.elementList[self.hash(key)]
while element is not None:
if element.key == key:
return element.value
element = element.next
return None
def getPosition(self, key):
element = self.elementList[self.hash(key)]
position = 0
while element is not None:
if element.key == key:
return (key,position)
element = element.next
position += 1
return None
def resizeAndRehash(self):
self.capacity *= 2
copyElementList = copy.deepcopy(self.elementList)
self.elementList = [None] * self.capacity
self.noOfElements = 0
for element in copyElementList:
copyElement = copy.deepcopy(element)
while copyElement is not None:
self.insert(copyElement.key, copyElement.value)
copyElement = copyElement.next
def __str__(self):
var = ""
for element in self.elementList:
while element is not None:
var += f"{element.key} -> {element.value}\n"
element = element.next
return var
@@ -0,0 +1,69 @@
class Main{
void entry Main(){
Problem1([3,5,7,2])
Problem2([3,5,7,2])
int[] x = [3,5,7,2]
Problem3(x,[8,4,2,8])
}
int Problem1(int[] numbers){
int max = -1;
int index = 0;
while(index < numbers.lenght){
int number = numbers[index];
if(number > max){
max = number;
}
index = index + 1;
}
return max;
}
int Problem2(int[] numbers){
var prod = 0;
int index = 0;
while(index < numbers.lenght){
int number = numbers[index];
prod *= number;
}
index = index + 1;
return prod;
}
void Problem3(int[] numbers1, int[] numbers2){
while(index < numbers.lenght){
numbers1[index] = numbers1[index] + numbers2[index];
index = index + 1;
}
}
Problem1err(number, power){
return number ** power
}
}
// Key Features of the Language:
// OOP:
// The programming language supports classes and object. Everything written must belong to a class
// Entry Point:
// The entry point of the program is defined by a method with the keyword entry.
// Method Definitions:
// Methods are defined using modifiers such as public and return types like int or var.
// Dynamic Typing and Static Typing:
// var is used for variables where the type is dynamically inferred, similar to languages like Python. This suggests a flexible type system where variables can hold different types based on context. It can however also support static typing
// Loops and Iteration:
// The foreach loop is used to iterate over collections, such as lists. The syntax is familiar to C# or Python-style iteration.
// Lexical Rules:
// Functions are declared with a return type (must be present even if void or dynamic), followed by the function name, and the parameter list. The parameter list can have strong types (like List<int>) or flexible types (like var), but must contain a type. Every statement must be followed by a semi-colon (;), and code is separated into blocks using { and }
@@ -0,0 +1,103 @@
from ParserOutput import ParserOutput, TreeNode
class RecursiveDescentParser:
def __init__(self, grammar, input_string):
self.grammar = grammar
self.input = input_string.split()
self.current_pos = 0
self.stack = [] # Stack for backtracking
self.parsed_stack = [] # Current sequence of symbols being parsed
self.production_sequence = [] # To track applied productions
self.parse_tree = ParserOutput(self.grammar.terminals, self.grammar.nonterminals) # Parse tree output
def expand(self, nonterminal, prod_index=0):
"""Expand a nonterminal using the specified production index."""
if nonterminal in self.grammar.productions:
production = self.grammar.productions[nonterminal][prod_index]
self.stack.append((nonterminal, prod_index, self.current_pos, len(self.parsed_stack))) # Push state
self.production_sequence.append((nonterminal, production)) # Track production
self.parsed_stack = production.split() + self.parsed_stack # Add production to parsed stack
else:
raise ValueError(f"No production for {nonterminal}")
def advance(self):
if self.current_pos < len(self.input) and self.parsed_stack:
next_symbol = self.parsed_stack.pop(0)
if next_symbol == self.input[self.current_pos]:
self.current_pos += 1
return True
else:
self.parsed_stack.insert(0, next_symbol) # Push it back
return False
return False
def back(self):
if self.stack:
# Pop the last saved state
nonterminal, prod_index, prev_pos, stack_size = self.stack.pop()
# Restore the previous position in the input
self.current_pos = prev_pos
# Restore the stack to the state it was before expanding the production
self.parsed_stack = self.parsed_stack[:stack_size]
self.production_sequence.pop()
# Try the next production for the same nonterminal
return self.another_try(nonterminal, prod_index)
# If the stack is empty, backtracking is not possible
return False
def another_try(self, nonterminal, prod_index):
"""Try the next production of the nonterminal."""
prod_list = self.grammar.productions.get(nonterminal, [])
if prod_index + 1 < len(prod_list):
self.expand(nonterminal, prod_index + 1) # Expand using the next production
return True
return False
def success(self):
"""Check if parsing succeeded."""
return self.current_pos == len(self.input) and not self.parsed_stack
def parse(self):
if not self.grammar.start_symbol:
raise ValueError("Grammar must have a start symbol defined.")
self.expand(self.grammar.start_symbol)
while True:
# If parsing succeeds
if self.success():
self.parse_tree.build_tree(self.production_sequence)
return True
# If there's something to parse
if self.parsed_stack:
next_symbol = self.parsed_stack[0]
# If next symbol is a terminal, try to match it
if next_symbol in self.grammar.terminals:
if not self.advance():
# If matching fails, backtrack
if not self.back() and len(self.stack) <= 1:
return False
elif next_symbol in self.grammar.nonterminals:
# Expand nonterminal
self.parsed_stack.pop(0)
self.expand(next_symbol)
else:
# Handle unexpected symbols
print(f"Error: Unexpected symbol {next_symbol}")
return False
else:
if not self.back() and len(self.stack) <= 1:
return False
def print_parse_tree(self):
"""Prints the parse tree to the screen."""
self.parse_tree.print_to_screen()
def save_parse_tree(self, filename):
"""Saves the parse tree representation to a file."""
self.parse_tree.save_to_file(filename)
@@ -0,0 +1,111 @@
import string
class TreeNode:
def __init__(self, value, father=None):
self.value = value # Grammar symbol (terminal/nonterminal)
self.father = father # Parent node
self.sibling = None # Sibling node
self.children = [] # List of children for easy access
def add_child(self, child):
"""Adds a child to the current node."""
if self.children:
# Set sibling for the last child
self.children[-1].sibling = child
self.children.append(child)
def __str__(self):
"""String representation of the node."""
return self.value
class ParserOutput:
def __init__(self, terminal, nonterminal):
self.root = None # Root of the parse tree
self.terminal = terminal
self.nonterminal = nonterminal
def build_tree(self, production_sequence):
"""
Builds the parse tree from a sequence of productions.
:param production_sequence: List of (nonterminal, production) tuples
"""
if not production_sequence:
return None
stack = [] # Stack for constructing the tree
for nonterminal, production in production_sequence:
if not self.root:
# Create the root node
self.root = TreeNode(nonterminal)
stack.append(self.root)
current = stack.pop()
symbols = production.split()
for symbol in symbols:
child = TreeNode(symbol, current)
current.add_child(child)
if symbol in self.nonterminal: # Nonterminal
stack.append(child)
else:
# Create nodes based on production
current = stack.pop()
symbols = production.split()
for symbol in symbols:
child = TreeNode(symbol, current)
current.add_child(child)
if symbol in self.nonterminal: # Nonterminal
stack.append(child)
def transform_representation(self, node=None, level=0):
if node is None:
node = self.root
result = "-" * level + str(node) + "\n"
for child in node.children:
result += self.transform_representation(child, level + 1)
return result
def print_to_screen(self):
print(self.print_table())
def print_table(self):
"""
Prints a table representation of the parse tree.
"""
rows = []
index_map = {}
def traverse(node, index=1, parent_index=None):
current_index = len(rows)
index_map[node] = current_index
# Determine right sibling
sibling_index = None
if node.sibling:
sibling_index = len(rows) + 1 # Right sibling will be the next node added
rows.append((current_index, node.value, parent_index, sibling_index))
for child in node.children:
traverse(child, len(rows), current_index)
traverse(self.root)
# Print the table
s = ""
s += "+-------+-------+--------+---------------+" + "\n"
s += "| Index | Value | Parent | Right Sibling |" + "\n"
s += "+-------+-------+--------+---------------+" + "\n"
for index, value, parent, sibling in rows:
s += f"| {index:<3} | {value:<3} | {parent + 1 if parent is not None else '0':<4} | {sibling if sibling is not None else '0':<11} |" + "\n"
s += "+-------+-------+--------+---------------+" + "\n"
return s
def save_to_file(self, filename):
with open(filename, 'w') as file:
file.write(self.print_table())
@@ -0,0 +1,84 @@
from operator import le
from SymbolTable import SymbolTable
from Hashtable import HashTable
import re
class Scanner:
def __init__(self, tokensPath):
self.tokensPath = tokensPath
self.symbolTable = SymbolTable()
self.indentifierRegex = r"^[a-zA-Z][a-zA-Z0-9]*$"
self.constantRegex = r"^0$|^[1-9][0-9]*$|^-[1-9][0-9]*$"
self.tokens = []
self.pif = {}
self.readTokens()
def readTokens(self):
with open(self.tokensPath, "r") as file:
isKeyword = True
isOperator = False
for line in file:
self.tokens.append(line.strip())
self.tokensRegex = '|'.join(map(re.escape, self.tokens))
def isIdentifier(self, token):
return re.match(self.indentifierRegex, token)
def isConstant(self, token):
return re.match(self.constantRegex, token)
def isToken(self, token):
return token in self.tokens
def scan(self, codePath):
with open(codePath, "r") as file:
identifierCounter = 1
constantCounter = 1
lineCounter = 0
try:
for line in file:
line = line.strip()
tokens = re.findall(self.tokensRegex + r"|\w+", line)
for token in tokens:
if self.isToken(token):
self.pif[token] = -1
elif self.isIdentifier(token):
position = self.symbolTable.getPositionIdentifier(token)
if position is None:
self.symbolTable.addIdentifier(token, identifierCounter)
self.pif["Identifier"] = identifierCounter
identifierCounter += 1
else:
self.pif["Identifier"] = position[1]
elif self.isConstant(token):
position = self.symbolTable.getPositionConstants(token)
if position is None:
self.symbolTable.addConstants(token, constantCounter)
self.pif['Constant'] = constantCounter
constantCounter += 1
else:
self.pif["Constant"] = position[1]
else:
raise Exception(f"Invalid token {token} at line {lineCounter}")
lineCounter += 1
print("Lexically correct")
except Exception as e:
print(e)
return
def main():
scanner = Scanner("tokens.in")
scanner.scan("p1error.in")
#save output to file
with open("PIF.out", "w") as file:
for key in scanner.pif:
file.write(f"{key} -> {scanner.pif[key]}\n")
with open("ST.out", "w") as file:
file.write(str(scanner.symbolTable))
if __name__ == "__main__":
main()
@@ -0,0 +1,40 @@
from Hashtable import HashTable
class SymbolTable:
def __init__(self):
self.symboltableConstants = HashTable()
self.symboltableIdentifier = HashTable()
def addIdentifier(self, identifier, value):
self.symboltableIdentifier.insert(identifier, value)
def getIdentifier(self, identifier):
return self.symboltableIdentifier.get(identifier)
def getPositionIdentifier(self, identifier):
return self.symboltableIdentifier.getPosition(identifier)
def addConstants(self, constants, value):
self.symboltableConstants.insert(constants, value)
def getConstants(self, constants):
return self.symboltableConstants.get(constants)
def getPositionConstants(self, constants):
return self.symboltableConstants.getPosition(constants)
def __str__(self):
var = "Identifier Table\n"
for i in range(self.symboltableIdentifier.capacity):
element = self.symboltableIdentifier.elementList[i]
while element is not None:
var += str(element.key) + " " + str(element.value) + "\n"
element = element.next
var += "Constants Table\n"
for i in range(self.symboltableConstants.capacity):
element = self.symboltableConstants.elementList[i]
while element is not None:
var += str(element.key) + " " + str(element.value) + "\n"
element = element.next
return var
@@ -0,0 +1,4 @@
G = ({S, A}, {a, b}, P, S)
P :
S -> a A
A -> a | b | a A | b A
@@ -0,0 +1,40 @@
G = ({program, statement_list, statement, assignment_stmt, input_stmt, output_stmt, if_stmt, for_stmt, array_decl_stmt, condition, increment_stmt, expression, term, factor, relational_operator, binary_operator, concatenation},{=, (, ), [, ], if, else, for, ARRAY, echo, readline, +, -, *, /, <, <=, ==, >=, !=, ++, --, :, ;, IDENTIFIER, INTEGER_CONST, FLOAT_CONST, STRING_CONST},P, program)
P :
program -> statement_list
statement_list -> statement | statement statement_list
statement -> assignment_stmt | input_stmt | output_stmt | if_stmt | for_stmt | array_decl_stmt
assignment_stmt -> IDENTIFIER = expression
input_stmt -> IDENTIFIER = readline_function ( STRING_CONST )
output_stmt -> echo_function ( STRING_CONST concatenation IDENTIFIER )
if_stmt -> if ( condition ) : statement | if ( condition ) : statement else : statement
for_stmt -> for ( assignment_stmt ; condition ; increment_stmt ) : statement
array_decl_stmt -> IDENTIFIER = ARRAY [ INTEGER_CONST ]
condition -> expression relational_operator expression
increment_stmt -> IDENTIFIER ++ | IDENTIFIER --
expression -> term | term binary_operator expression
term -> factor | factor binary_operator term
factor -> IDENTIFIER | INTEGER_CONST | FLOAT_CONST | STRING_CONST
relational_operator -> < | <= | == | >= | !=
binary_operator -> + | - | * | /
concatenation -> +
echo_function -> echo
readline_function -> readline
@@ -0,0 +1,112 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lang.tab.h"
// Define YYSTYPE structure
extern YYSTYPE yylval;
extern int yydebug; // Declare yydebug
// Token definitions
// File pointers
FILE *yyin, *yyout;
%}
%%
"int"|"char"|"void" { fprintf(yyout, "SIMPLETYPE\n"); return SIMPLETYPE; }
"class" { fprintf(yyout, "CLASS\n"); return CLASS; }
"entry" { fprintf(yyout, "ENTRY\n"); return ENTRY; }
"if" { fprintf(yyout, "IF\n"); return IF; }
"while" { fprintf(yyout, "WHILE\n"); return WHILE; }
"write" { fprintf(yyout, "WRITE\n"); return WRITE; }
"read" { fprintf(yyout, "READ\n"); return READ; }
"return" { fprintf(yyout, "RETURN\n"); return RETURN; }
"{" { fprintf(yyout, "LBRACE\n"); return LBRACE; }
"}" { fprintf(yyout, "RBRACE\n"); return RBRACE; }
"(" { fprintf(yyout, "LPAREN\n"); return LPAREN; }
")" { fprintf(yyout, "RPAREN\n"); return RPAREN; }
"[" { fprintf(yyout, "LBRACKET\n"); return LBRACKET; }
"]" { fprintf(yyout, "RBRACKET\n"); return RBRACKET; }
"+" { fprintf(yyout, "PLUS\n"); return PLUS; }
"-" { fprintf(yyout, "MINUS\n"); return MINUS; }
"*" { fprintf(yyout, "MULT\n"); return MULT; }
"/" { fprintf(yyout, "DIV\n"); return DIV; }
"=" { fprintf(yyout, "ASSIGN\n"); return ASSIGN; }
"==" { fprintf(yyout, "EQ\n"); return EQ; }
"<" { fprintf(yyout, "LT\n"); return LT; }
"<=" { fprintf(yyout, "LE\n"); return LE; }
">" { fprintf(yyout, "GT\n"); return GT; }
">=" { fprintf(yyout, "GE\n"); return GE; }
";" { fprintf(yyout, "SEMICOLON\n"); return SEMICOLON; }
"." { fprintf(yyout, "DOT\n"); return DOT; }
"," { fprintf(yyout, "COMMA\n"); return COMMA; }
[0-9]+ { yylval.intval = atoi(yytext); fprintf(yyout, "CONSTANTEXP %d\n", yylval.intval); return CONSTANTEXP; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.strval = strdup(yytext); fprintf(yyout, "IDENTIFIER %s\n", yylval.strval); return IDENTIFIER; }
[ \t\n]+ { /* Ignore spaces and tabs */ }
\r\n { /* Increment line count if needed */ }
. { fprintf(yyout, "Unknown character: %s\n", yytext); }
%%
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
return 1;
}
// Open input and output files
yyin = fopen(argv[1], "r");
if (!yyin) {
perror("Failed to open input file");
return 1;
}
yyout = fopen(argv[2], "w");
if (!yyout) {
perror("Failed to open output file");
fclose(yyin);
return 1;
}
int token;
while ((token = yylex()) != 0) {
// Process tokens
}
fclose(yyin);
fclose(yyout);
yyin = fopen(argv[1], "r");
if (!yyin) {
perror("Failed to open input file");
return 1;
}
yyout = stdout;
if (!yyout) {
perror("Failed to open output file");
fclose(yyin);
return 1;
}
// Close files
// printf("%d\n", yylex());
// printf("%d\n", yylex());
// printf("%d\n", yylex());
// printf("%d\n", yylex());
yydebug = 1;
if (yyparse() == 0) {
printf("Parsing successful\n");
} else {
printf("Parsing failed\n");
}
fclose(yyin);
fclose(yyout);
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,103 @@
/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_YY_LANG_TAB_H_INCLUDED
# define YY_YY_LANG_TAB_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 1
#endif
#if YYDEBUG
extern int yydebug;
#endif
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
SIMPLETYPE = 258, /* SIMPLETYPE */
CLASS = 259, /* CLASS */
ENTRY = 260, /* ENTRY */
IF = 261, /* IF */
WHILE = 262, /* WHILE */
WRITE = 263, /* WRITE */
READ = 264, /* READ */
RETURN = 265, /* RETURN */
IDENTIFIER = 266, /* IDENTIFIER */
CONSTANTEXP = 267, /* CONSTANTEXP */
LBRACE = 268, /* LBRACE */
RBRACE = 269, /* RBRACE */
LPAREN = 270, /* LPAREN */
RPAREN = 271, /* RPAREN */
LBRACKET = 272, /* LBRACKET */
RBRACKET = 273, /* RBRACKET */
ASSIGN = 274, /* ASSIGN */
EQ = 275, /* EQ */
LT = 276, /* LT */
LE = 277, /* LE */
GT = 278, /* GT */
GE = 279, /* GE */
SEMICOLON = 280, /* SEMICOLON */
DOT = 281, /* DOT */
PLUS = 282, /* PLUS */
MINUS = 283, /* MINUS */
MULT = 284, /* MULT */
DIV = 285, /* DIV */
COMMA = 286 /* COMMA */
};
typedef enum yytokentype yytoken_kind_t;
#endif
/* Value type. */
typedef struct {
int intval;
char *strval;
} YYSTYPE;
extern YYSTYPE yylval;
int yyparse (void);
#endif /* !YY_YY_LANG_TAB_H_INCLUDED */
@@ -0,0 +1,153 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void yyerror(const char *s);
typedef struct ASTNode {
char *type;
char *value;
struct ASTNode *left;
struct ASTNode *right;
} ASTNode;
ASTNode *createNode(const char *type, const char *value, ASTNode *left, ASTNode *right);
%}
%token SIMPLETYPE CLASS ENTRY IF WHILE WRITE READ RETURN
%token IDENTIFIER
%token CONSTANTEXP
%token LBRACE RBRACE LPAREN RPAREN LBRACKET RBRACKET ASSIGN EQ LT LE GT GE SEMICOLON DOT PLUS MINUS MULT DIV
%token COMMA
%start program
%left PLUS MINUS
%left MULT DIV
%left LT LE GT GE EQ
%%
program:
CLASS IDENTIFIER LBRACE entry_declaration class_body RBRACE
;
class_body:
%empty
| atrib_declaration class_body
| method_declaration class_body
;
atrib_declaration:
SIMPLETYPE IDENTIFIER SEMICOLON
| SIMPLETYPE IDENTIFIER ASSIGN CONSTANTEXP SEMICOLON
;
method_declaration:
SIMPLETYPE IDENTIFIER LPAREN method_params RPAREN LBRACE method_body RBRACE
;
method_params:
%empty
| SIMPLETYPE IDENTIFIER
| SIMPLETYPE IDENTIFIER COMMA method_params
;
method_body:
%empty
| statement_list
;
statement_list:
%empty
| statement statement_list
;
statement:
atrib_statement
| if_statement
| while_statement
| write_statement
| read_statement
| return_statement
;
atrib_statement:
IDENTIFIER ASSIGN expression SEMICOLON
;
if_statement:
IF LPAREN expression RPAREN LBRACE statement_list RBRACE
;
while_statement:
WHILE LPAREN expression RPAREN LBRACE statement_list RBRACE
;
write_statement:
WRITE LPAREN expression RPAREN SEMICOLON
;
read_statement:
READ LPAREN IDENTIFIER RPAREN SEMICOLON
;
return_statement:
RETURN expression SEMICOLON
;
expression:
CONSTANTEXP
| expression PLUS expression
| expression MINUS expression
| expression MULT expression
| expression DIV expression
| expression EQ expression
| expression LT expression
| expression LE expression
| expression GT expression
| expression GE expression
| LPAREN expression RPAREN
| IDENTIFIER
| IDENTIFIER LBRACKET expression RBRACKET
| LBRACKET array_list RBRACKET
| class_method_call
| class_expression
;
class_expression:
IDENTIFIER
| IDENTIFIER DOT class_expression
;
class_method_call:
class_expression LPAREN array_list RPAREN
array_list:
%empty
| expression
| expression COMMA array_list
;
entry_declaration:
SIMPLETYPE ENTRY IDENTIFIER LPAREN RPAREN LBRACE statement_list RBRACE
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
ASTNode *createNode(const char *type, const char *value, ASTNode *left, ASTNode *right) {
ASTNode *node = (ASTNode *)malloc(sizeof(ASTNode));
node->type = strdup(type);
node->value = value ? strdup(value) : NULL;
node->left = left;
node->right = right;
return node;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,22 @@
#test the symbol table
from SymbolTable import SymbolTable
def main():
symbol_table = SymbolTable()
symbol_table.addIdentifier("a", 0)
symbol_table.addIdentifier("ba", 1)
symbol_table.addIdentifier("ab", 2)
print(symbol_table.getIdentifier("a"))
print(symbol_table.getIdentifier("ba"))
print(symbol_table.getIdentifier("ab"))
print(symbol_table.getPositionIdentifier("a"))
print(symbol_table.getPositionIdentifier("ba"))
print(symbol_table.getPositionIdentifier("ab"))
print(symbol_table.getIdentifier("d"))
print(symbol_table.getPositionIdentifier("d"))
symbol_table.addIdentifier("d", 4)
print(symbol_table.getIdentifier("d"))
print(symbol_table.getPositionIdentifier("d"))
if __name__ == "__main__":
main()
@@ -0,0 +1,16 @@
CLASS
IDENTIFIER Main
LBRACE
SIMPLETYPE
ENTRY
IDENTIFIER Main
LPAREN
RPAREN
LBRACE
WRITE
LPAREN
CONSTANTEXP 1
RPAREN
SEMICOLON
RBRACE
RBRACE
@@ -0,0 +1,5 @@
class Main{
void entry Main(){
write(1);
}
}
@@ -0,0 +1,7 @@
class Main{
Problem1err(number, power){
return 01 ** power
}
}
@@ -0,0 +1,23 @@
class Main{
void entry Main(){
Problem2([3,5,7,2])
}
int Problem2(int[] numbers){
var prod = 0;
int index = 0;
while(index < numbers.lenght){
int number = numbers[index];
prod *= number;
}
index = index + 1;
return prod;
}
void Problem3(int[] numbers1, int[] numbers2){
while(index < numbers.lenght){
numbers1[index] = numbers1[index] + numbers2[index];
index = index + 1;
}
}
}
@@ -0,0 +1,16 @@
class Main{
void entry Main(){
int[] x = [3,5,7,2]
Problem3(x,[8,4,2,8])
}
void Problem3(int[] numbers1, int[] numbers2){
while(index < numbers.lenght){
numbers1[index] = numbers1[index] + numbers2[index];
index = index + 1;
}
}
Problem1err(number, power){
return number ** power
}
}
@@ -0,0 +1 @@
class
@@ -0,0 +1,32 @@
+
-
*
/
[
{
}
(
)
;
]
=
<
>
<=
>=
==
;
,
.
int
char
class
if
while
read
write
entry
return
null
void