Skip to content

Commit

Permalink
more semantics implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Mellywins committed May 9, 2022
1 parent 0c401e5 commit ab5b6de
Show file tree
Hide file tree
Showing 9 changed files with 1,533 additions and 1,253 deletions.
16 changes: 11 additions & 5 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ type Node struct {
Name string
Token *lexmachine.Token
Children []*Node
parent *Node
Parent *Node
Context map[string]*AbstractLocalVariable
}

const (
Expand All @@ -23,16 +24,17 @@ const (

func NewNode(name string, token *lexmachine.Token) *Node {
return &Node{
Name: name,
Token: token,
Name: name,
Token: token,
Context: make(map[string]*AbstractLocalVariable),
}
}

// Add a child at the end of the children list to a node.
func (n *Node) AddKid(kid *Node) *Node {
n.Children = append(n.Children, kid)
if kid != nil {
kid.parent = n
kid.Parent = n
}
return n
}
Expand All @@ -42,10 +44,14 @@ func (n *Node) PrependKid(kid *Node) *Node {
kids := append(make([]*Node, 0, cap(n.Children)+1), kid)
n.Children = append(kids, n.Children...)
if kid != nil {
kid.parent = n
kid.Parent = n
}
return n
}
func (n *Node) AddParent(parent *Node) *Node {
n.Parent = parent
return n
}

// String makes the AST human readable

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/Mellywins/GoLexThatJava

go 1.17
go 1.18

require (
github.com/timtadh/getopt v1.0.1
Expand Down
2 changes: 1 addition & 1 deletion lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (g *golex) Lex(lval *yySymType) (tokenType int) {
// you call into the parser.
func (l *golex) Error(message string) {
// is there a better way to handle this in the context of goyacc?
panic(fmt.Errorf(fmt.Sprintf("error occured attt (%d) with message %s \n", l.Scanner.TC, message)))
panic(fmt.Errorf(fmt.Sprintf("error occured at,(%d) with message %s \n", l.Scanner.TC, message)))
panic(fmt.Errorf("error occured at "))
}
func newLexer() *lexmachine.Lexer {
Expand Down
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ func main() {
for _, stmt := range stmts {
fmt.Println(stmt)
}
for _, v := range CheckVariableHierarchyQueue {
FindHealthyOccurenceInParentContexts(v, v.Token.Value.(string))
}
}

func parse(lexer *lexmachine.Lexer, fin io.Reader) (stmts []*Node, err error) {
Expand Down
90 changes: 90 additions & 0 deletions semantics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"fmt"
"github.com/timtadh/lexmachine"
"log"
)

type AbstractGlobalVariable struct {
Value string
Type string
}
type AbstractLocalVariable struct {
Value string
Type string
Name string
State string // Has 2 states, either pristine (untouched, will throw an error if it reahes end of program without being used) or dirty(used in the code afterwards, this is the normal accepted behavior)
}
type FunctionSignature struct {
Name string
ReturnType string
ParamList []AbstractLocalVariable
}

func NewFunctionSignature(name string, returnType string, paramList []AbstractLocalVariable) *FunctionSignature {
return &FunctionSignature{Name: name, ReturnType: returnType, ParamList: paramList}
}

var CheckVariableHierarchyQueue []*Node
var GlobalVars = make(map[string]*AbstractGlobalVariable)
var LocalVars = make(map[string]*AbstractLocalVariable)
var FunctionDeclarations = make(map[string]*FunctionSignature)

func NewAbstractGlobalVariable(node *Node) *AbstractGlobalVariable {
name, value, varType := destructureElementsFromVarDeclaration(node)
constructedNode := &AbstractGlobalVariable{
Value: value,
Type: varType,
}
GlobalVars[name] = constructedNode
return constructedNode
}
func NewAbstractLocalVariable(val string, typ string, name string) *AbstractLocalVariable {
return &AbstractLocalVariable{
Value: val,
Type: typ,
Name: name,
State: "Pristine",
}
}
func destructureElementsFromVarDeclaration(node *Node) (name string, value string, varType string) {
childrenCount := len(node.Children)
tokenList := make([]*lexmachine.Token, childrenCount)
for i, tok := range node.Children {
tokenList[i] = tok.Token // [int x = 5 ; ]
}
if childrenCount > 3 { // uninitialized var
return tokenList[1].Value.(string), tokenList[3].Value.(string), tokenList[0].Value.(string)
} else {
return tokenList[1].Value.(string), "", tokenList[0].Value.(string)
}
}
func (n *Node) AddContext(node *Node) {
name, value, varType := destructureElementsFromVarDeclaration(node)
constructedNode := &AbstractLocalVariable{
Value: value,
Type: varType,
}
n.Context[name] = constructedNode
}

// TODO: Try to find a way to backtrack to the nearest parent context.
func QueueElementForChecking(node *Node) {
CheckVariableHierarchyQueue = append(CheckVariableHierarchyQueue, node)
}

// FindHealthyOccurenceInParentContexts Function that recursively checks for the variable existance within the parent scope until it reaches the parent = nil
func FindHealthyOccurenceInParentContexts(node *Node, name string) {

if node.Parent == nil {
if _, ok := node.Context[name]; !ok {
log.Fatal(fmt.Errorf("variable %s is not defined previously", name))
return
} else {
return
}
} else { // Incase parent exists, recurse and keep looking for occurence.
FindHealthyOccurenceInParentContexts(node.Parent, name)
}
}
91 changes: 65 additions & 26 deletions syntax.y
Original file line number Diff line number Diff line change
Expand Up @@ -71,32 +71,37 @@ Program : MainClass { yylex.(*golex).stmts = append(yylex.(*golex).stmts, $1.ast
yylex.(*golex).stmts=append(yylex.(*golex).stmts,$2.ast)
} ;

MainClass : CLASS IDENTIFIER LEFTANGLEBRACKET PUBLIC STATIC VOID MAIN LEFTPARENTHESIS STRING LEFTBRACKET RIGHTBRACKET IDENTIFIER RIGHTPARENTHESIS LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET RIGHTANGLEBRACKET
MainClass : CLASS IDENTIFIER LEFTANGLEBRACKET VarDeclaration PUBLIC STATIC VOID MAIN LEFTPARENTHESIS STRING LEFTBRACKET RIGHTBRACKET IDENTIFIER RIGHTPARENTHESIS LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET RIGHTANGLEBRACKET
{
NewAbstractGlobalVariable($4.ast)
$$.ast=NewNode("MAINCLASS: ",nil).
AddKid(NewNode("class",$1.token)).
AddKid(NewNode("",$2.token)).
AddKid(NewNode("{",$3.token)).
AddKid(NewNode("",$4.token)).
AddKid($4.ast).
AddKid(NewNode("",$5.token)).
AddKid(NewNode("",$6.token)).
AddKid(NewNode("",$7.token)).
AddKid(NewNode("(",$8.token)).
AddKid(NewNode("",$9.token)).
AddKid(NewNode("[",$10.token)).
AddKid(NewNode("]",$11.token)).
AddKid(NewNode("",$12.token)).
AddKid(NewNode(")",$13.token)).
AddKid(NewNode("{",$14.token)).
AddKid($15.ast).
AddKid(NewNode("}",$16.token)).
AddKid(NewNode("}",$16.token))
AddKid(NewNode("",$8.token)).
AddKid(NewNode("(",$9.token)).
AddKid(NewNode("",$10.token)).
AddKid(NewNode("[",$11.token)).
AddKid(NewNode("]",$12.token)).
AddKid(NewNode("",$13.token)).
AddKid(NewNode(")",$14.token)).
AddKid(NewNode("{",$15.token)).
AddKid($16.ast).
AddKid(NewNode("}",$17.token)).
AddKid(NewNode("}",$18.token)).
AddParent(NewNode("Main Program",nil))
$4.ast.AddParent($$.ast)


}
;
ClassDeclaration : CLASS IDENTIFIER Extension LEFTANGLEBRACKET VarDeclaration MethodDeclaration RIGHTANGLEBRACKET
{

$$.ast= NewNode("<NewClassDeclaration>:", nil).
AddKid(NewNode("",$1.token)).
AddKid(NewNode("",$2.token)).
Expand All @@ -105,6 +110,11 @@ ClassDeclaration : CLASS IDENTIFIER Extension LEFTANGLEBRACKET VarDeclaration
AddKid($5.ast).
AddKid($6.ast).
AddKid(NewNode("}",$7.token))
$3.ast.AddParent($$.ast)
$5.ast.AddParent($$.ast)
$6.ast.AddParent($$.ast)
$$.ast.AddContext($5.ast)


}
| ClassDeclaration ClassDeclaration
Expand All @@ -123,23 +133,32 @@ Extension: EXTENDS IDENTIFIER
}
| ;

VarDeclaration : VarDeclaration VarDeclaration
{
$$.ast=NewNode("<Variable definitions>:",nil).
AddKid($1.ast).
AddKid($2.ast)
}

| Type IDENTIFIER SEMICOLON
VarDeclaration : Type IDENTIFIER SEMICOLON VarDeclaration
{
$$.ast=NewNode("",nil).
$$.ast=NewNode("<Uninitialized variable definition>:",nil).
AddKid($1.ast).
AddKid(NewNode("",$2.token)).
AddKid(NewNode("",$3.token))

AddKid(NewNode("",$3.token)).
AddKid($4.ast)
}
| { $$.ast=nil }
;
| Type IDENTIFIER SEMICOLON
{
$$.ast=NewNode("<Uninitialized variable definition>:",nil).
AddKid($1.ast).
AddKid(NewNode("",$2.token)).
AddKid(NewNode("",$3.token))

}
| Type IDENTIFIER EQUAL Expression SEMICOLON
{
$$.ast=NewNode("<Initialized variable definition>:",nil).
AddKid($1.ast).
AddKid(NewNode("",$2.token)).
AddKid(NewNode("",$3.token)).
AddKid($4.ast).
AddKid(NewNode("",$5.token))
$4.ast.AddParent($$.ast)
}

Statement : LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET
{
Expand All @@ -158,6 +177,7 @@ Statement : LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET
AddKid($5.ast).
AddKid(NewNode("",$6.token)).
AddKid($7.ast)
$3.ast.AddParent($$.ast)
}
| WHILE LEFTPARENTHESIS Expression RIGHTPARENTHESIS Statement
{
Expand All @@ -167,7 +187,7 @@ Statement : LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET
AddKid($3.ast).
AddKid(NewNode(")",$4.token)).
AddKid($4.ast)

$3.ast.AddParent($$.ast)
}
| SYSTEMOUTPRINTLN LEFTPARENTHESIS Expression RIGHTPARENTHESIS SEMICOLON
{
Expand All @@ -177,14 +197,21 @@ Statement : LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET
AddKid($3.ast).
AddKid(NewNode(")",$4.token)).
AddKid(NewNode("",$5.token))
$3.ast.AddParent($$.ast)
QueueElementForChecking($3.ast)

}
| IDENTIFIER EQUAL Expression SEMICOLON
{

$$.ast=NewNode("<Affectation>",nil).
AddKid(NewNode("",$1.token)).
AddKid(NewNode("=",$2.token)).
AddKid($3.ast).
AddKid(NewNode("",$4.token))
$3.ast.AddParent($$.ast)


}
| IDENTIFIER LEFTBRACKET Expression RIGHTBRACKET EQUAL Expression SEMICOLON
{
Expand All @@ -196,13 +223,21 @@ Statement : LEFTANGLEBRACKET Statement RIGHTANGLEBRACKET
AddKid(NewNode("=",$5.token)).
AddKid($6.ast).
AddKid(NewNode("",$7.token))
$3.ast.AddParent($$.ast)
$6.ast.AddParent($$.ast)


}
| Statement Statement
{
$$.ast=NewNode("<BlockOfStatements>:",nil).
AddKid($1.ast).
AddKid($2.ast)
}
| VarDeclaration
{
$$.ast=$1.ast
}
| {$$.ast=NewNode("empty statement content",nil) } ;
Type: INT LEFTBRACKET RIGHTBRACKET { $$.ast=NewNode("int[]",$1.token)}
| BOOLEAN {$$.ast=NewNode("",$1.token)}
Expand Down Expand Up @@ -241,6 +276,10 @@ MethodDeclaration : PUBLIC Type IDENTIFIER LEFTPARENTHESIS MethodTypeDeclaration
AddKid($11.ast).
AddKid(NewNode(";",$12.token)).
AddKid(NewNode("}",$13.token))
$$.ast.AddContext($8.ast)
$11.ast.AddParent($$.ast)
QueueElementForChecking($$.ast)

}
| MethodDeclaration MethodDeclaration
{
Expand Down
31 changes: 15 additions & 16 deletions test/example.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
class HelloWorld{
class HelloWorld {
int kwx=5;
public static void main(String[] args){
{
if (1 && 2)
{
x=1;
whilae(1)

{
System.out.println(he);
}
}
else
{
System.out.println(Hello);
}
}
kwx=6;
}


}

class Test extends Thread {
int kwzae=5;
public int run(int x){
int k=5;
System.out.println(z);
return x;
}
}

Loading

0 comments on commit ab5b6de

Please # to comment.