зеркало из https://github.com/github/ruby.git
[ruby/yarp] Extract error messages into diagnostic.c and use canonical message IDs
The parser now passes around `yp_diagnostic_id_t` for diagnostic messages instead of character strings, and we rely on the function `diagnostic_message()` to resolve that to a string. In addition, many messages were edited so that the parser expresses coordinate ideas in similar form [1] using consistent voice and typographic conventions. Closes https://github.com/ruby/yarp/pull/1379, and makes progress on #941. [1] Strunk & White rule 19 https://github.com/ruby/yarp/commit/0b6dd85bf1
This commit is contained in:
Родитель
2d37b44603
Коммит
4efcaf956e
|
@ -8,8 +8,8 @@ module YARP
|
|||
|
||||
def test_constant_path_with_invalid_token_after
|
||||
assert_error_messages "A::$b", [
|
||||
"Expected identifier or constant after '::'",
|
||||
"Expected a newline or semicolon after statement."
|
||||
"Expected a constant after the `::` operator",
|
||||
"Expected a newline or semicolon after the statement"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -26,7 +26,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "module Parent module end", [
|
||||
["Expected to find a module name after `module`.", 20..20]
|
||||
["Expected a constant name after `module`", 20..20]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -42,7 +42,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "for in 1..10\ni\nend", [
|
||||
["Expected index after for.", 0..0]
|
||||
["Expected an index after `for`", 0..0]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -58,9 +58,9 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "for end", [
|
||||
["Expected index after for.", 0..0],
|
||||
["Expected keyword in.", 3..3],
|
||||
["Expected collection.", 3..3]
|
||||
["Expected an index after `for`", 0..0],
|
||||
["Expected an `in` after the index in a `for` statement", 3..3],
|
||||
["Expected a collection after the `in` in a `for` statement", 3..3]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -73,7 +73,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "BEGIN 1 }", [
|
||||
["Expected '{' after 'BEGIN'.", 5..5]
|
||||
["Expected a `{` after `BEGIN`", 5..5]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -98,37 +98,37 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "BEGIN { 1 + }", [
|
||||
["Expected a value after the operator.", 11..11]
|
||||
["Expected an expression after the operator", 11..11]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_embdoc
|
||||
assert_errors expression("1"), "1\n=begin\n", [
|
||||
["Unterminated embdoc", 2..9]
|
||||
["Could not find a terminator for the embedded document", 2..9]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_i_list
|
||||
assert_errors expression("%i["), "%i[", [
|
||||
["Expected a closing delimiter for a `%i` list.", 3..3]
|
||||
["Expected a closing delimiter for the `%i` list", 3..3]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_w_list
|
||||
assert_errors expression("%w["), "%w[", [
|
||||
["Expected a closing delimiter for a `%w` list.", 3..3]
|
||||
["Expected a closing delimiter for the `%w` list", 3..3]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_W_list
|
||||
assert_errors expression("%W["), "%W[", [
|
||||
["Expected a closing delimiter for a `%W` list.", 3..3]
|
||||
["Expected a closing delimiter for the `%W` list", 3..3]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_regular_expression
|
||||
assert_errors expression("/hello"), "/hello", [
|
||||
["Expected a closing delimiter for a regular expression.", 1..1]
|
||||
["Expected a closing delimiter for the regular expression", 1..1]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -136,178 +136,178 @@ module YARP
|
|||
source = "<<-END + /b\nEND\n"
|
||||
|
||||
assert_errors expression(source), source, [
|
||||
["Expected a closing delimiter for a regular expression.", 10..10]
|
||||
["Expected a closing delimiter for the regular expression", 10..10]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_xstring
|
||||
assert_errors expression("`hello"), "`hello", [
|
||||
["Expected a closing delimiter for an xstring.", 1..1]
|
||||
["Expected a closing delimiter for the `%x` or backtick string", 1..1]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_string
|
||||
assert_errors expression('"hello'), '"hello', [
|
||||
["Expected a closing delimiter for an interpolated string.", 1..1]
|
||||
["Expected a closing delimiter for the interpolated string", 1..1]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_s_symbol
|
||||
assert_errors expression("%s[abc"), "%s[abc", [
|
||||
["Expected a closing delimiter for a dynamic symbol.", 3..3]
|
||||
["Expected a closing delimiter for the dynamic symbol", 3..3]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_parenthesized_expression
|
||||
assert_errors expression('(1 + 2'), '(1 + 2', [
|
||||
["Expected to be able to parse an expression.", 6..6],
|
||||
["Expected a closing parenthesis.", 6..6]
|
||||
["Cannot parse the expression", 6..6],
|
||||
["Expected a matching `)`", 6..6]
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_argument_expression
|
||||
assert_errors expression('a %'), 'a %', [
|
||||
["Unexpected end of input", 2..3],
|
||||
["Expected a value after the operator.", 3..3],
|
||||
["Invalid `%` token", 2..3],
|
||||
["Expected an expression after the operator", 3..3],
|
||||
]
|
||||
end
|
||||
|
||||
def test_cr_without_lf_in_percent_expression
|
||||
assert_errors expression("%\r"), "%\r", [
|
||||
["Invalid %% token", 0..2],
|
||||
["Invalid `%` token", 0..2],
|
||||
]
|
||||
end
|
||||
|
||||
def test_1_2_3
|
||||
assert_errors expression("(1, 2, 3)"), "(1, 2, 3)", [
|
||||
["Expected to be able to parse an expression.", 2..2],
|
||||
["Expected a closing parenthesis.", 2..2],
|
||||
["Expected a newline or semicolon after statement.", 2..2],
|
||||
["Expected to be able to parse an expression.", 2..2],
|
||||
["Expected a newline or semicolon after statement.", 5..5],
|
||||
["Expected to be able to parse an expression.", 5..5],
|
||||
["Expected a newline or semicolon after statement.", 8..8],
|
||||
["Expected to be able to parse an expression.", 8..8],
|
||||
["Cannot parse the expression", 2..2],
|
||||
["Expected a matching `)`", 2..2],
|
||||
["Expected a newline or semicolon after the statement", 2..2],
|
||||
["Cannot parse the expression", 2..2],
|
||||
["Expected a newline or semicolon after the statement", 5..5],
|
||||
["Cannot parse the expression", 5..5],
|
||||
["Expected a newline or semicolon after the statement", 8..8],
|
||||
["Cannot parse the expression", 8..8],
|
||||
]
|
||||
end
|
||||
|
||||
def test_return_1_2_3
|
||||
assert_error_messages "return(1, 2, 3)", [
|
||||
"Expected to be able to parse an expression.",
|
||||
"Expected a closing parenthesis.",
|
||||
"Expected a newline or semicolon after statement.",
|
||||
"Expected to be able to parse an expression."
|
||||
"Cannot parse the expression",
|
||||
"Expected a matching `)`",
|
||||
"Expected a newline or semicolon after the statement",
|
||||
"Cannot parse the expression",
|
||||
]
|
||||
end
|
||||
|
||||
def test_return_1
|
||||
assert_errors expression("return 1,;"), "return 1,;", [
|
||||
["Expected to be able to parse an argument.", 9..9]
|
||||
["Expected an argument", 9..9]
|
||||
]
|
||||
end
|
||||
|
||||
def test_next_1_2_3
|
||||
assert_errors expression("next(1, 2, 3)"), "next(1, 2, 3)", [
|
||||
["Expected to be able to parse an expression.", 6..6],
|
||||
["Expected a closing parenthesis.", 6..6],
|
||||
["Expected a newline or semicolon after statement.", 12..12],
|
||||
["Expected to be able to parse an expression.", 12..12]
|
||||
["Cannot parse the expression", 6..6],
|
||||
["Expected a matching `)`", 6..6],
|
||||
["Expected a newline or semicolon after the statement", 12..12],
|
||||
["Cannot parse the expression", 12..12],
|
||||
]
|
||||
end
|
||||
|
||||
def test_next_1
|
||||
assert_errors expression("next 1,;"), "next 1,;", [
|
||||
["Expected to be able to parse an argument.", 7..7]
|
||||
["Expected an argument", 7..7]
|
||||
]
|
||||
end
|
||||
|
||||
def test_break_1_2_3
|
||||
assert_errors expression("break(1, 2, 3)"), "break(1, 2, 3)", [
|
||||
["Expected to be able to parse an expression.", 7..7],
|
||||
["Expected a closing parenthesis.", 7..7],
|
||||
["Expected a newline or semicolon after statement.", 13..13],
|
||||
["Expected to be able to parse an expression.", 13..13],
|
||||
["Cannot parse the expression", 7..7],
|
||||
["Expected a matching `)`", 7..7],
|
||||
["Expected a newline or semicolon after the statement", 13..13],
|
||||
["Cannot parse the expression", 13..13],
|
||||
]
|
||||
end
|
||||
|
||||
def test_break_1
|
||||
assert_errors expression("break 1,;"), "break 1,;", [
|
||||
["Expected to be able to parse an argument.", 8..8]
|
||||
["Expected an argument", 8..8]
|
||||
]
|
||||
end
|
||||
|
||||
def test_argument_forwarding_when_parent_is_not_forwarding
|
||||
assert_errors expression('def a(x, y, z); b(...); end'), 'def a(x, y, z); b(...); end', [
|
||||
["unexpected ... when parent method is not forwarding.", 18..21]
|
||||
["Unexpected `...` when the parent method is not forwarding", 18..21]
|
||||
]
|
||||
end
|
||||
|
||||
def test_argument_forwarding_only_effects_its_own_internals
|
||||
assert_errors expression('def a(...); b(...); end; def c(x, y, z); b(...); end'),
|
||||
'def a(...); b(...); end; def c(x, y, z); b(...); end', [
|
||||
["unexpected ... when parent method is not forwarding.", 43..46]
|
||||
["Unexpected `...` when the parent method is not forwarding", 43..46]
|
||||
]
|
||||
end
|
||||
|
||||
def test_top_level_constant_with_downcased_identifier
|
||||
assert_error_messages "::foo", [
|
||||
"Expected a constant after ::.",
|
||||
"Expected a newline or semicolon after statement."
|
||||
"Expected a constant after the `::` operator",
|
||||
"Expected a newline or semicolon after the statement"
|
||||
]
|
||||
end
|
||||
|
||||
def test_top_level_constant_starting_with_downcased_identifier
|
||||
assert_error_messages "::foo::A", [
|
||||
"Expected a constant after ::.",
|
||||
"Expected a newline or semicolon after statement."
|
||||
"Expected a constant after the `::` operator",
|
||||
"Expected a newline or semicolon after the statement"
|
||||
]
|
||||
end
|
||||
|
||||
def test_aliasing_global_variable_with_non_global_variable
|
||||
assert_errors expression("alias $a b"), "alias $a b", [
|
||||
["Expected a global variable.", 9..10]
|
||||
["Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 9..10]
|
||||
]
|
||||
end
|
||||
|
||||
def test_aliasing_non_global_variable_with_global_variable
|
||||
assert_errors expression("alias a $b"), "alias a $b", [
|
||||
["Expected a bare word or symbol argument.", 8..10]
|
||||
["Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 8..10]
|
||||
]
|
||||
end
|
||||
|
||||
def test_aliasing_global_variable_with_global_number_variable
|
||||
assert_errors expression("alias $a $1"), "alias $a $1", [
|
||||
["Can't make alias for number variables.", 9..11]
|
||||
["Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 9..11]
|
||||
]
|
||||
end
|
||||
|
||||
def test_def_with_expression_receiver_and_no_identifier
|
||||
assert_errors expression("def (a); end"), "def (a); end", [
|
||||
["Expected '.' or '::' after receiver", 7..7]
|
||||
["Expected a `.` or `::` after the receiver in a method definition", 7..7]
|
||||
]
|
||||
end
|
||||
|
||||
def test_def_with_multiple_statements_receiver
|
||||
assert_errors expression("def (\na\nb\n).c; end"), "def (\na\nb\n).c; end", [
|
||||
["Expected closing ')' for receiver.", 7..7],
|
||||
["Expected '.' or '::' after receiver", 7..7],
|
||||
["Expected to be able to parse an expression.", 10..10],
|
||||
["Expected to be able to parse an expression.", 11..11]
|
||||
["Expected a matching `)`", 7..7],
|
||||
["Expected a `.` or `::` after the receiver in a method definition", 7..7],
|
||||
["Cannot parse the expression", 10..10],
|
||||
["Cannot parse the expression", 11..11]
|
||||
]
|
||||
end
|
||||
|
||||
def test_def_with_empty_expression_receiver
|
||||
assert_errors expression("def ().a; end"), "def ().a; end", [
|
||||
["Expected to be able to parse receiver.", 5..5]
|
||||
["Expected a receiver for the method definition", 5..5]
|
||||
]
|
||||
end
|
||||
|
||||
def test_block_beginning_with_brace_and_ending_with_end
|
||||
assert_error_messages "x.each { x end", [
|
||||
"Expected a newline or semicolon after statement.",
|
||||
"Expected to be able to parse an expression.",
|
||||
"Expected to be able to parse an expression.",
|
||||
"Expected block beginning with '{' to end with '}'."
|
||||
"Expected a newline or semicolon after the statement",
|
||||
"Cannot parse the expression",
|
||||
"Cannot parse the expression",
|
||||
"Expected a block beginning with `{` to end with `}`"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -328,7 +328,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "a(**kwargs, *args)", [
|
||||
["Unexpected splat argument after double splat.", 12..17]
|
||||
["Unexpected `*` splat argument after a `**` keyword splat argument", 12..17]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -349,15 +349,15 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "a(&block, foo)", [
|
||||
["Unexpected argument after block argument.", 10..13]
|
||||
["Unexpected argument after a block argument", 10..13]
|
||||
]
|
||||
end
|
||||
|
||||
def test_arguments_binding_power_for_and
|
||||
assert_error_messages "foo(*bar and baz)", [
|
||||
"Expected a ')' to close the argument list.",
|
||||
"Expected a newline or semicolon after statement.",
|
||||
"Expected to be able to parse an expression."
|
||||
"Expected a `)` to close the arguments",
|
||||
"Expected a newline or semicolon after the statement",
|
||||
"Cannot parse the expression"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -384,7 +384,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "a(foo: bar, *args)", [
|
||||
["Unexpected splat argument after double splat.", 12..17]
|
||||
["Unexpected `*` splat argument after a `**` keyword splat argument", 12..17]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -405,7 +405,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo;module A;end;end", [
|
||||
["Module definition in method body", 8..14]
|
||||
["Unexpected module definition in a method body", 8..14]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -443,7 +443,7 @@ module YARP
|
|||
Location()
|
||||
)
|
||||
|
||||
assert_errors expected, <<~RUBY, [["Module definition in method body", 21..27]]
|
||||
assert_errors expected, <<~RUBY, [["Unexpected module definition in a method body", 21..27]]
|
||||
def foo
|
||||
bar do
|
||||
module Foo;end
|
||||
|
@ -480,7 +480,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo;class A;end;end", [
|
||||
["Class definition in method body", 8..13]
|
||||
["Unexpected class definition in a method body", 8..13]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -506,10 +506,10 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(A, @a, $A, @@a);end", [
|
||||
["Formal argument cannot be a constant", 8..9],
|
||||
["Formal argument cannot be an instance variable", 11..13],
|
||||
["Formal argument cannot be a global variable", 15..17],
|
||||
["Formal argument cannot be a class variable", 19..22],
|
||||
["Invalid formal argument; formal argument cannot be a constant", 8..9],
|
||||
["Invalid formal argument; formal argument cannot be an instance variable", 11..13],
|
||||
["Invalid formal argument; formal argument cannot be a global variable", 15..17],
|
||||
["Invalid formal argument; formal argument cannot be a class variable", 19..22],
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -540,15 +540,15 @@ module YARP
|
|||
end
|
||||
RUBY
|
||||
assert_errors expected, source, [
|
||||
["reserved for numbered parameter", 8..10],
|
||||
["reserved for numbered parameter", 14..16],
|
||||
["reserved for numbered parameter", 20..22],
|
||||
["reserved for numbered parameter", 26..28],
|
||||
["reserved for numbered parameter", 32..34],
|
||||
["reserved for numbered parameter", 40..42],
|
||||
["reserved for numbered parameter", 46..48],
|
||||
["reserved for numbered parameter", 52..54],
|
||||
["reserved for numbered parameter", 58..60],
|
||||
["Token reserved for a numbered parameter", 8..10],
|
||||
["Token reserved for a numbered parameter", 14..16],
|
||||
["Token reserved for a numbered parameter", 20..22],
|
||||
["Token reserved for a numbered parameter", 26..28],
|
||||
["Token reserved for a numbered parameter", 32..34],
|
||||
["Token reserved for a numbered parameter", 40..42],
|
||||
["Token reserved for a numbered parameter", 46..48],
|
||||
["Token reserved for a numbered parameter", 52..54],
|
||||
["Token reserved for a numbered parameter", 58..60],
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -577,7 +577,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(a,b,c,);end", [
|
||||
["Unexpected ','.", 13..14]
|
||||
["Unexpected `,` in parameters", 13..14]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -596,7 +596,7 @@ module YARP
|
|||
nil
|
||||
)
|
||||
assert_errors expected, "-> (a, b, ) {}", [
|
||||
["Unexpected ','.", 8..9]
|
||||
["Unexpected `,` in parameters", 8..9]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -604,13 +604,13 @@ module YARP
|
|||
expected = StringNode(Location(), Location(), nil, "\u0001\u0002")
|
||||
|
||||
assert_errors expected, '?\u{0001 0002}', [
|
||||
["Multiple codepoints at single character literal", 9..12]
|
||||
["Invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal", 9..12]
|
||||
]
|
||||
end
|
||||
|
||||
def test_invalid_hex_escape
|
||||
assert_errors expression('"\\xx"'), '"\\xx"', [
|
||||
["Invalid hex escape.", 1..3],
|
||||
["Invalid hexadecimal escape sequence", 1..3],
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -618,7 +618,7 @@ module YARP
|
|||
expected = StringNode(Location(), Location(), Location(), "\u0001")
|
||||
|
||||
assert_errors expected, '"\u{0000001}"', [
|
||||
["invalid Unicode escape.", 4..11],
|
||||
["Invalid Unicode escape sequence; maximum length is 6 digits", 4..11],
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -626,13 +626,13 @@ module YARP
|
|||
expected = StringNode(Location(), Location(), Location(), "\u0000z}")
|
||||
|
||||
assert_errors expected, '"\u{000z}"', [
|
||||
["unterminated Unicode escape", 7..7],
|
||||
["Invalid Unicode escape sequence", 7..7],
|
||||
]
|
||||
end
|
||||
|
||||
def test_unterminated_unicode_brackets_should_be_a_syntax_error
|
||||
assert_errors expression('?\\u{3'), '?\\u{3', [
|
||||
["invalid Unicode escape.", 1..5],
|
||||
["Invalid Unicode escape sequence; needs closing `}`", 1..5],
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -923,7 +923,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "case :a\nelse\nend", [
|
||||
["Unexpected else without no when clauses in case statement.", 8..12]
|
||||
["Unexpected `else` in `case` statement; a `when` clause must precede `else`", 8..12]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -944,7 +944,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def a=() = 42", [
|
||||
["Setter method cannot be defined in an endless method definition", 4..6]
|
||||
["Invalid method name; a setter method cannot be defined in an endless method definition", 4..6]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -959,7 +959,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "->(...) {}", [
|
||||
["Unexpected ...", 3..6]
|
||||
["Unexpected `...` when the parent method is not forwarding", 3..6]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -983,7 +983,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "a {|...|}", [
|
||||
["Unexpected ...", 4..7]
|
||||
["Unexpected `...` when the parent method is not forwarding", 4..7]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -1000,7 +1000,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "class A; return; end", [
|
||||
["Invalid return in class/module body", 15..16]
|
||||
["Invalid `return` in a class or module body", 15..16]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -1015,7 +1015,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "module A; return; end", [
|
||||
["Invalid return in class/module body", 16..17]
|
||||
["Invalid `return` in a class or module body", 16..17]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -1033,8 +1033,8 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "begin\n$+ = nil\n$1466 = nil\nend", [
|
||||
["Can't set variable", 6..8],
|
||||
["Can't set variable", 15..20]
|
||||
["Immutable variable as a write target", 6..8],
|
||||
["Immutable variable as a write target", 15..20]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -1058,7 +1058,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(a,b,a);end", [
|
||||
["Duplicated parameter name.", 12..13]
|
||||
["Repeated parameter name", 12..13]
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -1078,7 +1078,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(a,b,*a);end", [
|
||||
["Duplicated parameter name.", 13..14]
|
||||
["Repeated parameter name", 13..14]
|
||||
]
|
||||
|
||||
expected = DefNode(
|
||||
|
@ -1097,7 +1097,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(a,b,**a);end", [
|
||||
["Duplicated parameter name.", 14..15]
|
||||
["Repeated parameter name", 14..15]
|
||||
]
|
||||
|
||||
expected = DefNode(
|
||||
|
@ -1116,7 +1116,7 @@ module YARP
|
|||
)
|
||||
|
||||
assert_errors expected, "def foo(a,b,&a);end", [
|
||||
["Duplicated parameter name.", 13..14]
|
||||
["Repeated parameter name", 13..14]
|
||||
]
|
||||
|
||||
expected = DefNode(
|
||||
|
@ -1134,12 +1134,12 @@ module YARP
|
|||
Location()
|
||||
)
|
||||
|
||||
assert_errors expected, "def foo(a = 1,b,*c);end", [["Unexpected parameter *", 16..17]]
|
||||
assert_errors expected, "def foo(a = 1,b,*c);end", [["Unexpected parameter `*`", 16..17]]
|
||||
end
|
||||
|
||||
def test_unterminated_global_variable
|
||||
assert_errors expression("$"), "$", [
|
||||
["Invalid global variable.", 0..1]
|
||||
["Invalid global variable", 0..1]
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,264 @@
|
|||
#include "yarp/diagnostic.h"
|
||||
|
||||
/*
|
||||
## Message composition
|
||||
|
||||
When composing an error message, use sentence fragments.
|
||||
|
||||
Try describing the property of the code that caused the error, rather than the rule that is being
|
||||
violated. It may help to use a fragment that completes a sentence beginning, "The parser
|
||||
encountered (a) ...". If appropriate, add a description of the rule violation (or other helpful
|
||||
context) after a semicolon.
|
||||
|
||||
For example:, instead of "Control escape sequence cannot be doubled", prefer:
|
||||
|
||||
> "Invalid control escape sequence; control cannot be repeated"
|
||||
|
||||
In some cases, where the failure is more general or syntax expectations are violated, it may make
|
||||
more sense to use a fragment that completes a sentence beginning, "The parser ...".
|
||||
|
||||
For example:
|
||||
|
||||
> "Expected an expression after `(`"
|
||||
> "Cannot parse the expression"
|
||||
|
||||
|
||||
## Message style guide
|
||||
|
||||
- Use articles like "a", "an", and "the" when appropriate.
|
||||
- e.g., prefer "Cannot parse the expression" to "Cannot parse expression".
|
||||
- Use the common name for tokens and nodes.
|
||||
- e.g., prefer "keyword splat" to "assoc splat"
|
||||
- e.g., prefer "embedded document" to "embdoc"
|
||||
- Capitalize the initial word of the message.
|
||||
- Use back ticks around token literals
|
||||
- e.g., "Expected a `=>` between the hash key and value"
|
||||
- Do not use `.` or other punctuation at the end of the message.
|
||||
- Do not use contractions like "can't". Prefer "cannot" to "can not".
|
||||
- For tokens that can have multiple meanings, reference the token and its meaning.
|
||||
- e.g., "`*` splat argument" is clearer and more complete than "splat argument" or "`*` argument"
|
||||
|
||||
|
||||
## Error names (YP_ERR_*)
|
||||
|
||||
- When appropriate, prefer node name to token name.
|
||||
- e.g., prefer "SPLAT" to "STAR" in the context of argument parsing.
|
||||
- Prefer token name to common name.
|
||||
- e.g., prefer "STAR" to "ASTERISK".
|
||||
- Try to order the words in the name from more general to more specific,
|
||||
- e.g., "INVALID_NUMBER_DECIMAL" is better than "DECIMAL_INVALID_NUMBER".
|
||||
- When in doubt, look for similar patterns and name them so that they are grouped when lexically
|
||||
sorted. See YP_ERR_ARGUMENT_NO_FORWARDING_* for an example.
|
||||
*/
|
||||
|
||||
static const char* const diagnostic_messages[YP_DIAGNOSTIC_ID_LEN] = {
|
||||
[YP_ERR_ALIAS_ARGUMENT] = "Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable",
|
||||
[YP_ERR_AMPAMPEQ_MULTI_ASSIGN] = "Unexpected `&&=` in a multiple assignment",
|
||||
[YP_ERR_ARGUMENT_AFTER_BLOCK] = "Unexpected argument after a block argument",
|
||||
[YP_ERR_ARGUMENT_BARE_HASH] = "Unexpected bare hash argument",
|
||||
[YP_ERR_ARGUMENT_BLOCK_MULTI] = "Multiple block arguments; only one block is allowed",
|
||||
[YP_ERR_ARGUMENT_FORMAL_CLASS] = "Invalid formal argument; formal argument cannot be a class variable",
|
||||
[YP_ERR_ARGUMENT_FORMAL_CONSTANT] = "Invalid formal argument; formal argument cannot be a constant",
|
||||
[YP_ERR_ARGUMENT_FORMAL_GLOBAL] = "Invalid formal argument; formal argument cannot be a global variable",
|
||||
[YP_ERR_ARGUMENT_FORMAL_IVAR] = "Invalid formal argument; formal argument cannot be an instance variable",
|
||||
[YP_ERR_ARGUMENT_NO_FORWARDING_AMP] = "Unexpected `&` when the parent method is not forwarding",
|
||||
[YP_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = "Unexpected `...` when the parent method is not forwarding",
|
||||
[YP_ERR_ARGUMENT_NO_FORWARDING_STAR] = "Unexpected `*` when the parent method is not forwarding",
|
||||
[YP_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = "Unexpected `*` splat argument after a `**` keyword splat argument",
|
||||
[YP_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = "Unexpected `*` splat argument after a `*` splat argument",
|
||||
[YP_ERR_ARGUMENT_TERM_PAREN] = "Expected a `)` to close the arguments",
|
||||
[YP_ERR_ARRAY_ELEMENT] = "Expected an element for the array",
|
||||
[YP_ERR_ARRAY_EXPRESSION] = "Expected an expression for the array element",
|
||||
[YP_ERR_ARRAY_EXPRESSION_AFTER_STAR] = "Expected an expression after `*` in the array",
|
||||
[YP_ERR_ARRAY_SEPARATOR] = "Expected a `,` separator for the array elements",
|
||||
[YP_ERR_ARRAY_TERM] = "Expected a `]` to close the array",
|
||||
[YP_ERR_BEGIN_LONELY_ELSE] = "Unexpected `else` in `begin` block; a `rescue` clause must precede `else`",
|
||||
[YP_ERR_BEGIN_TERM] = "Expected an `end` to close the `begin` statement",
|
||||
[YP_ERR_BEGIN_UPCASE_BRACE] = "Expected a `{` after `BEGIN`",
|
||||
[YP_ERR_BEGIN_UPCASE_TERM] = "Expected a `}` to close the `BEGIN` statement",
|
||||
[YP_ERR_BLOCK_PARAM_LOCAL_VARIABLE] = "Expected a local variable name in the block parameters",
|
||||
[YP_ERR_BLOCK_PARAM_PIPE_TERM] = "Expected the block parameters to end with `|`",
|
||||
[YP_ERR_BLOCK_TERM_BRACE] = "Expected a block beginning with `{` to end with `}`",
|
||||
[YP_ERR_BLOCK_TERM_END] = "Expected a block beginning with `do` to end with `end`",
|
||||
[YP_ERR_CANNOT_PARSE_EXPRESSION] = "Cannot parse the expression",
|
||||
[YP_ERR_CANNOT_PARSE_STRING_PART] = "Cannot parse the string part",
|
||||
[YP_ERR_CASE_EXPRESSION_AFTER_CASE] = "Expected an expression after `case`",
|
||||
[YP_ERR_CASE_EXPRESSION_AFTER_WHEN] = "Expected an expression after `when`",
|
||||
[YP_ERR_CASE_LONELY_ELSE] = "Unexpected `else` in `case` statement; a `when` clause must precede `else`",
|
||||
[YP_ERR_CASE_TERM] = "Expected an `end` to close the `case` statement",
|
||||
[YP_ERR_CLASS_IN_METHOD] = "Unexpected class definition in a method body",
|
||||
[YP_ERR_CLASS_NAME] = "Expected a constant name after `class`",
|
||||
[YP_ERR_CLASS_SUPERCLASS] = "Expected a superclass after `<`",
|
||||
[YP_ERR_CLASS_TERM] = "Expected an `end` to close the `class` statement",
|
||||
[YP_ERR_CONDITIONAL_ELSIF_PREDICATE] = "Expected a predicate expression for the `elsif` statement",
|
||||
[YP_ERR_CONDITIONAL_IF_PREDICATE] = "Expected a predicate expression for the `if` statement",
|
||||
[YP_ERR_CONDITIONAL_TERM] = "Expected an `end` to close the conditional clause",
|
||||
[YP_ERR_CONDITIONAL_TERM_ELSE] = "Expected an `end` to close the `else` clause",
|
||||
[YP_ERR_CONDITIONAL_UNLESS_PREDICATE] = "Expected a predicate expression for the `unless` statement",
|
||||
[YP_ERR_CONDITIONAL_UNTIL_PREDICATE] = "Expected a predicate expression for the `until` statement",
|
||||
[YP_ERR_CONDITIONAL_WHILE_PREDICATE] = "Expected a predicate expression for the `while` statement",
|
||||
[YP_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = "Expected a constant after the `::` operator",
|
||||
[YP_ERR_DEF_ENDLESS] = "Could not parse the endless method body",
|
||||
[YP_ERR_DEF_ENDLESS_SETTER] = "Invalid method name; a setter method cannot be defined in an endless method definition",
|
||||
[YP_ERR_DEF_NAME] = "Expected a method name",
|
||||
[YP_ERR_DEF_NAME_AFTER_RECEIVER] = "Expected a method name after the receiver",
|
||||
[YP_ERR_DEF_PARAMS_TERM] = "Expected a delimiter to close the parameters",
|
||||
[YP_ERR_DEF_PARAMS_TERM_PAREN] = "Expected a `)` to close the parameters",
|
||||
[YP_ERR_DEF_RECEIVER] = "Expected a receiver for the method definition",
|
||||
[YP_ERR_DEF_RECEIVER_TERM] = "Expected a `.` or `::` after the receiver in a method definition",
|
||||
[YP_ERR_DEF_TERM] = "Expected an `end` to close the `def` statement",
|
||||
[YP_ERR_DEFINED_EXPRESSION] = "Expected an expression after `defined?`",
|
||||
[YP_ERR_EMBDOC_TERM] = "Could not find a terminator for the embedded document",
|
||||
[YP_ERR_EMBEXPR_END] = "Expected a `}` to close the embedded expression",
|
||||
[YP_ERR_EMBVAR_INVALID] = "Invalid embedded variable",
|
||||
[YP_ERR_END_UPCASE_BRACE] = "Expected a `{` after `END`",
|
||||
[YP_ERR_END_UPCASE_TERM] = "Expected a `}` to close the `END` statement",
|
||||
[YP_ERR_ESCAPE_INVALID_CONTROL] = "Invalid control escape sequence",
|
||||
[YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = "Invalid control escape sequence; control cannot be repeated",
|
||||
[YP_ERR_ESCAPE_INVALID_HEXADECIMAL] = "Invalid hexadecimal escape sequence",
|
||||
[YP_ERR_ESCAPE_INVALID_META] = "Invalid meta escape sequence",
|
||||
[YP_ERR_ESCAPE_INVALID_META_REPEAT] = "Invalid meta escape sequence; meta cannot be repeated",
|
||||
[YP_ERR_ESCAPE_INVALID_UNICODE] = "Invalid Unicode escape sequence",
|
||||
[YP_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = "Invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags",
|
||||
[YP_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = "Invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal",
|
||||
[YP_ERR_ESCAPE_INVALID_UNICODE_LONG] = "Invalid Unicode escape sequence; maximum length is 6 digits",
|
||||
[YP_ERR_ESCAPE_INVALID_UNICODE_TERM] = "Invalid Unicode escape sequence; needs closing `}`",
|
||||
[YP_ERR_EXPECT_ARGUMENT] = "Expected an argument",
|
||||
[YP_ERR_EXPECT_EOL_AFTER_STATEMENT] = "Expected a newline or semicolon after the statement",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = "Expected an expression after `&&=`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = "Expected an expression after `||=`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_COMMA] = "Expected an expression after `,`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = "Expected an expression after `=`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = "Expected an expression after `<<`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = "Expected an expression after `(`",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = "Expected an expression after the operator",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = "Expected an expression after `*` splat in an argument",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = "Expected an expression after `**` in a hash",
|
||||
[YP_ERR_EXPECT_EXPRESSION_AFTER_STAR] = "Expected an expression after `*`",
|
||||
[YP_ERR_EXPECT_IDENT_REQ_PARAMETER] = "Expected an identifier for the required parameter",
|
||||
[YP_ERR_EXPECT_LPAREN_REQ_PARAMETER] = "Expected a `(` to start a required parameter",
|
||||
[YP_ERR_EXPECT_RBRACKET] = "Expected a matching `]`",
|
||||
[YP_ERR_EXPECT_RPAREN] = "Expected a matching `)`",
|
||||
[YP_ERR_EXPECT_RPAREN_AFTER_MULTI] = "Expected a `)` after multiple assignment",
|
||||
[YP_ERR_EXPECT_RPAREN_REQ_PARAMETER] = "Expected a `)` to end a required parameter",
|
||||
[YP_ERR_EXPECT_STRING_CONTENT] = "Expected string content after opening string delimiter",
|
||||
[YP_ERR_EXPECT_WHEN_DELIMITER] = "Expected a delimiter after the predicates of a `when` clause",
|
||||
[YP_ERR_EXPRESSION_BARE_HASH] = "Unexpected bare hash in expression",
|
||||
[YP_ERR_FOR_COLLECTION] = "Expected a collection after the `in` in a `for` statement",
|
||||
[YP_ERR_FOR_INDEX] = "Expected an index after `for`",
|
||||
[YP_ERR_FOR_IN] = "Expected an `in` after the index in a `for` statement",
|
||||
[YP_ERR_FOR_TERM] = "Expected an `end` to close the `for` loop",
|
||||
[YP_ERR_HASH_EXPRESSION_AFTER_LABEL] = "Expected an expression after the label in a hash",
|
||||
[YP_ERR_HASH_KEY] = "Expected a key in the hash literal",
|
||||
[YP_ERR_HASH_ROCKET] = "Expected a `=>` between the hash key and value",
|
||||
[YP_ERR_HASH_TERM] = "Expected a `}` to close the hash literal",
|
||||
[YP_ERR_HASH_VALUE] = "Expected a value in the hash literal",
|
||||
[YP_ERR_HEREDOC_TERM] = "Could not find a terminator for the heredoc",
|
||||
[YP_ERR_INCOMPLETE_QUESTION_MARK] = "Incomplete expression at `?`",
|
||||
[YP_ERR_INCOMPLETE_VARIABLE_CLASS] = "Incomplete class variable",
|
||||
[YP_ERR_INCOMPLETE_VARIABLE_INSTANCE] = "Incomplete instance variable",
|
||||
[YP_ERR_INVALID_ENCODING_MAGIC_COMMENT] = "Unknown or invalid encoding in the magic comment",
|
||||
[YP_ERR_INVALID_FLOAT_EXPONENT] = "Invalid exponent",
|
||||
[YP_ERR_INVALID_NUMBER_BINARY] = "Invalid binary number",
|
||||
[YP_ERR_INVALID_NUMBER_DECIMAL] = "Invalid decimal number",
|
||||
[YP_ERR_INVALID_NUMBER_HEXADECIMAL] = "Invalid hexadecimal number",
|
||||
[YP_ERR_INVALID_NUMBER_OCTAL] = "Invalid octal number",
|
||||
[YP_ERR_INVALID_PERCENT] = "Invalid `%` token", // TODO WHAT?
|
||||
[YP_ERR_INVALID_TOKEN] = "Invalid token", // TODO WHAT?
|
||||
[YP_ERR_INVALID_VARIABLE_GLOBAL] = "Invalid global variable",
|
||||
[YP_ERR_LAMBDA_OPEN] = "Expected a `do` keyword or a `{` to open the lambda block",
|
||||
[YP_ERR_LAMBDA_TERM_BRACE] = "Expected a lambda block beginning with `{` to end with `}`",
|
||||
[YP_ERR_LAMBDA_TERM_END] = "Expected a lambda block beginning with `do` to end with `end`",
|
||||
[YP_ERR_LIST_I_LOWER_ELEMENT] = "Expected a symbol in a `%i` list",
|
||||
[YP_ERR_LIST_I_LOWER_TERM] = "Expected a closing delimiter for the `%i` list",
|
||||
[YP_ERR_LIST_I_UPPER_ELEMENT] = "Expected a symbol in a `%I` list",
|
||||
[YP_ERR_LIST_I_UPPER_TERM] = "Expected a closing delimiter for the `%I` list",
|
||||
[YP_ERR_LIST_W_LOWER_ELEMENT] = "Expected a string in a `%w` list",
|
||||
[YP_ERR_LIST_W_LOWER_TERM] = "Expected a closing delimiter for the `%w` list",
|
||||
[YP_ERR_LIST_W_UPPER_ELEMENT] = "Expected a string in a `%W` list",
|
||||
[YP_ERR_LIST_W_UPPER_TERM] = "Expected a closing delimiter for the `%W` list",
|
||||
[YP_ERR_MALLOC_FAILED] = "Failed to allocate memory",
|
||||
[YP_ERR_MODULE_IN_METHOD] = "Unexpected module definition in a method body",
|
||||
[YP_ERR_MODULE_NAME] = "Expected a constant name after `module`",
|
||||
[YP_ERR_MODULE_TERM] = "Expected an `end` to close the `module` statement",
|
||||
[YP_ERR_MULTI_ASSIGN_MULTI_SPLATS] = "Multiple splats in multiple assignment",
|
||||
[YP_ERR_NOT_EXPRESSION] = "Expected an expression after `not`",
|
||||
[YP_ERR_NUMBER_LITERAL_UNDERSCORE] = "Number literal ending with a `_`",
|
||||
[YP_ERR_OPERATOR_MULTI_ASSIGN] = "Unexpected operator for a multiple assignment",
|
||||
[YP_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = "Unexpected multiple `**` splat parameters",
|
||||
[YP_ERR_PARAMETER_BLOCK_MULTI] = "Multiple block parameters; only one block is allowed",
|
||||
[YP_ERR_PARAMETER_NAME_REPEAT] = "Repeated parameter name",
|
||||
[YP_ERR_PARAMETER_NO_DEFAULT] = "Expected a default value for the parameter",
|
||||
[YP_ERR_PARAMETER_NO_DEFAULT_KW] = "Expected a default value for the keyword parameter",
|
||||
[YP_ERR_PARAMETER_NUMBERED_RESERVED] = "Token reserved for a numbered parameter",
|
||||
[YP_ERR_PARAMETER_ORDER] = "Unexpected parameter order",
|
||||
[YP_ERR_PARAMETER_SPLAT_MULTI] = "Unexpected multiple `*` splat parameters",
|
||||
[YP_ERR_PARAMETER_STAR] = "Unexpected parameter `*`",
|
||||
[YP_ERR_PARAMETER_WILD_LOOSE_COMMA] = "Unexpected `,` in parameters",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = "Expected a pattern expression after the `[` operator",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = "Expected a pattern expression after `,`",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = "Expected a pattern expression after `=>`",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_IN] = "Expected a pattern expression after the `in` keyword",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_KEY] = "Expected a pattern expression after the key",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_PAREN] = "Expected a pattern expression after the `(` operator",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_PIN] = "Expected a pattern expression after the `^` pin operator",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = "Expected a pattern expression after the `|` operator",
|
||||
[YP_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = "Expected a pattern expression after the range operator",
|
||||
[YP_ERR_PATTERN_HASH_KEY] = "Expected a key in the hash pattern",
|
||||
[YP_ERR_PATTERN_HASH_KEY_LABEL] = "Expected a label as the key in the hash pattern", // TODO // THIS // AND // ABOVE // IS WEIRD
|
||||
[YP_ERR_PATTERN_IDENT_AFTER_HROCKET] = "Expected an identifier after the `=>` operator",
|
||||
[YP_ERR_PATTERN_LABEL_AFTER_COMMA] = "Expected a label after the `,` in the hash pattern",
|
||||
[YP_ERR_PATTERN_REST] = "Unexpected rest pattern",
|
||||
[YP_ERR_PATTERN_TERM_BRACE] = "Expected a `}` to close the pattern expression",
|
||||
[YP_ERR_PATTERN_TERM_BRACKET] = "Expected a `]` to close the pattern expression",
|
||||
[YP_ERR_PATTERN_TERM_PAREN] = "Expected a `)` to close the pattern expression",
|
||||
[YP_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = "Unexpected `||=` in a multiple assignment",
|
||||
[YP_ERR_REGEXP_TERM] = "Expected a closing delimiter for the regular expression",
|
||||
[YP_ERR_RESCUE_EXPRESSION] = "Expected a rescued expression",
|
||||
[YP_ERR_RESCUE_MODIFIER_VALUE] = "Expected a value after the `rescue` modifier",
|
||||
[YP_ERR_RESCUE_TERM] = "Expected a closing delimiter for the `rescue` clause",
|
||||
[YP_ERR_RESCUE_VARIABLE] = "Expected an exception variable after `=>` in a rescue statement",
|
||||
[YP_ERR_RETURN_INVALID] = "Invalid `return` in a class or module body",
|
||||
[YP_ERR_STRING_CONCATENATION] = "Expected a string for concatenation",
|
||||
[YP_ERR_STRING_INTERPOLATED_TERM] = "Expected a closing delimiter for the interpolated string",
|
||||
[YP_ERR_STRING_LITERAL_TERM] = "Expected a closing delimiter for the string literal",
|
||||
[YP_ERR_SYMBOL_INVALID] = "Invalid symbol", // TODO expected symbol? yarp.c ~9719
|
||||
[YP_ERR_SYMBOL_TERM_DYNAMIC] = "Expected a closing delimiter for the dynamic symbol",
|
||||
[YP_ERR_SYMBOL_TERM_INTERPOLATED] = "Expected a closing delimiter for the interpolated symbol",
|
||||
[YP_ERR_TERNARY_COLON] = "Expected a `:` after the true expression of a ternary operator",
|
||||
[YP_ERR_TERNARY_EXPRESSION_FALSE] = "Expected an expression after `:` in the ternary operator",
|
||||
[YP_ERR_TERNARY_EXPRESSION_TRUE] = "Expected an expression after `?` in the ternary operator",
|
||||
[YP_ERR_UNDEF_ARGUMENT] = "Invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument",
|
||||
[YP_ERR_UNARY_RECEIVER_BANG] = "Expected a receiver for unary `!`",
|
||||
[YP_ERR_UNARY_RECEIVER_MINUS] = "Expected a receiver for unary `-`",
|
||||
[YP_ERR_UNARY_RECEIVER_PLUS] = "Expected a receiver for unary `+`",
|
||||
[YP_ERR_UNARY_RECEIVER_TILDE] = "Expected a receiver for unary `~`",
|
||||
[YP_ERR_UNTIL_TERM] = "Expected an `end` to close the `until` statement",
|
||||
[YP_ERR_WHILE_TERM] = "Expected an `end` to close the `while` statement",
|
||||
[YP_ERR_WRITE_TARGET_READONLY] = "Immutable variable as a write target",
|
||||
[YP_ERR_WRITE_TARGET_UNEXPECTED] = "Unexpected write target",
|
||||
[YP_ERR_XSTRING_TERM] = "Expected a closing delimiter for the `%x` or backtick string",
|
||||
[YP_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = "Ambiguous first argument; put parentheses or a space even after `-` operator",
|
||||
[YP_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = "Ambiguous first argument; put parentheses or a space even after `+` operator",
|
||||
[YP_WARN_AMBIGUOUS_PREFIX_STAR] = "Ambiguous `*` has been interpreted as an argument prefix",
|
||||
[YP_WARN_AMBIGUOUS_SLASH] = "Ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator",
|
||||
};
|
||||
|
||||
static const char*
|
||||
yp_diagnostic_message(yp_diagnostic_id_t diag_id) {
|
||||
assert(diag_id < YP_DIAGNOSTIC_ID_LEN);
|
||||
const char *message = diagnostic_messages[diag_id];
|
||||
assert(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
// Append an error to the given list of diagnostic.
|
||||
bool
|
||||
yp_diagnostic_list_append(yp_list_t *list, const uint8_t *start, const uint8_t *end, const char *message) {
|
||||
yp_diagnostic_list_append(yp_list_t *list, const uint8_t *start, const uint8_t *end, yp_diagnostic_id_t diag_id) {
|
||||
yp_diagnostic_t *diagnostic = (yp_diagnostic_t *) malloc(sizeof(yp_diagnostic_t));
|
||||
if (diagnostic == NULL) return false;
|
||||
|
||||
*diagnostic = (yp_diagnostic_t) { .start = start, .end = end, .message = message };
|
||||
*diagnostic = (yp_diagnostic_t) { .start = start, .end = end, .message = yp_diagnostic_message(diag_id) };
|
||||
yp_list_append(list, (yp_list_node_t *) diagnostic);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
// This struct represents a diagnostic found during parsing.
|
||||
typedef struct {
|
||||
|
@ -15,8 +16,204 @@ typedef struct {
|
|||
const char *message;
|
||||
} yp_diagnostic_t;
|
||||
|
||||
typedef enum {
|
||||
YP_ERR_ALIAS_ARGUMENT,
|
||||
YP_ERR_AMPAMPEQ_MULTI_ASSIGN,
|
||||
YP_ERR_ARGUMENT_AFTER_BLOCK,
|
||||
YP_ERR_ARGUMENT_BARE_HASH,
|
||||
YP_ERR_ARGUMENT_BLOCK_MULTI,
|
||||
YP_ERR_ARGUMENT_FORMAL_CLASS,
|
||||
YP_ERR_ARGUMENT_FORMAL_CONSTANT,
|
||||
YP_ERR_ARGUMENT_FORMAL_GLOBAL,
|
||||
YP_ERR_ARGUMENT_FORMAL_IVAR,
|
||||
YP_ERR_ARGUMENT_NO_FORWARDING_AMP,
|
||||
YP_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
|
||||
YP_ERR_ARGUMENT_NO_FORWARDING_STAR,
|
||||
YP_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT,
|
||||
YP_ERR_ARGUMENT_SPLAT_AFTER_SPLAT,
|
||||
YP_ERR_ARGUMENT_TERM_PAREN,
|
||||
YP_ERR_ARRAY_ELEMENT,
|
||||
YP_ERR_ARRAY_EXPRESSION,
|
||||
YP_ERR_ARRAY_EXPRESSION_AFTER_STAR,
|
||||
YP_ERR_ARRAY_SEPARATOR,
|
||||
YP_ERR_ARRAY_TERM,
|
||||
YP_ERR_BEGIN_LONELY_ELSE,
|
||||
YP_ERR_BEGIN_TERM,
|
||||
YP_ERR_BEGIN_UPCASE_BRACE,
|
||||
YP_ERR_BEGIN_UPCASE_TERM,
|
||||
YP_ERR_BLOCK_PARAM_LOCAL_VARIABLE,
|
||||
YP_ERR_BLOCK_PARAM_PIPE_TERM,
|
||||
YP_ERR_BLOCK_TERM_BRACE,
|
||||
YP_ERR_BLOCK_TERM_END,
|
||||
YP_ERR_CANNOT_PARSE_EXPRESSION,
|
||||
YP_ERR_CANNOT_PARSE_STRING_PART,
|
||||
YP_ERR_CASE_EXPRESSION_AFTER_CASE,
|
||||
YP_ERR_CASE_EXPRESSION_AFTER_WHEN,
|
||||
YP_ERR_CASE_LONELY_ELSE,
|
||||
YP_ERR_CASE_TERM,
|
||||
YP_ERR_CLASS_IN_METHOD,
|
||||
YP_ERR_CLASS_NAME,
|
||||
YP_ERR_CLASS_SUPERCLASS,
|
||||
YP_ERR_CLASS_TERM,
|
||||
YP_ERR_CONDITIONAL_ELSIF_PREDICATE,
|
||||
YP_ERR_CONDITIONAL_IF_PREDICATE,
|
||||
YP_ERR_CONDITIONAL_TERM,
|
||||
YP_ERR_CONDITIONAL_TERM_ELSE,
|
||||
YP_ERR_CONDITIONAL_UNLESS_PREDICATE,
|
||||
YP_ERR_CONDITIONAL_UNTIL_PREDICATE,
|
||||
YP_ERR_CONDITIONAL_WHILE_PREDICATE,
|
||||
YP_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT,
|
||||
YP_ERR_DEF_ENDLESS,
|
||||
YP_ERR_DEF_ENDLESS_SETTER,
|
||||
YP_ERR_DEF_NAME,
|
||||
YP_ERR_DEF_NAME_AFTER_RECEIVER,
|
||||
YP_ERR_DEF_PARAMS_TERM,
|
||||
YP_ERR_DEF_PARAMS_TERM_PAREN,
|
||||
YP_ERR_DEF_RECEIVER,
|
||||
YP_ERR_DEF_RECEIVER_TERM,
|
||||
YP_ERR_DEF_TERM,
|
||||
YP_ERR_DEFINED_EXPRESSION,
|
||||
YP_ERR_EMBDOC_TERM,
|
||||
YP_ERR_EMBEXPR_END,
|
||||
YP_ERR_EMBVAR_INVALID,
|
||||
YP_ERR_END_UPCASE_BRACE,
|
||||
YP_ERR_END_UPCASE_TERM,
|
||||
YP_ERR_ESCAPE_INVALID_CONTROL,
|
||||
YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT,
|
||||
YP_ERR_ESCAPE_INVALID_HEXADECIMAL,
|
||||
YP_ERR_ESCAPE_INVALID_META,
|
||||
YP_ERR_ESCAPE_INVALID_META_REPEAT,
|
||||
YP_ERR_ESCAPE_INVALID_UNICODE,
|
||||
YP_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS,
|
||||
YP_ERR_ESCAPE_INVALID_UNICODE_LITERAL,
|
||||
YP_ERR_ESCAPE_INVALID_UNICODE_LONG,
|
||||
YP_ERR_ESCAPE_INVALID_UNICODE_TERM,
|
||||
YP_ERR_EXPECT_ARGUMENT,
|
||||
YP_ERR_EXPECT_EOL_AFTER_STATEMENT,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_COMMA,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_EQUAL,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_LPAREN,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_QUESTION,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_SPLAT,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH,
|
||||
YP_ERR_EXPECT_EXPRESSION_AFTER_STAR,
|
||||
YP_ERR_EXPECT_IDENT_REQ_PARAMETER,
|
||||
YP_ERR_EXPECT_LPAREN_REQ_PARAMETER,
|
||||
YP_ERR_EXPECT_RBRACKET,
|
||||
YP_ERR_EXPECT_RPAREN,
|
||||
YP_ERR_EXPECT_RPAREN_AFTER_MULTI,
|
||||
YP_ERR_EXPECT_RPAREN_REQ_PARAMETER,
|
||||
YP_ERR_EXPECT_STRING_CONTENT,
|
||||
YP_ERR_EXPECT_WHEN_DELIMITER,
|
||||
YP_ERR_EXPRESSION_BARE_HASH,
|
||||
YP_ERR_FOR_COLLECTION,
|
||||
YP_ERR_FOR_IN,
|
||||
YP_ERR_FOR_INDEX,
|
||||
YP_ERR_FOR_TERM,
|
||||
YP_ERR_HASH_EXPRESSION_AFTER_LABEL,
|
||||
YP_ERR_HASH_KEY,
|
||||
YP_ERR_HASH_ROCKET,
|
||||
YP_ERR_HASH_TERM,
|
||||
YP_ERR_HASH_VALUE,
|
||||
YP_ERR_HEREDOC_TERM,
|
||||
YP_ERR_INCOMPLETE_QUESTION_MARK,
|
||||
YP_ERR_INCOMPLETE_VARIABLE_CLASS,
|
||||
YP_ERR_INCOMPLETE_VARIABLE_INSTANCE,
|
||||
YP_ERR_INVALID_ENCODING_MAGIC_COMMENT,
|
||||
YP_ERR_INVALID_FLOAT_EXPONENT,
|
||||
YP_ERR_INVALID_NUMBER_BINARY,
|
||||
YP_ERR_INVALID_NUMBER_DECIMAL,
|
||||
YP_ERR_INVALID_NUMBER_HEXADECIMAL,
|
||||
YP_ERR_INVALID_NUMBER_OCTAL,
|
||||
YP_ERR_INVALID_PERCENT,
|
||||
YP_ERR_INVALID_TOKEN,
|
||||
YP_ERR_INVALID_VARIABLE_GLOBAL,
|
||||
YP_ERR_LAMBDA_OPEN,
|
||||
YP_ERR_LAMBDA_TERM_BRACE,
|
||||
YP_ERR_LAMBDA_TERM_END,
|
||||
YP_ERR_LIST_I_LOWER_ELEMENT,
|
||||
YP_ERR_LIST_I_LOWER_TERM,
|
||||
YP_ERR_LIST_I_UPPER_ELEMENT,
|
||||
YP_ERR_LIST_I_UPPER_TERM,
|
||||
YP_ERR_LIST_W_LOWER_ELEMENT,
|
||||
YP_ERR_LIST_W_LOWER_TERM,
|
||||
YP_ERR_LIST_W_UPPER_ELEMENT,
|
||||
YP_ERR_LIST_W_UPPER_TERM,
|
||||
YP_ERR_MALLOC_FAILED,
|
||||
YP_ERR_MODULE_IN_METHOD,
|
||||
YP_ERR_MODULE_NAME,
|
||||
YP_ERR_MODULE_TERM,
|
||||
YP_ERR_MULTI_ASSIGN_MULTI_SPLATS,
|
||||
YP_ERR_NOT_EXPRESSION,
|
||||
YP_ERR_NUMBER_LITERAL_UNDERSCORE,
|
||||
YP_ERR_OPERATOR_MULTI_ASSIGN,
|
||||
YP_ERR_PARAMETER_ASSOC_SPLAT_MULTI,
|
||||
YP_ERR_PARAMETER_BLOCK_MULTI,
|
||||
YP_ERR_PARAMETER_NAME_REPEAT,
|
||||
YP_ERR_PARAMETER_NO_DEFAULT,
|
||||
YP_ERR_PARAMETER_NO_DEFAULT_KW,
|
||||
YP_ERR_PARAMETER_NUMBERED_RESERVED,
|
||||
YP_ERR_PARAMETER_ORDER,
|
||||
YP_ERR_PARAMETER_SPLAT_MULTI,
|
||||
YP_ERR_PARAMETER_STAR,
|
||||
YP_ERR_PARAMETER_WILD_LOOSE_COMMA,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_BRACKET,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_HROCKET,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_COMMA,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_IN,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_KEY,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_PAREN,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_PIN,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_PIPE,
|
||||
YP_ERR_PATTERN_EXPRESSION_AFTER_RANGE,
|
||||
YP_ERR_PATTERN_HASH_KEY,
|
||||
YP_ERR_PATTERN_HASH_KEY_LABEL,
|
||||
YP_ERR_PATTERN_IDENT_AFTER_HROCKET,
|
||||
YP_ERR_PATTERN_LABEL_AFTER_COMMA,
|
||||
YP_ERR_PATTERN_REST,
|
||||
YP_ERR_PATTERN_TERM_BRACE,
|
||||
YP_ERR_PATTERN_TERM_BRACKET,
|
||||
YP_ERR_PATTERN_TERM_PAREN,
|
||||
YP_ERR_PIPEPIPEEQ_MULTI_ASSIGN,
|
||||
YP_ERR_REGEXP_TERM,
|
||||
YP_ERR_RESCUE_EXPRESSION,
|
||||
YP_ERR_RESCUE_MODIFIER_VALUE,
|
||||
YP_ERR_RESCUE_TERM,
|
||||
YP_ERR_RESCUE_VARIABLE,
|
||||
YP_ERR_RETURN_INVALID,
|
||||
YP_ERR_STRING_CONCATENATION,
|
||||
YP_ERR_STRING_INTERPOLATED_TERM,
|
||||
YP_ERR_STRING_LITERAL_TERM,
|
||||
YP_ERR_SYMBOL_INVALID,
|
||||
YP_ERR_SYMBOL_TERM_DYNAMIC,
|
||||
YP_ERR_SYMBOL_TERM_INTERPOLATED,
|
||||
YP_ERR_TERNARY_COLON,
|
||||
YP_ERR_TERNARY_EXPRESSION_FALSE,
|
||||
YP_ERR_TERNARY_EXPRESSION_TRUE,
|
||||
YP_ERR_UNDEF_ARGUMENT,
|
||||
YP_ERR_UNARY_RECEIVER_BANG,
|
||||
YP_ERR_UNARY_RECEIVER_MINUS,
|
||||
YP_ERR_UNARY_RECEIVER_PLUS,
|
||||
YP_ERR_UNARY_RECEIVER_TILDE,
|
||||
YP_ERR_UNTIL_TERM,
|
||||
YP_ERR_WHILE_TERM,
|
||||
YP_ERR_WRITE_TARGET_READONLY,
|
||||
YP_ERR_WRITE_TARGET_UNEXPECTED,
|
||||
YP_ERR_XSTRING_TERM,
|
||||
YP_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS,
|
||||
YP_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS,
|
||||
YP_WARN_AMBIGUOUS_PREFIX_STAR,
|
||||
YP_WARN_AMBIGUOUS_SLASH,
|
||||
/* This must be the last member. */
|
||||
YP_DIAGNOSTIC_ID_LEN,
|
||||
} yp_diagnostic_id_t;
|
||||
|
||||
// Append a diagnostic to the given list of diagnostics.
|
||||
bool yp_diagnostic_list_append(yp_list_t *list, const uint8_t *start, const uint8_t *end, const char *message);
|
||||
bool yp_diagnostic_list_append(yp_list_t *list, const uint8_t *start, const uint8_t *end, yp_diagnostic_id_t diag_id);
|
||||
|
||||
// Deallocate the internal state of the given diagnostic list.
|
||||
void yp_diagnostic_list_free(yp_list_t *list);
|
||||
|
|
|
@ -94,7 +94,7 @@ static inline size_t
|
|||
unescape_hexadecimal(const uint8_t *backslash, uint8_t *value, const uint8_t *end, yp_list_t *error_list) {
|
||||
*value = 0;
|
||||
if (backslash + 2 >= end || !yp_char_is_hexadecimal_digit(backslash[2])) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid hex escape.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_HEXADECIMAL);
|
||||
return 2;
|
||||
}
|
||||
*value = unescape_hexadecimal_digit(backslash[2]);
|
||||
|
@ -157,7 +157,7 @@ unescape_unicode_write(uint8_t *dest, uint32_t value, const uint8_t *start, cons
|
|||
// If we get here, then the value is too big. This is an error, but we don't
|
||||
// want to just crash, so instead we'll add an error to the error list and put
|
||||
// in a replacement character instead.
|
||||
if (error_list) yp_diagnostic_list_append(error_list, start, end, "Invalid Unicode escape sequence.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, start, end, YP_ERR_ESCAPE_INVALID_UNICODE);
|
||||
dest[0] = 0xEF;
|
||||
dest[1] = 0xBF;
|
||||
dest[2] = 0xBD;
|
||||
|
@ -235,7 +235,7 @@ unescape(
|
|||
// \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
|
||||
case 'u': {
|
||||
if ((flags & YP_UNESCAPE_FLAG_CONTROL) | (flags & YP_UNESCAPE_FLAG_META)) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Unicode escape sequence cannot be used with control or meta flags.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -252,11 +252,11 @@ unescape(
|
|||
|
||||
// \u{nnnn} character literal allows only 1-6 hexadecimal digits
|
||||
if (hexadecimal_length > 6) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "invalid Unicode escape.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, YP_ERR_ESCAPE_INVALID_UNICODE_LONG);
|
||||
}
|
||||
// there are not hexadecimal characters
|
||||
else if (hexadecimal_length == 0) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "unterminated Unicode escape");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, YP_ERR_ESCAPE_INVALID_UNICODE);
|
||||
return unicode_cursor;
|
||||
}
|
||||
|
||||
|
@ -277,13 +277,13 @@ unescape(
|
|||
|
||||
// ?\u{nnnn} character literal should contain only one codepoint and cannot be like ?\u{nnnn mmmm}
|
||||
if (flags & YP_UNESCAPE_FLAG_EXPECT_SINGLE && codepoints_count > 1) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, extra_codepoints_start, unicode_cursor - 1, "Multiple codepoints at single character literal");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, extra_codepoints_start, unicode_cursor - 1, YP_ERR_ESCAPE_INVALID_UNICODE_LITERAL);
|
||||
}
|
||||
|
||||
if (unicode_cursor < end && *unicode_cursor == '}') {
|
||||
unicode_cursor++;
|
||||
} else {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, unicode_cursor, "invalid Unicode escape.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, unicode_cursor, YP_ERR_ESCAPE_INVALID_UNICODE_TERM);
|
||||
}
|
||||
|
||||
return unicode_cursor;
|
||||
|
@ -298,7 +298,7 @@ unescape(
|
|||
return backslash + 6;
|
||||
}
|
||||
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid Unicode escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_UNICODE);
|
||||
return backslash + 2;
|
||||
}
|
||||
// \c\M-x meta control character, where x is an ASCII printable character
|
||||
|
@ -306,12 +306,12 @@ unescape(
|
|||
// \cx control character, where x is an ASCII printable character
|
||||
case 'c':
|
||||
if (backslash + 2 >= end) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
||||
return end;
|
||||
}
|
||||
|
||||
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -325,7 +325,7 @@ unescape(
|
|||
return backslash + 3;
|
||||
default: {
|
||||
if (!char_is_ascii_printable(backslash[2])) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -339,17 +339,17 @@ unescape(
|
|||
// \C-? delete, ASCII 7Fh (DEL)
|
||||
case 'C':
|
||||
if (backslash + 3 >= end) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
||||
return end;
|
||||
}
|
||||
|
||||
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
if (backslash[2] != '-') {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_CONTROL);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@ unescape(
|
|||
return backslash + 4;
|
||||
default:
|
||||
if (!char_is_ascii_printable(backslash[3])) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_CONTROL);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -377,17 +377,17 @@ unescape(
|
|||
// \M-x meta character, where x is an ASCII printable character
|
||||
case 'M': {
|
||||
if (backslash + 3 >= end) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 1, YP_ERR_ESCAPE_INVALID_META);
|
||||
return end;
|
||||
}
|
||||
|
||||
if (flags & YP_UNESCAPE_FLAG_META) {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Meta escape sequence cannot be doubled.");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META_REPEAT);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
if (backslash[2] != '-') {
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META);
|
||||
return backslash + 2;
|
||||
}
|
||||
|
||||
|
@ -402,7 +402,7 @@ unescape(
|
|||
return backslash + 4;
|
||||
}
|
||||
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
||||
if (error_list) yp_diagnostic_list_append(error_list, backslash, backslash + 2, YP_ERR_ESCAPE_INVALID_META);
|
||||
return backslash + 3;
|
||||
}
|
||||
// \n
|
||||
|
@ -474,7 +474,7 @@ yp_unescape_manipulate_string_or_char_literal(yp_parser_t *parser, yp_string_t *
|
|||
// within the string.
|
||||
uint8_t *allocated = malloc(string->length);
|
||||
if (allocated == NULL) {
|
||||
yp_diagnostic_list_append(&parser->error_list, string->source, string->source + string->length, "Failed to allocate memory for unescaping.");
|
||||
yp_diagnostic_list_append(&parser->error_list, string->source, string->source + string->length, YP_ERR_MALLOC_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
608
yarp/yarp.c
608
yarp/yarp.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче