diff --git a/parser/parser.go b/parser/parser.go index 9528ae0..6510986 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -16,10 +16,14 @@ type Parser struct { lexer *lexer.Lexer // points to the lexer currToken token.Token // the current token in examination peekedToken token.Token // the next token after the current one + errors []string } func InitParser(l *lexer.Lexer) *Parser{ - p := &Parser{lexer: l} + p := &Parser{ + lexer: l, + errors: []string{}, + } p.NextToken() // to peek the first token p.NextToken() // first token in the currentToken @@ -37,6 +41,16 @@ func (p *Parser) NextToken(){ p.currToken = p.peekedToken p.peekedToken = p.lexer.NextToken() } + +/* +* function to return the encountered errors +* while parsing +*/ + +func (p *Parser) Errors() []string{ + return p.errors +} + /* This function is to parse a given program */ @@ -44,7 +58,7 @@ func (p *Parser) Parse() *ast.Program{ program := &ast.Program{} program.Statements = []ast.Statement{}; - for p.currToken.Type != token.FILE_ENDED { + for !p.currentTokenEquals(token.FILE_ENDED) { stm := p.parseStmt() //fmt.Println(stm.TokenLiteral()) @@ -80,15 +94,14 @@ func (p *Parser) parseDefStmt() *ast.DefStatement { stm := &ast.DefStatement{Token: p.currToken} // syntax error's - if !p.expectedNextToken(token.IDENTIFIER){ + if !p.expectedNextToken(token.NewToken(token.IDENTIFIER,"IDENT")){ return nil } - fmt.Println("------HERE-----------") stm.Name = &ast.Identifier{ Token: p.currToken, Value: p.currToken.Value, } - if !p.expectedNextToken(token.ASSIGN){ + if !p.expectedNextToken(token.NewToken(token.ASSIGN,"=")){ return nil } @@ -113,10 +126,27 @@ func (p *Parser) peekTokenEquals(t token.TokenType) bool { * if it is returns true and advances the token * if not returns false */ -func (p *Parser) expectedNextToken(t token.TokenType) bool{ - if p.peekTokenEquals(t){ +func (p *Parser) expectedNextToken(t token.Token) bool{ + if p.peekTokenEquals(t.Type){ p.NextToken() return true } + // peek errors + p.peekedError(t) return false +} + +/* +* function to peek Errors in next token +* takes the peeked wrong token and adds error +* message to the errors array of the parser +*/ +func (p *Parser) peekedError(encounteredToken token.Token) { + + errorMessage := fmt.Sprintf("wrong next token type expected token is %s instead got %s", + encounteredToken.Value, p.peekedToken.Value) + + // append message to the errors array + p.errors =append(p.errors, errorMessage) + } \ No newline at end of file diff --git a/parser/parser_test.go b/parser/parser_test.go index de96c24..59e5724 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -1,7 +1,6 @@ package parser import ( - "fmt" "testing" ast "github.com/houcine7/JIPL/AST" @@ -11,20 +10,22 @@ import ( func TestDefStatement(t *testing.T) { input := ` -def num1 = 5; -def num2 = 10; -def foobar = 838383; +def num1 = 13; +def num2 = 0; +def foobar = 5321; ` l := lexer.InitLexer(input) - fmt.Println("-----------------------") - fmt.Println("lexer", l) + + t.Log("-----------------------") + t.Log("lexer", l) parser := InitParser(l) - fmt.Println("-----------------------") - fmt.Println("parser",parser) + t.Log("-----------------------") + t.Log("parser",parser) program := parser.Parse() - fmt.Println(program) + // check parser errors + checkParserErrors(parser,t) if program==nil{ t.Fatalf("parse returned a nil value") @@ -51,9 +52,30 @@ def foobar = 838383; return } } - } + + +func checkParserErrors(p *Parser,t *testing.T){ + errors := p.Errors() + + if len(errors) ==0 { + t.Log("INFO: no ERRORS OCCURRED") + return + } + + // + t.Log("-------PARSING ERRORS: --------") + t.Errorf("%d error found on the parser",len(errors)) + + for i,msg := range errors { + t.Errorf("Parser index:%d has message %s",i,msg) + } + + t.FailNow() // mark tests as failed and stop execution +} + + func testDefStatement(t *testing.T, stm ast.Statement, name string) bool { if stm.TokenLiteral() !="def" { t.Errorf("s.tokenLiteral is not 'def'. got instead:%q",stm.TokenLiteral()) @@ -80,3 +102,4 @@ func testDefStatement(t *testing.T, stm ast.Statement, name string) bool { return true; } + diff --git a/token/token.go b/token/token.go index 397afe8..44a2aa3 100644 --- a/token/token.go +++ b/token/token.go @@ -17,7 +17,7 @@ type Token struct { * Create a new token helper function */ -func NewToken (tType TokenType, value string) Token{ +func NewToken(tType TokenType, value string) Token{ return Token{Type: tType , Value: value}; } @@ -42,4 +42,4 @@ func GetIdentifierTokenType(identifier string) TokenType{ return tokenType } return IDENTIFIER -} \ No newline at end of file +}