'Go 언어로 만든 해석기'의 후속~ for 문구를 설치해보세요~
그나저나 지난번에 다시 대입할 수 있는 변수를 실현했다.
규격
이번에 실시된 for문장의 격식은 다음과 같다.
for ( var i = 0; i < 10; i = i + 1) { // 初期化; 継続条件; 増分処理
puts(i); // 文
}
자구 분석
키워드에 for
를 추가합니다.
token.govar keywords = map[string]TokenType{
...
"for": FOR,
}
문법 분석
for 문장을 나타내는 AST 노드를 정의합니다.
ast.gotype ForStatement struct {
Token token.Token
InitialStatement Statement // 初期化
Condition Expression // 継続条件
PostStatement Statement // 増分処理
Block *BlockStatement // 本体のブロック
}
그리고 다음과 같은 문법 분석을 진행한다.
parser.go// "for"のTokenを読み込むと呼ばれる関数
func (p *Parser) parseForStatement() *ast.ForStatement {
stmt := &ast.ForStatement{Token: p.curToken}
// forの次は"("
if !p.expectPeek(token.LPAREN) {
return nil
}
p.nextToken()
// 初期化の文の解析
stmt.InitialStatement = p.parseStatement()
p.nextToken()
// 継続条件の式の解析
stmt.Condition = p.parseExpression(LOWEST)
if !p.expectPeek(token.SEMICOLON) {
return nil
}
p.nextToken()
// 増分処理の文の解析
stmt.PostStatement = p.parseStatement()
// 増分処理の次は")"のはず。ただし、増分処理が空の場合はすでに")"が読まれている。
if p.peekTokenIs(token.RPAREN) {
p.nextToken()
}
p.nextToken()
// 本体の文の解析
stmt.Block = p.parseBlockStatement()
return stmt
}
평가
평가는 아래와 같다.
evaluator.go// for文のNodeを評価するときに呼ばれる関数
func evalForStatement(stmt *ast.ForStatement, env *object.Environment) object.Object {
// 初期化の文を評価
initStmt := Eval(stmt.InitialStatement, env)
if isError(initStmt) {
return initStmt
}
var result object.Object
for {
// まず継続条件を評価
condition := Eval(stmt.Condition, env)
if isError(condition) {
return condition
}
if !isTruthy(condition) {
// 評価結果が偽だったらループを抜ける
break
}
// 本体の文を評価
result = Eval(stmt.Block, env)
// エラーもしくはreturnで返り値が渡ってきたらそのまま返す
if isError(result) || isReturn(result) {
return result
}
// 増分処理の文を評価
postStmt := Eval(stmt.PostStatement, env)
if isError(postStmt) {
return postStmt
}
}
return result
}
이제 설치가 완료되었습니다.
REPL로 해볼게요. >> for (var i = 0; i < 10; i = i + 1) { puts(i); }
0
1
2
3
4
5
6
7
8
9
잘 움직이는 것 같네요.
마지막
이 글은 일부 코드만 기재되어 있으니 전체적인 차이를 보고 싶은 사람은 보세요이쪽 PR..
Reference
이 문제에 관하여('Go 언어로 만든 해석기'의 후속~ for 문구를 설치해보세요~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tatsumack/items/8e745e4ee927cebb1875
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
for ( var i = 0; i < 10; i = i + 1) { // 初期化; 継続条件; 増分処理
puts(i); // 文
}
키워드에
for
를 추가합니다.token.go
var keywords = map[string]TokenType{
...
"for": FOR,
}
문법 분석
for 문장을 나타내는 AST 노드를 정의합니다.
ast.gotype ForStatement struct {
Token token.Token
InitialStatement Statement // 初期化
Condition Expression // 継続条件
PostStatement Statement // 増分処理
Block *BlockStatement // 本体のブロック
}
그리고 다음과 같은 문법 분석을 진행한다.
parser.go// "for"のTokenを読み込むと呼ばれる関数
func (p *Parser) parseForStatement() *ast.ForStatement {
stmt := &ast.ForStatement{Token: p.curToken}
// forの次は"("
if !p.expectPeek(token.LPAREN) {
return nil
}
p.nextToken()
// 初期化の文の解析
stmt.InitialStatement = p.parseStatement()
p.nextToken()
// 継続条件の式の解析
stmt.Condition = p.parseExpression(LOWEST)
if !p.expectPeek(token.SEMICOLON) {
return nil
}
p.nextToken()
// 増分処理の文の解析
stmt.PostStatement = p.parseStatement()
// 増分処理の次は")"のはず。ただし、増分処理が空の場合はすでに")"が読まれている。
if p.peekTokenIs(token.RPAREN) {
p.nextToken()
}
p.nextToken()
// 本体の文の解析
stmt.Block = p.parseBlockStatement()
return stmt
}
평가
평가는 아래와 같다.
evaluator.go// for文のNodeを評価するときに呼ばれる関数
func evalForStatement(stmt *ast.ForStatement, env *object.Environment) object.Object {
// 初期化の文を評価
initStmt := Eval(stmt.InitialStatement, env)
if isError(initStmt) {
return initStmt
}
var result object.Object
for {
// まず継続条件を評価
condition := Eval(stmt.Condition, env)
if isError(condition) {
return condition
}
if !isTruthy(condition) {
// 評価結果が偽だったらループを抜ける
break
}
// 本体の文を評価
result = Eval(stmt.Block, env)
// エラーもしくはreturnで返り値が渡ってきたらそのまま返す
if isError(result) || isReturn(result) {
return result
}
// 増分処理の文を評価
postStmt := Eval(stmt.PostStatement, env)
if isError(postStmt) {
return postStmt
}
}
return result
}
이제 설치가 완료되었습니다.
REPL로 해볼게요. >> for (var i = 0; i < 10; i = i + 1) { puts(i); }
0
1
2
3
4
5
6
7
8
9
잘 움직이는 것 같네요.
마지막
이 글은 일부 코드만 기재되어 있으니 전체적인 차이를 보고 싶은 사람은 보세요이쪽 PR..
Reference
이 문제에 관하여('Go 언어로 만든 해석기'의 후속~ for 문구를 설치해보세요~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tatsumack/items/8e745e4ee927cebb1875
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
type ForStatement struct {
Token token.Token
InitialStatement Statement // 初期化
Condition Expression // 継続条件
PostStatement Statement // 増分処理
Block *BlockStatement // 本体のブロック
}
// "for"のTokenを読み込むと呼ばれる関数
func (p *Parser) parseForStatement() *ast.ForStatement {
stmt := &ast.ForStatement{Token: p.curToken}
// forの次は"("
if !p.expectPeek(token.LPAREN) {
return nil
}
p.nextToken()
// 初期化の文の解析
stmt.InitialStatement = p.parseStatement()
p.nextToken()
// 継続条件の式の解析
stmt.Condition = p.parseExpression(LOWEST)
if !p.expectPeek(token.SEMICOLON) {
return nil
}
p.nextToken()
// 増分処理の文の解析
stmt.PostStatement = p.parseStatement()
// 増分処理の次は")"のはず。ただし、増分処理が空の場合はすでに")"が読まれている。
if p.peekTokenIs(token.RPAREN) {
p.nextToken()
}
p.nextToken()
// 本体の文の解析
stmt.Block = p.parseBlockStatement()
return stmt
}
평가는 아래와 같다.
evaluator.go
// for文のNodeを評価するときに呼ばれる関数
func evalForStatement(stmt *ast.ForStatement, env *object.Environment) object.Object {
// 初期化の文を評価
initStmt := Eval(stmt.InitialStatement, env)
if isError(initStmt) {
return initStmt
}
var result object.Object
for {
// まず継続条件を評価
condition := Eval(stmt.Condition, env)
if isError(condition) {
return condition
}
if !isTruthy(condition) {
// 評価結果が偽だったらループを抜ける
break
}
// 本体の文を評価
result = Eval(stmt.Block, env)
// エラーもしくはreturnで返り値が渡ってきたらそのまま返す
if isError(result) || isReturn(result) {
return result
}
// 増分処理の文を評価
postStmt := Eval(stmt.PostStatement, env)
if isError(postStmt) {
return postStmt
}
}
return result
}
이제 설치가 완료되었습니다.REPL로 해볼게요. >> for (var i = 0; i < 10; i = i + 1) { puts(i); }
0
1
2
3
4
5
6
7
8
9
잘 움직이는 것 같네요.
마지막
이 글은 일부 코드만 기재되어 있으니 전체적인 차이를 보고 싶은 사람은 보세요이쪽 PR..
Reference
이 문제에 관하여('Go 언어로 만든 해석기'의 후속~ for 문구를 설치해보세요~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tatsumack/items/8e745e4ee927cebb1875
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
>> for (var i = 0; i < 10; i = i + 1) { puts(i); }
0
1
2
3
4
5
6
7
8
9
이 글은 일부 코드만 기재되어 있으니 전체적인 차이를 보고 싶은 사람은 보세요이쪽 PR..
Reference
이 문제에 관하여('Go 언어로 만든 해석기'의 후속~ for 문구를 설치해보세요~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tatsumack/items/8e745e4ee927cebb1875텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)