diff --git a/spec/examples/pipe b/spec/examples/pipe index 533a953ad..ab0726818 100644 --- a/spec/examples/pipe +++ b/spec/examples/pipe @@ -64,3 +64,15 @@ component Main { "" } } +------------------------------------------------------------------------------- +component Main { + fun test (value : String) { + value + } + + fun render : Html { + "test" |> test + +
+ } +} diff --git a/src/parser/top_level.cr b/src/parser/top_level.cr index ab8b69d57..50dcd5c3a 100644 --- a/src/parser/top_level.cr +++ b/src/parser/top_level.cr @@ -79,7 +79,6 @@ module Mint component || constant || property || - operator || provider || function || comment || diff --git a/src/parsers/operator.cr b/src/parsers/operator.cr index 49180d9e7..2e399137a 100644 --- a/src/parsers/operator.cr +++ b/src/parsers/operator.cr @@ -26,40 +26,63 @@ module Mint "!" => 16, } - # Parses an operator. - # - # All operators must follow a whitespace because we don't have an end of - # line token, so the expression can leak through to the next entity, for - # example: - # - # const NAME = "Joe" - # - # /* This is a comment. */ - # fun greet (name : String = NAME) { ... } - # - # In this case the start token of the comment (/*) can be interpreted as an - # operation (/) and the whitespace prevents that. def operator : String? - parse do + parse do |start_position| whitespace saved_position = position operator = - OPERATORS.keys.find { |item| word! item } + OPERATORS.keys.find { |item| word? item } next unless operator - next if operator != "|>" && !whitespace? + + case operator + when "<" + # If we are in a different line then left side then it's probably + # not a operation: + # + # Left side + # |---| + #
+ #
+ # | + # Potential operator + # + next if start_position.line < position.line + + # If the right side parses as a base expression: + # + # Left side Right side + # |---| |---| + #
+ # | + # Potential operator + # + next if parse { whitespace; base_expression } + + # This prevents the this to parse as a regexp literal: + # + # Start tag Variable Potential operator + # |---| |-------| | + #
variable
+ # | + # Regexp literal start + # + next if next_char == '/' + when "/" + # It's probably a comment (`// comment`, `/* comment */`) + next if next_char.in?('*', '/') + end + + word! operator case operator when "or" # This is not an operation but part of a statements - # "or return" section. - next if parse do - whitespace - keyword! "return" - end + # `or return` section. + next if parse { whitespace; keyword! "return" } ast.keywords << {from: saved_position, to: saved_position + operator.size} else