"Давайте создадим компилятор!" - читать интересную книгу автора (Креншоу Джек)ОсноваКаждая программа нуждается в некоторых шаблонах … подпрограммы ввода/вывода, подпрограммы сообщений об ошибках и т.д. Программы, которые мы будем разрабатывать, не составляют исключения. Я попытался выполнить их на минимальном уровне, чтобы мы могли сконцентрироваться на более важных вещах и не заблудиться. Код, размещенный ниже, представляет собой минимум, необходимый нам, чтобы что-нибудь сделать. Он состоит из нескольких подпрограмм ввода/вывод, подпрограммы обработки ошибок и скелета – пустой основной программы. Назовем ее Cradle. По мере создания других подпрограмм, мы будем добавлять их к Cradle и добавлять вызовы этих подпрограмм. Скопируйте Cradle и сохраните его, потому что мы будем использовать его неоднократно. Существует множество различных путей для организации процесса сканирования в синтаксическом анализаторе. В Unix системах авторы обычно используют getc и ungetc. Удачный метод, примененный мной, заключается в использовании одиночного, глобального упреждающего символа. Части процедуры инициализации служит для «запуска помпы», считывая первый символ из входного потока. Никаких других специальных методов не требуется… каждый удачный вызов GetChar считывает следующий символ из потока. {–} program Cradle; {–} { Constant Declarations } const TAB = ^I; {–} { Variable Declarations } var Look: char; { Lookahead Character } {–} { Read New Character From Input Stream } procedure GetChar; begin Read(Look); end; {–} { Report an Error } procedure Error(s: string); begin WriteLn; WriteLn(^G, 'Error: ', s, '.'); end; {–} { Report Error and Halt } procedure Abort(s: string); begin Error(s); Halt; end; {–} { Report What Was Expected } procedure Expected(s: string); begin Abort(s + ' Expected'); end; {–} { Match a Specific Input Character } procedure Match(x: char); begin if Look = x then GetChar else Expected('''' + x + ''''); end; {–} { Recognize an Alpha Character } function IsAlpha(c: char): boolean; begin IsAlpha := upcase(c) in ['A'..'Z']; end; {–} { Recognize a Decimal Digit } function IsDigit(c: char): boolean; begin IsDigit := c in ['0'..'9']; end; {–} { Get an Identifier } function GetName: char; begin if not IsAlpha(Look) then Expected('Name'); GetName := UpCase(Look); GetChar; end; {–} { Get a Number } function GetNum: char; begin if not IsDigit(Look) then Expected('Integer'); GetNum := Look; GetChar; end; {–} { Output a String with Tab } procedure Emit(s: string); begin Write(TAB, s); end; {–} { Output a String with Tab and CRLF } procedure EmitLn(s: string); begin Emit(s); WriteLn; end; {–} { Initialize } procedure Init; begin GetChar; end; {–} { Main Program } begin Init; end. {–} Скопируйте код, представленный выше, в TP и откомпилируйте. Удостоверьтесь, что программа откомпилировалась и запустилась корректно. Затем переходим к первому уроку, синтаксическому анализу выражений. |
|
|