Skip to content

Commit

Permalink
Merge pull request #1 from houcine7/feature/prefix-parsing
Browse files Browse the repository at this point in the history
Feature/prefix parsing
  • Loading branch information
houcine7 authored Dec 14, 2023
2 parents 912b60f + 41d48c8 commit d9384e8
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 232 deletions.
149 changes: 97 additions & 52 deletions AST/ast_imp.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ type Program struct {
Statements []Statement
}

func (prog *Program) TokenLiteral() string{
if len(prog.Statements) > 0 {
func (prog *Program) TokenLiteral() string {
if len(prog.Statements) > 0 {
return prog.Statements[0].TokenLiteral()
}
return ""
Expand All @@ -24,137 +24,127 @@ func (prog *Program) TokenLiteral() string{
func (prog *Program) ToString() string {
var bf bytes.Buffer

for _,stm := range prog.Statements {
for _, stm := range prog.Statements {
bf.WriteString(stm.ToString())
}

return bf.String()
}




/*
* Def statement Node (def x = add(1,2) - 1 + (10/5))
*/
*/
type DefStatement struct {
Token token.Token // toke.DEF token
Name *Identifier
Name *Identifier
Value Expression
}

// method satisfies the Node interface
func (defStm *DefStatement) TokenLiteral() string{
return defStm.Token.Value;
func (defStm *DefStatement) TokenLiteral() string {
return defStm.Token.Value
}

// toString method from Node interface
func (defStm *DefStatement) ToString() string{
func (defStm *DefStatement) ToString() string {
var bf bytes.Buffer

bf.WriteString(defStm.TokenLiteral()+" ")
bf.WriteString(defStm.TokenLiteral() + " ")
bf.WriteString(defStm.Name.ToString())
bf.WriteString(" = ")
if defStm.Value !=nil{
if defStm.Value != nil {
bf.WriteString(defStm.Value.ToString())
}
}
bf.WriteString(";")
return bf.String()
}
// satisfies the statement interface
func (defStm *DefStatement) statementNode() {}



// satisfies the statement interface
func (defStm *DefStatement) statementNode() {}

/*
* Identifier node as an expression node
*/
type Identifier struct{ //
*/
type Identifier struct { //
Token token.Token // token.IDENTIFIER token
Value string
}

// to imp Nodes
// to imp Nodes
func (ident *Identifier) TokenLiteral() string {
return ident.Token.Value;
return ident.Token.Value
}

func (ident *Identifier) ToString() string{
func (ident *Identifier) ToString() string {
return ident.Value
}

// to imp Expression Node
// even do in let identifiers are not expressions but in other
//parts they does provide a value
// even do in let identifiers are not expressions but in other
// parts they does provide a value
func (ident *Identifier) expressionNode() {}




/*
* return statement node
* return statement node
* return 5; || return f1(1,2); ==> return <expression>;
*/
type ReturnStatement struct{
Token token.Token // the token is "return"
*/
type ReturnStatement struct {
Token token.Token // the token is "return"
ReturnValue Expression
}

//Node interface methods
func (reStm *ReturnStatement) TokenLiteral() string{ // satisfies the node interface
// Node interface methods
func (reStm *ReturnStatement) TokenLiteral() string { // satisfies the node interface
return reStm.Token.Value
}

func (resStm *ReturnStatement) ToString() string {
var bf bytes.Buffer
bf.WriteString(resStm.TokenLiteral())
if resStm.ReturnValue !=nil{
if resStm.ReturnValue != nil {
bf.WriteString(resStm.ReturnValue.ToString())
}
bf.WriteString(";")
return bf.String()
}

// statements imp
func (reStm *ReturnStatement) statementNode() { } // satisfies the statement interface



func (reStm *ReturnStatement) statementNode() {} // satisfies the statement interface

/*
* Expressions statement node
* they are wrappers that consists solely of one expression
*/
type ExpressionStatement struct{
Token token.Token
*/
type ExpressionStatement struct {
Token token.Token
Expression Expression
}
// Node's interface methods
func (exStm *ExpressionStatement) TokenLiteral() string{

// Node's interface methods
func (exStm *ExpressionStatement) TokenLiteral() string {
return exStm.Token.Value
}

func (exStm *ExpressionStatement) ToString() string{
func (exStm *ExpressionStatement) ToString() string {
var bf bytes.Buffer
if exStm.Expression !=nil {
if exStm.Expression != nil {
bf.WriteString(exStm.Expression.ToString())
}
return bf.String()
}

func (exStm *ExpressionStatement) statementNode(){}



func (exStm *ExpressionStatement) statementNode() {}

/*
* Integer Literals Node
* they can Occur in different type of expression's
*/
*/
type IntegerLiteral struct {
Token token.Token
Value int // we do not specify int size to make it platform independent (32,64)
}

func (intLiteral *IntegerLiteral) TokenLiteral() string{
func (intLiteral *IntegerLiteral) TokenLiteral() string {
return intLiteral.Token.Value
}

Expand All @@ -164,3 +154,58 @@ func (intLiteral *IntegerLiteral) ToString() string {
return intLiteral.Token.Value
}

/*
Prefix Expression Nodes
-5; !8787;
*/
type PrefixExpression struct {
Token token.Token // the prefix token
Operator string
Right Expression
}

func (prefixExp *PrefixExpression) TokenLiteral() string {
return prefixExp.Token.Value
}

func (prefixExp *PrefixExpression) ToString() string {
var bf bytes.Buffer

bf.WriteRune('(')
bf.WriteString(prefixExp.Operator)
bf.WriteString(prefixExp.Right.ToString())
bf.WriteRune(')')

return bf.String()
}

func (prefixExp *PrefixExpression) expressionNode() {}

/*
Infix Expression Nodes
left + right
*/
type InfixExpression struct {
Token token.Token // the operator token
Right Expression
Left Expression
Operator string
}

func (infixExp *InfixExpression) TokenLiteral() string {
return infixExp.Token.Value
}

func (infixExp *InfixExpression) ToString() string {
var bf bytes.Buffer

bf.WriteRune('(')
bf.WriteString(infixExp.Left.ToString())
bf.WriteString(infixExp.Operator)
bf.WriteString(infixExp.Right.ToString())
bf.WriteRune(')')

return bf.String()
}

func (infixExp *InfixExpression) expressionNode() {}
1 change: 0 additions & 1 deletion AST/ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ func TestString(t *testing.T){
}
}


18 changes: 15 additions & 3 deletions lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Lexer struct {

/*
* Init a Lexer
*/
*/
func InitLexer(input string) *Lexer {
l := &Lexer{input: input}
l.readChar() // READ FIRST CHAR
Expand All @@ -42,9 +42,21 @@ func (l *Lexer) NextToken() token.Token {
test = token.NewToken(token.ASSIGN,string(l.char));
}
case '+':
test = token.NewToken(token.PLUS, string(l.char))
if l.peek()=='+'{
prev := l.char
l.readChar()
test = token.NewToken(token.INCREMENT, string(prev)+ string(l.char))
}else{
test = token.NewToken(token.PLUS, string(l.char))
}
case '-':
test = token.NewToken(token.MINUS,string(l.char))
if l.peek()=='-' {
prev :=l.char
l.readChar()
test = token.NewToken(token.DECREMENT,string(l.char)+string(prev))
}else{
test = token.NewToken(token.MINUS,string(l.char))
}
case '/':
test = token.NewToken(token.SLASH,string(l.char))
case '*':
Expand Down
8 changes: 8 additions & 0 deletions lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ func TestNextToken3(t *testing.T){
10 != 7;
10 <= 20;
10 >= 0;
10++;
10--;
`

var tests = []struct {
Expand Down Expand Up @@ -247,6 +249,12 @@ func TestNextToken3(t *testing.T){
{expectedTokenType: token.INT , expectedValue: "0"},
{expectedTokenType: token.S_COLON, expectedValue: ";"},

{expectedTokenType: token.INT, expectedValue: "10"},
{expectedTokenType: token.INCREMENT, expectedValue: "++"},
{expectedTokenType: token.S_COLON, expectedValue: ";"},
{expectedTokenType: token.INT, expectedValue: "10"},
{expectedTokenType: token.DECREMENT, expectedValue: "--"},
{expectedTokenType: token.S_COLON, expectedValue: ";"},


}
Expand Down
Loading

0 comments on commit d9384e8

Please sign in to comment.