| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 | package astimport (	"bytes"	"code.osinet.fr/fgm/waiig15/token")// The base Node interface// Node is the interface implemented by every node in the AST. It extends the// fmt.Stringer interface, allowing simple printing of nodes.type Node interface {	// TokenLiteral returns the literal value of the token it's associated to.	TokenLiteral() string	String() string}// All statement nodes implement this// Statement extends Node and is only a way to differentiate between expressions// and statements.type Statement interface {	Node	statementNode()}// All expression nodes implement this// Expression extends Node and is only a way to differentiate between// expressions and statements.type Expression interface {	// Expression extends Node.	Node	expressionNode()}// Program represents the outer structure of the parser program.type Program struct {	Statements []Statement}// TokenLiteral returns the string contents of the first statement token, which// can be an empty string if the program is empty.func (p *Program) TokenLiteral() string {	if len(p.Statements) > 0 {		return p.Statements[0].TokenLiteral()	}	return ""}// String satisfies the Node and fmt.Stringer interfaces.func (p *Program) String() string {	var out bytes.Buffer	for _, s := range p.Statements {		out.WriteString(s.String())	}	return out.String()}// LetStatement is the Node type for Let statements.type LetStatement struct {	Token token.Token // the token.LET token. Why do we need it ?	Name  *Identifier	Value Expression}func (ls *LetStatement) statementNode() {}// TokenLiteral satisfies the Node interface.func (ls *LetStatement) TokenLiteral() string {	return ls.Token.Literal}// String implements Node and fmt.Stringer.func (ls *LetStatement) String() string {	var out bytes.Buffer	out.WriteString(ls.TokenLiteral() + " ")	out.WriteString(ls.Name.String())	out.WriteString(" = ")	if ls.Value != nil {		out.WriteString(ls.Value.String())	}	out.WriteString(";")	return out.String()}// ReturnStatement fulfills the Node and Statement interfaces.type ReturnStatement struct {	Token       token.Token // the token.RETURN token. Why do we need it ?	Name        *Identifier	ReturnValue Expression}func (rs *ReturnStatement) statementNode() {}// TokenLiteral satisfies the Node interface.func (rs *ReturnStatement) TokenLiteral() string {	return rs.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (rs *ReturnStatement) String() string {	var out bytes.Buffer	out.WriteString(rs.TokenLiteral() + " ")	if rs.ReturnValue != nil {		out.WriteString(rs.ReturnValue.String())	}	out.WriteString(";")	return out.String()}// ExpressionStatement fulfills the Node and Statement interfaces.// It represents a statement made of a bare expression like://   x + 10;type ExpressionStatement struct {	Token      token.Token // the first token of the expression	Expression Expression}func (es *ExpressionStatement) statementNode() {}// TokenLiteral satisfies the Node interface.func (es *ExpressionStatement) TokenLiteral() string {	return es.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (es *ExpressionStatement) String() string {	if es.Expression != nil {		return es.Expression.String()	}	return ""}// BlockStatement fulfills the Node and Statement interfaces.// It represents a suite of statements.type BlockStatement struct {	Token      token.Token // the { token	Statements []Statement}func (bs *BlockStatement) statementNode() {}// TokenLiteral satisfies the Node interface.func (bs *BlockStatement) TokenLiteral() string {	return bs.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (bs *BlockStatement) String() string {	var out bytes.Buffer	for _, s := range bs.Statements {		out.WriteString(s.String())	}	return out.String()}// Identifier is the Node type for identifiers.type Identifier struct {	Token token.Token // the token.IDENT token. Why do we need it ?	Value string      // The identifier string.}func (i *Identifier) expressionNode() {}// TokenLiteral satisfies the Node interface.func (i *Identifier) TokenLiteral() string {	return i.Token.Literal}func (i *Identifier) String() string {	return i.Value}// Boolean is the Node type for booleans.type Boolean struct {	Token token.Token	Value bool // true or false, for the equivalent Monkey tokens.}func (b *Boolean) expressionNode() {}func (b *Boolean) TokenLiteral() string {	return b.Token.Literal}func (b *Boolean) String() string {	return b.Token.Literal}// IntegerLiteral fulfills ast.Expression.type IntegerLiteral struct {	Token token.Token	Value int64}func (il *IntegerLiteral) expressionNode() {}// TokenLiteral satisfies the Node interface.func (il *IntegerLiteral) TokenLiteral() string {	return il.Token.Literal}func (il *IntegerLiteral) String() string {	return il.Token.Literal}// PrefixExpression fulfills the Node and Expression interfaces.// It represents a prefixed expression like:// "-5;"type PrefixExpression struct {	Token    token.Token // The prefix token, e.g. !	Operator string	Right    Expression}func (pe *PrefixExpression) expressionNode() {}// TokenLiteral satisfies the Node interface.func (pe *PrefixExpression) TokenLiteral() string {	return pe.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (pe *PrefixExpression) String() string {	var out bytes.Buffer	out.WriteString("(")	out.WriteString(pe.Operator)	out.WriteString(pe.Right.String())	out.WriteString(")")	return out.String()}// InfixExpression fulfills the Node and Expression interfaces.// It represents an infix expression like:// "5 + 6;"type InfixExpression struct {	Token    token.Token // The operator token, e.g. +	Left     Expression	Operator string	Right    Expression}func (ie *InfixExpression) expressionNode() {}// TokenLiteral satisfies the Node interface.func (ie *InfixExpression) TokenLiteral() string {	return ie.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (ie *InfixExpression) String() string {	var out bytes.Buffer	out.WriteString("(")	out.WriteString(ie.Left.String())	out.WriteString(" " + ie.Operator + " ")	out.WriteString(ie.Right.String())	out.WriteString(")")	return out.String()}// IfExpression fulfills the Node and Expression interfaces.// It represents a condition expression like:// "if true 5 else 6;"// Note that if/else are expressions, not just statements.type IfExpression struct {	Token       token.Token // The "if" token	Condition   Expression	Consequence *BlockStatement	Alternative *BlockStatement}func (ie *IfExpression) expressionNode() {}// TokenLiteral satisfies the Node interface.func (ie *IfExpression) TokenLiteral() string {	return ie.Token.Literal}// String satisfies the Node and fmt.Stringer interfaces.func (ie *IfExpression) String() string {	var out bytes.Buffer	out.WriteString("if")	out.WriteString(ie.Condition.String())	out.WriteString(" ")	out.WriteString(ie.Consequence.String())	if ie.Alternative != nil {		out.WriteString("else ")		out.WriteString(ie.Alternative.String())	}	return out.String()}
 |