피터의 계산기

아직 제출이 없습니다시간 제한1초메모리 제한128 MB

문제

지난주에 피터의 계산기가 고장 났다. 이제 피터에게 남은 것은 계산기 앱이 없는 컴퓨터, 그리고 공학자에게는 너무 번거로운 종이와 연필뿐이다. 피터의 친구인 여러분은 그를 위해 계산기 프로그램을 만들어 달라는 부탁을 받았다. 피터와 이야기해 본 결과 다음을 알게 되었다.

  • 피터는 정수 연산만 한다. 필요한 연산은 덧셈, 뺄셈, 곱셈이다.
  • 이름의 길이가 최대 50자인 변수를 원하는 만큼 사용하고 싶어 한다.
  • 주된 계산 방식은 여러 수식을 입력해 변수에 대입하는 것이다. 어떤 수식은 아직 정의되지 않은 변수를 참조할 수도 있는 복잡한 식이고, 어떤 수식은 하나의 숫자로만 이루어져 있다. 그런 다음 피터는 어떤 변수의 값을 묻는다. 즉, 그 변수의 수식을 계산한다.
  • 피터는 또한 일부 변수를 다시 정의한 뒤, 그 변수에 의존하는 수식을 다시 계산하고 싶어 한다.

입력은 다음 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는 문법 구조 AB 뒤에 C가 오는 형태임을 뜻한다. A = B | CAB이거나 또는 C임을 뜻한다. A = [ B ]AB이거나 아무것도 아님을 뜻하고, 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) 상태가 된다.

  • 아직 정의되지 않았거나, 아직 정의되지 않은 변수를 참조하는 경우
  • 변수의 정의에 순환(cycle)이 포함된 경우

피터의 계산기를 구현하는 프로그램을 작성하라. 모든 변수 정의를 저장하고, PRINT 문마다 가장 최근의 정의를 기준으로 지정된 변수를 계산해야 한다. RESET 문을 만나면 저장된 모든 변수를 삭제하여 모든 변수를 다시 정의되지 않은 상태로 만들어야 한다.

입력

입력에는 위 문법을 따르는 계산이 들어 있다. 각 줄은 변수에 대한 대입, PRINT 문, RESET 문 중 하나이거나 빈 줄이다.

출력

입력에 있는 각 PRINT 문에 대해, 지정된 변수의 숫자 값을 한 줄에 출력한다. 변수가 정의되지 않았다면 UNDEF를 출력한다.