Skip to content

Commit

Permalink
enhances; code refacor
Browse files Browse the repository at this point in the history
  • Loading branch information
Houcine EL ADDALI committed Dec 22, 2023
1 parent cd50f08 commit 60b711f
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 69 deletions.
1 change: 1 addition & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
pull_request:
branches:
- main
- feature/*

jobs:
build:
Expand Down
19 changes: 9 additions & 10 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ It is also very easy to learn. It is a very simple language and is not very powe

1. Clone the repo

````
git clone```
```
git clone
````
```

2. cd to the repo

````
cd JIPL```
```
cd JIPL
````
```

3. Run the main.go file

````
go run ./cmd/main.go```
```
go run ./cmd/main.go
````
```

4. Now you can use JIPL in the terminal

Expand Down Expand Up @@ -75,4 +75,3 @@ It is also very easy to learn. It is a very simple language and is not very powe
1. `for (initialization; condition; increment) { body ;}`
2. example
1. `for (def i = 0; i <= 10; i++) { if(i==3){return 3;}}`
5.
2 changes: 2 additions & 0 deletions cmd/REPL/repel.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ func Start(in io.Reader, out io.Writer) {
pr := repParser.Parse()
errs := repParser.Errors()

fmt.Println(pr.ToString())

if len(errs) != 0 {
io.WriteString(out, fmt.Sprintf("%d errors ❌ occurred while parsing your input \n", len(errs)))
for idx, e := range errs {
Expand Down
58 changes: 58 additions & 0 deletions cmd/test/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"fmt"
"io/ioutil"
"os"

"github.com/houcine7/JIPL/internal/lexer"
"github.com/houcine7/JIPL/internal/parser"
"github.com/houcine7/JIPL/internal/runtime"
"github.com/houcine7/JIPL/internal/types"
)

func main() {
// read file and evalal the code

// read file

fl, err := os.Open("./test.jipl")
defer fl.Close()

if err != nil {
panic(err)
}

// read file content
content, err := ioutil.ReadAll(fl)

if err != nil {
panic(err)
}

// eval the code
// lexer

// fmt.Println(string(content))
l := lexer.InitLexer(string(content))

p := parser.InitParser(l)

pr :=p.Parse()

// if err
if len(p.Errors()) != 0 {
for _, e := range p.Errors() {
panic(e)
}
}

ctx := types.NewContext()

//eval
evl,_ :=runtime.Eval(pr,ctx)
if evl!=nil {
fmt.Println(evl.ToString())
}

}
22 changes: 22 additions & 0 deletions cmd/test/test.jipl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
out("begin interpreting");

function isPrime(n) {
if (n < 2) {
return false;
} else {
for (def i = 2; i < n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
};

out("here test 7 ");

out(isPrime(7));

out("here test 2");

out(isPrime(1));
15 changes: 15 additions & 0 deletions internal/AST/ast_imp.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,21 @@ func (exStm *ExpressionStatement) ToString() string {

func (exStm *ExpressionStatement) statementNode() {}


// string literal node
type StringLiteral struct {
Token token.Token
Value string
}

func (strLit *StringLiteral) TokenLiteral() string {
return strLit.Token.Value
}
func (strLit *StringLiteral) ToString() string {
return strLit.Token.Value
}
func (strLit *StringLiteral) expressionNode() {}

/*
* Integer Literals Node
* they can Occur in different type of expression's
Expand Down
2 changes: 1 addition & 1 deletion internal/AST/ast_interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Node interface{
* Expression nodes : does return a value
*/
type Statement interface {
Node
Node
statementNode()
}
type Expression interface {
Expand Down
81 changes: 48 additions & 33 deletions internal/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,112 +28,114 @@ func InitLexer(input string) *Lexer {
*/
func (l *Lexer) NextToken() token.Token {
// var tokens []token.Token
var test token.Token
var tok token.Token
l.ignoreWhiteSpace()

switch l.char {
case '=':
if l.peek() == '=' {
prev := l.char
l.readChar()
test = token.CreateToken(token.EQUAL, string(prev)+string(l.char))
tok = token.CreateToken(token.EQUAL, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.ASSIGN, string(l.char))
tok = token.CreateToken(token.ASSIGN, string(l.char))
}
case '&':
if l.peek() == '&' {
prev := l.char
l.readChar()
test = token.CreateToken(token.AND, string(prev)+string(l.char))
tok = token.CreateToken(token.AND, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.ILLEGAL, string(l.char))
tok = token.CreateToken(token.ILLEGAL, string(l.char))
}

case '|':
if l.peek() == '|' {
prev := l.char
l.readChar()
test = token.CreateToken(token.OR, string(prev)+string(l.char))
tok = token.CreateToken(token.OR, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.ILLEGAL, string(l.char))
tok = token.CreateToken(token.ILLEGAL, string(l.char))
}
case '+':
if l.peek() == '+' {
prev := l.char
l.readChar()
test = token.CreateToken(token.INCREMENT, string(prev)+string(l.char))
tok = token.CreateToken(token.INCREMENT, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.PLUS, string(l.char))
tok = token.CreateToken(token.PLUS, string(l.char))
}
case '-':
if l.peek() == '-' {
prev := l.char
l.readChar()
test = token.CreateToken(token.DECREMENT, string(l.char)+string(prev))
tok = token.CreateToken(token.DECREMENT, string(l.char)+string(prev))
} else {
test = token.CreateToken(token.MINUS, string(l.char))
tok = token.CreateToken(token.MINUS, string(l.char))
}
case '/':
test = token.CreateToken(token.SLASH, string(l.char))
tok = token.CreateToken(token.SLASH, string(l.char))
case '%':
test = token.CreateToken(token.MODULO, string(l.char))
tok = token.CreateToken(token.MODULO, string(l.char))
case '*':
test = token.CreateToken(token.STAR, string(l.char))
tok = token.CreateToken(token.STAR, string(l.char))
case '!':
if l.peek() == '=' {
prev := l.char
l.readChar()
test = token.CreateToken(token.NOT_EQUAL, string(prev)+string(l.char))
tok = token.CreateToken(token.NOT_EQUAL, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.EX_MARK, string(l.char))
tok = token.CreateToken(token.EX_MARK, string(l.char))
}
case '<':
if l.peek() == '=' {
prev := l.char
l.readChar()
test = token.CreateToken(token.LT_OR_EQ, string(prev)+string(l.char))
tok = token.CreateToken(token.LT_OR_EQ, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.LT, string(l.char))
tok = token.CreateToken(token.LT, string(l.char))
}
case '>':
if l.peek() == '=' {
prev := l.char
l.readChar()
test = token.CreateToken(token.GT_OR_EQ, string(prev)+string(l.char))
tok = token.CreateToken(token.GT_OR_EQ, string(prev)+string(l.char))
} else {
test = token.CreateToken(token.GT, string(l.char))
tok = token.CreateToken(token.GT, string(l.char))
}
case ')':
test = token.CreateToken(token.RP, string(l.char))
tok = token.CreateToken(token.RP, string(l.char))
case '(':
test = token.CreateToken(token.LP, string(l.char))
tok = token.CreateToken(token.LP, string(l.char))
case '{':
test = token.CreateToken(token.LCB, string(l.char))
tok = token.CreateToken(token.LCB, string(l.char))
case '}':
test = token.CreateToken(token.RCB, string(l.char))
tok = token.CreateToken(token.RCB, string(l.char))
case ',':
test = token.CreateToken(token.COMMA, string(l.char))
tok = token.CreateToken(token.COMMA, string(l.char))
case ';':
test = token.CreateToken(token.S_COLON, string(l.char))
tok = token.CreateToken(token.S_COLON, string(l.char))
case '"':
tok = token.CreateToken(token.STRING, l.ReadString())
case 0:
// program ends here
test = token.CreateToken(token.FILE_ENDED, string(rune(0)))
tok = token.CreateToken(token.FILE_ENDED, string(rune(0)))
default:
if utils.IsLetter(l.char) {
ident := l.ReadIdentifier()
test = token.CreateToken(token.GetIdentifierTokenType(ident), ident)
return test
tok = token.CreateToken(token.GetIdentifierTokenType(ident), ident)
return tok
} else if utils.IsDigit(l.char) {
num := l.ReadNumber()
test = token.CreateToken(token.INT, num)
return test // this prevents calling read char which is already done with the method ReadNumber()
tok = token.CreateToken(token.INT, num)
return tok // this prevents calling read char which is already done with the method ReadNumber()
} else {
test = token.CreateToken(token.ILLEGAL, string(l.char))
tok = token.CreateToken(token.ILLEGAL, string(l.char))
}
}

l.readChar() // move to next char
return test
return tok
}

// HELPER FUNCTIONS
Expand All @@ -152,6 +154,19 @@ func (l *Lexer) readChar() {
}
}


// read string literals
func (l *Lexer) ReadString() string {
currPosition := l.currentPos + 1
for {
l.readChar()
if l.char == '"' || l.char == 0 {
break
}
}
return l.input[currPosition:l.currentPos]
}

/*
* This function peeks the next character
* used in case of tokens that are compose of more than 2 tokens ( like "==" and "<=" ">=" and "!=")
Expand Down
15 changes: 10 additions & 5 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ type Parser struct {
currToken token.Token // the current token in examination
peekedToken token.Token // the next token after the current one

prefixParseFuncs map[token.TokenType]prefixParse
infixParseFuncs map[token.TokenType]infixParse
prefixParseFuncs map[token.TokenType]prefixParse // function used for prefix parsing
infixParseFuncs map[token.TokenType]infixParse // function used for infix parsing
}

/*
Expand Down Expand Up @@ -60,7 +60,7 @@ func InitParser(l *lexer.Lexer) *Parser {
p.addPrefixFn(token.IF, p.parseIfExpression)
p.addPrefixFn(token.FUNCTION, p.parseFunctionExpression)
p.addPrefixFn(token.FOR, p.parseForLoopExpression)

p.addPrefixFn(token.STRING, p.parseStringLit)
// infix expresion parseres
p.infixParseFuncs = make(map[token.TokenType]infixParse)
infixParseTokens := []token.TokenType{
Expand Down Expand Up @@ -133,7 +133,6 @@ func (p *Parser) Parse() *ast.Program {
// Advance with token
p.Next()
}

return program
}

Expand Down Expand Up @@ -327,6 +326,12 @@ func (p *Parser) parseFnArgs() []ast.Expression {
return ans
}

// parse string lit
func (p *Parser) parseStringLit() ast.Expression {
exp := &ast.StringLiteral{Token: p.currToken, Value: p.currToken.Value}
return exp
}

// to parse Return statement
func (p *Parser) parseReturnStmt() *ast.ReturnStatement {
stm := &ast.ReturnStatement{Token: p.currToken}
Expand All @@ -352,7 +357,7 @@ func (p *Parser) parseGroupExpression() ast.Expression {
return grpExp
}

// parser if expresssions
// parser if expressions
func (p *Parser) parseIfExpression() ast.Expression {

exp := &ast.IfExpression{Token: p.currToken}
Expand Down
2 changes: 0 additions & 2 deletions internal/parser/parser_cte.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ const (
PREFIX // -a or !a
CALL // hello(a)



INCREMENT // -- ++
)

Expand Down
Loading

0 comments on commit 60b711f

Please sign in to comment.