Вот несколько примеров:
- компилятор Rubinius Ruby написан на Ruby,
- компилятор YARV Ruby написан на C,
- компилятор XRuby Ruby написан на Java,
- Ruby.NET Ruby-компилятор написан на C #,
- компилятор MacRuby Ruby написан на Objective-C,
- компилятор IronJS ECMAScript написан на F #,
- компилятор MS Visual F # написан на F #,
- компилятор MS Visual C # написан на C ++, в настоящее время переписывается на C #,
- компилятор MS Visual Basic.NET написан на C ++, в настоящее время переписывается в Visual Basic.NET,
- компилятор GCC C написан на C,
- компилятор Clang C написан на C ++,
- большинство компиляторов Паскаля написаны на Паскале,
- большинство компиляторов Оберона написаны на Обероне,
- компиляторы 6g / 8g и gccgo Go написаны на языке C.
В общем, компиляторы могут быть написаны на любом языке, который на самом деле достаточно мощный, чтобы писать компилятор. Это, очевидно, включает любой язык, полный Тьюринга. Но возможно даже написать компилятор на языке, не полном Тьюринга. (Например, я не вижу очевидной причины, по которой компилятор не может быть тотальной функцией, но итоговые функции явно не являются полными по Тьюрингу.)
На практике, однако, компиляторы в основном написаны на трех конкретных классах языков с разными плюсами и минусами:
- тот же язык, который реализует компилятор (плюсы: большее сообщество, потому что все, кто знает язык, могут работать на компиляторе, в противном случае им нужно будет знать оба языка; минусы: проблема с загрузкой)
- основной низкоуровневый язык системного программирования платформы, на которой должен работать компилятор, например C на Unix, Java на JVM, C # на CLI (плюсы: очень быстро; минусы: часто эти языки просто не очень хороши для написания компиляторов, также я на самом деле не верю, что преимущества производительности реальны)
- язык, который очень хорош для написания таких компиляторов, как ML, Haskell, Lisp, Scheme (плюсы: эти компиляторы, как правило, очень легко понять и взломать; минусы: вам все равно нужно знать оба языка)
- особый случай вышеупомянутого: предметно-ориентированный язык для написания компиляторов, таких как OMeta или для синтаксического анализа ANTLR, YACC (плюсы: те же, что и выше, но даже больше; минусы: те же, что и выше)
Все это по сути компромиссы: написание компилятора на одном языке облегчает понимание, потому что вам не нужно изучать другой язык. Это также может усложнить понимание, потому что язык не очень хорош при написании компиляторов. (Представьте, например, написание компилятора SQL на SQL.) Возможно, даже невозможно написать компилятор, например (для довольно свободного определения «язык» и «компилятор») это невозможно написать компилятор CSS в CSS или компилятор HTML в HTML.
С другой стороны: написание компилятора на специализированном языке написания компилятора, вероятно, облегчает его понимание, но в то же время требует изучения нового языка.
Обратите внимание, что три класса не являются непересекающимися: компилятор может делиться на несколько классов. Например, компилятор для специализированного языка написания компиляторов, написанный сам по себе, подпадает под категорию 1 (написан сам по себе) и 3 (написан на языке, хорошо пишущем компиляторы).
В некоторых случаях вы действительно можете попасть в сладкое пятно. Например, F # - это родной язык с родной скоростью в CLI, и он очень хорош при написании компиляторов. Таким образом, написание компилятора F # на F # дает вам № 1 (писать самому), № 2 (писать на родном, быстром языке) и № 3 (писать на языке, который хорош для написания компиляторов). То же самое относится и к Scala.