지난주에 피터의 계산기가 고장 났다. 이제 피터에게 남은 것은 계산기 앱이 없는 컴퓨터, 그리고 공학자에게는 너무 번거로운 종이와 연필뿐이다. 피터의 친구인 여러분은 그를 위해 계산기 프로그램을 만들어 달라는 부탁을 받았다. 피터와 이야기해 본 결과 다음을 알게 되었다.
입력은 다음 EBNF 문법을 엄격히 따른다.
file = line { line } .
line = [ assignment | print | reset ] .
assignment = var ":=" expression.
print = "PRINT" var.
reset = "RESET".
expression = term { addop term }.
term = factor { mulop factor }.
factor = "(" expression ")" | var | number.
addop = "+" | "-".
mulop = "*".
EBNF(확장 배커스-나우르 형식)에서 A = B C는 문법 구조 A가 B 뒤에 C가 오는 형태임을 뜻한다. A = B | C는 A가 B이거나 또는 C임을 뜻한다. A = [ B ]는 A가 B이거나 아무것도 아님을 뜻하고, A = { B }는 A가 임의 개수(0개 포함)의 B를 이어 붙인 것임을 뜻한다.
var는 변수의 이름으로, 한 개의 글자 뒤에 최대 49개의 글자 또는 숫자가 오는 형태이다. 글자는 대문자와 소문자 모두 가능하다. number는 정수를 나타낸다. 이 두 생성 규칙의 정확한 문법은 다음과 같다.
var = letter { letter | digit }.
number = [ "-" ] digit { digit }.
letter = "A" | "B" | ... | "Z" | "a" | "b" | ... | "z".
digit = "0" | "1" | ... | "8" | "9".
문법 구조의 각 부분 사이에는 공백이 몇 개든 올 수 있지만, 변수 이름이나 정수 안에는 공백이 올 수 없다. <EOF>는 입력의 끝을, <CR>는 줄바꿈 문자를 나타낸다. 입력의 모든 줄은 200자보다 짧다. 변수와 키워드 모두 대소문자를 구분한다.
변수의 값은 다음 경우에 정의되지 않음(undefined) 상태가 된다.
피터의 계산기를 구현하는 프로그램을 작성하라. 모든 변수 정의를 저장하고, PRINT 문마다 가장 최근의 정의를 기준으로 지정된 변수를 계산해야 한다. RESET 문을 만나면 저장된 모든 변수를 삭제하여 모든 변수를 다시 정의되지 않은 상태로 만들어야 한다.
입력에는 위 문법을 따르는 계산이 들어 있다. 각 줄은 변수에 대한 대입, PRINT 문, RESET 문 중 하나이거나 빈 줄이다.
입력에 있는 각 PRINT 문에 대해, 지정된 변수의 숫자 값을 한 줄에 출력한다. 변수가 정의되지 않았다면 UNDEF를 출력한다.