Skip to content

Commit 178ff7e

Browse files
committed
Fix parser to reject (|) as syntax error per ISO spec
Fixes #3140 The parser was incorrectly accepting (|) and converting it to the atom '|', when it should produce a syntax_error according to ISO/IEC 13211-1 Technical Corrigendum 2, Section C2. Changes: - Modified reduce_brackets() in parser.rs to reject HeadTailSeparator inside parentheses, treating (|) as incomplete/forbidden syntax - Updated builtins.pl to use quoted atom '|' instead of (|) in error term - Added comprehensive tests in src/tests/iso_syntax_errors.pl covering: * (|) syntax error * ISO operator creation restrictions for {} and '|' * Valid operator declarations with proper priorities
1 parent e4d9692 commit 178ff7e

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

src/lib/builtins.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@
14661466
lists:member(OpSpec, [xfx, xfy, yfx]),
14671467
( Priority >= 1001 ; Priority == 0 )
14681468
-> '$op'(Priority, OpSpec, Op)
1469-
; throw(error(permission_error(create, operator, (|)), op/3))) % www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing#72
1469+
; throw(error(permission_error(create, operator, '|'), op/3))) % www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing#72
14701470
; valid_op(Op), op_priority(Priority), op_specifier(OpSpec) ->
14711471
'$op'(Priority, OpSpec, Op)
14721472
; list_of_op_atoms(Op), op_priority(Priority), op_specifier(OpSpec) ->

src/parser/parser.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
829829

830830
match td.tt {
831831
TokenType::Open | TokenType::OpenCT => {
832-
if self.stack[idx].tt == TokenType::Comma {
833-
return false;
832+
// Reject incomplete reductions and ISO-forbidden syntax
833+
// See: https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#C2
834+
match self.stack[idx].tt {
835+
TokenType::Comma => {
836+
return false;
837+
}
838+
TokenType::HeadTailSeparator => {
839+
// (|) is forbidden by ISO spec
840+
return false;
841+
}
842+
_ => {}
834843
}
835844

836845
if let Some(atom) = self.stack[idx].tt.sep_to_atom() {

src/tests/iso_syntax_errors.pl

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
:- module(iso_syntax_errors_tests, []).
2+
:- use_module(test_framework).
3+
:- use_module(library(charsio)).
4+
5+
% ISO/IEC 13211-1 Technical Corrigendum 2, Section C2
6+
% See https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#C2
7+
8+
test("single_bar_in_parens_should_error", (
9+
% see https://github.com/mthom/scryer-prolog/issues/3140
10+
% (|) should cause a syntax error when parsed
11+
catch(
12+
(read_from_chars("(|).", _), false),
13+
error(syntax_error(_), _),
14+
true
15+
)
16+
)).
17+
18+
test("op_create_empty_curly_should_error", (
19+
catch(
20+
op(500, xfy, {}),
21+
error(permission_error(create, operator, {}), _),
22+
true
23+
)
24+
)).
25+
26+
test("op_create_empty_curly_in_list_should_error", (
27+
catch(
28+
op(500, xfy, [{}]),
29+
error(permission_error(create, operator, {}), _),
30+
true
31+
)
32+
)).
33+
34+
test("op_create_bar_priority_1000_should_error", (
35+
catch(
36+
op(1000, xfy, '|'),
37+
error(permission_error(create, operator, '|'), _),
38+
true
39+
)
40+
)).
41+
42+
test("op_create_bar_in_list_priority_1000_should_error", (
43+
catch(
44+
op(1000, xfy, ['|']),
45+
error(permission_error(create, operator, '|'), _),
46+
true
47+
)
48+
)).
49+
50+
test("op_create_bar_prefix_should_error", (
51+
catch(
52+
op(1150, fx, '|'),
53+
error(permission_error(create, operator, '|'), _),
54+
true
55+
)
56+
)).
57+
58+
test("op_create_bar_priority_1105_should_succeed", (
59+
op(1105, xfy, '|'),
60+
% Clean up
61+
op(0, xfy, '|')
62+
)).
63+
64+
test("op_remove_bar_should_succeed", (
65+
op(1105, xfy, '|'),
66+
op(0, xfy, '|')
67+
)).
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
args = ["-f", "--no-add-history", "src/tests/iso_syntax_errors.pl", "-f", "-g", "use_module(library(iso_syntax_errors_tests)), iso_syntax_errors_tests:main_quiet(iso_syntax_errors_tests)"]

0 commit comments

Comments
 (0)