Подсветка синтаксиса OCaml

 
0
 
Functional languages
Comments (15)
ava
Void | 19.01.2006, 17:06 #
 Начальство дало добро, ну а мы рады стараться :)


Правила подсветки:


Язык чувствителен к регистру.

Ключевые слова (#0000FF):

and
as
assert
begin
class
constraint
do
done
downto
else
end
exception
external
false
for
fun
function
functor
if
in
include
inherit
initializer
lazy
let
match
method
module
mutable
new
object
of
open
private
rec
sig
struct
then
to
true
try
type
val
virtual
when
while
with


Некоторые встроенные типы и функции (#800000):

unit
int
float
char
string
bool
exn
array
list
option
int32
int64
nativeint
lazy_t
ref
in_channel
out_channel
raise
not
or
mod
land
lor
lxor
lnot
lsl
lsr
asr
ignore
exit


Стандартные модули (#6a5acd):

Arg
Arith_status
Array
Array1
Array2
Array3
ArrayLabels
Big_int
Bigarray
Buffer
Callback
CamlinternalMod
CamlinternalOO
Char
Complex
Condition
Dbm
Digest
Dynlink
Event
Filename
Format
Gc
Genlex
Graphics
GraphicsX11
Hashtbl
Int32
Int64
LargeFile
Lazy
Lexing
List
ListLabels
Map
Marshal
MoreLabels
Mutex
Nativeint
Num
Obj
Oo
Parsing
Printexc
Printf
Queue
Random
Scanf
Set
Sort
Stack
StdLabels
Str
Stream
String
StringLabels
Sys
Thread
ThreadUnix
Unix
UnixLabels
Weak


Комментарии (#008080):
Между (* и *), могут быть вложенными:

(*
  comment1
  (* comment2 *)
  comment1
*)

(Я смотрю, в подсветке Delphi вложенные комментарии не обрабатываются. Если это сложно, то и не надо.)

Символьные литералы (#008000):
Регулярное выражение:

'([^\\\r\n]|(\\['"ntbr])|(\\\d{3})|(\\x[[:xdigit:]]{2}))'

Пример:
'a', ' ', '\n', '\022', '\xAC' - корректно
'ab', '\z', '\17', '\xGG' - некорректно
Важно в точности следовать этим правилам, потому что апостроф ' может входить в состав идентификатора, в т.ч. и в начале слова.

Строковые литералы (#008000):

"([^\\\r\n]|(\\['"ntbr])|(\\\d{3})|(\\x[[:xdigit:]]{2}))*"


Численные константы (#00008b):
целые:

((\d[\d_]*)|(0x[[:xdigit:]]([[:xdigit:]]|_)*)|(0o[0-7][0-7_]*)|(0b[01][01_]*))[nlL]?

вещественные:

\d[\d_]*(\.[\d_]*)?([eE][+-]?\d[\d_]*)?

Т.е. правила почти те же самые, что и в Си, только внутри чисел символы подчеркивания _ игнорируются; восьмеричные и двоичные константы начинаются с 0o и 0b соответственно; у целых чисел может быть один из суффиксов n, l, L.


Жду замечаний и предложений. 
ava
sergejzr | 25.01.2006, 21:07 #
 Насчёт регов не понял, сорри. Остальное почти вставил.
И ещё.. Можешь кусок кода дать для тестов?
added later:
Пока так работает: http://poligon.vingrad.ru/index.php?showto...mp;#entry613424 
ava
Void | 25.01.2006, 22:07 #
 
Цитата (sergej.z @  25.1.2006,  23:07 findReferencedText)
Насчёт регов не понял, сорри.

Это реги, которым удовлетворяют соответствующие лексемы. Я предполагал, что движок подсветки может использовать их напрямую. Ну и вообще, легче написать регэксп, чем пытаться на словах объяснить :)

Цитата (sergej.z @  25.1.2006,  23:07 findReferencedText)


И ещё.. Можешь кусок кода дать для тестов? 


Без проблем. Вот код, в аттаче то, как он должен выглядеть:


(* environment.mli *)

type ('var, 'func) t

exception Unbound_symbol of string

val make_empty : unit -> ('var, 'func) t
val add_scope : ('var, 'func) t -> ('var, 'func) t
val get_var : ('var, 'func) t -> string -> 'var
val set_var : ('var, 'func) t -> string -> 'var -> unit
val get_func : ('var, 'func) t -> string -> 'func
val add_func : ('var, 'func) t -> string -> 'func -> unit


(* environment.ml *)

open Hashtbl

type ('var, 'func) t = {
    vars : (string, 'var) Hashtbl.t list;
    funcs : (string, 'func) Hashtbl.t }

exception Unbound_symbol of string

let unbound name = raise (Unbound_symbol name)

let make_empty () = { vars = [create 17]; funcs = create 17 }

let add_scope env = { env with vars = create 7 :: env.vars }

let get_var env name =
    let rec scan = function
          [] -> unbound name
        | scope :: tail ->
            try find scope name
            with Not_found -> scan tail in
    scan env.vars

let set_var env = replace (List.hd env.vars)

let get_func env name =
    try find env.funcs name
    with Not_found -> unbound name

let add_func env = replace env.funcs


(* Some random tests.
  (* This is nested comment. *)
*)

let the_string = "Hello\044\x20\"world\"!" (* equivalent to 'Hello, "world"!' *)

let char1 = 'a'
and char2 = '\097'
and char3 = '\xFF'
and char4 = (* This is wrong character! *) '\44'
and char5 = (* This is wrong character also! *) '\xGE'

let array_of_integers = [| 0; 0o1; 0x1; 0b1; 23_17_16 |]
and list_of_reals = [ 2.; 3E1; 2.718_281_828E+00_00; (* This is wrong numbers! *) .123; 4.E_01 ]
and nativeint_int32_int64_tuple = 23n, 0x23l, 0o22L

let poly_variant_tuple = `Foo, `Bar

(* CamlP4 directives — no need to highlight specially. *)
#load "pa_extend.cmo";;


Аттач переименовать в ZIP. 
ava
sergejzr | 25.01.2006, 22:08 #
 Аттач не открывается :( 
ava
Void | 25.01.2006, 22:10 #
 P.S. Название языка OCaml smile Objective Caml; Caml — от Categorial Abstract Machine Language, а последние две буквы по совместительству означают принадлежность к семейству ML smile
added later:
Сейчас перезагружу 
ava
sergejzr | 25.01.2006, 22:19 #
 Гы! ОК smile переименую попозже smile Я вообщето это знаю(как то играл с ним), но каждый раз путаю smile 
ava
Void | 25.01.2006, 22:31 #
 Коротко основные баги, в порядке убывания важности:
  • Как и я предполагал, неправильно подсвечиваются символы: просто от апострофа до апострофа. Это надо поправить в любом случае, потому что идентификаторы, начинающиеся с ' встречаются постоянно — это переменные типов.
  • Строки не подсвечиваются вообще.
  • Не распознаются числа, разделенные подчеркиваниями, и суффиксы n и l.
Да, и комментарии лучше все-таки курсивом
Подумал, и решил, что, несмотря на то, что в подсветке большинства языков на форуме в комментариях используется italic, обычный текст читается лучше.

Пока вроде все.

Цитата
Гы! ОК smile переименую попозже smile Я вообщето это знаю(как то играл с ним), но каждый раз путаю smile

smile 
ava
sergejzr | 26.01.2006, 17:16 #
 Насчёт символьных - так и не въехал. Можешь словами расписать?
И ещё. При подсветке мы исходим из того, что код БЕЗ синтактических ошибок. То есть если код с ошибками подсвечивается неправильно, то это ОК. Наша задача - всего лишь чтобы правильный код правильно подсвечивался.
поэтому я не понимаю определения "корректно" smile 
ava
Void | 26.01.2006, 18:49 #
 
Цитата (sergej.z @  26.1.2006,  19:16 findReferencedText)
Насчёт символьных - так и не въехал. Можешь словами расписать?

Попытаюсь. Правило довольно мудреное.
Итак, символьные константы заключаются в одинарные кавычки. Но они должны содержать только один символ — обыкновенный или escape-последовательность. Поэтому, встретив апостроф, мы не имеем права подсвечивать все подряд до следующего апострофа, как символ. В зависимости от того, является ли следующий за ним символ escape-последовательностью, мы должны проверить, является ли символ на позиции +2 ('a'), +3 ('\n'), +5 ('\032' или '\xEF') апострофом. Если нет — это уже НЕ символ.
Но это еще не все. Дело в том, что вот это:
'var   foo'   foo'b'def   abc''

— валидные идентификаторы. А вот это:
'a'b

уже рассматривается как последовательность символа и идентификатора, т.е. синтаксическая ошибка.
Т.о. апостроф наряду с буквами, цифрами и подчеркиванем может быть частью идентификатора.

При последовательном лексическом разборе все это разруливается на раз (собственно, я при написании регов основывался на исходниках лексера компилятора OCaml smile ). Как быть в случае с нашим движком подсветки — не знаю. В принципе, будет достаточно, чтобы принималась во внимание только первая часть правила: что символьные константы должны быть ровно в один символ. Идентификаторы с апострофами посередине я в реальном коде не видел ни разу. А вот в начале или в конце — постоянно.

Подводя итог, для наших целей будет достаточно, чтобы текст между апострофами подсвечивался как символ тогда и только тогда:
  •  когда он состоит из одного символа, кроме \ и '
  •  когда он состоит из бэкслэша и одного из символов n t b r ' " \ и пробел.
  •  когда он состоит из бэкслэша и трех десятичных цифр
  •  когда он состоит из "\x" и двух шестнадцатеричных цифр.
  •  как вариант крайнего упрощения: вместо трех последних пунктов — бэкслэш и от одного до трех любых символов.

Цитата (sergej.z @  26.1.2006,  19:16 findReferencedText)
И ещё. При подсветке мы исходим из того, что код БЕЗ синтактических ошибок. То есть если код с ошибками подсвечивается неправильно, то это ОК. Наша задача - всего лишь чтобы правильный код правильно подсвечивался. поэтому я не понимаю определения "корректно"

Я это понимаю smile Просто в некоторых случаях может получится так, что мы неправильно подсветим синтаксически правильный код.
 
ava
[email protected]$h | 11.10.2006, 21:26 #
Думаю, соответствующие участники уже знают про подсветку кода OCaml. Для вставки кодов OCaml используйте подсветку синтаксиса из выплывающего списка Код в форме ответа.
Тему открепляю. О подсветке сообщено в шапке форума.

Void, скажи, если  реализация ещё не отлажена. Тему можно будет опять зафиксировать.
ava
Void | 11.10.2006, 21:54 #
Цитата ([email protected]$h @  11.10.2006,  23:26 findReferencedText)
Void, скажи, если  реализация ещё не отлажена. Тему можно будет опять зафиксировать. 

Говорю: она не работает. Т.е., если я правильно понимаю, OCaml добавлен в список кодов на форме, но сама реализация подсветки на форум не загружена.
let fact = function
    | 0 -> 1
    | n when n > 0 -> n * fact (n - 1)
ava
[email protected]$h | 11.10.2006, 22:02 #
Хорошо, тогда фиксирую её обратно  ;-)
Быстрое же у тебя время отклика получилось
ava
Void | 11.10.2006, 22:14 #
С одной стороны, не сказать, что это так критично сейчас (последняя тема с кодом на *ML была много месяцев назад). С другой, надо бы админам намекнуть smile Так как теперь даже Полигона нет, чтобы проверить.
ava
[email protected]$h | 11.10.2006, 23:10 #
Да. Можешь напрямую Сергея попросить посмотреть. С Fortran там тоже не реализовано...
ava
sergejzr | 12.10.2006, 12:46 #
Блин. всё руки не доходят до оставшихся подсветок :( Любой, кто знает яваскрипт может помочь...
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit