If-Else conditions with APL? - if-statement

So, I'm wondering/asking; Is it possible to do an If-Statement in APL? If so how?
Here's my code
'Please enter a number to count to: '
number ←⎕
⍳number
How do I get an if-statement to where if the user inputs a number over 100 it will print out "too high" and end; or if it's 100 or under then it will just continue?
Thanks!

In Dyalog APL you have this neat little thing called guards.
They can be used in dfns and evaluate code when a certain condition matches.
func ← {⍵>100 : 'too high' ⋄ 1 : 'number is ok'}

If your APL supports control structures then this should work:
∇ generateAll number
:If number>100
⎕←'Too high'
:else
⎕←⍳ number
:endif
∇
If it does NOT support control structures (like APL2) you will need to branch:
∇ generateAll number
→(number>100)/error
⎕←⍳ number
→0
error:
⎕←'Too high'
∇
You can also use tricks like execute but this is less readable.

A "classical" way of doing error handling* in APL2 is with the ⎕ES or ⎕EA.
Your code would look something like this:
⎕ES(NUMBER>100)/'Too high'
⍳NUMBER
What happens here is that IF the parentheses evaluate to true, THEN the ⎕ES will halt the execution and echo the quoted string.
If you don't want your THEN to terminate, have a look at ⎕EA in some APL documentation.
Please note that I'm on APL2 in a GreenOnBlack environment, so there are likely more neat ways of doing this in a more modern dialect like Dyalog.
*I know you're asking about conditionals and not error handling, but since you're example terminates execution, it might as well be error handling.
There is a crucial difference between this and what MBaas suggests: His solution will gracefully exit the current function which might return a value. Using ⎕ES or ⎕EA with terminate all execution.

Depends on the dialect you're using. Some APL-Implementations support control-strucures, so you could write something like
:If number>100
⎕←'Too high'
→0
:endif
⍳number
In "tradtional APL" you would probably do something like
⍎(number>100)/'⎕←''Too high'' ⋄ →0'
⍳number

Related

Using IF function, getting "too many

HELP! I'm getting a "too many arguments for this function" error.
=IF(B13>149,000,"T1",IF(B13>180,000,"T2",IF(B13>210,000,"T3",IF(B13>240,000,"T4",IF(B13>270,000,"T5",IF(B13>300,000,"T6"))))))
Remove the commas from the numbers; Excel thinks "comma" means "new argument." Like this...
=IF(B13>149000,"T1",IF(B13>180000,"T2",IF(B13>210000,"T3",IF(B13>240000,"T4",IF(B13>270000,"T5",IF(B13>300000,"T6"))))))
...but your code will still not do what you want it to do because assuming B13 is greater than 149000, we'll never get past evaluating your first IF and setting to T1, because it looks like the function parser stops after it finds a true condition (like B13 being greater than 149000; whether or not other IFs in your function would also evaluate to true doesn't matter to Excel - it already found a true condition). The solution is to reverse the order, like this:
=IF(B13>300000,"T6",IF(B13>270000,"T5",IF(B13>240000,"T4",IF(B13>210000,"T3",IF(B13>180000,"T2",IF(B13>149000,"T1"))))))

How can you require an undetermined character to be repeated consecutively a certain number of times in Ruby Treetop?

I want to create a rule that requires a non-number, non-letter character to be consecutively repeated three times. The rule would look something like this:
# Note, this code does not do what I want!
grammar ThreeCharacters
rule threeConsecutiveCharacters
(![a-zA-Z0-9] .) 3..3
end
end
Is there any way to require the first character that it detects to be repeated three times?
There was previously a similar question about detecting the number of indentations: PEG for Python style indentation
The solution there was to first initialize the indentation stack:
&{|s| #indents = [-1] }
Then save the indentation for the current line:
&{|s|
level = s[0].indentation.text_value.length
#indents << level
true
}
Whenever a new line begins it peeks at the indentation like this:
!{|s|
# Peek at the following indentation:
save = index; i = _nt_indentation; index = save
# We're closing if the indentation is less or the same as our enclosing block's:
closing = i.text_value.length <= #indents.last
}
If the indentation is larger it adds the new indentation level to the stack.
I could create something similar for my problem, but this seems like a very tedious way to solve it.
Are there any other ways to create my rule?
Yes, you can do it this way in Treetop. This kind of thing not generally possible with a PEG because of the way packrat parsing works; it's greedy but you need to limit its greed using semantic information from earlier in the parse. It's only the addition in Treetop of semantic predicates (&{...}} that make it possible. So yes, it's tedious. You might consider using Rattler instead, as it has a significant number of features in addition to those available in Treetop. I can't advise (as maintainer of Treetop, but not being a user of Rattler) but I am very impressed by its feature set and I think it will handle this case better.
If you proceed with Treetop, bear in mind that every semantic predicate should return a boolean value indicating success or failure. This is not explicit in the initialisation of #indents above.

TCL syntax errors

I have an automatically generated TCL proc, which has many if condition, some lines inside some if condition never gets executed for any possible combinations of proc inputs.
But I found some syntactical errors in those lines like extra ] or multiplication [1*1] instead of [expr 1*1]. I want to find out these TCL syntactical errors in all the lines. Is there any clever way to do achieve this?
You can use a tool like Nagelfar for syntax analysis; the website even has an online demo that you can try. It might not catch all the problems, but it could catch some.

