diff options
author | lukeg <lukeg> | 2003-02-21 19:01:14 +0000 |
---|---|---|
committer | lukeg <lukeg> | 2003-02-21 19:01:14 +0000 |
commit | e7d48fe500f6ed676ee1b212ebd61408bced1c5b (patch) | |
tree | 11a756c7bb4906f3e186c1cb8331cb7ed27bc69c /mods | |
download | ermacs-fork-e7d48fe500f6ed676ee1b212ebd61408bced1c5b.tar.gz |
*** empty log message ***
Diffstat (limited to 'mods')
-rw-r--r-- | mods/src/Makefile | 12 | ||||
-rw-r--r-- | mods/src/em_erlang.erl | 501 | ||||
-rw-r--r-- | mods/src/em_erlang_scan.erl | 780 | ||||
-rw-r--r-- | mods/src/em_erlang_scan.xrl | 135 | ||||
-rw-r--r-- | mods/src/em_scan.erl | 381 | ||||
-rw-r--r-- | mods/src/em_scheme.erl | 184 | ||||
-rw-r--r-- | mods/src/em_scheme_scan.erl | 531 | ||||
-rw-r--r-- | mods/src/em_scheme_scan.xrl | 18 | ||||
-rw-r--r-- | mods/src/em_stdlib.erl | 21 | ||||
-rw-r--r-- | mods/src/em_test_scan.erl | 255 | ||||
-rw-r--r-- | mods/src/em_test_scan.xrl | 12 | ||||
-rw-r--r-- | mods/src/leex.hrl | 217 |
12 files changed, 3047 insertions, 0 deletions
diff --git a/mods/src/Makefile b/mods/src/Makefile new file mode 100644 index 0000000..8314a10 --- /dev/null +++ b/mods/src/Makefile @@ -0,0 +1,12 @@ +include ../../../../support/include.mk + +# Ermacs includes +ERLC_FLAGS += -I ../../.. -pa ../../ebin + +all: $(ERL_OBJECTS) + +$(ERL_OBJECTS): ../../include/edit.hrl + +clean: + -rm -f $(ERL_OBJECTS) + diff --git a/mods/src/em_erlang.erl b/mods/src/em_erlang.erl new file mode 100644 index 0000000..dd13e9d --- /dev/null +++ b/mods/src/em_erlang.erl @@ -0,0 +1,501 @@ +%%%---------------------------------------------------------------------- +%%% File : em_erlang.erl +%%% Author : Luke Gorrie <luke@bluetail.com> +%%% Purpose : Erlang "Major Mode" +%%% Created : 10 Mar 2001 by Luke Gorrie <luke@bluetail.com> +%%%---------------------------------------------------------------------- + +-module(em_erlang). +-author('luke@bluetail.com'). + +-include_lib("ermacs/include/edit.hrl"). +-import(edit_lib, [buffer/1]). +-export([mod_init/0, erlang_mode/1, reindent_cmd/1]). + +-define(keymap, erlang_mode_map). + +%% Called by the editor when this module is load/require'd +%% +%% NB: may be called several times due to explicit "load" calls. +mod_init() -> + catch edit_keymap:delete(?keymap), + init_map(), + edit_keymap:global_set_key("C-x e", {?MODULE, erlang_mode, []}), + edit_var:add_to_list(auto_mode_alist, + {"\.erl$$", {em_erlang, erlang_mode}}), + ok. + +erlang_mode(State) -> + Mode = #mode{name="Erlang", + id=erlang, + keymaps=[?keymap]}, + Buf = buffer(State), + edit_buf:set_mode(Buf, Mode), + State. + +init_map() -> + edit_keymap:new(?keymap), + edit_keymap:bind_each(?keymap, bindings()). + +bindings() -> + [{"C-i", {?MODULE, reindent_cmd, []}} + ]. + +reindent_cmd(State) -> + case scan_fun(State) of + no_previous_line -> + State; + Scan -> + B = buffer(State), + Indent = max(0, + idt(Scan)), %% + indent_cur_line_adjust(B)), + reindent(B, edit_lib:beginning_of_line_pos(B), Indent) + end. + +indent_cur_line_adjust(B) -> + case cur_line_first_token(B) of + nomatch -> + 0; + {match, Tok} -> + adjust_value(Tok) + end. + +adjust_value('when') -> 2; +adjust_value(')') -> -1; +adjust_value('}') -> -1; +adjust_value(']') -> -1; +adjust_value('>>') -> -2; +adjust_value(_) -> 0. + +strip_scan(X) -> lists:flatten(strip_scan1(X)). + +strip_scan1([]) -> []; +strip_scan1([{lit,_}|T]) -> ["lit "|strip_scan1(T)]; +strip_scan1([{X,Y}|T]) -> [atom_to_list(X) ++ " "|strip_scan1(T)]. + +reindent(Buf, Pos, Lvl) -> + Pred = fun(C) -> (C /= $ ) and (C /= $\t) end, + End = max(Pos, edit_lib:find_char_forward(Buf, Pred, Pos, 1)), + edit_buf:replace(Buf, lists:duplicate(Lvl, $ ), Pos, End). + +max(X, Y) when X > Y -> X; +max(X, Y) -> Y. + +min(X, Y) when X < Y -> X; +min(X, Y) -> Y. + + +beginning_of_function(State) -> + B = buffer(State), + Pos = beginning_of_function_pos(B), + edit_buf:move_mark(B, point, Pos). + +beginning_of_function_pos(B) -> + Point = min(edit_buf:point_max(B) - 1, + max(1, edit_lib:beginning_of_line_pos(B) - 1)), + Cord = edit_buf:get_cord(B), + case cord_regexp:first_match("^[a-z'$-?]", Cord, Point, backward) of + nomatch -> + 1; + {match, Start, End} -> + Start + end. + +%%% ---------------------------------------------------------------------- +%%% Indentation +%%% ---------------------------------------------------------------------- + +%% Calculate the indentation level for the next line of a +%% function. `Scan' is the result of tokenising from the start of the +%% function. +idt(Scan) -> + idt(Scan, [], [], 0). + +%% Stack item +-record(si, + {id, % icr | '->' | open + tok, % token + col, % column number of `tok' + old_indent % indent level when `tok' was found + }). + +%% icr means "if/case/receive(/begin/fun)" - really anything that's +%% matched by an 'end' + +%% Variable names: C = Column, O = OldToken, S = Stack, I = IndentLevel + +%% if case receive begin +idt([{Icr, C} | T], O, S, I) + when Icr == 'if'; Icr == 'case'; Icr == 'receive'; Icr == 'begin'-> + CI = calc_clause_indent({Icr, C}, T, C), + idt(T, Icr, push_icr(Icr, C, I, S), CI); + +%% fun +idt([{'fun', C}, {'(', OpenC} | T], O, S, I) -> + Rest = [{'(', OpenC} | T], + CI = calc_clause_indent({'fun', C}, Rest, C), + idt(Rest, 'fun', push_icr('fun', C, I, S), CI); + +%% end +idt([{'end', C} | T], O, S, I) -> + case unwind_icr(S) of + nomatch -> + idt(T, 'end', [], 0); + {SI, S2} -> + idt(T, 'end', S2, SI#si.old_indent) + end; + +%% ( [ { << +idt([{Open, C} | T], O, S, I) + when Open == '('; Open == '['; Open == '{'; Open == '<<' -> + Width = length(atom_to_list(Open)), + idt(T, Open, push_open(Open, C, I, S), C+Width); + +%% ) ] } >> +idt([{Close, C} | T], O, S, I) + when Close == ')'; Close == ']'; Close == '}'; Close == '>>' -> + case unwind_close(matching(Close), S) of + nomatch -> + idt(T, Close, [], 0); + {SI, S2} -> + idt(T, Close, S2, SI#si.old_indent) + end; + +%% -> +idt([{'->', C} | T], O, S, I) -> + NewIndent = case unwind_icr(S) of + nomatch -> + 4; + {ICR_SI, ICR_S2} -> + ICR_SI#si.col + 8 + end, + case unwind_when(S) of + {SI, S2} -> + idt(T, '->', push_arrow(C, SI#si.old_indent, S2), NewIndent); + nomatch -> + idt(T, '->', push_arrow(C, I, S), NewIndent) + end; + +%% when +idt([{'when', C}, {Next, NextC} | T], Old, S, I) when Next /= '->' -> + idt(T, 'when', push_when(C, I, S), NextC); + + +%% ; +idt([{';', C} | T], O, S = [SI = #si{id='when'}|_], I) -> + idt(T, ';', S, I); + +idt([{',', C} | T], O, S = [SI = #si{id='when'}|_], I) -> + idt(T, ';', S, I); + +idt([{';', C} | T], O, S, I) -> + case unwind_arrow(S) of + nomatch -> + idt(T, ';', [], 0); + {SI, S2} -> + idt(T, ';', S2, SI#si.old_indent) + end; + +idt([{'when', C} | T], '\n', S, I) -> + idt(T, 'when', S, I+2); + +%% Period: end of function +idt([{'.', C} | T], O, S, I) -> + idt(T, start, [], 0); + +%% Skip blank lines +idt([{'\n', C}, {'\n', _} | T], O, S, I) -> + idt([{'\n', C} | T], O, S, I); + +idt([{'\n', C} | T], O, S = [#si{id=open}|_], I) -> + idt(T, '\n', S, I); + +%% End of line. The preceeding token indicates whether we need to be unwinding +idt([{'\n', C} | T], Old, S, I) +%%when member(Old, ?ICR_TOKENS) -> + when Old == '.'; Old == ';'; Old == 'of'; Old == 'begin'; + Old == 'receive'; Old == 'if'; Old == '->'; Old == ','; + Old == '|' -> + idt(T, '\n', S, I); + +idt([{'\n', C} | T], O, S = [#si{id=open, old_indent=OldIndent}|_], I) -> + idt(T, '\n', S, OldIndent); + +idt([{'\n', C} | T], O, S, I) -> + case unwind_icr(S) of + nomatch -> + idt(T, '\n', [], 0); + {SI, _S2} -> + idt(T, '\n', S, SI#si.col) + end; + +idt([{'||', C} | T], O, S, I) -> + idt(T, '||', S, C + 3); + +%% Quotes + +idt([{Quote, C} | T], O, S, I) when Quote == '\''; + Quote == '"' -> + match_quote(Quote, T, S, I); + +%% Boring stuff +idt([{Tok,_}|T], O, S, I) -> + idt(T, Tok, S, I); + +idt([], O, S, I) -> + I. + +push_icr(Atom, Col, Indent, Stack) -> + [#si{id=icr, tok=Atom, col=Col, old_indent=Indent} | Stack]. + +push_open(Atom, Col, Indent, Stack) -> + [#si{id=open, tok=Atom, col=Col, old_indent=Indent} | Stack]. + +push_arrow(Col, Indent, Stack) -> + [#si{id=arrow, tok='->', col=Col, old_indent=Indent} | Stack]. + +push_when(Col, Indent, Stack) -> + [#si{id='when', tok='when', col=Col, old_indent=Indent} | Stack]. + +%% Unwind the stack to find a match for a closing bracket. For a +%% syntactically correct function, the head of the stack should always +%% match, but otherwise I just keep unwinding to be "forgiving" - +%% i.e. just give the wrong answer instead of an error :-) + +unwind_close(Tok, [SI = #si{id=open, tok=Tok} | T]) -> + {SI, T}; +unwind_close(Tok, [H|T]) -> + unwind_close(Tok, T); +unwind_close(Tok, []) -> + nomatch. + +unwind_icr([SI = #si{id=icr} | T]) -> + {SI, T}; +unwind_icr([H|T]) -> + unwind_icr(T); +unwind_icr([]) -> + nomatch. + +%% Returns: {SI, ICR_SI, Stack} +unwind_arrow([SI = #si{id=arrow} | T]) -> + {SI, T}; +unwind_arrow([H|T]) -> + unwind_arrow(T); +unwind_arrow([]) -> + nomatch. + +unwind_when([SI = #si{id='when'}|T]) -> + {SI, T}; +unwind_when([H|T]) -> + unwind_when(T); +unwind_when([]) -> + nomatch. + +match_quote(Quote, [{'\\', _}, _ | T], S, I) -> + %% Something is being escaped, hop over it + match_quote(Quote, T, S, I); +match_quote(Quote, [Tok = {Quote, _} | T], S, I) -> + idt(T, Quote, S, I); +match_quote(Quote, [Tok|T], S, I) -> + match_quote(Quote, T, S, I); +match_quote(Quote, [], S, I) -> + %% Out of tokens while inside a quote + 0. + +calc_clause_indent({IRF, X}, [{Next, Y}|T], I) + when IRF == 'if'; IRF == 'receive'; IRF == 'fun' -> + if + Next == '\n' -> + I + 4; + true -> + Y + end; +calc_clause_indent(_, _, I) -> + I + 4. + +matching(')') -> '('; +matching(']') -> '['; +matching('}') -> '{'; +matching('>>') -> '<<'. + +%%% ---------------------------------------------------------------------- +%%% Scanner +%%% ---------------------------------------------------------------------- + +% make_erlang_scanner() -> +% em_scan:make_scanner(em_erlang_scan:yystate(), +% {em_erlang_scan, yystate}, +% {em_erlang_scan, yyaction}). + +% scan_fun(State) -> +% B = buffer(State), +% RStart = beginning_of_function_pos(B), +% REnd = min(edit_lib:beginning_of_line_pos(B), +% edit_buf:point_max(B) - 1), +% Region = if +% REnd > RStart -> +% edit_buf:get_region(B, RStart, REnd); +% true -> +% "" +% end, +% scan(cord:new(Region)). + +% scan(Cord) -> +% Scanner = make_erlang_scanner(), +% Walker = cord:walker(Cord), +% case em_scan:edit_scan(Scanner, Walker) of +% {error, Rsn} -> +% {error, Rsn}; +% {ok, Toks} -> +% %% This module expects {Class, Column} +% [{Type, Col} || {Type, Col, Line} <- Toks] +% end. + +%%%%%%% OLD (current) SCANNER + +%% Token = {Class, Column} + +-define(MAX_TOKEN_LENGTH, 64). + +first_token(Str) -> + case scan(Str) of + [] -> + nomatch; + [{Tok,_}|_] -> + {match, Tok} + end. + +%% Returns: nomatch | {match, Token} +cur_line_first_token(Buf) -> + Max = edit_buf:point_max(Buf), + Start = edit_lib:beginning_of_line_pos(Buf), + End = min(Max - 1, + min(Start + ?MAX_TOKEN_LENGTH, + edit_lib:end_of_line_pos(Buf))), + if + End > Start -> + Str = edit_buf:get_region(Buf, Start, End), + first_token(Str); + true -> + nomatch + end. + +scan_fun(State) -> + B = buffer(State), + RStart = beginning_of_function_pos(B), + REnd = min(edit_lib:beginning_of_line_pos(B), + edit_buf:point_max(B) - 1), + Region = if + REnd > RStart -> + edit_buf:get_region(B, RStart, REnd); + true -> + "" + end, + scan(Region). + +strip(X) -> [element(1, E) || E <- X]. + +scan(Str) -> + S = merge_literals(scan1(Str, true, 0)), + S. + +merge_literals([]) -> []; +merge_literals([{lit,P},{lit,_}|T]) -> merge_literals([{lit,P}|T]); +merge_literals([H|T]) -> [H|merge_literals(T)]. + +scan1([], _, P) -> + []; +scan1([$%|T], _, P) -> + skip_comments(T, P); +scan1([$$,_|T], _, P) -> + [{lit,P}|scan1(T, true, P+2)]; +scan1([$.,X|T], _, P) -> + case lists:member(X, ws()) of + true -> + [{'.',P} | scan1([X|T], true, P)]; + false -> + [{lit,P}|scan1([X|T], true, P)] + end; +scan1(Str, Fresh, P) -> + case match(Str, Fresh) of + nomatch when hd(Str) /= $ , hd(Str) /= $\t -> + [{lit,P}|scan1(tl(Str), not symchar(hd(Str)), P+1)]; + nomatch -> + scan1(tl(Str), not symchar(hd(Str)), P+1); + {match, "\n"} -> + [{'\n',P} | + scan1(tl(Str), true, 0)]; + {match, M} -> + Len = length(M), + Rest = lists:nthtail(Len, Str), + [{list_to_atom(M), P} | + scan1(Rest, true, P+Len)] + end. + +match(Str, true) -> + case match_alone(Str) of + nomatch -> + match(Str, false); + X -> + X + end; +match(Str, false) -> + match_anywhere(Str). + +match_alone(Str) -> + match_alone(Str, alone()). + +match_alone(Str, [Str|_]) -> + {match, Str}; +match_alone(Str, [X|T]) -> + case lists:prefix(X, Str) of + true -> + case not symchar(lists:nth(length(X)+1, Str)) of + true -> + {match, X}; + false -> + match_alone(Str, T) + end; + false -> + match_alone(Str, T) + end; +match_alone(Str, [_|T]) -> + match_alone(Str, T); +match_alone(Str, []) -> + nomatch. + +match_anywhere(Str) -> + match_anywhere(Str, anywhere()). + +match_anywhere(Str, [X|T]) -> + case lists:prefix(X, Str) of + true -> {match, X}; + false -> match_anywhere(Str, T) + end; +match_anywhere(Str, []) -> + nomatch. + +skip_comments([$\n|T], P) -> + scan1(T, true, P); +skip_comments([_|T], P) -> + skip_comments(T, 0); +skip_comments([], P) -> + []. + +%% Tokens that can appear anywhere +anywhere() -> + ["{","}","<<",">>","(",")","[","]",";",".","->","||","|",";",",","\n", + "\"", "'", "\\"]. + +%% Tokens that must appear "alone" +alone() -> + ["begin", "end", "case", "if", "receive", "fun", "of", "when"]. + +ws() -> "\r\t\n ". + +symchar(C) when C >= $a, C =< $z -> true; +symchar(C) when C >= $A, C =< $Z -> true; +symchar(C) when C >= $0, C =< $9 -> true; +symchar($_) -> true; +symchar(_) -> false. + diff --git a/mods/src/em_erlang_scan.erl b/mods/src/em_erlang_scan.erl new file mode 100644 index 0000000..46ddba3 --- /dev/null +++ b/mods/src/em_erlang_scan.erl @@ -0,0 +1,780 @@ +%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE +%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE +%% AND BETTER INTERFACE - BE WARNED +%% PLEASE REPORT ALL BUGS TO THE AUTHOR. + +-module('em_erlang_scan'). + +-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]). +-export([format_error/1]). + +%% luke +-export([yystate/0, yystate/6, yyaction/4]). + +%% User code. This is placed here to allow extra attributes. + +-author('rv@cslab.ericsson.se'). +-copyright('Copyright (c) 1996 Ericsson Telecommunications AB'). + +-export([reserved_word/1]). + +reserved_word('after') -> true; +reserved_word('begin') -> true; +reserved_word('case') -> true; +reserved_word('catch') -> true; +reserved_word('end') -> true; +reserved_word('fun') -> true; +reserved_word('if') -> true; +reserved_word('let') -> true; +reserved_word('of') -> true; +reserved_word('query') -> true; +reserved_word('receive') -> true; +reserved_word('when') -> true; +reserved_word('bnot') -> true; +reserved_word('not') -> true; +reserved_word('div') -> true; +reserved_word('rem') -> true; +reserved_word('band') -> true; +reserved_word('and') -> true; +reserved_word('bor') -> true; +reserved_word('bxor') -> true; +reserved_word('bsl') -> true; +reserved_word('bsr') -> true; +reserved_word('or') -> true; +reserved_word('xor') -> true; +reserved_word(_) -> false. + +base(L, Cs) -> + H = string:chr(Cs, $#), + case list_to_integer(string:substr(Cs, 1, H-1)) of + B when B > 16 -> {error,"illegal base"}; + B -> + case base(string:substr(Cs, H+1), B, 0) of + error -> {error,"illegal based number"}; + N -> {token,{integer,L,N}} + end + end. + +base([C|Cs], Base, SoFar) when C >= $0, C =< $9, C < Base + $0 -> + Next = SoFar * Base + (C - $0), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) when C >= $a, C =< $f, C < Base + $a - 10 -> + Next = SoFar * Base + (C - $a + 10), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) when C >= $A, C =< $F, C < Base + $A - 10 -> + Next = SoFar * Base + (C - $A + 10), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) -> error; +base([], Base, N) -> N. + +cc_convert([$$,$\\|Cs]) -> + hd(string_escape(Cs)); +cc_convert([$$,C]) -> C. + +string_gen([$\\|Cs]) -> + string_escape(Cs); +string_gen([C|Cs]) -> + [C|string_gen(Cs)]; +string_gen([]) -> []. + +string_escape([O1,O2,O3|S]) when + O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 -> + [(O1*8 + O2)*8 + O3 - 73*$0|string_gen(S)]; +string_escape([$^,C|Cs]) -> + [C band 31|string_gen(Cs)]; +string_escape([C|Cs]) when C >= 0, C =< $ -> + string_gen(Cs); +string_escape([C|Cs]) -> + [escape_char(C)|string_gen(Cs)]. + +escape_char($n) -> $\n; %\n = LF +escape_char($r) -> $\r; %\r = CR +escape_char($t) -> $\t; %\t = TAB +escape_char($v) -> $\v; %\v = VT +escape_char($b) -> $\b; %\b = BS +escape_char($f) -> $\f; %\f = FF +escape_char($e) -> $\e; %\e = ESC +escape_char($s) -> $ ; %\s = SPC +escape_char($d) -> $\d; %\d = DEL +escape_char(C) -> C. + + +format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)]; +format_error({user,S}) -> S. + +string(String) -> string(String, 1). + +string(String, Line) -> string(String, Line, String, []). + +%% string(InChars, Line, TokenChars, Tokens) -> +%% {ok,Tokens,Line} | {error,ErrorInfo,Line}. + +string([], L, [], Ts) -> %No partial tokens! + {ok,yyrev(Ts),L}; +string(Ics0, L0, Tcs, Ts) -> + case yystate(yystate(), Ics0, L0, 0, reject, 0) of + {A,Alen,Ics1,L1} -> %Accepting end state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {A,Alen,Ics1,L1,S1} -> %After an accepting state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {reject,Alen,Tlen,Ics1,L1,S1} -> + {error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1}; + {A,Alen,Tlen,Ics1,L1,S1} -> + string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts) + end. + +%% string_cont(RestChars, Line, Token, Tokens) +%% Test for and remove the end token wrapper. + +string_cont(Rest, Line, {token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, {end_token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, skip_token, Ts) -> + string(Rest, Line, Rest, Ts); +string_cont(Rest, Line, {error,S}, Ts) -> + {error,{Line,?MODULE,{user,S}},Line}. + +%% token(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +token(Cont, Chars) -> token(Cont, Chars, 1). + +token([], Chars, Line) -> + token(Chars, Line, yystate(), Chars, 0, reject, 0); +token({Line,State,Tcs,Tlen,Action,Alen}, Chars, _) -> + token(Chars, Line, State, Tcs ++ Chars, Tlen, Action, Alen). + +%% token(InChars, Line, State, TokenChars, TokenLen, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +token(Ics0, L0, S0, Tcs, Tlen0, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{L1,S1,Tcs,Alen1,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{L1,S1,Tcs,Tlen1,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{eof,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + {done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},L1},Ics1}; + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1)) + end. + +%% tokens_cont(RestChars, Line, Token) +%% Test if we have detected the end token, if so return done else continue. + +token_cont(Rest, Line, {token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, {end_token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, skip_token) -> + token(Rest, Line, yystate(), Rest, 0, reject, 0); +token_cont(Rest, Line, {error,S}) -> + {done,{error,{Line,?MODULE,{user,S}},Line},Rest}. + +%% tokens(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +tokens(Cont, Chars) -> tokens(Cont, Chars, 1). + +tokens([], Chars, Line) -> + tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0); +tokens({tokens,Line,State,Tcs,Tlen,Ts,Action,Alen}, Chars, _) -> + tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Ts, Action, Alen); +tokens({skip_tokens,Line,State,Tcs,Tlen,Error,Action,Alen}, Chars, _) -> + skip_tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Error, Action, Alen). + +%% tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +tokens(Ics0, L0, S0, Tcs, Tlen0, Ts, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{tokens,L1,S1,Tcs,Tlen1,Ts,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,if Ts == [] -> {eof,L1}; + true -> {ok,yyrev(Ts),L1} end,[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1+1), L1, + {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}}); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts) + end. + +%% tokens_cont(RestChars, Line, Token, Tokens) +%% Test if we have detected the end token, if so return done else continue. + +tokens_cont(Rest, Line, {token,T}, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0); +tokens_cont(Rest, Line, {end_token,T}, Ts) -> + {done,{ok,yyrev(Ts, [T]),Line},Rest}; +tokens_cont(Rest, Line, skip_token, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0); +tokens_cont(Rest, Line, {error,S}, Ts) -> + skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}). + +%% token_skip(InChars, Line, Error) -> {done,ReturnVal,RestChars}. +%% Skip tokens until an end token, junk everything and return the error. + +%%skip_tokens(Ics, Line, Error) -> {done,{error,Error,Line},Ics}. + +skip_tokens(Ics, Line, Error) -> + skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0). + +%% skip_tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +skip_tokens(Ics0, L0, S0, Tcs, Tlen0, Error, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{skip_tokens,L1,S1,Tcs,Tlen1,Error,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{error,Error,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1), L1, Error); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error) + end. + +%% skip_cont(RestChars, Line, Token, Error) +%% Test if we have detected the end token, if so return done else continue. + +skip_cont(Rest, Line, {token,T}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, {end_token,T}, Error) -> + {done,{error,Error,Line},Rest}; +skip_cont(Rest, Line, {error,S}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, skip_token, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0). + +yyrev(L) -> yyrev(L, []). + +yyrev([H|T], Acc) -> yyrev(T, [H|Acc]); +yyrev([], Acc) -> Acc. + +yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)]; +yypre(L, N) -> []. + +yysuf([H|T], N) when N > 0 -> yysuf(T, N-1); +yysuf(L, 0) -> L. + +yysplit(L, N) -> yysplit(L, N, []). +yysplit([H|T], N, Acc) when N > 0 -> yysplit(T, N-1, [H|Acc]); +yysplit(L, 0, Acc) -> {lists:reverse(Acc), L}. + +%% yystate() -> InitialState. +%% yystate(State, InChars, Line, Token, ) -> +%% {Action, AcceptLength, RestChars, Line} | Accepting end state +%% {Action, AcceptLength, RestChars, Line, State} | Accepting state +%% {Action, AcceptLength, TokLength, RestChars, Line, State} | +%% {reject, AcceptLength, TokLength, RestChars, Line, State}. +%% Generated state transition functions. + +yystate() -> 49. + +yystate(52, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(52, Ics, Line, Tlen+1, 21, Tlen); +yystate(52, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $ÿ -> + yystate(52, Ics, Line, Tlen+1, 21, Tlen); +yystate(52, Ics, Line, Tlen, Action, Alen) -> + {21,Tlen,Ics,Line,52}; +yystate(51, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line}; +yystate(50, Ics, Line, Tlen, Action, Alen) -> + {20,Tlen,Ics,Line}; +yystate(49, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(45, Ics, Line+1, Tlen+1, Action, Alen); +yystate(49, [$!|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$"|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$#|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$$|Ics], Line, Tlen, Action, Alen) -> + yystate(21, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$%|Ics], Line, Tlen, Action, Alen) -> + yystate(2, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$'|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$+|Ics], Line, Tlen, Action, Alen) -> + yystate(26, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$,|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$-|Ics], Line, Tlen, Action, Alen) -> + yystate(34, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$.|Ics], Line, Tlen, Action, Alen) -> + yystate(46, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$/|Ics], Line, Tlen, Action, Alen) -> + yystate(48, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$:|Ics], Line, Tlen, Action, Alen) -> + yystate(8, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$;|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$<|Ics], Line, Tlen, Action, Alen) -> + yystate(0, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(7, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$>|Ics], Line, Tlen, Action, Alen) -> + yystate(35, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$?|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$[|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$]|Ics], Line, Tlen, Action, Alen) -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [$_|Ics], Line, Tlen, Action, Alen) -> + yystate(43, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(45, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $\s -> + yystate(45, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $(, C =< $* -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(40, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $Z -> + yystate(43, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $z -> + yystate(47, Ics, Line, Tlen+1, Action, Alen); +yystate(49, [C|Ics], Line, Tlen, Action, Alen) when C >= ${, C =< $} -> + yystate(51, Ics, Line, Tlen+1, Action, Alen); +yystate(49, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,49}; +yystate(48, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(44, Ics, Line, Tlen+1, 19, Tlen); +yystate(48, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,48}; +yystate(47, [$_|Ics], Line, Tlen, Action, Alen) -> + yystate(47, Ics, Line, Tlen+1, 3, Tlen); +yystate(47, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(47, Ics, Line, Tlen+1, 3, Tlen); +yystate(47, [C|Ics], Line, Tlen, Action, Alen) when C >= $@, C =< $Z -> + yystate(47, Ics, Line, Tlen+1, 3, Tlen); +yystate(47, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $z -> + yystate(47, Ics, Line, Tlen+1, 3, Tlen); +yystate(47, Ics, Line, Tlen, Action, Alen) -> + {3,Tlen,Ics,Line,47}; +yystate(46, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(50, Ics, Line+1, Tlen+1, 19, Tlen); +yystate(46, [$%|Ics], Line, Tlen, Action, Alen) -> + yystate(52, Ics, Line, Tlen+1, 19, Tlen); +yystate(46, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(50, Ics, Line, Tlen+1, 19, Tlen); +yystate(46, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $\s -> + yystate(50, Ics, Line, Tlen+1, 19, Tlen); +yystate(46, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,46}; +yystate(45, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(45, Ics, Line+1, Tlen+1, 22, Tlen); +yystate(45, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(45, Ics, Line, Tlen+1, 22, Tlen); +yystate(45, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $\s -> + yystate(45, Ics, Line, Tlen+1, 22, Tlen); +yystate(45, Ics, Line, Tlen, Action, Alen) -> + {22,Tlen,Ics,Line,45}; +yystate(44, Ics, Line, Tlen, Action, Alen) -> + {13,Tlen,Ics,Line}; +yystate(43, [$_|Ics], Line, Tlen, Action, Alen) -> + yystate(43, Ics, Line, Tlen+1, 4, Tlen); +yystate(43, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(43, Ics, Line, Tlen+1, 4, Tlen); +yystate(43, [C|Ics], Line, Tlen, Action, Alen) when C >= $@, C =< $Z -> + yystate(43, Ics, Line, Tlen+1, 4, Tlen); +yystate(43, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $z -> + yystate(43, Ics, Line, Tlen+1, 4, Tlen); +yystate(43, Ics, Line, Tlen, Action, Alen) -> + {4,Tlen,Ics,Line,43}; +yystate(42, Ics, Line, Tlen, Action, Alen) -> + {8,Tlen,Ics,Line}; +yystate(41, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line+1, Tlen+1, Action, Alen); +yystate(41, [$"|Ics], Line, Tlen, Action, Alen) -> + yystate(37, Ics, Line, Tlen+1, Action, Alen); +yystate(41, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(33, Ics, Line, Tlen+1, Action, Alen); +yystate(41, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(41, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(41, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(41, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(41, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,41}; +yystate(40, [$#|Ics], Line, Tlen, Action, Alen) -> + yystate(36, Ics, Line, Tlen+1, 2, Tlen); +yystate(40, [$.|Ics], Line, Tlen, Action, Alen) -> + yystate(28, Ics, Line, Tlen+1, 2, Tlen); +yystate(40, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(40, Ics, Line, Tlen+1, 2, Tlen); +yystate(40, Ics, Line, Tlen, Action, Alen) -> + {2,Tlen,Ics,Line,40}; +yystate(39, Ics, Line, Tlen, Action, Alen) -> + {14,Tlen,Ics,Line}; +yystate(38, Ics, Line, Tlen, Action, Alen) -> + {18,Tlen,Ics,Line}; +yystate(37, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line}; +yystate(36, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(32, Ics, Line, Tlen+1, Action, Alen); +yystate(36, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F -> + yystate(32, Ics, Line, Tlen+1, Action, Alen); +yystate(36, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f -> + yystate(32, Ics, Line, Tlen+1, Action, Alen); +yystate(36, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,36}; +yystate(35, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(39, Ics, Line, Tlen+1, 19, Tlen); +yystate(35, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,35}; +yystate(34, [$-|Ics], Line, Tlen, Action, Alen) -> + yystate(38, Ics, Line, Tlen+1, 19, Tlen); +yystate(34, [$>|Ics], Line, Tlen, Action, Alen) -> + yystate(42, Ics, Line, Tlen+1, 19, Tlen); +yystate(34, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,34}; +yystate(33, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line+1, Tlen+1, Action, Alen); +yystate(33, [$"|Ics], Line, Tlen, Action, Alen) -> + yystate(29, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(33, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [$]|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [$^|Ics], Line, Tlen, Action, Alen) -> + yystate(25, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(33, [C|Ics], Line, Tlen, Action, Alen) when C >= $_, C =< $ÿ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(33, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,33}; +yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(32, Ics, Line, Tlen+1, 1, Tlen); +yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $A, C =< $F -> + yystate(32, Ics, Line, Tlen+1, 1, Tlen); +yystate(32, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $f -> + yystate(32, Ics, Line, Tlen+1, 1, Tlen); +yystate(32, Ics, Line, Tlen, Action, Alen) -> + {1,Tlen,Ics,Line,32}; +yystate(31, Ics, Line, Tlen, Action, Alen) -> + {11,Tlen,Ics,Line}; +yystate(30, Ics, Line, Tlen, Action, Alen) -> + {17,Tlen,Ics,Line}; +yystate(29, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line+1, Tlen+1, 5, Tlen); +yystate(29, [$"|Ics], Line, Tlen, Action, Alen) -> + yystate(37, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(33, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(41, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! -> + yystate(41, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ -> + yystate(41, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(41, Ics, Line, Tlen+1, 5, Tlen); +yystate(29, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,29}; +yystate(28, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(24, Ics, Line, Tlen+1, Action, Alen); +yystate(28, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,28}; +yystate(27, Ics, Line, Tlen, Action, Alen) -> + {15,Tlen,Ics,Line}; +yystate(26, [$+|Ics], Line, Tlen, Action, Alen) -> + yystate(30, Ics, Line, Tlen+1, 19, Tlen); +yystate(26, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,26}; +yystate(25, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(41, Ics, Line+1, Tlen+1, Action, Alen); +yystate(25, [$"|Ics], Line, Tlen, Action, Alen) -> + yystate(29, Ics, Line, Tlen+1, Action, Alen); +yystate(25, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(33, Ics, Line, Tlen+1, Action, Alen); +yystate(25, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(25, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $! -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(25, [C|Ics], Line, Tlen, Action, Alen) when C >= $#, C =< $[ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(25, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(41, Ics, Line, Tlen+1, Action, Alen); +yystate(25, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,25}; +yystate(24, [$E|Ics], Line, Tlen, Action, Alen) -> + yystate(12, Ics, Line, Tlen+1, 0, Tlen); +yystate(24, [$e|Ics], Line, Tlen, Action, Alen) -> + yystate(12, Ics, Line, Tlen+1, 0, Tlen); +yystate(24, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(24, Ics, Line, Tlen+1, 0, Tlen); +yystate(24, Ics, Line, Tlen, Action, Alen) -> + {0,Tlen,Ics,Line,24}; +yystate(23, Ics, Line, Tlen, Action, Alen) -> + {12,Tlen,Ics,Line}; +yystate(22, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line+1, Tlen+1, Action, Alen); +yystate(22, [$'|Ics], Line, Tlen, Action, Alen) -> + yystate(18, Ics, Line, Tlen+1, Action, Alen); +yystate(22, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(14, Ics, Line, Tlen+1, Action, Alen); +yystate(22, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(22, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $& -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(22, [C|Ics], Line, Tlen, Action, Alen) when C >= $(, C =< $[ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(22, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(22, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,22}; +yystate(21, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(5, Ics, Line, Tlen+1, Action, Alen); +yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $[ -> + yystate(5, Ics, Line, Tlen+1, Action, Alen); +yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(5, Ics, Line, Tlen+1, Action, Alen); +yystate(21, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,21}; +yystate(20, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(16, Ics, Line, Tlen+1, Action, Alen); +yystate(20, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,20}; +yystate(19, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(23, Ics, Line, Tlen+1, Action, Alen); +yystate(19, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,19}; +yystate(18, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line+1, Tlen+1, 6, Tlen); +yystate(18, [$'|Ics], Line, Tlen, Action, Alen) -> + yystate(10, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(14, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(6, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $& -> + yystate(6, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $(, C =< $[ -> + yystate(6, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(6, Ics, Line, Tlen+1, 6, Tlen); +yystate(18, Ics, Line, Tlen, Action, Alen) -> + {6,Tlen,Ics,Line,18}; +yystate(17, [$^|Ics], Line, Tlen, Action, Alen) -> + yystate(1, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $/ -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $7 -> + yystate(13, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $8, C =< $] -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $_, C =< $ÿ -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(17, Ics, Line, Tlen, Action, Alen) -> + {7,Tlen,Ics,Line,17}; +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(16, Ics, Line, Tlen+1, 0, Tlen); +yystate(16, Ics, Line, Tlen, Action, Alen) -> + {0,Tlen,Ics,Line,16}; +yystate(15, Ics, Line, Tlen, Action, Alen) -> + {10,Tlen,Ics,Line}; +yystate(14, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line+1, Tlen+1, Action, Alen); +yystate(14, [$'|Ics], Line, Tlen, Action, Alen) -> + yystate(18, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(14, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [$]|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [$^|Ics], Line, Tlen, Action, Alen) -> + yystate(22, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $& -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $(, C =< $[ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $_, C =< $ÿ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(14, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,14}; +yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $7 -> + yystate(9, Ics, Line, Tlen+1, 7, Tlen); +yystate(13, Ics, Line, Tlen, Action, Alen) -> + {7,Tlen,Ics,Line,13}; +yystate(12, [$+|Ics], Line, Tlen, Action, Alen) -> + yystate(20, Ics, Line, Tlen+1, Action, Alen); +yystate(12, [$-|Ics], Line, Tlen, Action, Alen) -> + yystate(20, Ics, Line, Tlen+1, Action, Alen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $9 -> + yystate(16, Ics, Line, Tlen+1, Action, Alen); +yystate(12, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,12}; +yystate(11, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(15, Ics, Line, Tlen+1, Action, Alen); +yystate(11, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,11}; +yystate(10, Ics, Line, Tlen, Action, Alen) -> + {6,Tlen,Ics,Line}; +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $0, C =< $7 -> + yystate(5, Ics, Line, Tlen+1, Action, Alen); +yystate(9, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,9}; +yystate(8, [$-|Ics], Line, Tlen, Action, Alen) -> + yystate(4, Ics, Line, Tlen+1, 19, Tlen); +yystate(8, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,8}; +yystate(7, [$/|Ics], Line, Tlen, Action, Alen) -> + yystate(11, Ics, Line, Tlen+1, 19, Tlen); +yystate(7, [$:|Ics], Line, Tlen, Action, Alen) -> + yystate(19, Ics, Line, Tlen+1, 19, Tlen); +yystate(7, [$<|Ics], Line, Tlen, Action, Alen) -> + yystate(27, Ics, Line, Tlen+1, 19, Tlen); +yystate(7, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(31, Ics, Line, Tlen+1, 19, Tlen); +yystate(7, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,7}; +yystate(6, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line+1, Tlen+1, Action, Alen); +yystate(6, [$'|Ics], Line, Tlen, Action, Alen) -> + yystate(10, Ics, Line, Tlen+1, Action, Alen); +yystate(6, [$\\|Ics], Line, Tlen, Action, Alen) -> + yystate(14, Ics, Line, Tlen+1, Action, Alen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $& -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $(, C =< $[ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $], C =< $ÿ -> + yystate(6, Ics, Line, Tlen+1, Action, Alen); +yystate(6, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,6}; +yystate(5, Ics, Line, Tlen, Action, Alen) -> + {7,Tlen,Ics,Line}; +yystate(4, Ics, Line, Tlen, Action, Alen) -> + {9,Tlen,Ics,Line}; +yystate(3, Ics, Line, Tlen, Action, Alen) -> + {16,Tlen,Ics,Line}; +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(2, Ics, Line, Tlen+1, 23, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $ÿ -> + yystate(2, Ics, Line, Tlen+1, 23, Tlen); +yystate(2, Ics, Line, Tlen, Action, Alen) -> + {23,Tlen,Ics,Line,2}; +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $\v, C =< $ÿ -> + yystate(5, Ics, Line, Tlen+1, 7, Tlen); +yystate(1, Ics, Line, Tlen, Action, Alen) -> + {7,Tlen,Ics,Line,1}; +yystate(0, [$=|Ics], Line, Tlen, Action, Alen) -> + yystate(3, Ics, Line, Tlen+1, 19, Tlen); +yystate(0, Ics, Line, Tlen, Action, Alen) -> + {19,Tlen,Ics,Line,0}; +yystate(S, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,S}. + + +%% yyaction(Action, TokenLength, TokenChars, Line) -> +%% {token,Token} | {end_token, Token} | skip_token | {error,String}. +%% Generated action function. + +yyaction(0, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{float,YYline,list_to_float(YYtext)}}; +yyaction(1, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + base(YYline,YYtext); +yyaction(2, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{integer,YYline,list_to_integer(YYtext)}}; +yyaction(3, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + Atom = list_to_atom(YYtext), + {token,case reserved_word(Atom) of + true -> + {Atom,YYline}; + false -> + {atom,YYline,Atom} + end}; +yyaction(4, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{var,YYline,list_to_atom(YYtext)}}; +yyaction(5, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + S = lists:sublist(YYtext,2,length(YYtext) - 2), + {token,{string,YYline,string_gen(S)}}; +yyaction(6, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + S = lists:sublist(YYtext,2,length(YYtext) - 2), + {token,{atom,YYline,list_to_atom(string_gen(S))}}; +yyaction(7, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{integer,YYline,cc_convert(YYtext)}}; +yyaction(8, YYlen, YYtcs, YYline) -> + {token,{'->',YYline}}; +yyaction(9, YYlen, YYtcs, YYline) -> + {token,{':-',YYline}}; +yyaction(10, YYlen, YYtcs, YYline) -> + {token,{'=/=',YYline}}; +yyaction(11, YYlen, YYtcs, YYline) -> + {token,{'==',YYline}}; +yyaction(12, YYlen, YYtcs, YYline) -> + {token,{'=:=',YYline}}; +yyaction(13, YYlen, YYtcs, YYline) -> + {token,{'/=',YYline}}; +yyaction(14, YYlen, YYtcs, YYline) -> + {token,{'>=',YYline}}; +yyaction(15, YYlen, YYtcs, YYline) -> + {token,{'=<',YYline}}; +yyaction(16, YYlen, YYtcs, YYline) -> + {token,{'<=',YYline}}; +yyaction(17, YYlen, YYtcs, YYline) -> + {token,{'++',YYline}}; +yyaction(18, YYlen, YYtcs, YYline) -> + {token,{'--',YYline}}; +yyaction(19, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{list_to_atom(YYtext),YYline}}; +yyaction(20, YYlen, YYtcs, YYline) -> + {end_token,{dot,YYline}}; +yyaction(21, YYlen, YYtcs, YYline) -> + {end_token,{dot,YYline}}; +yyaction(22, YYlen, YYtcs, YYline) -> skip_token; +yyaction(23, YYlen, YYtcs, YYline) -> + skip_token; +yyaction(_, _, _, _) -> error. diff --git a/mods/src/em_erlang_scan.xrl b/mods/src/em_erlang_scan.xrl new file mode 100644 index 0000000..572cb29 --- /dev/null +++ b/mods/src/em_erlang_scan.xrl @@ -0,0 +1,135 @@ +%% Token Definitions for Erlang. + +Definitions. +O = [0-7] +D = [0-9] +H = [0-9a-fA-F] +A = [a-z_A-Z@0-9] +WS = [\000-\s] + +Rules. +{D}+\.{D}+((E|e)(\+|\-)?{D}+)? : + {token,{float,YYline,list_to_float(YYtext)}}. +{D}+#{H}+ : base(YYline, YYtext). +{D}+ : {token,{integer,YYline,list_to_integer(YYtext)}}. +[a-z]{A}* : Atom = list_to_atom(YYtext), + {token,case reserved_word(Atom) of + true -> {Atom,YYline}; + false -> {atom,YYline,Atom} + end}. +[_A-Z]{A}* : {token,{var,YYline,list_to_atom(YYtext)}}. +"(\\\^.|\\.|[^"])*" : + %% Strip quotes. + S = lists:sublist(YYtext, 2, length(YYtext) - 2), + {token,{string,YYline,string_gen(S)}}. +'(\\\^.|\\.|[^'])*' : + %% Strip quotes. + S = lists:sublist(YYtext, 2, length(YYtext) - 2), + {token,{atom,YYline,list_to_atom(string_gen(S))}}. +\$(\\{O}{O}{O}|\\\^.|\\.|.) : + {token,{integer,YYline,cc_convert(YYtext)}}. +-> : {token,{'->',YYline}}. +:- : {token,{':-',YYline}}. +=/= : {token,{'=/=',YYline}}. +== : {token,{'==',YYline}}. +=:= : {token,{'=:=',YYline}}. +/= : {token,{'/=',YYline}}. +>= : {token,{'>=',YYline}}. +=< : {token,{'=<',YYline}}. +<= : {token,{'<=',YYline}}. +\+\+ : {token,{'++',YYline}}. +-- : {token,{'--',YYline}}. +[!?/;:,.*+#()[\]|<>={}-] : + {token,{list_to_atom(YYtext),YYline}}. +\.{WS} : {end_token,{dot,YYline}}. +\.%.* : {end_token,{dot,YYline}}. %Must special case this +{WS}+ : . %No token returned, eqivalent +\%.* : skip_token. % to 'skip_token' + +Erlang code. + +-author('rv@cslab.ericsson.se'). +-copyright('Copyright (c) 1996 Ericsson Telecommunications AB'). + +-export([reserved_word/1]). + +reserved_word('after') -> true; +reserved_word('begin') -> true; +reserved_word('case') -> true; +reserved_word('catch') -> true; +reserved_word('end') -> true; +reserved_word('fun') -> true; +reserved_word('if') -> true; +reserved_word('let') -> true; +reserved_word('of') -> true; +reserved_word('query') -> true; +reserved_word('receive') -> true; +reserved_word('when') -> true; +reserved_word('bnot') -> true; +reserved_word('not') -> true; +reserved_word('div') -> true; +reserved_word('rem') -> true; +reserved_word('band') -> true; +reserved_word('and') -> true; +reserved_word('bor') -> true; +reserved_word('bxor') -> true; +reserved_word('bsl') -> true; +reserved_word('bsr') -> true; +reserved_word('or') -> true; +reserved_word('xor') -> true; +reserved_word(_) -> false. + +base(L, Cs) -> + H = string:chr(Cs, $#), + case list_to_integer(string:substr(Cs, 1, H-1)) of + B when B > 16 -> {error,"illegal base"}; + B -> + case base(string:substr(Cs, H+1), B, 0) of + error -> {error,"illegal based number"}; + N -> {token,{integer,L,N}} + end + end. + +base([C|Cs], Base, SoFar) when C >= $0, C =< $9, C < Base + $0 -> + Next = SoFar * Base + (C - $0), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) when C >= $a, C =< $f, C < Base + $a - 10 -> + Next = SoFar * Base + (C - $a + 10), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) when C >= $A, C =< $F, C < Base + $A - 10 -> + Next = SoFar * Base + (C - $A + 10), + base(Cs, Base, Next); +base([C|Cs], Base, SoFar) -> error; +base([], Base, N) -> N. + +cc_convert([$$,$\\|Cs]) -> + hd(string_escape(Cs)); +cc_convert([$$,C]) -> C. + +string_gen([$\\|Cs]) -> + string_escape(Cs); +string_gen([C|Cs]) -> + [C|string_gen(Cs)]; +string_gen([]) -> []. + +string_escape([O1,O2,O3|S]) when + O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 -> + [(O1*8 + O2)*8 + O3 - 73*$0|string_gen(S)]; +string_escape([$^,C|Cs]) -> + [C band 31|string_gen(Cs)]; +string_escape([C|Cs]) when C >= 0, C =< $ -> + string_gen(Cs); +string_escape([C|Cs]) -> + [escape_char(C)|string_gen(Cs)]. + +escape_char($n) -> $\n; %\n = LF +escape_char($r) -> $\r; %\r = CR +escape_char($t) -> $\t; %\t = TAB +escape_char($v) -> $\v; %\v = VT +escape_char($b) -> $\b; %\b = BS +escape_char($f) -> $\f; %\f = FF +escape_char($e) -> $\e; %\e = ESC +escape_char($s) -> $ ; %\s = SPC +escape_char($d) -> $\d; %\d = DEL +escape_char(C) -> C. + diff --git a/mods/src/em_scan.erl b/mods/src/em_scan.erl new file mode 100644 index 0000000..5467423 --- /dev/null +++ b/mods/src/em_scan.erl @@ -0,0 +1,381 @@ +%%%---------------------------------------------------------------------- +%%% File : em_scan.erl +%%% Author : Luke Gorrie <luke@bluetail.com> +%%% Purpose : Scanner for leex-style DFAs. +%%% Created : 1 May 2001 by Luke Gorrie <luke@bluetail.com> +%%%---------------------------------------------------------------------- + +-module(em_scan). +-author('luke@bluetail.com'). + +-record(scanner, {initial_state, dfa_fn, action_fn}). + +%% Token record. The actual lexeme, if returned by the scanner, is +%% discarded - all that's taken from the user-written "actions" is the +%% token type. Instead we just keep the start/finish positions in a +%% cord. +%% +%% Not retaining line/column information. Hopefully that's convenient +%% to derive later. +-record(token, + { + %% type chosen by scanner. There is also a special type: + %% 'em_skipped', when the scanner returns 'skip_token' but + %% we record it anyway. + type, + %% start position in cord + start, + %% finish position in cord (point *after* the last character) + finish, + %% number of characters beyond the end of the lexeme that + %% the scanner state machine examined, recorded to track + %% dependency + lookahead, + %% for book keeping, saying whether the token is known to + %% need re-scanning + dirty=false + }). + +-compile(export_all). +%%-export([Function/Arity, ...]). + +%% Bogus line number to pass to leex/yecc, because I don't want to +%% track lines at this low level. It's not safe to use an atom, but +%% hopefully -42 looks deliberate enough to prompt a grep :-) + +-define(line, -42). %% Confusing number appearing where line # should be :-) + +make_scanner(State0, DFA, Action) -> + #scanner{initial_state=State0, + dfa_fn=DFA, + action_fn=Action}. + +make_scheme_scanner() -> make_leex_scanner(em_scheme_scan). +make_erlang_scanner() -> make_leex_scanner(em_erlang_scan). +make_test_scanner() -> make_leex_scanner(em_test_scan). + +make_leex_scanner(Mod) -> + make_scanner(Mod:yystate(), + {Mod, yystate}, + {Mod, yyaction}). + +scan_annotation(Scanner, _S0, Cord, RText, Start, End) -> + Walker = cord:walker(Cord), + case edit_scan(Scanner, Walker) of + {ok, Toks} -> + {ok, Toks}; + {error, Reason} -> + {ok, bad_scan} + end. + +test_test(Str) -> + case test_string(Str) of + {ok, Toks} -> + {ok, lists:map(fun(T) -> element(1, T) end, + Toks)}; + X -> + X + end. + +erlang_test(Str) -> + case erlang_string(Str) of + {ok, Toks} -> + {ok, lists:map(fun(T) -> element(1, T) end, + Toks)}; + X -> + X + end. + +scheme_test(Str) -> + case scheme_string(Str) of + {ok, Toks} -> + {ok, lists:map(fun(T) -> element(1, T) end, + Toks)}; + X -> + X + end. + +test_string(Str) -> + Cord = list_to_binary(Str), + Scan = make_test_scanner(), + edit_scan(Scan, cord:walker(Cord)). + +scheme_string(Str) -> + Cord = list_to_binary(Str), + Scan = make_scheme_scanner(), + edit_scan(Scan, cord:walker(Cord)). + +erlang_string(Str) -> + Cord = list_to_binary(Str), + Scan = make_erlang_scanner(), + edit_scan(Scan, cord:walker(Cord)). + +%% Returns: {ok, [#token]} | {error, Reason} +edit_scan(Scn, Walker) -> + edit_scan(Scn, Walker, 1, []). + +edit_scan(Scn, Walker, Pos) -> + edit_scan(Scn, Walker, 1, []). + +edit_scan(Scn, W0, Pos, Acc) -> + case token(Scn, W0) of + {done, eof} -> + {ok, lists:reverse(Acc)}; + {done, Result, W1} -> + Token = make_token(Pos, Result), + edit_scan(Scn, W1, Token#token.finish, [Token|Acc]); + {error, Reason} -> + {error, Reason} + end. + +make_skipped_token(Pos, Len, LookAhead) -> + #token{type=em_skipped, + start=Pos, + finish=Pos+Len, + lookahead=LookAhead}. + +% tokens(Scn, Walker) -> +% tokens(Scn, Walker, []). + +% tokens(Scn, W0, Acc) -> +% case token(Scn, W0) of +% {done, {ok, T, Acs}, W1} -> +% tokens(Scn, W1, [T|Acc]); +% {done, {skip_token, Acs}, W1} -> +% tokens(Scn, W1, Acc); +% {done, eof} -> +% {ok, lists:reverse(Acc)}; +% {error, Reason} -> +% {error, Reason} +% end. + +token(Scn, Walker) -> + State0 = Scn#scanner.initial_state, + token(Scn, Walker, State0, [], 0, reject, 0). + +token(Scn, W0, S0, Tcs0, Tlen0, A0, Alen0) -> + ActionF = Scn#scanner.action_fn, + DFA_F = Scn#scanner.dfa_fn, + {Ics, Tcs1, W1} = case cord:walker_next(W0) of + {done, WEOF} -> + {eof, Tcs0, WEOF}; + {Ch, Wnext} -> + {[Ch], [Ch|Tcs0], Wnext} + end, + case DFA_F(S0, Ics, ?line, Tlen0, A0, Alen0) of + {A1,Alen1,[],L1} -> % accepting end state + TcsFwd = lists:reverse(Tcs1), + token_cont(Scn,TcsFwd,W1,[],ActionF(A1,Alen1,TcsFwd,?line)); + {A1,Alen1,[],L1,S1} -> % after accepting state + token(Scn,W1,S1,Tcs1,Alen1,A1,Alen1); + {A1,Alen1,Ics1,L1,S1} -> % accepting state with leftover + % chars.. sounds like a time + % to act. + TcsFwd = lists:reverse(Tcs1), + Acs = yypre(TcsFwd, Alen1), + token_cont(Scn,Acs,W1,Ics1,ActionF(A1,Alen1,TcsFwd,?line)); + {A1,Alen1,Tlen1,[],L1,S1} -> % after a non-accepting state + token(Scn,W1,S1,Tcs1,Tlen1,A1,Alen1); + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,eof}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + {done, + {error,{illegal,yypre(Tcs1, Tlen1+1)}}, + Ics1}; + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + TcsFwd = lists:reverse(Tcs1), + {Acs, Rest} = yysplit(TcsFwd, Alen1), + token_cont(Scn,Acs,W1,Rest,ActionF(A1,Alen1,TcsFwd,?line)) + end. + +token_cont(Scn, Acs, W, Rest, {token, T}) -> + {done, {ok, T, Acs, length_of(Rest)}, pushback(W, Rest)}; +token_cont(Scn, Acs, W, Rest, {end_token, T}) -> + {done, {ok, T, Acs, length_of(Rest)}, pushback(W, Rest)}; +token_cont(Scn, Acs, W, Rest, SkipToken) -> + {done, {skip_token, Acs, length_of(Rest)}, pushback(W, Rest)}; +token_cont(Scn, Acs, W, Rest, {error, S}) -> + {done, {error, {user,S}}, pushback(W, Rest)}. + +adjust_pos(C, L, [$\n|T]) -> adjust_pos(0, L+1, T); +adjust_pos(C, L, [_|T]) -> adjust_pos(C+1, L, T); +adjust_pos(C, L, []) -> {C, L}. + +length_of(eof) -> 0; +length_of(List) -> length(List). + +pushback(W, eof) -> + W; +pushback(W, Chars) -> + lists:foldr(fun(C, Wn) -> cord:walker_push(C, Wn) end, + W, + Chars). + +yyrev([H|T], Acc) -> yyrev(T, [H|Acc]); +yyrev([], Acc) -> Acc. + +yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)]; +yypre(L, N) -> []. + +yysuf([H|T], N) when N > 0 -> yysuf(T, N-1); +yysuf(L, 0) -> L. + +yysplit(L, N) -> yysplit(L, N, []). +yysplit([H|T], N, Acc) when N > 0 -> yysplit(T, N-1, [H|Acc]); +yysplit(L, 0, Acc) -> {lists:reverse(Acc), L}. + +%%%%% +%% Experimentation with incremental parsing (working) + +str0() -> "-bar+ +foo-". +toks0() -> + {ok, Toks} = test_string(str0()), + Toks. + +%% Hand-hacked version of Toks0 with the space character deleted and +%% its token marked as dirty. When properly re-scanned, this should be +%% the same as toks1 (basis of the test case) +dirty_toks() -> [OK_A,OK_B,OK_C,Changed0|Following0] = toks0(), + Changed1 = Changed0#token{dirty=true}, + Following1 = lists:map(fun(T) -> + Start = T#token.start, + Finish = T#token.finish, + T#token{start=Start-1, + finish=Finish-1} + end, + Following0), + [OK_A,OK_B,OK_C,Changed1|Following1]. + +%% for: "bar++foo" +%% The space has been changed (now length 0) and is marked dirty. +str1() -> str0() -- " ". +toks1() -> + {ok, Toks} = test_string(str1()), + Toks. + +rescan_test() -> + Scn = make_test_scanner(), + Dirty = mark_dirty(dirty_toks()), + Cord = cord:new(str1()), + Result = rescan(Scn, Cord, Dirty), + {Result == toks1(), Result, Dirty}. + +%% What should happen with this simple algorithm and test case: +%% 1. We see that a token is dirty. +%% 2. We scan backwards for dependencies (by seeing what has a look-ahead +%% that reaches the dirty token, or another token that does, etc) +%% 3. From the earliest dependency, we start re-scanning everything +%% until we scan a token which leaves the state of the lexer the same as +%% it was previously (i.e. so the following token is known to be +%% unchanged) +%% +%% So, how is the state of the lexer defined? In leex it seems to me +%% that the internal scanner state is always the same at the start of +%% each token (barring anything magical done in actions - which for +%% now I ignore). So, I think it's safe to assume that a token will be +%% unchanged if both the chars in its lexeme and the ones reached by +%% its look-ahead are the same. For "tricky stuff" it may be necessary +%% to capture the process dictionary and include (some of) it in the +%% state. +%% +%% So I will terminate when I reach a token beyond the changed text +%% which is starting in the same place. +%% +%% NB: We shouldn't need to go *too* far backwards when marking +%% dependencies in languages I can think of, because of common +%% zero-lookahead tokens like: \n , ; ( ) ...etc and most other +%% tokens will just be 1-lookahead. + +re_lex(Toks0) -> + Toks1 = mark_dirty(Toks0). + +mark_dirty(Toks) -> + mark_dirty(Toks, []). + +mark_dirty([H|T], Acc) when H#token.dirty == true -> + mark_dirty1([H|T], H#token.start, Acc); +mark_dirty([H|T], Acc) -> + mark_dirty(T, [H|Acc]); +mark_dirty([], Acc) -> + lists:reverse(Acc). + +mark_dirty1(OK, DirtyPos, Toks0) -> + F = fun(Tok, DP) -> + case (Tok#token.finish-1) + Tok#token.lookahead of + P when P >= DP -> + {Tok#token{dirty=true}, + Tok#token.start}; + _ -> + {Tok, DP} + end + end, + {Toks1, _} = lists:mapfoldl(F, DirtyPos, Toks0), + lists:reverse(Toks1) ++ OK. + +%% Rescan dirty tokens. +rescan(Scn, Cord, []) -> + []; +rescan(Scn, Cord, [H|T]) when H#token.dirty == false -> + [H|rescan(Scn, Cord, T)]; +rescan(Scn, Cord, [H|T]) when H#token.dirty == true -> + Pos = H#token.start, + {_, Region} = cord:split(Cord, Pos-1), + Walker = cord:walker(Region), + rescan_dirty(Scn, Walker, Pos, [H|T]). + +%% rescan_dirty(Toks) +%% +%% The first token is dirty. Scan until we get back to a sane state +rescan_dirty(Scn, W0, Pos, [Tok|Toks]) -> + Start = Tok#token.start, + io:format("(Pos = ~p) Rescanning ~p~n", [Pos, Tok]), + case token(Scn, W0) of + {done, eof} -> + []; + {done, Result, W1} -> + Token = make_token(Pos, Result), + [Token|rescan_dirty_cont(Scn, W1, Token#token.finish, Toks)]; + {error, Reason} -> + %% FIXME: should make an error-token and carry on + {error, Reason} + end. + +rescan_dirty_cont(Scn, W, Pos, []) -> + []; +rescan_dirty_cont(Scn, W, Pos, Rest) -> + Next = hd(Rest), + if + %% This token no longer exists! + Next#token.finish =< Pos -> + io:format("(Pos = ~p) Discaring token: ~p~n", [Pos, Next]), + rescan_dirty_cont(Scn, W, Pos, tl(Rest)); + %% We need to carry on if the token is known to be dirty, or + %% if we aren't at the same place that it was scanned from + %% before + Next#token.dirty == true; + Next#token.start /= Pos -> + rescan_dirty(Scn, W, Pos, Rest); + true -> + Rest + end. + +make_token(Pos, {ok, T, Acs, LookAhead}) -> + Type = element(1, T), + Len = length(Acs), + #token{type=Type, + start=Pos, + finish=Pos+Len, + lookahead=LookAhead}; +make_token(Pos, {skip_token, Acs, LookAhead}) -> + Len = length(Acs), + #token{type=em_skipped, + start=Pos, + finish=Pos+Len, + lookahead=LookAhead}. + +make_error_token(Pos) -> + #token{type=em_error, + start=Pos, + finish=Pos+1, + lookahead=1}. + diff --git a/mods/src/em_scheme.erl b/mods/src/em_scheme.erl new file mode 100644 index 0000000..fd4bd14 --- /dev/null +++ b/mods/src/em_scheme.erl @@ -0,0 +1,184 @@ +%%%---------------------------------------------------------------------- +%%% File : em_scheme.erl +%%% Author : Luke Gorrie <luke@bluetail.com> +%%% Purpose : Scheme-mode +%%% Created : 30 Apr 2001 by Luke Gorrie <luke@bluetail.com> +%%%---------------------------------------------------------------------- + +-module(em_scheme). +-author('luke@bluetail.com'). + +-include_lib("ermacs/include/edit.hrl"). +-import(edit_lib, [buffer/1]). + +-compile(export_all). +%%-export([Function/Arity, ...]). + +-define(keymap, scheme_mode_map). + +-record(tok, {column, % Column number + line, % Line number + read_ahead, % # chars read ahead + token % Token returned from leex + }). + +mod_init() -> + catch edit_keymap:delete(?keymap), + init_map(), + edit_keymap:global_set_key("C-x s", {?MODULE, scheme_mode, []}), + edit_var:add_to_list(auto_mode_alist, + {"\.scheme$$", {?MODULE, scheme_mode}}), + ok. + +init_map() -> + edit_keymap:new(?keymap), + edit_keymap:bind_each(?keymap, bindings()). + +bindings() -> + [{"C-i", {?MODULE, reindent_cmd, []}} + ]. + +%% test buffer annotation +ann_trace(S0, Cord, Text, Start, End) -> + io:format("trace: ~p at (~p,~p)~n", [Text, Start, End]), + {ok, S0}. + +scheme_mode(State) -> + Mode = #mode{name="Scheme", + id=scheme, + keymaps=[?keymap]}, + Buf = buffer(State), + Scanner = em_scan:make_scheme_scanner(), + edit_buf:add_annotation(Buf, scan, {em_scan, scan_annotation, [Scanner]}, + no_scan), + %%edit_buf:add_annotation(Buf, scheme, {?MODULE, ann_trace, []}, []), + edit_buf:set_mode(Buf, Mode), + State. + +scan_buffer(State) -> + B = buffer(State), + C = edit_buf:get_cord(B), + Walker = cord:walker(C), + Scanner = make_scheme_scanner(), + case em_scan:edit_scan(Scanner, Walker) of + {error, Rsn} -> + edit_util:status_msg(State, "Error: ~s", + [em_scheme_scan:format_error(Rsn)]); + {ok, Toks} -> + edit_util:status_msg(State, "Scan: (~p) ~s", + [length(Toks), format_tokens(Toks)]) + end. + +make_scheme_scanner() -> + em_scan:make_scanner(em_scheme_scan:yystate(), + {em_scheme_scan, yystate}, + {em_scheme_scan, yyaction}). + +format_tokens([A,B|T]) -> + format_token(A) ++ ", " ++ format_tokens([B|T]); +format_tokens([A]) -> + format_token(A). + +format_token({T, C, L}) -> + io_lib:format("~p:~p:~p", [T, C, L]). + +scan(W) -> + em_scan:edit_scan(make_scheme_scanner(), W). + +%%%---------------------------------------------------------------------- +%%% Reindent + +reindent_cmd(State) -> + B = buffer(State), + Start = beginning_of_fun_pos(B), + End = edit_lib:beginning_of_line_pos(B), + Region = edit_buf:get_region_cord(B, Start, End), + Walker = cord:walker(Region), + {ok, Scan} = scan(Walker), + reindent(B, End, calc_indent(munge(Scan))). + +munge([A = {_,_,LineA}, B = {_,_,LineB} | T]) when LineA /= LineB -> + [strip(A), newline | munge([B|T])]; +munge([H|T]) -> + [strip(H) | munge(T)]; +munge([]) -> + [newline]. + +strip({Type, Col, Line}) -> {Type, Col}. + +reindent(Buf, Pos, Lvl) -> + Pred = fun(C) -> (C /= $ ) and (C /= $\t) end, + End = max(Pos, edit_lib:find_char_forward(Buf, Pred, Pos, 1)), + edit_buf:replace(Buf, lists:duplicate(Lvl, $ ), Pos, End). + +beginning_of_fun_pos(B) -> + Point = min(edit_buf:point_max(B) - 1, + max(1, edit_lib:beginning_of_line_pos(B) - 1)), + Cord = edit_buf:get_cord(B), + case cord_regexp:first_match("^\\(", Cord, Point, backward) of + nomatch -> + 1; + {match, Start, End} -> + Start + end. + +%% Calculate the indent level for the line *following* the tokens `Toks'. +calc_indent(Toks) -> + io:format("calc_indent: ~p~n", [Toks]), + calc_indent(Toks, 0, []). + +%% ( s : (lambda +%% push; |(|+2 +calc_indent([{'(', OC},{special,SC}|T], Lvl0, S0) -> + S1 = [Lvl0|S0], + calc_indent(T, OC+2, S1); +%% ( a:!\n b:!\n +%% push; |b| +calc_indent([{'(',OC}, {_,_}, {_,C}|T], Lvl0, S0) -> + S1 = [Lvl0|S0], + calc_indent(T, C, S1); +calc_indent([{'(',OC}|T], Lvl0, S0) -> + S1 = [Lvl0|S0], + calc_indent(T, OC+1, S1); +calc_indent([{')',CC}|T], Lvl0, S0) -> + [Lvl1|S1] = S0, + calc_indent(T, Lvl1, S1); +calc_indent([H|T], Lvl, S) -> + calc_indent(T, Lvl, S); +calc_indent([], Lvl, S) -> + Lvl. + +%% calc_indent(Tokens, CurrentLevel, State, Stack) +%% State = normal | special +%% Stack = [{State, Level}] + + +%% Opening + +% calc_indent([{'(',COpen}, {special, CSpecial}|T], Lvl0, S0, Stk0) -> +% %% opening a special form +% calc_indent(T, COpen + 2, special, [{S0, Lvl0}|Stk0]); +% calc_indent([{'(',COpen}|T], Lvl0, S0, Stk0) -> +% calc_indent(T, COpen+1, normal, [{S0, Lvl0}|Stk0]); +% calc_indent([{')', _}|T], Lvl0, S, [{SPrev,LvlPrev}|Stk]) -> +% calc_indent(T, LvlPrev, SPrev, Stk); +% calc_indent([{')', _}|T], Lvl0, S, []) -> +% %% Too many )'s - go back to 0 +% calc_indent(T, 0, normal, []); +% calc_indent([{Symbol, SC}, newline | T], Lvl0, normal, Stk0) +% when Symbol == atom; Symbol == special -> +% calc_indent(T, SC, normal0, Stk0); +% calc_indent([{atom, _}|T], Lvl0, S0, Stk0) -> +% calc_indent(T, Lvl0, S0, Stk0); +% calc_indent([{special, _}|T], Lvl0, S0, Stk0) -> +% calc_indent(T, Lvl0, S0, Stk0); +% calc_indent([newline|T], Lvl, S, Stk) -> +% calc_indent(T, Lvl, S, Stk); +% calc_indent([], Lvl, S, Stk) -> +% Lvl. + +max(X, Y) when X > Y -> X; +max(X, Y) -> Y. + +min(X, Y) when X < Y -> X; +min(X, Y) -> Y. diff --git a/mods/src/em_scheme_scan.erl b/mods/src/em_scheme_scan.erl new file mode 100644 index 0000000..8021791 --- /dev/null +++ b/mods/src/em_scheme_scan.erl @@ -0,0 +1,531 @@ +%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE +%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE +%% AND BETTER INTERFACE - BE WARNED +%% PLEASE REPORT ALL BUGS TO THE AUTHOR. + +-module('em_scheme_scan'). + +-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]). +-export([format_error/1]). + +%% luke +-export([yystate/0, yystate/6, yyaction/4]). + +%% User code. This is placed here to allow extra attributes. + +format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)]; +format_error({user,S}) -> S. + +string(String) -> string(String, 1). + +string(String, Line) -> string(String, Line, String, []). + +%% string(InChars, Line, TokenChars, Tokens) -> +%% {ok,Tokens,Line} | {error,ErrorInfo,Line}. + +string([], L, [], Ts) -> %No partial tokens! + {ok,yyrev(Ts),L}; +string(Ics0, L0, Tcs, Ts) -> + case yystate(yystate(), Ics0, L0, 0, reject, 0) of + {A,Alen,Ics1,L1} -> %Accepting end state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {A,Alen,Ics1,L1,S1} -> %After an accepting state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {reject,Alen,Tlen,Ics1,L1,S1} -> + {error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1}; + {A,Alen,Tlen,Ics1,L1,S1} -> + string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts) + end. + +%% string_cont(RestChars, Line, Token, Tokens) +%% Test for and remove the end token wrapper. + +string_cont(Rest, Line, {token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, {end_token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, skip_token, Ts) -> + string(Rest, Line, Rest, Ts); +string_cont(Rest, Line, {error,S}, Ts) -> + {error,{Line,?MODULE,{user,S}},Line}. + +%% token(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +token(Cont, Chars) -> token(Cont, Chars, 1). + +token([], Chars, Line) -> + token(Chars, Line, yystate(), Chars, 0, reject, 0); +token({Line,State,Tcs,Tlen,Action,Alen}, Chars, _) -> + token(Chars, Line, State, Tcs ++ Chars, Tlen, Action, Alen). + +%% token(InChars, Line, State, TokenChars, TokenLen, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +token(Ics0, L0, S0, Tcs, Tlen0, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{L1,S1,Tcs,Alen1,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{L1,S1,Tcs,Tlen1,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{eof,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + {done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},L1},Ics1}; + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1)) + end. + +%% tokens_cont(RestChars, Line, Token) +%% Test if we have detected the end token, if so return done else continue. + +token_cont(Rest, Line, {token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, {end_token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, skip_token) -> + token(Rest, Line, yystate(), Rest, 0, reject, 0); +token_cont(Rest, Line, {error,S}) -> + {done,{error,{Line,?MODULE,{user,S}},Line},Rest}. + +%% tokens(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +tokens(Cont, Chars) -> tokens(Cont, Chars, 1). + +tokens([], Chars, Line) -> + tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0); +tokens({tokens,Line,State,Tcs,Tlen,Ts,Action,Alen}, Chars, _) -> + tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Ts, Action, Alen); +tokens({skip_tokens,Line,State,Tcs,Tlen,Error,Action,Alen}, Chars, _) -> + skip_tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Error, Action, Alen). + +%% tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +tokens(Ics0, L0, S0, Tcs, Tlen0, Ts, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{tokens,L1,S1,Tcs,Tlen1,Ts,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,if Ts == [] -> {eof,L1}; + true -> {ok,yyrev(Ts),L1} end,[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1+1), L1, + {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}}); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts) + end. + +%% tokens_cont(RestChars, Line, Token, Tokens) +%% Test if we have detected the end token, if so return done else continue. + +tokens_cont(Rest, Line, {token,T}, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0); +tokens_cont(Rest, Line, {end_token,T}, Ts) -> + {done,{ok,yyrev(Ts, [T]),Line},Rest}; +tokens_cont(Rest, Line, skip_token, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0); +tokens_cont(Rest, Line, {error,S}, Ts) -> + skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}). + +%% token_skip(InChars, Line, Error) -> {done,ReturnVal,RestChars}. +%% Skip tokens until an end token, junk everything and return the error. + +%%skip_tokens(Ics, Line, Error) -> {done,{error,Error,Line},Ics}. + +skip_tokens(Ics, Line, Error) -> + skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0). + +%% skip_tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +skip_tokens(Ics0, L0, S0, Tcs, Tlen0, Error, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{skip_tokens,L1,S1,Tcs,Tlen1,Error,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{error,Error,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1), L1, Error); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error) + end. + +%% skip_cont(RestChars, Line, Token, Error) +%% Test if we have detected the end token, if so return done else continue. + +skip_cont(Rest, Line, {token,T}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, {end_token,T}, Error) -> + {done,{error,Error,Line},Rest}; +skip_cont(Rest, Line, {error,S}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, skip_token, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0). + +yyrev(L) -> yyrev(L, []). + +yyrev([H|T], Acc) -> yyrev(T, [H|Acc]); +yyrev([], Acc) -> Acc. + +yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)]; +yypre(L, N) -> []. + +yysuf([H|T], N) when N > 0 -> yysuf(T, N-1); +yysuf(L, 0) -> L. + +yysplit(L, N) -> yysplit(L, N, []). +yysplit([H|T], N, Acc) when N > 0 -> yysplit(T, N-1, [H|Acc]); +yysplit(L, 0, Acc) -> {lists:reverse(Acc), L}. + +%% yystate() -> InitialState. +%% yystate(State, InChars, Line, Token, ) -> +%% {Action, AcceptLength, RestChars, Line} | Accepting end state +%% {Action, AcceptLength, RestChars, Line, State} | Accepting state +%% {Action, AcceptLength, TokLength, RestChars, Line, State} | +%% {reject, AcceptLength, TokLength, RestChars, Line, State}. +%% Generated state transition functions. + +yystate() -> 15. + +yystate(18, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 3, Tlen); +yystate(18, Ics, Line, Tlen, Action, Alen) -> + {3,Tlen,Ics,Line,18}; +yystate(17, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(17, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,17}; +yystate(16, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [$e|Ics], Line, Tlen, Action, Alen) -> + yystate(18, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $d -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, [C|Ics], Line, Tlen, Action, Alen) when C >= $f, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(16, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,16}; +yystate(15, [$\n|Ics], Line, Tlen, Action, Alen) -> + yystate(11, Ics, Line+1, Tlen+1, Action, Alen); +yystate(15, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$\r|Ics], Line, Tlen, Action, Alen) -> + yystate(11, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$\s|Ics], Line, Tlen, Action, Alen) -> + yystate(11, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$(|Ics], Line, Tlen, Action, Alen) -> + yystate(7, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$)|Ics], Line, Tlen, Action, Alen) -> + yystate(3, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$d|Ics], Line, Tlen, Action, Alen) -> + yystate(0, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [$l|Ics], Line, Tlen, Action, Alen) -> + yystate(14, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $c -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $e, C =< $k -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= $m, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, Action, Alen); +yystate(15, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,15}; +yystate(14, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [$a|Ics], Line, Tlen, Action, Alen) -> + yystate(10, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [$e|Ics], Line, Tlen, Action, Alen) -> + yystate(9, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $` -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $b, C =< $d -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, [C|Ics], Line, Tlen, Action, Alen) when C >= $f, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(14, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,14}; +yystate(13, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 4, Tlen); +yystate(13, Ics, Line, Tlen, Action, Alen) -> + {4,Tlen,Ics,Line,13}; +yystate(12, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [$n|Ics], Line, Tlen, Action, Alen) -> + yystate(16, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $m -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, [C|Ics], Line, Tlen, Action, Alen) when C >= $o, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(12, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,12}; +yystate(11, Ics, Line, Tlen, Action, Alen) -> + {6,Tlen,Ics,Line}; +yystate(10, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [$m|Ics], Line, Tlen, Action, Alen) -> + yystate(6, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $l -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, [C|Ics], Line, Tlen, Action, Alen) when C >= $n, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(10, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,10}; +yystate(9, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [$t|Ics], Line, Tlen, Action, Alen) -> + yystate(13, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $s -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, [C|Ics], Line, Tlen, Action, Alen) when C >= $u, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(9, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,9}; +yystate(8, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [$i|Ics], Line, Tlen, Action, Alen) -> + yystate(12, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $h -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, [C|Ics], Line, Tlen, Action, Alen) when C >= $j, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(8, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,8}; +yystate(7, Ics, Line, Tlen, Action, Alen) -> + {0,Tlen,Ics,Line}; +yystate(6, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [$b|Ics], Line, Tlen, Action, Alen) -> + yystate(2, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $a -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, [C|Ics], Line, Tlen, Action, Alen) when C >= $c, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(6, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,6}; +yystate(5, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 2, Tlen); +yystate(5, Ics, Line, Tlen, Action, Alen) -> + {2,Tlen,Ics,Line,5}; +yystate(4, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [$f|Ics], Line, Tlen, Action, Alen) -> + yystate(8, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $e -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $g, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(4, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,4}; +yystate(3, Ics, Line, Tlen, Action, Alen) -> + {1,Tlen,Ics,Line}; +yystate(2, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [$d|Ics], Line, Tlen, Action, Alen) -> + yystate(1, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $c -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $e, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(2, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,2}; +yystate(1, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [$a|Ics], Line, Tlen, Action, Alen) -> + yystate(5, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $` -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, [C|Ics], Line, Tlen, Action, Alen) when C >= $b, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(1, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,1}; +yystate(0, [$\v|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [$\f|Ics], Line, Tlen, Action, Alen) -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [$e|Ics], Line, Tlen, Action, Alen) -> + yystate(4, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $\000, C =< $\t -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $\016, C =< $\037 -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $!, C =< $' -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $*, C =< $d -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= $f, C =< $ÿ -> + yystate(17, Ics, Line, Tlen+1, 5, Tlen); +yystate(0, Ics, Line, Tlen, Action, Alen) -> + {5,Tlen,Ics,Line,0}; +yystate(S, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,S}. + + +%% yyaction(Action, TokenLength, TokenChars, Line) -> +%% {token,Token} | {end_token, Token} | skip_token | {error,String}. +%% Generated action function. + +yyaction(0, YYlen, YYtcs, YYline) -> + {token,{'(',YYline}}; +yyaction(1, YYlen, YYtcs, YYline) -> + {token,{')',YYline}}; +yyaction(2, YYlen, YYtcs, YYline) -> + {token,{special,YYline}}; +yyaction(3, YYlen, YYtcs, YYline) -> + {token,{special,YYline}}; +yyaction(4, YYlen, YYtcs, YYline) -> + {token,{special,YYline}}; +yyaction(5, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{atom,YYline,YYtext}}; +yyaction(6, YYlen, YYtcs, YYline) -> + skip_token; +yyaction(_, _, _, _) -> error. diff --git a/mods/src/em_scheme_scan.xrl b/mods/src/em_scheme_scan.xrl new file mode 100644 index 0000000..632cf13 --- /dev/null +++ b/mods/src/em_scheme_scan.xrl @@ -0,0 +1,18 @@ +Definitions. + +AtomChar = [^\s\r\n\(\)] +WS = [\s\r\n] + +Rules. + +\( : {token, {'(', YYline}}. +\) : {token, {')', YYline}}. + +lambda : {token, {special, YYline}}. +define : {token, {special, YYline}}. +let : {token, {special, YYline}}. + +({AtomChar}{AtomChar}*) : {token, {atom, YYline, YYtext}}. +%% Ignore +{WS} : skip_token. + diff --git a/mods/src/em_stdlib.erl b/mods/src/em_stdlib.erl new file mode 100644 index 0000000..1bc4687 --- /dev/null +++ b/mods/src/em_stdlib.erl @@ -0,0 +1,21 @@ +%%%---------------------------------------------------------------------- +%%% File : em_stdlib.erl +%%% Author : Luke Gorrie <luke@bluetail.com> +%%% Purpose : Module for loading the standard library of editor commands. +%%% This module is loaded/initialised on editor startup. +%%% Created : 29 Apr 2001 by Luke Gorrie <luke@bluetail.com> +%%%---------------------------------------------------------------------- + +-module(em_stdlib). +-author('luke@bluetail.com'). + +-export([mod_init/0]). + +mod_init() -> + lists:foreach(fun(Mod) -> edit_mod:require(Mod) end, + mods()). + +%% List of modules to be initialised at start-up. +mods() -> + [em_erlang, em_scheme]. + diff --git a/mods/src/em_test_scan.erl b/mods/src/em_test_scan.erl new file mode 100644 index 0000000..4a39ca3 --- /dev/null +++ b/mods/src/em_test_scan.erl @@ -0,0 +1,255 @@ +%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE +%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE +%% AND BETTER INTERFACE - BE WARNED +%% PLEASE REPORT ALL BUGS TO THE AUTHOR. + +-module('em_test_scan'). + +-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]). +-export([format_error/1]). + +%% luke +-export([yystate/0, yystate/6, yyaction/4]). + +%% User code. This is placed here to allow extra attributes. + +format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)]; +format_error({user,S}) -> S. + +string(String) -> string(String, 1). + +string(String, Line) -> string(String, Line, String, []). + +%% string(InChars, Line, TokenChars, Tokens) -> +%% {ok,Tokens,Line} | {error,ErrorInfo,Line}. + +string([], L, [], Ts) -> %No partial tokens! + {ok,yyrev(Ts),L}; +string(Ics0, L0, Tcs, Ts) -> + case yystate(yystate(), Ics0, L0, 0, reject, 0) of + {A,Alen,Ics1,L1} -> %Accepting end state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {A,Alen,Ics1,L1,S1} -> %After an accepting state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {reject,Alen,Tlen,Ics1,L1,S1} -> + {error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1}; + {A,Alen,Tlen,Ics1,L1,S1} -> + string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts) + end. + +%% string_cont(RestChars, Line, Token, Tokens) +%% Test for and remove the end token wrapper. + +string_cont(Rest, Line, {token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, {end_token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, skip_token, Ts) -> + string(Rest, Line, Rest, Ts); +string_cont(Rest, Line, {error,S}, Ts) -> + {error,{Line,?MODULE,{user,S}},Line}. + +%% token(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +token(Cont, Chars) -> token(Cont, Chars, 1). + +token([], Chars, Line) -> + token(Chars, Line, yystate(), Chars, 0, reject, 0); +token({Line,State,Tcs,Tlen,Action,Alen}, Chars, _) -> + token(Chars, Line, State, Tcs ++ Chars, Tlen, Action, Alen). + +%% token(InChars, Line, State, TokenChars, TokenLen, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +token(Ics0, L0, S0, Tcs, Tlen0, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{L1,S1,Tcs,Alen1,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{L1,S1,Tcs,Tlen1,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{eof,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + {done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},L1},Ics1}; + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1)) + end. + +%% tokens_cont(RestChars, Line, Token) +%% Test if we have detected the end token, if so return done else continue. + +token_cont(Rest, Line, {token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, {end_token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, skip_token) -> + token(Rest, Line, yystate(), Rest, 0, reject, 0); +token_cont(Rest, Line, {error,S}) -> + {done,{error,{Line,?MODULE,{user,S}},Line},Rest}. + +%% tokens(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +tokens(Cont, Chars) -> tokens(Cont, Chars, 1). + +tokens([], Chars, Line) -> + tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0); +tokens({tokens,Line,State,Tcs,Tlen,Ts,Action,Alen}, Chars, _) -> + tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Ts, Action, Alen); +tokens({skip_tokens,Line,State,Tcs,Tlen,Error,Action,Alen}, Chars, _) -> + skip_tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Error, Action, Alen). + +%% tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +tokens(Ics0, L0, S0, Tcs, Tlen0, Ts, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{tokens,L1,S1,Tcs,Tlen1,Ts,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,if Ts == [] -> {eof,L1}; + true -> {ok,yyrev(Ts),L1} end,[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1+1), L1, + {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}}); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts) + end. + +%% tokens_cont(RestChars, Line, Token, Tokens) +%% Test if we have detected the end token, if so return done else continue. + +tokens_cont(Rest, Line, {token,T}, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0); +tokens_cont(Rest, Line, {end_token,T}, Ts) -> + {done,{ok,yyrev(Ts, [T]),Line},Rest}; +tokens_cont(Rest, Line, skip_token, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0); +tokens_cont(Rest, Line, {error,S}, Ts) -> + skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}). + +%% token_skip(InChars, Line, Error) -> {done,ReturnVal,RestChars}. +%% Skip tokens until an end token, junk everything and return the error. + +%%skip_tokens(Ics, Line, Error) -> {done,{error,Error,Line},Ics}. + +skip_tokens(Ics, Line, Error) -> + skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0). + +%% skip_tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +skip_tokens(Ics0, L0, S0, Tcs, Tlen0, Error, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{skip_tokens,L1,S1,Tcs,Tlen1,Error,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{error,Error,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1), L1, Error); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error) + end. + +%% skip_cont(RestChars, Line, Token, Error) +%% Test if we have detected the end token, if so return done else continue. + +skip_cont(Rest, Line, {token,T}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, {end_token,T}, Error) -> + {done,{error,Error,Line},Rest}; +skip_cont(Rest, Line, {error,S}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, skip_token, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0). + +yyrev(L) -> yyrev(L, []). + +yyrev([H|T], Acc) -> yyrev(T, [H|Acc]); +yyrev([], Acc) -> Acc. + +yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)]; +yypre(L, N) -> []. + +yysuf([H|T], N) when N > 0 -> yysuf(T, N-1); +yysuf(L, 0) -> L. + +yysplit(L, N) -> yysplit(L, N, []). +yysplit([H|T], N, Acc) when N > 0 -> yysplit(T, N-1, [H|Acc]); +yysplit(L, 0, Acc) -> {lists:reverse(Acc), L}. + +%% yystate() -> InitialState. +%% yystate(State, InChars, Line, Token, ) -> +%% {Action, AcceptLength, RestChars, Line} | Accepting end state +%% {Action, AcceptLength, RestChars, Line, State} | Accepting state +%% {Action, AcceptLength, TokLength, RestChars, Line, State} | +%% {reject, AcceptLength, TokLength, RestChars, Line, State}. +%% Generated state transition functions. + +yystate() -> 2. + +yystate(5, [$+|Ics], Line, Tlen, Action, Alen) -> + yystate(3, Ics, Line, Tlen+1, 0, Tlen); +yystate(5, Ics, Line, Tlen, Action, Alen) -> + {0,Tlen,Ics,Line,5}; +yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $z -> + yystate(4, Ics, Line, Tlen+1, 4, Tlen); +yystate(4, Ics, Line, Tlen, Action, Alen) -> + {4,Tlen,Ics,Line,4}; +yystate(3, Ics, Line, Tlen, Action, Alen) -> + {1,Tlen,Ics,Line}; +yystate(2, [$\s|Ics], Line, Tlen, Action, Alen) -> + yystate(1, Ics, Line, Tlen+1, Action, Alen); +yystate(2, [$+|Ics], Line, Tlen, Action, Alen) -> + yystate(5, Ics, Line, Tlen+1, Action, Alen); +yystate(2, [$-|Ics], Line, Tlen, Action, Alen) -> + yystate(0, Ics, Line, Tlen+1, Action, Alen); +yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= $a, C =< $z -> + yystate(4, Ics, Line, Tlen+1, Action, Alen); +yystate(2, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,2}; +yystate(1, Ics, Line, Tlen, Action, Alen) -> + {3,Tlen,Ics,Line}; +yystate(0, Ics, Line, Tlen, Action, Alen) -> + {2,Tlen,Ics,Line}; +yystate(S, Ics, Line, Tlen, Action, Alen) -> + {Action,Alen,Tlen,Ics,Line,S}. + + +%% yyaction(Action, TokenLength, TokenChars, Line) -> +%% {token,Token} | {end_token, Token} | skip_token | {error,String}. +%% Generated action function. + +yyaction(0, YYlen, YYtcs, YYline) -> + {token,{'+',YYline}}; +yyaction(1, YYlen, YYtcs, YYline) -> + {token,{'++',YYline}}; +yyaction(2, YYlen, YYtcs, YYline) -> + {token,{'-',YYline}}; +yyaction(3, YYlen, YYtcs, YYline) -> + skip_token; +yyaction(4, YYlen, YYtcs, YYline) -> + YYtext = yypre(YYtcs, YYlen), + {token,{atom,YYline,YYtext}}; +yyaction(_, _, _, _) -> error. diff --git a/mods/src/em_test_scan.xrl b/mods/src/em_test_scan.xrl new file mode 100644 index 0000000..05ac6bb --- /dev/null +++ b/mods/src/em_test_scan.xrl @@ -0,0 +1,12 @@ +Definitions. + +Ch = [a-z] + +Rules. + +\+ : {token, {'+', YYline}}. +\+\+ : {token, {'++', YYline}}. +- : {token, {'-', YYline}}. +\s : skip_token. +({Ch}{Ch}*) : {token, {atom, YYline, YYtext}}. + diff --git a/mods/src/leex.hrl b/mods/src/leex.hrl new file mode 100644 index 0000000..4845418 --- /dev/null +++ b/mods/src/leex.hrl @@ -0,0 +1,217 @@ +%% THIS IS A PRE-RELEASE OF LEEX - RELEASED ONLY BECAUSE MANY PEOPLE +%% WANTED IT - THE OFFICIAL RELEASE WILL PROVIDE A DIFFERENT INCOMPATIBLE +%% AND BETTER INTERFACE - BE WARNED +%% PLEASE REPORT ALL BUGS TO THE AUTHOR. + +##module + +-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]). +-export([format_error/1]). + +%% luke +-export([yystate/0, yystate/6, yyaction/4]). + +%% User code. This is placed here to allow extra attributes. +##code + +format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)]; +format_error({user,S}) -> S. + +string(String) -> string(String, 1). + +string(String, Line) -> string(String, Line, String, []). + +%% string(InChars, Line, TokenChars, Tokens) -> +%% {ok,Tokens,Line} | {error,ErrorInfo,Line}. + +string([], L, [], Ts) -> %No partial tokens! + {ok,yyrev(Ts),L}; +string(Ics0, L0, Tcs, Ts) -> + case yystate(yystate(), Ics0, L0, 0, reject, 0) of + {A,Alen,Ics1,L1} -> %Accepting end state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {A,Alen,Ics1,L1,S1} -> %After an accepting state + string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts); + {reject,Alen,Tlen,Ics1,L1,S1} -> + {error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1}; + {A,Alen,Tlen,Ics1,L1,S1} -> + string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts) + end. + +%% string_cont(RestChars, Line, Token, Tokens) +%% Test for and remove the end token wrapper. + +string_cont(Rest, Line, {token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, {end_token,T}, Ts) -> + string(Rest, Line, Rest, [T|Ts]); +string_cont(Rest, Line, skip_token, Ts) -> + string(Rest, Line, Rest, Ts); +string_cont(Rest, Line, {error,S}, Ts) -> + {error,{Line,?MODULE,{user,S}},Line}. + +%% token(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +token(Cont, Chars) -> token(Cont, Chars, 1). + +token([], Chars, Line) -> + token(Chars, Line, yystate(), Chars, 0, reject, 0); +token({Line,State,Tcs,Tlen,Action,Alen}, Chars, _) -> + token(Chars, Line, State, Tcs ++ Chars, Tlen, Action, Alen). + +%% token(InChars, Line, State, TokenChars, TokenLen, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +token(Ics0, L0, S0, Tcs, Tlen0, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{L1,S1,Tcs,Alen1,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1)); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{L1,S1,Tcs,Tlen1,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{eof,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + {done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},L1},Ics1}; + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1)) + end. + +%% tokens_cont(RestChars, Line, Token) +%% Test if we have detected the end token, if so return done else continue. + +token_cont(Rest, Line, {token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, {end_token,T}) -> + {done,{ok,T,Line},Rest}; +token_cont(Rest, Line, skip_token) -> + token(Rest, Line, yystate(), Rest, 0, reject, 0); +token_cont(Rest, Line, {error,S}) -> + {done,{error,{Line,?MODULE,{user,S}},Line},Rest}. + +%% tokens(Continuation, Chars, Line) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. +%% Must be careful when re-entering to append the latest characters to the +%% after characters in an accept. + +tokens(Cont, Chars) -> tokens(Cont, Chars, 1). + +tokens([], Chars, Line) -> + tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0); +tokens({tokens,Line,State,Tcs,Tlen,Ts,Action,Alen}, Chars, _) -> + tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Ts, Action, Alen); +tokens({skip_tokens,Line,State,Tcs,Tlen,Error,Action,Alen}, Chars, _) -> + skip_tokens(Chars, Line, State, Tcs ++ Chars, Tlen, Error, Action, Alen). + +%% tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +tokens(Ics0, L0, S0, Tcs, Tlen0, Ts, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{tokens,L1,S1,Tcs,Tlen1,Ts,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,if Ts == [] -> {eof,L1}; + true -> {ok,yyrev(Ts),L1} end,[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1+1), L1, + {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}}); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts) + end. + +%% tokens_cont(RestChars, Line, Token, Tokens) +%% Test if we have detected the end token, if so return done else continue. + +tokens_cont(Rest, Line, {token,T}, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0); +tokens_cont(Rest, Line, {end_token,T}, Ts) -> + {done,{ok,yyrev(Ts, [T]),Line},Rest}; +tokens_cont(Rest, Line, skip_token, Ts) -> + tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0); +tokens_cont(Rest, Line, {error,S}, Ts) -> + skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}). + +%% token_skip(InChars, Line, Error) -> {done,ReturnVal,RestChars}. +%% Skip tokens until an end token, junk everything and return the error. + +%%skip_tokens(Ics, Line, Error) -> {done,{error,Error,Line},Ics}. + +skip_tokens(Ics, Line, Error) -> + skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0). + +%% skip_tokens(InChars, Line, State, TokenChars, TokenLen, Tokens, Accept) -> +%% {more,Continuation} | {done,ReturnVal,RestChars}. + +skip_tokens(Ics0, L0, S0, Tcs, Tlen0, Error, A0, Alen0) -> + case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of + {A1,Alen1,Ics1,L1} -> %Accepting end state + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,[],L1,S1} -> %After an accepting state + {more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}}; + {A1,Alen1,Ics1,L1,S1} -> + skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error); + {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state + {more,{skip_tokens,L1,S1,Tcs,Tlen1,Error,A1,Alen1}}; + {reject,Alen1,Tlen1,eof,L1,S1} -> + {done,{error,Error,L1},[]}; + {reject,Alen1,Tlen1,Ics1,L1,S1} -> + skip_tokens(yysuf(Tcs, Tlen1), L1, Error); + {A1,Alen1,Tlen1,Ics1,L1,S1} -> + skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error) + end. + +%% skip_cont(RestChars, Line, Token, Error) +%% Test if we have detected the end token, if so return done else continue. + +skip_cont(Rest, Line, {token,T}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, {end_token,T}, Error) -> + {done,{error,Error,Line},Rest}; +skip_cont(Rest, Line, {error,S}, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0); +skip_cont(Rest, Line, skip_token, Error) -> + skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0). + +yyrev(L) -> yyrev(L, []). + +yyrev([H|T], Acc) -> yyrev(T, [H|Acc]); +yyrev([], Acc) -> Acc. + +yypre([H|T], N) when N > 0 -> [H|yypre(T, N-1)]; +yypre(L, N) -> []. + +yysuf([H|T], N) when N > 0 -> yysuf(T, N-1); +yysuf(L, 0) -> L. + +yysplit(L, N) -> yysplit(L, N, []). +yysplit([H|T], N, Acc) when N > 0 -> yysplit(T, N-1, [H|Acc]); +yysplit(L, 0, Acc) -> {lists:reverse(Acc), L}. + +%% yystate() -> InitialState. +%% yystate(State, InChars, Line, Token, ) -> +%% {Action, AcceptLength, RestChars, Line} | Accepting end state +%% {Action, AcceptLength, RestChars, Line, State} | Accepting state +%% {Action, AcceptLength, TokLength, RestChars, Line, State} | +%% {reject, AcceptLength, TokLength, RestChars, Line, State}. +%% Generated state transition functions. + +##dfa + +%% yyaction(Action, TokenLength, TokenChars, Line) -> +%% {token,Token} | {end_token, Token} | skip_token | {error,String}. +%% Generated action function. + +##actions |