"Expecting Expression" Error

BlitzPlus Forums/BlitzPlus Beginners Area/"Expecting Expression" Error

Necromancer(Posted 2013) [#1]
I made this calculator and now it's telling me "Expecting Expression" when I try to run it.

The code:
(code)
Print "Welcome to Lucas' advanced calculator!"
Delay 1000
Print ""
Print "The types of equations are:"
Print ""
Delay 1000

Repeat

Print "Multiply - m"
Delay 500
Print "Divide - d"
Delay 500
Print "Add - a"
Delay 500
Print "Subtract - s"
Delay 1000
Print ""
Print "You can also type 'q' at any time to quit the program."
Print ""
Delay 1000
Print ""
Quitnow$ = Input("Type q now if you wish to quit the calculator. Otherwise, type go. ")
If Not Quitnow = "q" Then
Print ""
numbercount = Input("How many numbers do you want in your equation? (2 or 3)")

If numbercount = "2" Then
equationtype2$ = Input("What kind of equation would you like to do? ")
Print ""
number1 = Input("First number: ")
Print ""
Delay 500
number2 = Input("Second number: ")
Print ""
Delay 500
Delay 1000
Print "Calculating..."
Print ""
Delay 2000
Print "The answer of your equation is: "
Print ""
If Lower(equationtype2) = "a" Then Print number1 + number2
If Lower(equationtype2) = "s" Then Print number1 - number2
If Lower(equationtype2) = "m" Then Print number1 * number2
If Lower(equationtype2) = "d" Then Print number1 / number2
Print ""
Print ""
Print ""


ElseIf numbercount = "3" Then
equationtype3a$ = Input("What kind of equation would you like to do between your first and second number? ")
equationtype3b$ = Input("What kind of equation would you like to do between your second and third number? ")
Print ""
number1 = Input("First number: ")
Print ""
Delay 500
number2 = Input("Second number: ")
Print ""
Delay 500
number3 = Input("Third number: ")
Print ""
Delay 500
Delay 1000
Print "Calculating..."
Print ""
Delay 2000
Print "The answer of your equation is: "
Print ""
If equationtype3a = "a" And
equationtype3b = "a" Then Print number1 + number2 + number3
ElseIf equationtype3a = "a" And
equationtype3b = "s" Then Print number1 + number2 - number3
ElseIf equationtype3a = "a" And
equationtype3b = "m" Then Print number1 + number2 * number3
ElseIf equationtype3a = "a" And
equationtype3b = "d" Then Print number1 + number2 / number3
ElseIf equationtype3a = "s" And
equationtype3b = "a" Then Print number1 - number2 + number3
ElseIf equationtype3a = "s" And
equationtype3b = "s" Then Print number1 - number2 - number3
ElseIf equationtype3a = "s" And
equationtype3b = "m" Then Print number1 - number2 * number3
ElseIf equationtype3a = "s" And
equationtype3b = "d" Then Print number1 - number2 / number3
ElseIf equationtype3a = "m" And
equationtype3b = "a" Then Print number1 * number2 + number3
ElseIf equationtype3a = "m" And
equationtype3b = "s" Then Print number1 * number2 - number3
ElseIf equationtype3a = "m" And
equationtype3b = "m" Then Print number1 * number2 * number3
ElseIf equationtype3a = "m" And
equationtype3b = "d" Then Print number1 * number2 / number3
ElseIf equationtype3a = "d" And
equationtype3b = "a" Then Print number1 / number2 + number3
ElseIf equationtype3a = "d" And
equationtype3b = "s" Then Print number1 / number2 - number3
ElseIf equationtype3a = "d" And
equationtype3b = "m" Then Print number1 / number2 * number3
ElseIf equationtype3a = "d" And
equationtype3b = "d" Then Print number1 / number2 / number3
Print ""
Print ""
Print ""
Delay 1000
Print ""
Print ""
Print ""
EndIf
EndIf
EndIf
EndIf


Until Lower(Quitnow) = "q"

Print ""
Print ""
Print "Thanks for using Lucas's advanced calculator!"
Delay 2000
Print ""
Print "Bye!"
Delay 1000
End
(/code)


Necromancer(Posted 2013) [#2]
Sorry for not putting it in code or whatever, I don't know how the codes work on here. Along with answering my question could someone tell me if I am supposed to use BB code or what?


Yasha(Posted 2013) [#3]
Just replace the parentheses around your (code) tags with square brackets (i.e. yes, BBcode, mostly) and it will work. The link directly above the reply box has more details; "codebox" is best for long pastes.

Anyway it looks like you're using a newline/block convention that BlitzPlus doesn't support quite as you're expecting. The rules are:

-- any value expression must be on a single line. There are no line continuations. So those "And" expressions split over two lines are not valid.

-- if any statement directly follows "Then", on the same line and without a separator, the whole thing is assumed to be an "inline" If form that runs until the newline (the "inline" form can contain substatements separated by colons)

-- if any statement directly follows the controlling expression of the "If" with no "Then", it is also inline ("Then" is always optional)

-- a newline after "Then", or a colon or newline after the controlling expression of the "If", indicates that the If is using the "block form" and must be closed by "EndIf" (notice that this rule means colons are subordinate to newlines; once an "inline" form has started they can't close it)

It's hard to tell because of the lack of formatting, but I think you're mixing up a couple of different forms here. Make sure no value expressions have newlines, and try to ensure that you use either a block or an inline form for your If statements. I advise dropping the "Then" for the block form, as it looks a bit weird hanging there on its own.

The rules probably sound complicated presented in a row like that but they're actually quite simple and intuitive once you get used to seeing them in action. Most people don't think about them at all. You should take a look at the bundled sample code to see the different forms in action.


(There are actually some weird corner rules around BlitzPlus's block syntax that let you write odd things if you try, like blocks in the middle of lines and stuff... better to avoid these.)


Necromancer(Posted 2013) [#4]
Do you think you could tell me exactly what I need to change?


Yasha(Posted 2013) [#5]
To get rid of the "expecting expression" issue, delete the newline after each dangling "And" so that the whole expression is on one line. The error message is saying that "And" forms a binary expression; it needs something (a subexpression) to its right before the line can end.

This will then leave you with a message saying that it expects to see "EndIf" somewhere - this is because your If blocks aren't structured according to the rules above and it can't work out what you mean by them. You'll need to rearrange your code to reflect exactly what you mean for this bit.

(Are you using indenting when you edit? It's much easier to see what goes in a block when the block body is indented. The whole code block sticks out in a visually-coherent unit.)


Necromancer(Posted 2013) [#6]
Now when I try to run it it tells me it's expecting EndIf and moves my cursor to the end of this:

If equationtype3a = "a" And equationtype3b = "a" Then Print number1 + number2 + number3
	ElseIf equationtype3a = "a" And equationtype3b = "s" Then Print number1 + number2 - number3


Not sure what that means.


Yasha(Posted 2013) [#7]
See again the rules above. You're combining inline and multiline forms for this control block by the look of it (I'm actually hesitant to say so because I'm not sure where your intended blocks end).

If the above is one complete statement, it should either be entirely on one line including all Else clauses, or there should be newlines after the control expressions and an EndIf at the end:

If equationtype3a = "a" And equationtype3b = "a"
    Print number1 + number2 + number3
ElseIf equationtype3a = "a" And equationtype3b = "s"
    Print number1 + number2 - number3
EndIf


But omitting that first newline tells the compiler that the If is going to have no further newlines at all, so then it becomes confused in your version when stuff happens after a newline halfway along.

You could also simplify the above to only check that 3a="a" once, and place the tests against 3b in a further nested block. It wouldn't make a difference to execution but it would be significantly clearer to read, by enforcing conceptual groups (and reduce the amount of stuff onscreen).


Necromancer(Posted 2013) [#8]
Okay, so I rewrote that part of the code, it's still giving me "Expecting Endif" so what did I do wrong this time?

If equationtype3a = "a" Then
		If equationtype3b = "a" Then Print number1 + number2 + number3
		ElseIf equationtype3b = "s" Then Print number1 + number2 - number3
		ElseIf equationtype3b = "m" Then Print number1 + number2 * number3
		ElseIf equationtype3b = "d" Then Print number1 + number2 / number3
			EndIf
	EndIf
	
	If equationtype3a = "s" Then
		If equationtype3b = "a" Then Print number1 - number2 + number3
		ElseIf equationtype3b = "s" Then Print number1 - number2 - number3
		ElseIf equationtype3b = "m" Then Print number1 - number2 * number3
		ElseIf equationtype3b = "d" Then Print number1 - number2 / number3
			EndIf
	EndIf
	
	If equationtype3a = "m" Then
		If equationtype3b = "a" Then Print number1 * number2 + number3
		ElseIf equationtype3b = "s" Then Print number1 * number2 - number3
		ElseIf equationtype3b = "m" Then Print number1 * number2 * number3
		ElseIf equationtype3b = "d" Then Print number1 * number2 / number3
			EndIf
	EndIf
	
	If equationtype3a = "d" Then
		If equationtype3b = "a" Then Print number1 / number2 + number3
		ElseIf equationtype3b = "s" Then Print number1 / number2 - number3
		ElseIf equationtype3b = "m" Then Print number1 / number2 * number3
		ElseIf equationtype3b = "d" Then Print number1 / number2 / number3
			EndIf
	EndIf




Yasha(Posted 2013) [#9]
As in post #7... I would really recommend not mixing inline and multiline If forms. Either split the whole thing onto separate lines as in that example, or put the whole thing on one line (too long to be practical in this case). Those ElseIfs are on new lines, but their actions are inline: this isn't consistent.

Even if that's not the immediate source of the problem, once you do that the block structure of the program will become very clear and any missing terminators will be obvious. At the moment the block structure is confused. I don't think the compiler is able to see what you mean and the error message may even be misleading because a broken block structure means it doesn't know how to locate a point in the code properly.


Necromancer(Posted 2013) [#10]
I fixed it! Thank you all for your help!
This is what I did to fix it:
If equationtype3a = "a" Then
		If equationtype3b = "a" Then Print (number1 + number2) + number3 ElseIf equationtype3b = "s" Then Print (number1 + number2) - number3 ElseIf equationtype3b = "m" Then Print (number1 + number2) * number3 ElseIf equationtype3b = "d" Then Print (number1 + number2) / number3
			EndIf
	
	
	If equationtype3a = "s" Then
		If equationtype3b = "a" Then Print (number1 - number2) + number3 ElseIf equationtype3b = "s" Then Print (number1 - number2) - number3 ElseIf equationtype3b = "m" Then Print (number1 - number2) * number3 ElseIf equationtype3b = "d" Then Print (number1 - number2) / number3
			EndIf
	
	
	If equationtype3a = "m" Then
		If equationtype3b = "a" Then Print (number1 * number2) + number3 ElseIf equationtype3b = "s" Then Print (number1 * number2) - number3 ElseIf equationtype3b = "m" Then Print (number1 * number2) * number3 ElseIf equationtype3b = "d" Then Print (number1 * number2) / number3
			EndIf
	EndIf
	
	If equationtype3a = "d" Then
		If equationtype3b = "a" Then Print (number1 / number2) + number3 ElseIf equationtype3b = "s" Then Print (number1 / number2) - number3 ElseIf equationtype3b = "m" Then Print (number1 / number2) * number3 ElseIf equationtype3b = "d" Then Print (number1 / number2) / number3
			EndIf
	EndIf


And by the way, could someone tell me the command to make a number able to have a decimal after it instead of just being a whole number?


xlsior(Posted 2013) [#11]
There is no "command" to use fractional numbers, it depends on the datatypes you're using.

Integers only support whole numbers. Float and Double support fractions, but be aware that those are only accurate to 9 digits including the decimal point, and some fractions can't be accurate represented at all (That's a limitation of how floating point variables are stored in memory, it's not a limitation of blitzmax. Other languages like C++ have the exact same 'problem')

a:int=10.3 --> becomes 10
a:float=10.3 --> becomes 10.3
a:float=10.33333333333333333333 --> becomes 10.3333330
a:float=123456.3333333333333333 --> becomes 123456.336
a:float=10.2 --> becomes 10.1999998


Necromancer(Posted 2013) [#12]
number1 = Input("First number: ")


How would I allow this to be a decimal?


Yasha(Posted 2013) [#13]
Minor quibbles with post #11 - BlitzPlus doesn't support either the Double data type, or that syntax for attaching type annotations.


Anyway, to hold a fractional value, you need a fractional variable. In the same way that you declared some variables to be strings above by attaching $ to their first appearance, you can declare a variable to hold floating point fractional numbers by attaching # at declaration.

(There's also %, for integers; this is only really there for symmetry, as you've already seen that integers are the default.)

Floating point values convert automatically to and from a string in exactly the same way as integers; just as you can assign the string result of Input to the integers number1, number2, etc..., if those were floating point variables then the number would be read from the string as a float instead and the value stored as one. Just attach that # to all of your numeric variable declarations and the rest will "just work": the conversions from strings will produce floats instead of integers, and the math will be floating-point instead of integer math, and you'll be able to add 0.5 to 0.5 and get 1.

number1# = Input("First number: ")



As an aside: "decimal" is a representation, not a type of number. It just means that the numbers are written in base-10 digits. Floats are stored internally in base-2, so it makes no sense to call them decimals because they aren't (more specifically, because computers actually can do decimal math as well, and some languages e.g. Java actually support this, but it's slower and works differently).

To be even more pedantic, whether a number is a fraction or not has no connection to its written representation. Floats are always fractions and integers are always whole, but both are stored internally in base-2 and written out as decimals when converted to strings.


Necromancer(Posted 2013) [#14]
Thank you! Works like a charm!