Any way to speed up instaparse?

I'm trying to use instaparse on a dimacs file less than 700k in size, with the following grammar
<file>=<comment*> <problem?> clause+
comment=#'c.*'
problem=#'p\s+cnf\s+\d+\s+\d+\s*'
clause=literal* <'0'>
<literal>=#'[1-9]\d*'|#'-\d+'
calling like so
(def parser
(insta/parser (clojure.java.io/resource "dimacs.bnf") :auto-whitespace :standard))
...
(time (parser (slurp filename)))
and it's taking about a hundred seconds. That's three orders of magnitude slower than I was hoping for. Is there some way to speed it up, some way to tweak the grammar or some option I'm missing?
The grammar is wrong. It can't be satisfied.
Every file ends with a clause.
Every clause ends with a '0'.
The literal in the clause, being a greedy reg-exp,will eat
the final '0'.
Conclusion: No clause will ever be found.
For example ...
=> (parser "60")
Parse error at line 1, column 3:
60
^
Expected one of:
"0"
#"\s+"
#"-\d+"
#"[1-9]\d*"
We can parse a literal
=> (parser "60" :start :literal)
("60")
... but not a clause
=> (parser "60" :start :clause)
Parse error at line 1, column 3:
60
^
Expected one of:
"0" (followed by end-of-string)
#"\s+"
#"-\d+"
#"[1-9]\d*"
Why is it so slow?
If there is a comment:
it can swallow the whole file;
or be broken at any 'c' character into successive comments;
or terminate at any point after the initial 'c'.
This implies that every tail has to be presented to the rest of the grammar, which includes a reg-exp for literal that Instaparse can't see inside. Hence all have to be tried, and all will ultimately fail. No wonder it's slow.
I suspect that this file is actually divided into lines. And that your problems arise from trying to conflate newlines with other forms of white-space.
May I gently point out that playing with a few tiny examples - which is all I've done - might have saved you a deal of trouble.
I think that your extensive use of * is causing the problem. Your grammar is too ambiguous/ambitious (I guess). I would check two things:
;;run it as
(insta/parses grammar input)
;; with a small input
That will show you how much ambiguity is in your grammar definition: check "ambiguous grammar".
Read Engelberg performance notes, it would help understand your own problem and probably find out what fits best for you.

Indentation control while developing a small python like language

I'm developing a small python like language using flex, byacc (for lexical and parsing) and C++, but i have a few questions regarding scope control.
just as python it uses white spaces (or tabs) for indentation, not only that but i want to implement index breaking like for instance if you type "break 2" inside a while loop that's inside another while loop it would not only break from the last one but from the first loop as well (hence the number 2 after break) and so on.
example:
while 1
while 1
break 2
'hello world'!! #will never reach this. "!!" outputs with a newline
end
'hello world again'!! #also will never reach this. again "!!" used for cout
end
#after break 2 it would jump right here
but since I don't have an "anti" tab character to check when a scope ends (like C for example i would just use the '}' char) i was wondering if this method would the the best:
I would define a global variable, like "int tabIndex" on my yacc file that i would access in my lex file using extern. then every time i find a tab character on my lex file i would increment that variable by 1. when parsing on my yacc file if i find a "break" keyword i would decrement by the amount typed after it from the tabIndex variable, and when i reach and EOF after compiling and i get a tabIndex != 0 i would output compilation error.
now the problem is, whats the best way to see if the indentation got reduced, should i read \b (backspace) chars from lex and then reduce the tabIndex variable (when the user doesn't use break)?
another method to achieve this?
also just another small question, i want every executable to have its starting point on the function called start() should i hardcode this onto my yacc file?
sorry for the long question any help is greatly appreciated. also if someone can provide an yacc file for python would be nice as a guideline (tried looking on Google and had no luck).
thanks in advance.
I am currently implementing a programming language rather similar to this (including the multilevel break oddly enough). My solution was to have the tokenizer emit indent and dedent tokens based on indentation. Eg:
while 1: # colons help :)
print('foo')
break 1
becomes:
["while", "1", ":",
indent,
"print", "(", "'foo'", ")",
"break", "1",
dedent]
It makes the tokenizer's handling of '\n' somewhat complicated though. Also, i wrote the tokenizer and parser from scratch, so i'm not sure whether this is feasable in lex and yacc.
Edit:
Semi-working pseudocode example:
level = 0
levels = []
for c = getc():
if c=='\n':
emit('\n')
n = 0
while (c=getc())==' ':
n += 1
if n > level:
emit(indent)
push(levels,n)
while n < level:
emit(dedent)
level = pop(levels)
if level < n:
error tokenize
# fall through
emit(c) #lazy example
Very interesting exercise. Can't you use the end keyword to check when the scope ends?
On a different note, I have never seen a language that allows you to break out of several nested loops at once. There may be a good reason for that...