Lox는 Go 언어를 위한 파서/렉서 생성기입니다. 프로젝트의 문법과 Go 소스를 분석하는 lox
도구로 구성되어 있으며, Go로 의존성 없는 파서를 생성합니다.
플랫폼에 맞는 최신 버전의
lox를 다운로드하세요. 압축을 풀고 lox 바이너리를 PATH에 있는 디렉토리에
복사하세요.
lox가 Go 소스를 분석하기 때문에, 특히 Go 도구를 업그레이드할 때
자주 업데이트하는 것이 매우 중요합니다.
Lox를 배우는 가장 좋은 방법은 예제를 실행해보는 것입니다. 이 섹션에서는 계산기를 사용합니다.
먼저 터미널에서 calc 디렉토리로 이동한 후 go run .을 사용하여 예제를 실행해보세요.
2 * (1+3)과 같은 표현식을 입력하면 결과를 볼 수 있습니다.
다음으로, pow(2,8) - 1과 같은 것을 계산할 수 있도록 내장 함수를 지원하도록 프로젝트를
확장해봅시다. 함수 이름(sqrt, pow 등)과 일치할 식별자 토큰이 필요합니다.
또한 매개변수 구분자로 사용할 쉼표 토큰도 필요합니다.
편집기에서 calc.lox를 열고, NUM 정의 바로 다음인 @lexer
섹션 끝에 다음을 추가하세요:
COMMA = ','
ID = [A-Za-z][A-Za-z0-9]*
이제 함수 호출을 위한 파서 규칙을 추가합니다. @parser 섹션 끝(파일 끝부분)에
다음을 추가하세요:
func_call = ID '(' @list(expr, ',')? ')'
ID '(' ')' 부분은 간단해 보일 것입니다. @list(expr,
',') 항은 ,로 구분된 하나 이상의 expr과 일치합니다. ? 한정자는
이를 선택사항으로 만들어 매개변수를 받지 않는 함수(예: pi())를 가질 수 있게 합니다.
문법에서 토큰을 이름(예: COMMA) 또는 리터럴 값(예: ',')으로 참조할 수 있음을
주목하세요. 후자가 보통 읽기 쉽지만, 토큰 정의가 단순한 리터럴일 때만 허용됩니다.
이제 func_call을 포함하도록 expr의 정의를 변경하세요:
expr = expr '+' expr @left(1)
| expr '-' expr @left(1)
| expr '*' expr @left(2)
| expr '/' expr @left(2)
| expr '%' expr @left(2)
| expr '^' expr @right(3)
| '(' expr ')'
| num
| func_call
문법 변경이 완료되었습니다. Go 변경 사항으로 넘어가기 전에, calc 디렉토리에서
lox .를 실행하세요. 다음과 같은 오류가 표시될 것입니다:
$ lox .
calc.lox:35:1: rule missing action method: func_call
Error: errors ocurred
Lox는 모든 규칙의 모든 프로덕션이 해당하는 액션을 가지기를 기대하기 때문에 이 오류가 발생했습니다.
func_call을 위한 액션을 추가해봅시다. IDE에서 parser.go를 열고 파일 끝에
다음을 추가하세요:
func (p *calcParser) on_func_call(
id Token, _ Token, args []float64, _ Token,
) float64 {
name := string(id.Str)
switch name {
case "pow":
if len(args) != 2 {
p.errLogger.Errorf(id.Pos, "pow takes 2 arguments")
return 0
}
return math.Pow(args[0], args[1])
default:
p.errLogger.Errorf(id.Pos, "invalid function %v", name)
return 0
}
}
다시 lox .를 실행해보세요. 오류가 없어야 합니다. 그리고 프로젝트를 다시 실행하여
pow(2, 8) - 1과 같은 표현식의 결과를 얻을 수 있을 것입니다.
on_func_call의 구현이 꽤 간단해 보이길 바랍니다. 하지만 메서드 시그니처에서
많은 마법이 일어나고 있습니다. Lox는 액션을 프로덕션과 매칭하기 위해 메서드의 이름과
매개변수의 개수 및 타입을 모두 사용합니다. 자세한 내용은 액션 메서드
문서를 확인하세요.