Concerning the input (xxx yyy zzz) the OP wrote:
I would expect it to print zzz(xxx(yyy)).
Where did he get this requirement from, he didn’t
compare other Prolog systems, right? So it came from
his applicationdomain. But what was his application
domain? Ok, lets proceed to an example with multiple
brakets. Lets make the Pascal “begin” “end” example,
by replacing xxx and zzz by “begin” and “end”.
I get this result:
?- member(X,[begin,end]), current_op(Y,Z,X).
X = (begin), Y = 1100, Z = fy ;
X = (end), Y = 1100, Z = yf.
?- X = (begin
| x = 1;
| y = 2;
| begin
| z = 3
| end
| end).
X = (begin x=1;y=2;begin z=3 end end).
But is the abstract parse term, the Prolog result useful?
Here is the SWI-Prolog and the SICStus
Prolog abstract parse term. This is the real
nightmare of every computer science professor,
who wants to use Prolog in a compiler
construction course:
/* SWI-Prolog 9.3.14 */
end(end(begin(;(=(x,1),;(=(y,2),begin(=(z,3)))))))
/* SICStus Prolog 4.9.0 */
begin(;(=(x,1),;(=(y,2),begin(end(end(=(z,3)))))))
On the other hand mostlikely the OP @horsh
would expect:
/* What the End-User wants */ end(begin(;(=(x,1),;(=(y,2),end(begin(=(z,3)))))))
I think its impossible to do in any Prolog system,
you would need a programming language with the
possibility to do mixfix syntax definitions,
like for example in Isabelle/HOL:
(* Define the mixfix syntax for a Pascal-like block *)
syntax
"_begin_end" :: "'a ⇒ 'a" ("begin _ end")
Or otherwise use DCG to write your own parser
for the DSL at hand, that you want to parse.
Since Prolog operators cannot model mixfix syntax,
at least SWI-Prolog and SICStus Prolog fail,
and I guess other Prolog systems fail as well.
Mild Shock schrieb:
Concerning the input (xxx yyy zzz) the OP wrote:
I would expect it to print zzz(xxx(yyy)).
Where did he get this requirement from, he didn’t
compare other Prolog systems, right? So it came from
his applicationdomain. But what was his application
domain? Ok, lets proceed to an example with multiple
brakets. Lets make the Pascal “begin” “end” example,
by replacing xxx and zzz by “begin” and “end”.
I get this result:
?- member(X,[begin,end]), current_op(Y,Z,X).
X = (begin), Y = 1100, Z = fy ;
X = (end), Y = 1100, Z = yf.
?- X = (begin
| x = 1;
| y = 2;
| begin
| z = 3
| end
| end).
X = (begin x=1;y=2;begin z=3 end end).
But is the abstract parse term, the Prolog result useful?
Lets cut through the thicket. There is no
real world use case of a (fy 1 yf). Take again
the Pascal “begin” “end” mixfix example.
Typically we want to then go on and write
for example a compiler:
:- op(1100,fy,begin).
:- op(1100,yf,end).
compile((begin X end)) --> compile(X). %%% scoping omitted
compile((X;Y)) --> compile(X), compile(Y).
compile((V=E)) --> [load(E),store(V)].
The problem is the pattern (begin X end) will
not work, if multiple (begin … end) are involved
in the compile/1 call. You can try yourself, no
Prolog system can do it:
/* SWI-Prolog */
?- X = (begin
x = 1;
begin
y = 2
end
end), compile(X, L, []).
false.
%%% expected L = [load(1),store(x),load(2),store(y)]
/* SICStus Prolog */
?- X = (begin
x = 1;
begin
y = 2
end
end), compile(X, L, []).
no.
%%% expected L = [load(1),store(x),load(2),store(y)]
The reason is that the parser will join multiple yf,
similarly it would join multiple fy. The parser will
not follow a braket pattern. At least I don’t know
any Prolog system that can do it.
Mild Shock schrieb:
Here is the SWI-Prolog and the SICStus
Prolog abstract parse term. This is the real
nightmare of every computer science professor,
who wants to use Prolog in a compiler
construction course:
/* SWI-Prolog 9.3.14 */
end(end(begin(;(=(x,1),;(=(y,2),begin(=(z,3)))))))
/* SICStus Prolog 4.9.0 */
begin(;(=(x,1),;(=(y,2),begin(end(end(=(z,3)))))))
On the other hand mostlikely the OP @horsh
would expect:
/* What the End-User wants */
end(begin(;(=(x,1),;(=(y,2),end(begin(=(z,3)))))))
I think its impossible to do in any Prolog system,
you would need a programming language with the
possibility to do mixfix syntax definitions,
like for example in Isabelle/HOL:
(* Define the mixfix syntax for a Pascal-like block *)
syntax
"_begin_end" :: "'a ⇒ 'a" ("begin _ end")
Or otherwise use DCG to write your own parser
for the DSL at hand, that you want to parse.
Since Prolog operators cannot model mixfix syntax,
at least SWI-Prolog and SICStus Prolog fail,
and I guess other Prolog systems fail as well.
Mild Shock schrieb:
Concerning the input (xxx yyy zzz) the OP wrote:
I would expect it to print zzz(xxx(yyy)).
Where did he get this requirement from, he didn’t
compare other Prolog systems, right? So it came from
his applicationdomain. But what was his application
domain? Ok, lets proceed to an example with multiple
brakets. Lets make the Pascal “begin” “end” example,
by replacing xxx and zzz by “begin” and “end”.
I get this result:
?- member(X,[begin,end]), current_op(Y,Z,X).
X = (begin), Y = 1100, Z = fy ;
X = (end), Y = 1100, Z = yf.
?- X = (begin
| x = 1;
| y = 2;
| begin
| z = 3
| end
| end).
X = (begin x=1;y=2;begin z=3 end end).
But is the abstract parse term, the Prolog result useful?
This seems to do the trick:
```
% SWI-Prolog 9.2.7
:- op(1100, fy, begin).
:- op(1100, yf, end).
compile((begin XEnd)) --> compile(XEnd).
compile((X end)) --> compile(X).
compile((X;Y)) --> compile(X), compile(Y).
compile((V=E)) --> [load(E),store(V)].
compile_t(X, L) :-
X = (
begin
x = 1;
begin
y = 2
end
end
),
compile(X, L, []).
```
```
?- compile_t(X, L).
X = (begin x=1;begin y=2 end end),
L = [load(1),store(x),load(2),store(y)].
```
-Julio
Typically we want to then go on and write<snip>
for example a compiler:
:- op(1100,fy,begin).
:- op(1100,yf,end).
compile((begin X end)) --> compile(X). %%% scoping omitted
compile((X;Y)) --> compile(X), compile(Y).
compile((V=E)) --> [load(E),store(V)].
The problem is the pattern (begin X end) will
not work, if multiple (begin … end) are involved
in the compile/1 call. You can try yourself, no
Prolog system can do it:
/* SWI-Prolog */
?- X = (begin
x = 1;
begin
y = 2
end
end), compile(X, L, []).
false.
%%% expected L = [load(1),store(x),load(2),store(y)]
Yes, maybe, it depends. You would
need to fill in some logic for the
block functionality, like opening
and closing a table with variable
names. And try it as such with a larger
variety of example. Also compare whether
it works for both SWI-Prolog and SICStus
Prolog. What one can already see for sure,
the compile is not extremly safe anymore.
It would also accept non well formed
input. Like you can call it with unbalanced
begin end now, and the compile/1 clause
pattern matching will not fail, and it
will start producing some code:
?- compile((begin x=1 end end)).
But maybe this is a minor problem. Another
challenge is for example the Pascal if-then-else.
Basically a mixfix with 3 holes.
if _ then _ else _
https://www.tutorialspoint.com/pascal/pascal_if_then_else_statement.htm
Just like in the begin end case, where
we can provide non-well formed input
like (begin x=1 end end). Ordinary
Prolog operators will again not provide
the safety and versatility for writing rules.
Julio Di Egidio schrieb:
This seems to do the trick:
```
% SWI-Prolog 9.2.7
:- op(1100, fy, begin).
:- op(1100, yf, end).
compile((begin XEnd)) --> compile(XEnd).
compile((X end)) --> compile(X).
compile((X;Y)) --> compile(X), compile(Y).
compile((V=E)) --> [load(E),store(V)].
compile_t(X, L) :-
X = (
begin
x = 1;
begin
y = 2
end
end
),
compile(X, L, []).
```
```
?- compile_t(X, L).
X = (begin x=1;begin y=2 end end),
L = [load(1),store(x),load(2),store(y)].
```
-Julio
Yes, maybe, it depends. You would
need to fill in some logic for the
block functionality, like opening
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 491 |
Nodes: | 16 (2 / 14) |
Uptime: | 147:01:24 |
Calls: | 9,694 |
Calls today: | 4 |
Files: | 13,732 |
Messages: | 6,178,670 |