Wrong parsing with ANTLR4's C.g4 - antlr4

Edit: I've added this as an issue on ANTLR's github: https://github.com/antlr/grammars-v4/issues/95.
I'm parsing the following code using ANTLR version 4.3 and C.g4 taken from https://github.com/antlr/grammars-v4/blob/master/c/C.g4:
void bad()
{
foo(a);
}
The grammar interprets the foo(a) as declaration, but it should be a postfixExpression. I've pasted the wrong parse tree here.
It can be interpreted correctly by changing the order of declaration and statement in the blockItem rule. Does doing that break something else?

foo(a); is a valid declaration, foo a;, as well as expression. The C11 spec shows:
blockItem
: declaration
| statement
;
Which ANTLR interprets as resolving any ambiguities to the declaration. W/o symbol table information, this cannot be resolved. :(

Related

Why can a variable be formatted, but not an element of an array when using the println macro?

Say you have
let x: u8 = 1
println!("{x}");
this works fine; however, if you instead have
let x: [u8; 1] = [1];
println!("{x[0]}");
then it throws the error
error: invalid format string: expected `'}'`, found `'['
|
| println!("{x[0]}");
| - ^ expected `}` in format string
| |
| because of this opening brace
|
= note: if you intended to print `{`, you can escape it using `{{`
why is this?
The inline print functionality is only intended for variable names. To be honest though, I rarely see this syntax used though. Most people prefer println!("{}", x[0]) instead, and this is one of the main reasons why.
I can defiantly see where they were coming from though. The {:?} or {:X} syntax might look weird since the colon does not seem to have a use in these statements to print in debug or hexadecimal mode, but I suspect it was made to mirror fields in structs and function arguments. It starts to look more familiar when you write it with the inline variable and spacing: format!("{name: ?}"). Under this reasoning it makes more sense to only allow idents here (Token for an identity. Essentially the name of a variable/type/module/etc). But this didn't really materialize (if it ever even was a thing) so we don't have this syntax.
Personally, I think they could have made it work, but you would end up with confusion about how :? (and other format specifiers) work in regards to expressions. For example, if people are taught that {x.foo()} will print the display of the expression x.foo() then does that mean x.foo(): ? is also a valid expression? What about -3.0:3.0?? It kinda looks like a range in python, but I have just worded it in a confusing way.
Edit: Found the RFC for this: https://rust-lang.github.io/rfcs/1618-ergonomic-format-args.html
Edit 2: I found a Rust forum post which better addresses your question (https://internals.rust-lang.org/t/how-to-allow-arbitrary-expressions-in-format-strings/15812). Their reasoning is as follows:
Curly braces in format strings are escaped with curly braces: format!("{{foo}}") prints {foo}. If arbitrary expressions were supported, parsing this would become ambiguous.
It's ambiguous when type ascription is enabled: format!("{foo:X}") could mean either type ascription or that the UpperHex trait should be used.
The ? operator could be easily confused with Debug formatting: "{foo?}" and "{foo:?}" look very similar.

What $() syntax means for Groovy language?

I found this in Groovy Syntax documentation at 4.6.1. Special cases:
As slashy strings were mostly designed to make regexp easier so a few
things that are errors in GStrings like $() or $5 will work with
slashy strings.
What $() syntax means? give some usage examples please
I also found it at Define the Contract Locally in the Repository of the Fraud Detection Service:
body([ // (4)
"client.id": $(regex('[0-9]{10}')),
loanAmount : 99999
])
but I don't understand what $() means when used with regex('[0-9]{10}').
It means nothing (or what you make of it). There are two places, you
are addressing, but they have nothing to do with each other.
The docs just mention this as "you can use slashy strings to write
things, that would give you an error with a GString" - the same is true
for just using '-Strings.
E.g.
"hello $()"
Gives this error:
unknown recognition error type: groovyjarjarantlr4.v4.runtime.LexerNoViableAltException
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/tmp/x.groovy: 1: token recognition error at: '(' # line 1, column 9.
"hello $()"
The parser either wants a { or any char, that is a valid first char
for a variable (neither ( nor 5 is).
The other place you encountered $() (in Spring cloud contract), this
is just a function with the name $.
Form the docs 8. Contract DSL:
You can set the properties inside the body either with the value method or, if you use the Groovy map notation, with $()
So this is just a function, with a very short name.
E.g. you can try this yourself:
void $(x) { println x }
$("Hello")

violation of Haskell indentation rules for if-then-else

According to the Haskell indentation rules, "Code which is part of some expression should be indented further in than the beginning of that expression". However, I found the following example, which seems to violate the rule above, compiles without any error or warning:
someFunction :: Bool -> Int -> Int -> Int
someFunction condition a b = if condition
then a - b
else a + b
Here I am defining a function someFunction, its body is an if-then-else block. According to the indentation rule, the then block is a part of the same expression in the first line, so it should be indented further than its previous line. Yet in my example, the second line then starts at the same column as the first line, and this example compiles.
I am not sure what is going on here. I am working with GHC version 8.0.1.
I'm reasonably sure this is an artifact of a deliberate GHC variation on the indentation rule. Nice catch!
GHC reads this
foo = do
item
if a
then b
else c
item
as
foo = do {
item ;
if a ;
then b ;
else c ;
item }
which should trigger a parse error.
However, this was so common that at a certain point the GHC devs decided to allow for an optional ; before then and else. This change to the if grammar makes the code compile.
This means that if became "special", in that it does not have to indented more, but only as much as the previous item. In the code posted in the question, then is indented as much as the previous item, so there's an implicit ; before it, and that makes the code compile.
I would still try to avoid this "style", though, since it's quirky.
(Personally, I wouldn't have added this special case to GHC. But it's not a big deal, anyway.)
I now noticed that the Wikibook mentions this variant as a "proposal" for a future version of Haskell. This is a bit outdated now, and has been implemented in GHC since then.

Groovy method naming convention or magic?

I try to create a small DSL, but i'm struggling with even simple stuff.
The following script gives me an error.
def DEMON(String input) {
['a': input]
}
DEMON 'Hello thingy' a
For some reasons, the parentheses around the parameters are not optional and i get an error.
This script runs fine:
def dEMON(String input) {
['a': input]
}
dEMON 'Hello thingy' a
Note: the only difference is the lowercase first char.
So what is going on here? Why are the scripts interpreted (compiled?) different? Is there some kind of method/class naming schemes i have to follow?
Update: The error message. I guess a Syntax error:
unexpected token: Hello thingy # line 4, column 7.
The groovy syntax is sometime complex, and the compiler use some rules to choose what it must do. One of this rule is simple : If a word starts with an uppercase, it's probably a class.
for example, f String is a syntax valid in groovy, and the compiler converts it to f(String.class).
you can use parenthesis to help groovy understand your DEMON is not a class but a method, DEMON('Hello thingy', a)

Haskell -- how to use the new 4-argument quasi quoter

It looks like the quasi quoter syntax has changed to now accept 4 arguments [ link ]. Has anyone used it yet? Thanks. I just want to build something really really simple, and the examples on the web won't work now.
Thanks in advance.
Each piece of the QuasiQuoter is just a function that takes a string (the content of the quasi-quote) and returns an appropriate value in the Q monad. If your quasiquoter doesn't support being used in some of those contexts, just return an error, e.g.:
someQuoter = QuasiQuoter { quoteType = const $ fail "type context unsupported"
, -- etc ...
}
The fail method calls report True, which produces a compiler error. This is pretty much the correct behavior.
Basically the changes are that you can now make quasiquoters for types and declarations (in addition to expressions and patterns).
It should be fine to set the type/declaration fields to error "This quasiquoter doesn't support splicing types/declarations" if you don't want to use them.

Resources