Re: advice on skipping unparsable text

49 переглядів
Перейти до першого непрочитаного повідомлення

markus

не прочитано,
2 бер. 2015 р., 12:07:2902.03.15
Кому: treet...@googlegroups.com
D --

> I am having the following conundrum:

> I have a format where someone decided it is a good idea to abuse if
> conditions for writing comments like this:

> !IF 0
> comments comments
> !ENDIF


What about a rule along the lines of:

"!IF" condition nl code_lines nl "!ENDIF" /
"!IF" condition nl any_non_endif_lines nl "!ENDIF"

Or, alternatively, if you want to narrow the acceptance of the idiom you
disapprove of:

"!IF 0" nl any_non_endif_lines nl "!ENDIF" /
"!IF" condition nl code_lines nl "!ENDIF"

-- MarkusQ



Clifford Heath

не прочитано,
2 бер. 2015 р., 21:47:1502.03.15
Кому: treet...@googlegroups.com
The trouble with Markus’ proposal is that any syntax error inside an enabled IF condition
will cause the whole block to be ignored as a comment.

Instead, I suggest that this is an excellent candidate for using a semantic predicate.
Here’s how:

rule if_block
‘!IF’ expr &{|s| expression = s[1]; expression.evaluate_falseness } (!(’!ENDIF’ / !.) if_comment_line)* ('!ENDIF’ / !.)
/ ‘!IF’ expr block ‘!ENDIF'
end

rule if_comment_line
.* “\n"
end

The way this works is to parse the !IF and expression, then, before the complete rule has been
matched (and the new sequence node created and extended with methods and accessors), the
semantic predicate captures the sequence being built into the sem-pred block as “s”. Then s[1] is
the SyntaxNode of the expression, which should have the method evaluate_falseness. If this
method returns true, the first path of if_block will continue, and assuming it succeeds, the second
alternative won’t be taken.

Note that I went to some trouble with the !. rules to ensure that EOF inside an if_block is parsed
so you can complain about it specifically.

You need to define the “block” rule yourself.

Clifford Heath.

> On 2 Mar 2015, at 9:36 pm, Diman Todorov <diman....@gmail.com> wrote:
>
> Hi,
>
> I am having the following conundrum:
>
> I have a format where someone decided it is a good idea to abuse if conditions for writing comments like this:
>
> !IF 0
> comments comments
> !ENDIF
>
> my approach to parsing the file was by building up a parse tree, adding .eval(env) in the node modules and calling eval on the lines in the branch if the "if" condition evaluated to true.
>
> Unfortunately my parser still tries to parse the code in the "if" branch that will never evaluate.
>
> I looked into semantic predicates but I couldn't find a good way to access the env there so I can evaluate the "if" condition within an env.
>
> Does this make any sense to you?
> If so, have you any advice on how best to tackle this?
>
> thanks,
> Diman
>
> --
> You received this message because you are subscribed to the Google Groups "Treetop Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to treetop-dev...@googlegroups.com.
> To post to this group, send email to treet...@googlegroups.com.
> Visit this group at http://groups.google.com/group/treetop-dev.
> For more options, visit https://groups.google.com/d/optout.

markus

не прочитано,
2 бер. 2015 р., 23:40:5702.03.15
Кому: treet...@googlegroups.com
> The trouble with Markus’ proposal is that any syntax error inside an enabled IF condition
> will cause the whole block to be ignored as a comment.

Good catch! At least in the first form, this is a major gotcha and I'm
somewhat embarrassed not to have seen in myself. I _think_ the second
form I suggested:


"!IF 0" nl any_non_endif_lines nl "!ENDIF" /
"!IF" condition nl code_lines nl "!ENDIF"

is free of that particular flaw, but as Clifford's brain is clearly
working better than mine at the moment I'd suggest going with his much
more throughly thought out approach.

-- MarkusQ


"Martin J. Dürst"

не прочитано,
2 бер. 2015 р., 23:46:4002.03.15
Кому: treet...@googlegroups.com
On 2015/03/03 13:39, markus wrote:
> Good catch! At least in the first form, this is a major gotcha and I'm
> somewhat embarrassed not to have seen in myself. I _think_ the second
> form I suggested:
>
>
> "!IF 0" nl any_non_endif_lines nl "!ENDIF" /
> "!IF" condition nl code_lines nl "!ENDIF"
>
> is free of that particular flaw, but as Clifford's brain is clearly
> working better than mine at the moment I'd suggest going with his much
> more throughly thought out approach.

Your approach works if "0" is the only way to express a false value. But
if e.g.
!IF 5<3
on anything like this also is allowed, then your approach wouldn't work.

Regards, Martin.

markus

не прочитано,
3 бер. 2015 р., 00:17:4503.03.15
Кому: treet...@googlegroups.com
Yeah. My thought was that if it's someone (e.g. a single users) abusing
conditional compilation for comments, they probably have a very
stereotyped idiom (someone _could_ use a unique way of writing "false"
for each comment but...seriously?) and the simplest solution may be to
just deal with that.

For anything even slightly more general, Clifford's solution is clearly
the way to go.

-- MarkusQ




Clifford Heath

не прочитано,
3 бер. 2015 р., 01:39:3603.03.15
Кому: treet...@googlegroups.com
>> Your approach works if "0" is the only way to express a false value. But
>> if e.g.
>> !IF 5<3
>> on anything like this also is allowed, then your approach wouldn't work.
>
> Yeah. My thought was that if it's someone (e.g. a single users) abusing
> conditional compilation for comments, they probably have a very
> stereotyped idiom

The most common pattern that will trap you is when folk use defined macros
to en/disable features:

!IF FEATURE_1_ENABLED

!END

The semantic predicate can evaluate the symbolic expression.

BTW, I *strongly* recommend that the OP doesn’t use Ruby’s “eval” here.
That would provide an open back-door to an attacker. Write a proper little
expression evaluator instead.

Clifford.

Clifford Heath

не прочитано,
3 бер. 2015 р., 20:25:2403.03.15
Кому: treet...@googlegroups.com
Oh yes, getting to the context is awkward. I create a wrapper around the input that has the extra context,
because input is always available. In retrospect this was a poor choice, but I’m not going to add a fourth
recursive SyntaxNode constructor parameter to the three existing ones, and I can’t change the existing
“input” parameter to “parser”, which would have been the logical choice.

Info on how I do the wrapper is in the archives, or see InputProxy here:
<https://github.com/cjheath/activefacts/blob/master/lib/activefacts/cql/parser.rb#L167>

Clifford Heath.

> On 4 Mar 2015, at 1:50 am, Diman Todorov <diman....@gmail.com> wrote:
>
> Thanks everyone for the replies!
>
> Clifford, i was trying to do this but to evaluate the boolean expression I need the context with variable values. Currently i am passing it around recursively in the .evaluate_expression function (much like in Nathans examples):
>
> rule somerule
> term {
> def eval(env <---)
> term.eval(env)
> end
> }
>
> but I am not sure how to get to it in the context of the %{} predicate?
>
> Thanks,
> Diman
Відповісти всім
Відповісти автору
Переслати
Повідомлення видалено
Повідомлення видалено
0 нових повідомлень