Live data from Hacker News

Weird Lexical Syntax

justine.lol

211–220 of 234 posts

Re: Weird Lexical Syntax

#211
post #187
post #22

Some random things that the author seem to have missed: > but TypeScript, Swift, Kotlin, and Scala take string interpolation to the furthest extreme of encouraging actual code being embedded inside strings Many more languages support that: C# $"{x} plus {y} equals {x + y}" Python f"{x} plus {y} equals {x + y}" JavaScript `${x} plus ${y} equals ${x + y}` Ruby "#{x} plus #{y} equals #{x + y}" Shell "$x plus $y equals $…

Ruby takes this to 100. As much as a I love Ruby, this is valid Ruby, and I can't defend this: puts "This is #{ Just to combine the string interpolation with her concern over Ruby heredocs. My other favorite evil quirk in Ruby is that whitespace is a valid quote character in Ruby. The string (without the quotes) "% hello " is a quoted string containing "hello" (without the quotes), as "%" in contexts where there is n…

And don't overlook the fact that the bare-world, or its "HERE" friend, are still in an interpolation context, so...

    puts "hello #{
yields

  hello recursion is recursive world
  that was fun
and then there's its backtick friend

    puts "hello #{
coughs up

    hello Sun Nov  3 17:25:32 UTC 2024 world
and for those trying out your percent-space trick, be aware that it only tolerates such a thing in a standalone expression context so

  puts (% hello )+" world"
  # or
  x = % hello #
  puts x
because when I tried it "normally" I got

    $ /usr/bin/ruby -e 'puts % hello  + "world"'

    -e:1:in `': undefined local variable or method `hello' for main:Object (NameError)
    $ /usr/bin/ruby -v
    ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.x86_64-darwin21]
but, at the intersection is "ruby parsing is the 15th circle of hell"

    ruby -e 'puts (% #{

Re: Weird Lexical Syntax

#212
post #100

The author may have missed that lexing C is actually context-sensitive, i.e. you need a symbol table: https://en.wikipedia.org/wiki/Lexer_hack Of course, for syntax highlighting this is only relevant if you want to highlight the multiplication operator differently from the dereferencing operator, or declarations differently from expressions. More generally, however, I find it useful to highlight (say) types different…

> this is only relevant if you want to highlight the multiplication operator differently from the dereferencing operator Can you mention one editor which does that?

I could be stretching the definition of "does" but the newfound(?) tree-sitter support in Emacs[1] I believe would allow that since it for sure understands the distinction but I don't possess enough font-lock ninjary to actually, for real, bind a different color to the distinct usages

  /* given foo.c */
  int main() {
    int a, *b;
    a = 5 * 10;
    b = &a;
    printf("a is %d\n", *b);
  }
and then M-x c-ts-mode followed by navigating to each * and invoking M-x treesit-inspect-node-at-point in turn produces, respectively:

  (declaration declarator: (pointer_declarator "*"))

  right: (binary_expression operator: "*")

  arguments: (argument_list (pointer_expression operator: "*"))
1: https://www.emacswiki.org/emacs/Tree-sitter

Re: Weird Lexical Syntax

#213
post #100

The author may have missed that lexing C is actually context-sensitive, i.e. you need a symbol table: https://en.wikipedia.org/wiki/Lexer_hack Of course, for syntax highlighting this is only relevant if you want to highlight the multiplication operator differently from the dereferencing operator, or declarations differently from expressions. More generally, however, I find it useful to highlight (say) types different…

> this is only relevant if you want to highlight the multiplication operator differently from the dereferencing operator Can you mention one editor which does that?

hey

Re: Weird Lexical Syntax

#214
post #199
post #127

Earlier quoted context omitted.

> C certainly could have added support for nested comments at any time After C89 was ratified, adding nested comments to C would have risked breaking existing code. For instance, this is a valid program in C89: #include int main() { /* /* Comment */ printf("hello */ world"); return 0; } However, if a later C standard were to introduce nested comments, it would break the above program because then the following part o…

