46 — 컴파일러: 표현식 언어
가이드 28과 29은 줄을 나누고 번역했습니다. 진짜 컴파일러는 식도 계산해야 하는데, 첫 규칙은 우선순위 — 2 + 3 * 4에서 곱셈이 먼저 일어납니다.
단계
줄을 숫자와 연산자의 혼합 목록으로 바꿉니다 —
2 + 3 * 4의 토큰 목록은[2, "+", 3, "*", 4]입니다:
실행해 보기 →line = "2 + 3 * 4" 값들 = [] for 단어 in line.split(): if 단어 in ["*", "+", "-"]: 값들.append(단어) else: 값들.append(int(단어))왼쪽부터 읽으면
(2 + 3) * 4 = 20이지만, 곱셈이 더 세게 묶여2 + (3 * 4) = 14가 정답입니다. 해결책은 목록을 두 번 지나가는 것 —곱셈통과먼저, 그다음덧셈통과. 계산기를expr.ko.nme으로 저장합니다:
실행해 보기 →# expr.ko.nme — 2 + 3 * 4 같은 식 계산기. # 실행: nme 실행 expr.ko def 곱셈통과(값들): i = 0 while i < len(값들): if 값들[i] == "*": 값들[i - 1 : i + 2] = [값들[i - 1] * 값들[i + 1]] i = i - 1 i = i + 1 return 값들 def 덧셈통과(값들): i = 0 while i < len(값들): if 값들[i] == "+": 값들[i - 1 : i + 2] = [값들[i - 1] + 값들[i + 1]] i = i - 1 elif 값들[i] == "-": 값들[i - 1 : i + 2] = [값들[i - 1] - 값들[i + 1]] i = i - 1 i = i + 1 return 값들 def 계산(line): 값들 = [] for 단어 in line.split(): if 단어 in ["*", "+", "-"]: 값들.append(단어) else: 값들.append(int(단어)) 값들 = 곱셈통과(값들) 값들 = 덧셈통과(값들) return 값들[0] 말해 "식 계산기 — 2 + 3 * 4, 또는 quit" while True: 물어봐 line, "> " if line == "quit": 말해 "안녕!" break if line == "": continue 답 = 계산(line) 말해 f"{line} = {답}"슬라이스
값들[i - 1 : i + 2] = [결과]가a,*,b세 칸을 그 곱으로 바꿔 목록을[14]하나로 접습니다.파이프로 식을 넣어 실행합니다:
printf '2 + 3 * 4\n10 - 2 * 3\n2 * 3 + 4\n1 + 2 + 3\n5 * 2 - 3\nquit\n' | nme 실행 expr.ko식 계산기 — 2 + 3 * 4, 또는 quit > 2 + 3 * 4 = 14 > 10 - 2 * 3 = 4 > 2 * 3 + 4 = 10 > 1 + 2 + 3 = 6 > 5 * 2 - 3 = 7 > 안녕!2 + 3 * 4는20이 아니라14— 곱셈 통과가 먼저 실행됐습니다.
직접 해보기
첫 번째 통과에 나눗셈을 더해 보세요 — 계산에서 "/"를 받고 곱셈통과에 elif 값들[i] == "/": 가지를 //로 만들어 10 - 8 / 2가 6이 되게 합니다.
배운 것
line.split()이 식을 단어로 만들고, 숫자와 연산자가 하나의 혼합 목록이 됩니다.*가+보다 세게 묶여2 + 3 * 4는20이 아니라14입니다.곱셈통과가 먼저*를 접고,덧셈통과가 그다음 더하고 뺍니다.- 목록을 두 번 지나가는 것이 표현식 파서의 씨앗입니다.