1:-module(parser_utils,
    2	 [read_file_to_string/2,
    3	 atomic_constant_list/3,
    4	 atomic_constant/3,
    5	 elementList/3, %PAY ATTENTION: HERE THE ORIGINAL PRED IS /1, BUT SINCE IT'S DCG, IT BECOMES /3 !!!
    6	 drop_whites/2,
    7	 drop_comments/2,
    8	 opening_parenthesis/2,
    9	 term/3,
   10	 term_list/3,
   11	 comma/2,
   12	 time/3,
   13	 closing_parenthesis/2,
   14	 funct/3,
   15	 number/3,
   16	 variable/3,
   17	 full_stop/2]).   18
   19
   20:-use_module(library(lists),
   21	     [append/3,
   22	      member/2]).   23
   24% Otherwise, if the file is local, open it
   25read_file_to_string(File,String):-
   26	open(File,read,Stream),
   27	%write('Open OK'),nl,
   28	read_stream_to_string(Stream,String),
   29	close(Stream).
   30
   31print_resp([]):-!.
   32print_resp([C|S]):- !,format('~s',[[C]]), print_resp(S).
   33
   34
   35
   36read_stream_to_string(Stream,[]):-
   37	at_end_of_stream(Stream),
   38	!.
   39read_stream_to_string(Stream,[C|T]):-
   40	get_code(Stream,C),
   41	read_stream_to_string(Stream,T).
   42
   43drop_whites([],[]).
   44drop_whites(Codes,NoWhiteCodes):-
   45	whites(Codes,MoreCodes),
   46	!,
   47	drop_whites(MoreCodes,NoWhiteCodes).
   48drop_whites([Code|MoreCodes],[Code|MoreNoWhiteCodes]):-
   49	drop_whites(MoreCodes,MoreNoWhiteCodes).
   50
   51
   52full_stop -->
   53	".".
   54comma -->
   55	",".
   56opening_parenthesis -->
   57	"(".
   58closing_parenthesis -->
   59	")".
   60
   61whites(Codes,MoreCodes):-
   62	white_codes(WhiteCodes),
   63	append(WhiteCodes,MoreCodes,Codes).
   64
   65white_codes(WhiteCodes):-
   66	white_atom(Atom),
   67	atom_codes(Atom,WhiteCodes).
   68white_codes([13]).
   69	
   70white_atom(' ').
   71white_atom('\t').
   72white_atom('\n').
   73
   74funct(Functor) -->
   75	atomic_constant(Functor),
   76	!.
   77funct(',')-->
   78	"".
   79
   80atomic_constant(Const) -->
   81	lowercase(LowerCase),
   82	alphanumeric_string_tail(Alpha),
   83	{atom_codes(Const,[LowerCase|Alpha])}.
   84
   85lowercase(C) -->
   86	[C],
   87	{char_code('a',A),
   88	 char_code('z',Z),
   89	 A =< C,
   90	 C =< Z}.
   91
   92uppercase(C) -->
   93	[C],
   94	{char_code('A',A),
   95	 char_code('Z',Z),
   96	 A =< C,
   97	 C =< Z}.
   98underscore(C) -->
   99	[C],
  100	{char_code('_',C)}.
  101
  102uppercase_or_underscore(C)-->
  103	uppercase(C),
  104	!.
  105uppercase_or_underscore(C)-->
  106	underscore(C).
  107
  108alphanumeric_string([Code|MoreCodes]) -->
  109	alphanumeric(Code),
  110	!,
  111	alphanumeric_string_tail(MoreCodes).
  112
  113alphanumeric_string_tail(String) -->
  114	alphanumeric_string(String),
  115	!.
  116alphanumeric_string_tail([]) -->
  117	[].
  118
  119alphanumeric(Code) -->
  120	lowercase(Code).
  121alphanumeric(Code) -->
  122	uppercase(Code).
  123alphanumeric(Code) -->
  124	digit(Code).
  125alphanumeric(Code) -->
  126	[Code],
  127	{char_code('_',Code)}.
  128
  129integer(Integer) -->
  130	digit_string(DigitString),
  131	{number_codes(Integer,DigitString)}.
  132
  133digit_string([Digit|MoreDigits]) -->
  134	digit(Digit),
  135	!,
  136	digit_string_tail(MoreDigits).
  137
  138digit_string_tail(DigitStringTail) -->
  139	digit_string(DigitStringTail),
  140	!.
  141digit_string_tail([]) -->
  142	[].
  143
  144digit(Digit) -->
  145	[Digit],
  146	{char_code('0',Zero),
  147	 char_code('9',Nine),
  148	 Zero =< Digit,
  149	 Digit =< Nine}.
  150
  151float(Float) -->
  152	digit_string(DigitString1),
  153	".",
  154	digit_string(DigitString2),
  155	{char_code('.',FullStopCode),
  156	 append(DigitString1,[FullStopCode|DigitString2],DigitString),
  157	 number_codes(Float,DigitString)}.
  158
  159number(Number) -->
  160	float(Number),
  161	!.
  162number(Number) -->
  163	integer(Number).
  164
  165
  166term(Term) -->
  167	funct(Functor),
  168	opening_parenthesis,
  169	!,
  170	term_list(Arguments),
  171	closing_parenthesis,
  172	{Term=..[Functor|Arguments]}.
  173
  174
  175
  176term(TermList) -->
  177	"[",
  178	!,
  179	term_list(TermList),
  180	"]".
  181	
  182term(Term) -->
  183	constant(Term),
  184	!.
  185term(Term) -->
  186	variable(Term),
  187	!.
  188
  189term1(Term) -->
  190	term(Term).
  191term1(Term) -->
  192	unary_operator_term(Term).
  193term1(Term) -->
  194	binary_operator_term(Term).
  195
  196unary_operator_term(Term) -->
  197	oper(Operator),
  198	term(Term1),
  199	{concat_atoms(Operator,Term1,Term)}.
  200
  201binary_operator_term(Term) -->
  202	term(Term1),
  203	oper(Operator),
  204	term(Term2),
  205	{concat_atoms(Term1,Operator,Term3),
  206	concat_atoms(Term3,Term2,Term)}.
  207
  208term_list([Term|MoreTerms]) -->
  209	term1(Term),
  210	term_list_tail(MoreTerms).
  211term_list([]) -->
  212	[].
  213
  214term_list_tail(TermListTail) -->
  215	comma,
  216	!,
  217	term_list(TermListTail).
  218term_list_tail([]) -->
  219	[].
  220
  221atomic_constant_list([Const|MoreConsts]) -->
  222	atomic_constant(Const),
  223	!,
  224	atomic_constant_list(MoreConsts).
  225atomic_constant_list([]) -->
  226	[].
  227
  228
  229constant(Const) -->
  230	atomic_constant(Const).
  231constant(Const) -->
  232	number(Const).
  233
  234oper(Operator) -->
  235	{member(Operator,[+,-,*,/]),
  236	 atom_codes(Operator,Codes)},
  237	Codes.
  238	 
  239
  240time(Time) -->
  241	variable(Time).
  242time(Time) -->
  243	number(Time).
  244
  245
  246variable(Variable) -->
  247	uppercase_or_underscore(UpperCase),
  248	alphanumeric_string_tail(Alpha),
  249	{atom_codes(Variable,[UpperCase|Alpha])}.
  250
  251concat_atoms(A1,A2,A3) :-
  252	atomo_codes(A1,S1),
  253	atomo_codes(A2,S2),
  254	append(S1,S2,S3),
  255	atomo_codes(A3,S3).
  256
  257atomo_codes(A,S):-
  258	number(A),
  259	!,
  260	number_codes(A,S).
  261atomo_codes(A,S):-
  262	atom_codes(A,S).
  263
  264
  265
  266%----------------------------------------------------------
  267% COMMENTS DCG
  268%----------------------------------------------------------
  269drop_comments(InputList, OutputList) :-
  270	phrase(elementList(OutputList),InputList).
  271
  272
  273elementList(MoreElements) -->
  274	comment,
  275	!,
  276	elementList(MoreElements).
  277elementList([Element|MoreElements]) --> 
  278	anElement(Element),
  279	!,
  280	elementList(MoreElements).
  281elementList([]) -->
  282	[].
  283
  284anElement(Element) -->
  285	[Element].
  286
  287comment -->
  288	commentStarter_sl, !, commentContent_sl.
  289comment -->
  290	commentStarter_ml, commentContent_ml.
  291
  292
  293%%% Comments on single-line
  294
  295commentStarter_sl -->
  296	"//", !.
  297commentStarter_sl -->
  298	"%".
  299
  300commentContent_sl -->
  301	commentEnder_sl, !.
  302commentContent_sl -->
  303	[_], commentContent_sl.
  304
  305commentEnder_sl -->
  306	{atom_codes('\n', X)}, X.
  307
  308
  309%%% Comments on multi-lines...
  310
  311commentStarter_ml -->
  312	"/*".
  313
  314commentContent_ml -->
  315	commentEnder_ml, !.
  316commentContent_ml -->
  317	[_], commentContent_ml.
  318
  319commentEnder_ml -->
  320	"*/"