Given the neighboring thread where I just learned that the lexer runs before the preprocessor, I’m not sure that would be the outcome. There’s no reason to assume the comment terminator wouldn’t be ignored in strings. And even today, you can safely write printf(“hello // world\n”); without risking a compile error, right?

> Given the neighboring thread where I just learned that the lexer runs before the preprocessor, I’m not sure that would be the outcome.

That is precisely why nested comments would end up breaking the C89 code example I provided above. I elaborate this further below.

> There’s no reason to assume the comment terminator wouldn’t be ignored in strings.

There is no notion of "comment terminator in strings" in C. At any point of time, the lexer is reading either a string or a comment but never one within the other. For example, in C89, C99, etc., this is an invalid C program too:

  #include 

  int main() {
      /* Comment
      printf("hello */ world");
      return 0;
  }
In this case, we wouldn't say that the lexer is "honoring the comment terminator in a string" because, at the point the comment terminator '*/' is read, there is no active string. There is only a comment that looks like this:

      /* Comment
      printf("hello */
The double quotation mark within the comment is immaterial. It is simply part of the comment. Once the lexer has read the opening '/*', it looks for the terminating '*/'. This behaviour would hold even if future C standards were to allow nested comments, which is why nested comments would break the C89 example I mentioned in my earlier HN comment.

> And even today, you can safely write printf("hello // world\n"); without risking a compile error, right?

Right. But it is not clear what this has got to do with my concern that nested comments would break valid C89 programs. In this printf() example, we only have an ordinary string, so obviously this compiles fine. Once the lexer has read the opening quotation mark as the beginning of a string, it looks for an unescaped terminating quotation mark. So clearly, everything until the unescaped terminating quotation mark is a string!

Re: Weird Lexical Syntax

#215
post #154

Earlier quoted context omitted.

> Emacs Lisp Reference Manual, which cannot be generated from docstrings, because the organization of the source code is hopelessly inadequate for a reference manual. Well, they're not doing themselves any favors by just willy nilly mixing C with "user-facing" defuns https://emba.gnu.org/emacs/emacs/-/blob/ed1d691184df4b50da6b... >. I was curious if they could benefit from "literate programming" since OrgMode is the…

I didn't mean that specifically the Emacs source code was not organized in the right way for a reference manual. I meant that C and Java source code in general isn't. And C++, which is actually where people use Doxygen more. The Python standard library manual is also exemplary, and also necessarily organized differently from the source code.

> The Python standard library manual is also exemplary

Maybe parts of it are, but as a concrete example https://docs.python.org/3/library/re.html#re.match is just some YOLO about what, specifically, is the first argument to re.match: string, or compiled expression? Well, it's both! Huzzah! I guess they get points for consistency because the first argument to re.compile is also "both"

But, any idea what type re.compile returns? cause https://docs.python.org/3/library/re.html#re.compile is all "don't you worry about it" versus its re.match friend who goes out of their way to state that it is an re.Match object

Would it have been so hard to actually state it, versus requiring someone to invoke type() to get ?

Re: Weird Lexical Syntax

#216
post #154

Earlier quoted context omitted.

I didn't mean that specifically the Emacs source code was not organized in the right way for a reference manual. I meant that C and Java source code in general isn't. And C++, which is actually where people use Doxygen more. The Python standard library manual is also exemplary, and also necessarily organized differently from the source code.

> The Python standard library manual is also exemplary Maybe parts of it are, but as a concrete example https://docs.python.org/3/library/re.html#re.match is just some YOLO about what, specifically , is the first argument to re.match: string, or compiled expression? Well, it's both! Huzzah! I guess they get points for consistency because the first argument to re.compile is also "both" But, any idea what type re.compi…

I'm surprised to see that it's allowed to pass a compiled expression to re.match, since the regular expression object has a .match method of its own. To me the fact that the argument is called pattern implies that it's a string, because at the beginning of that chapter, it says, "Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). (...) Usually patterns will be expressed in Python code using this raw string notation."

But this ability to pass a compiled regexp rather than a string can't have been an accidental feature, so I don't know why it isn't documented.

Probably it would be good to have an example of invoking re.match with a literal string in the documentation item for re.match that you linked. There are sixteen such examples in the chapter, the first being re.match(r"(\w+) (\w+)", "Isaac Newton, physicist"), so you aren't going to be able to read much of the chapter without figuring out that you can pass a string there, but all sixteen of them come after that section. A useful example might be:

    >>> [s for s in ["", " ", "a ", " a", "aa"] if re.match(r'\w', s)]
    ['a ', 'aa']
It's easy to make manuals worse by adding too much text to them, but in this case I think a small example like that would be an improvement.

As for what type re.compile returns, the section you linked to says, "Compile a regular expression pattern into a regular expression object, which can be used for matching using its match(), search() and other methods, described below." Is your criticism that it doesn't explicitly say that the regular expression object is returned (as opposed to, I suppose, stored in a table somewhere), or that it says "a regular expression object" instead of saying "an re.Pattern object"? Because the words "regular expression object" are a link to the "Regular Expression Objects" section, which begins by saying, "class re.Pattern: Compiled regular expression object returned by re.compile()." To me the name of the class doesn't seem like it adds much value here—to write programs that work using the re module, you don't need to know the name of the class the regular expression objects belong to, just what interface they support.

(It's unfortunate that the class name is documented, because it would be better to rename it to a term that wasn't already defined to mean "a string that can be compiled to a regular expression object"!)

But possibly I've been using the re module long enough that I'm blind to the deficiencies in its documentation?

Anyway, I think documentation questions like this, about gradual introduction, forward references, sequencing, publicly documented (and thus stable) versus internal-only names, etc., are hard to reconcile with the constraints of source code, impossible in most languages. In this case the source code is divided between Python and C, adding difficulty.

Re: Weird Lexical Syntax

#217
post #22

Some random things that the author seem to have missed: > but TypeScript, Swift, Kotlin, and Scala take string interpolation to the furthest extreme of encouraging actual code being embedded inside strings Many more languages support that: C# $"{x} plus {y} equals {x + y}" Python f"{x} plus {y} equals {x + y}" JavaScript `${x} plus ${y} equals ${x + y}` Ruby "#{x} plus #{y} equals #{x + y}" Shell "$x plus $y equals $…

jq: "\("hello" + "world")!!"

I wish PG had dollar-bracket quoting where you have to use the closing bracket to close, that way vim showmatch would work trivially. Something like ${...}$.

Re: Weird Lexical Syntax

#218
post #209
post #187

Earlier quoted context omitted.

Ruby takes this to 100. As much as a I love Ruby, this is valid Ruby, and I can't defend this: puts "This is #{ Just to combine the string interpolation with her concern over Ruby heredocs. My other favorite evil quirk in Ruby is that whitespace is a valid quote character in Ruby. The string (without the quotes) "% hello " is a quoted string containing "hello" (without the quotes), as "%" in contexts where there is n…

https://pbs.twimg.com/media/GbEfj6fbQAQRUB7?format=png&name=... That's so going in the blog post later today.

Heh. I love Ruby, but, yes, the parser is "interesting", for values of interesting left undefined for its high obscenity content.

Re: Weird Lexical Syntax

#219
post #22

Some random things that the author seem to have missed: > but TypeScript, Swift, Kotlin, and Scala take string interpolation to the furthest extreme of encouraging actual code being embedded inside strings Many more languages support that: C# $"{x} plus {y} equals {x + y}" Python f"{x} plus {y} equals {x + y}" JavaScript `${x} plus ${y} equals ${x + y}` Ruby "#{x} plus #{y} equals #{x + y}" Shell "$x plus $y equals $…

Python f-strings are kind of wild. They can even contain comments! They also have slightly different rules for parsing certain kinds of expressions, like := and lambdas. And until fairly recently, strings inside the expressions couldn't use the quote type of the f-string itself (or backslashes).
Post reply on HN