What in this Nearley grammar is causing an infinite loop? - infinite-loop

I'm attempting to write a Nearley grammar that will parse a .pbtxt file (a protobuf in textual format). I'm very close but seem to be encountering an infinite loop when tested in the Nearley playground (https://omrelli.ug/nearley-playground/). Can someone more comfortable with Nearley grammars spot the issue more readily?
#builtin "number.ne"
#builtin "string.ne"
#builtin "whitespace.ne"
Start -> Field:+
Field -> _ (ScalarField | MessageField) _ "\n":*
ScalarField -> FieldName _ ":" _ (ScalarValue | ScalarList) _
MessageField -> FieldName _ ":" _ (MessageValue | MessageList) _
FieldName -> [A-Za-z0-9_]:+
MessageValue -> "{" Field:+ "}"
MessageList -> "{" Field (_ "\n":+ Field):* "}"
ScalarValue -> String | Float | Integer
ScalarList -> "{" _ ScalarValue (_ "\n":+ ScalarValue):* "}"
String -> sqstring | dqstring | [A-Za-z0-9_]:+
Float -> decimal
Integer -> int
Here's an example .pbtxt that should pe parseable:
something: WHATEVER
some_list: {
bins: 32
bins: 64
bins: 128
bins: 256
}
things: {
some_path: "Data/thingything"
weight: 2
other_weights: {
positive_dense_bin: 8
low_heat: 1
}
}

Related

DynamoDB ConditionExpression if resulting value is positive?

I'm writing an application that has a function for tipping points. I want to make a conditional update which is only executed if the resulting value of a user's wallet would be 0 or higher. If the value is negative the update should not happen.
The function works without the conditional expression but when I add it, it breaks.
ConditionExpression: 'teleUser.wallet.points -:a > -1',
In the above line :a is a passed in integer. I'll post the context below, but the above line is where my problem occurs.
The error returned is ValidationException: Invalid ConditionExpression: Syntax error; token: "-", near: "points -:a".
Full function for context:
function removeFromWallet(msg, amount) {
console.log("remove");
let params = {
TableName: tableName,
Key: {"id": msg.from.id},
UpdateExpression: 'set teleUser.wallet.points = teleUser.wallet.points -:a',
ExpressionAttributeValues:{
":a": parseInt(amount)
},
ConditionExpression: 'teleUser.wallet.points -:a > -1',
ReturnValues:"UPDATED_NEW"
};
docClient.update(params, function(err, data) {
if (err) {
console.log(err);
} else {
const { Items } = data;
console.log(data.Attributes.teleUser.wallet.points);
addToWallet(msg, amount);
}
});
}
You can't perform calculations in ConditionExpression (see grammar for ConditionExpression)
condition-expression ::=
operand comparator operand
| operand BETWEEN operand AND operand
| operand IN ( operand (',' operand (, ...) ))
| function
| condition AND condition
| condition OR condition
| NOT condition
| ( condition )
comparator ::=
=
| <>
| <
| <=
| >
| >=
function ::=
attribute_exists (path)
| attribute_not_exists (path)
| attribute_type (path, type)
| begins_with (path, substr)
| contains (path, operand)
| size (path)
You can perform calculations in ExpressionAttributeValues, but in this particular case you'll probably have to use teleUser.wallet.points >= :a since column values aren't available in ExpressionAttributeValues

How to insert variables that might be `nothing` into strings in Julia?

I am trying to make a dynamic string in Julia by inserting the value of a variable into the string. Everything worked fine until today when the value returned nothing leaving me with an error.
How do I include a nothing in a string? At least without having to go through the hassle of some if n == nothing; n = "None" thing for every variable I want to insert into a string.
function charge_summary(charges_df)
if size(charges_df)[1] > 0
n_charges = size(charges_df)[1]
total_charges = round(abs(sum(charges_df[:amount])), digits=2)
avg_charges = round(abs(mean(charges_df[:amount])), digits=2)
most_frequent_vender = first(sort(by(charges_df, :transaction_description, nrow), :x1, rev=true))[:transaction_description]
sms_text = """You have $n_charges new transactions, totaling \$$total_charges.
Your average expenditure is \$$avg_charges.
Your most frequented vender is $most_frequent_vender.
"""
return sms_text
else
return nothing
end
end
sms_msg = charge_summary(charges_df)
Returns:
ArgumentError: `nothing` should not be printed; use `show`, `repr`, or custom output instead.
string at io.jl:156 [inlined]
charge_summary(::DataFrame) at get-summary.jl:18
top-level scope at none:0
include_string(::Module, ::String, ::String, ::Int64) at eval.jl:30
(::getfield(Atom, Symbol("##105#109")){String,Int64,String})() at eval.jl:91
withpath(::getfield(Atom, Symbol("##105#109")){String,Int64,String}, ::String) at utils.jl:30
withpath at eval.jl:46 [inlined]
#104 at eval.jl:90 [inlined]
hideprompt(::getfield(Atom, Symbol("##104#108")){String,Int64,String}) at repl.jl:76
macro expansion at eval.jl:89 [inlined]
(::getfield(Atom, Symbol("##103#107")))(::Dict{String,Any}) at eval.jl:84
handlemsg(::Dict{String,Any}, ::Dict{String,Any}) at comm.jl:168
(::getfield(Atom, Symbol("##14#17")){Array{Any,1}})() at task.jl:259
Unfortunately you have to explicitly handle nothing. For example like this:
Your most frequented vender is $(something(most_frequent_vender, "None")).
The reason for this is that it is not clear how you would want nothing to be converted to a string, so you have to provide this value (in your case you wanted "None").
A shorter version would be:
Your most frequented vender is $(repr(most_frequent_vender)).
but then nothing is printed as "nothing".
Define Base.string(x::Nothing) method:
➜ ~ julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.0.3 (2018-12-20)
_/ |\__'_|_|_|\__'_| | android-termux/900b8607fb* (fork: 1550 commits, 315 days)
|__/ |
julia> Base.string(x::Nothing) = repr(x) # or just return the string "None", that's up to you.
julia> "$(nothing)"
"nothing"
julia>
Julia 1.3 update
Allow nothing to be printed #32148

Recursive macro makes infinite recursion

I made a simple macro that returns the taken parameter.
macro_rules! n {
($n:expr) => {{
let val: usize = $n;
match val {
0 => 0,
_ => n!(val - 1),
}
}};
}
When I compile this code with the option external-macro-backtrace, it raises an error:
error: recursion limit reached while expanding the macro `n`
--> src/main.rs:15:18
|
10 | macro_rules! n {
| _-
| |_|
| |
11 | | ($n:expr) => {{
12 | | let val: usize = $n;
13 | | match val {
14 | | 0 => 0,
15 | | _ => n!(val - 1),
| | ^^^^^^^^^^^
| | |
| | in this macro invocation
16 | | }
17 | | }};
18 | | }
| | -
| |_|
| |_in this expansion of `n!`
| in this expansion of `n!`
...
31 | | n!(1);
| | ------ in this macro invocation
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
I changed the recursion_limit to 128 and higher, but the compiler error message just increase as well. Even when I call n!(0) it makes the same error. I think it is infinite recursion, but I can't find the reason.
Well, it really is an infinite recursion. Check what your macro invocation n!(0) will be expanded into:
{
let val: usize = 0;
match val {
0 => 0,
_ => n!(0 - 1),
}
}
...and since there's no way for argument of n! to stop growing negative, it'll repeat (with n!(0 - 1 - 1) in the second match arm, then n!(0 - 1 - 1 - 1) etc.) infinitely.
The key point here is that the macro expansion happens in compile-time, while the match statement you're trying to use to limit the recursion is invoked only at run-time and can't stop anything from appear before that. Unhappily, there's no easy way to do this, since Rust won't evaluate macro arguments (even if it's a constant expression), and so just adding the (0) => {0} branch to the macro won't work, since the macro will be invoked as (for example) n!(1 - 1).

SyntaxNet Tokenization for Italian and Spanish

We're trying to use SyntaxNet on English, Italian and Spanish with models pretrained on Universal Dependencies datasets that we found here https://github.com/tensorflow/models/blob/master/syntaxnet/universal.md.
For Italian and Spanish we are encountering some problems at the level of tokenisation for contractions and clitics. Contractions are a combination of a preposition and a determiner, so we want them to be split in the two parts. We noticed that the tokeniser always fails in doing so, which means that the whole analysis of the sentence becomes wrong. The same happens for clitics.
We are launching the models as follows:
MODEL_DIRECTORY=../pretrained/Italian
cat /mnt/test_ita.split | syntaxnet/models/parsey_universal/tokenize.sh \
$MODEL_DIRECTORY > /mnt/test_ita.tokenized
Below, an example of the output we are obtaining now and the one we wish to have.
Italian (SyntaxNet analisys)
1 Sarebbe _ VERB V Mood=Cnd|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|fPOS=VERB++V 2 cop _ _
2 bello _ ADJ A Gender=Masc|Number=Sing|fPOS=ADJ++A 0 ROOT _ _
3 esserci _ PRON PE fPOS=NOUN++S 2 nsubj _ _
4 . _ PUNCT FS fPOS=PUNCT++FS 2 punct _ _
Italian (desired output)
1 Sarebbe _ VERB V Mood=Cnd|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|fPOS=VERB++V 2 cop _ _
2 bello _ ADJ A Gender=Masc|Number=Sing|fPOS=ADJ++A 0 ROOT _ _
3 esser _ VERB V VerbForm=Inf|fPOS=VERB++V 2 csubj _ _
4 ci _ PRON PC PronType=Clit|fPOS=PRON++PC 3 advmod _ _
How can we handle this problem? Thanks in advance.

Coordinates to Grid Box Number

Let's say I have some grid that looks like this
_ _ _ _ _ _ _ _ _
| | | |
| 0 | 1 | 2 |
|_ _ _|_ _ _|_ _ _|
| | | |
| 3 | 4 | 5 |
|_ _ _|_ _ _|_ _ _|
| | | |
| 6 | 7 | 8 |
|_ _ _|_ _ _|_ _ _|
How do I find which cell I am in if I only know the coordinates? For example, how do I get 0 from (0,0), or how do I get 7 from (1,2)?
Also, I found this question, which does what I want to do in reverse, but I can't reverse it for my needs because as far as I know there is not a mathematical inverse to modulus.
In this case, given cell index A in the range [0, 9), the row is given by R = floor(A/3) and the column is given by C = A mod 3.
In the general case, where MN cells are arranged into a grid with M rows and N columns (an M x N grid), given a whole number B in [0, MN), the row is found by R = floor(B/N) and the column is found by C = B mod N.
Going the other way, if you are given a grid element (R, C) where R is in [0, M) and C is in [0, N), finding the element in the scheme you show is given by A = RN + C.
cell = x + y*width
Programmers use this often to treat a 1D-array like a 2D-array.
For future programmers
May this be useful:
let wide = 4;
let tall = 3;
let reso = ( wide * tall);
for (let indx=0; indx<reso; indx++)
{
let y = Math.floor(indx/wide);
let x = (indx % wide);
console.log(indx, `x:${x}`, `y:${y}`);
};

Resources