How can Pascal have conditions when it doesn't have boolean type? - grammar

Based on formal Pascal EBNF definition (pg69-75), I saw that Pascal only supports 3 primitive types: Integer, Real and String.
In C, any values which are different from 0 can be interpreted as a true literal. Pascal doesn't work like C. How can Pascal deal with conditional expressions when it doesn't have Boolean type?

The Pascal standard clearly defines the syntax and semantics of a Boolean-type.
Quoting from the document you link to:
6.4.2.2 Required simple-types
The following types shall exist:
…
c. Boolean-type. The required type-identifier Boolean shall denote the Boolean-type. The Boolean-type shall be an ordinal-type. The values shall be the enumeration of truth values denoted by the required constant-identifiers false and true, such that false is the predecessor of true.
(page 16)
The values true and false correspond to the EBNF production:
constant = [ sign ] (constant-identifier | number) | string
which can produce:
constant = constant-identifier
(since [ sign ] is optional)
A constant-identifier is just an identifier.
Also:
6.7.2.3 Boolean operators
…
Boolean-expression = expression .
A Boolean-expression shall be an expression that denotes a value of Boolean-type.
(page 49)
Table 6 (on the following page) defines the operand and result types of the comparison operators (==, <=, >=, <>, <, > and in). In all cases, the result type is "Boolean-type".
Finally:
6.8.3.4 If-statements
If the Boolean-expression of the if-statement yields the value true, the statement of the if-statement shall be executed. If the Boolean-expression yields the value false, the statement of the if-statement shall not be executed, and the statement of the else-part, if any, shall be executed.
(page 54)

The EBNF does not describe the type system, it describes the syntax, and only the syntax. Note, however, that if you declare a variable it has a type:
variable-declaration =
identifier-list ":" type .
And a type is defined as:
type =
simple-type | structured-type | pointer-type | type-identifier .
And type-identifier is just identifier can be boolean, but the EBNF won't tell you that. You have to look at the rest of the standard. ISO 7185 defines a dialect of Pascal, and the relevant section is 6.4.2.2:
The values shall be the enumeration of truth values denoted by the required constant-identifiers false and true...
In Pascal, you could end up with code like this:
program BooleanDemo;
var
myBool : boolean;
n : integer;
begin
n := 5;
myBool := n > 4;
if myBool then
writeln('myBool is true')
else
writeln('myBool is false')
end.
Try running this code yourself, and you will see that there is in fact a boolean type, and it works exactly as you'd expect.

Related

Doing BNF for a simplified SQL “where” clause

I have the following SQL statement with a rudimentary BNF applied:
SELECT
from_expression [, from_expression] ...
FROM
from_source
WHERE
condition
from_source:
table_name
from_expression:
literal # 'abc', 1,
column # Table.Field1, Table.Profit
function # ABS(...)
operator invocation # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
???
For now the WHERE condition is the same as the from_expression but evaluated as a boolean. What would be the proper way to show that?
The grammar doesn't care about semantics.
Syntactically, an expression is an expression, nothing more. If you later do some kind of semantic analysis, that is when you'll need to deal with the difference. You might do that in the reduction actions for condition and from_expression but it would be cleaner to just build an AST while parsing and do the semantic analysis later on the tree.
One option would be as follow, with examples in-line:
expression:
literal # 'abc', 1,
column # Table.Field1, Table.Profit
function call # ABS(...)
operator invocation # NOT field1, 2+3, Genres[0], Genres[1:2], Address.name
condition:
expression { = | != | < | <= | > | >= | IN } expression # Revenue > 0
expression IS [NOT] NULL # Revenue IS NOT NULL
condition { AND | OR } condition # Revenue > 0 AND Profit < 100
This is a comment that doesn't fit in the comments section.
I was hesitant to provide the link to the LiveSQL implementation, since it's specifically for Java language, it's open source, but we have never added any documentation whatsoever. Read at your own risk.
The main class is LiveSQL.java: in line 113 you can see the main variant of the select clause. It has many variants, but this is the one that allows the developer to include as many result set columns (expressions) as needed:
public SelectColumnsPhase<Map<String, Object>> select(
final ResultSetColumn... resultSetColumns) {
return new SelectColumnsPhase<Map<String, Object>>(this.sqlDialect,
this.sqlSession, this.liveSQLMapper, false,
resultSetColumns);
}
Of course, the SELECT clause has many other variants, that you can find in the same class if you explore it a bit. I think I was pretty exhaustive when I researched all variants. It should be [mostly] complete, except for non-standard SQL dialect variations that I didn't consider.
If you follow the QueryBuilder up the WHERE phase you can see how the predicate is assembled in the method where(final Predicate predicate) (line 101) of the SelectFrom.java class, as in:
public SelectWherePhase<R> where(final Predicate predicate) {
return new SelectWherePhase<R>(this.select, predicate);
}
As you can see the WHERE clause does not accept any type of expression. First of all, it only accepts a single expression, not a list. Second this expression must be a Predicate (boolean expression). Of course, this predicate can be as complex as you want, mixing all kinds of expressions and boolean logic. You can peek at the Predicate.java class to explore all the expressions that can be built.
Condition
Let's take as an example the Predicate class described above. If p and q are boolean expressions and a, b, c are of [mostly] any type you can express the condition as:
condition:
<predicate>
predicate:
p and q,
p or q,
not p,
( p ),
a == b,
a <> b,
a > b,
a < b,
a >= b,
a <= b,
a between b and c,
a not between b and c,
a in (b, c, ... )
a not in (b, c, ... )
Of course there are more operators but this gives you the gist of it.

Dynamic ASSIGN of table row expression

In my ABAP report I have some structure:
data:
begin of struct1,
field1 type char10,
end of struct1.
I can access to it's field field1 directly:
data(val) = struct1-field1
or dynamically with assign:
assign ('struct1-field1') to field-symbol(<val>).
Also I have some internal table:
data: table1 like standard table of struct1 with default key.
append initial line to table1.
I can access to column field1 of first row directly:
data(val) = table1[ 1 ]-field1.
But I can not get access to field1 with dynamic assign:
assign ('table1[ 1 ]-field1') to field-symbol(<val>).
After assignment sy-subrc equals "4".
Why?
The syntax of ASSIGN (syntax1) ... is not the same as the syntax of the Right-Hand Side (RHS) of assignments ... = syntax2.
The syntax for ASSIGN is explained in the documentation of ASSIGN (variable_containing_name) ... or ASSIGN ('name') ... (chapter 1. (name) of page ASSIGN - dynamic_dobj).
Here is an abstract of what is accepted:
"name can contain a chain of names consisting of component selectors [(-)]"
"the first name [can be] followed by an object component selector (->)"
"the first name [can be] followed by a class component selector (=>)"
No mention of table expressions, so they are forbidden. Same for meshes...
Concerning the RHS of assignments, as described in the documentation, it can be :
Data Objects
They can be attributes or components using selectors -, ->, =>, which can be chained multiple times (see Names for Individual Operands
Return values or results of functional methods, return values or results of built-in functions and constructor expressions, or return values or results of table expressions
Results of calculation expressions
Sandra is absolutely right, if table expressions are not specified in help, then they are not allowed.
You can use ASSIGN COMPONENT statement for your dynamicity:
FIELD-SYMBOLS: <tab> TYPE INDEX TABLE.
ASSIGN ('table1') TO <tab>.
ASSIGN COMPONENT 'field1' OF STRUCTURE <tab>[ 1 ] TO FIELD-SYMBOL(<val>).
However, such dynamics is only possible with index tables (standard + sorted) due to the nature of this version of row specification. If you try to pass hashed table into the field symbol, it will dump.

Why is (AnObject).AField = AValue a syntax error in VB.NET?

EDIT: Modified code sample to explicitly declare return type of function.
Consider the following minimal example:
Class AClass
Public AField As Integer
Public Sub New(aField As Integer)
Me.AField = aField
End Sub
Public Function AMethod() As Integer
Return AField
End Function
End Class
Module AModule
Sub Main()
Dim AnObject As AClass = New AClass(12)
Dim n As Integer = (AnObject).AField ' This is fine
Dim m As Integer = (AnObject).AMethod() ' This is fine
(AnObject).AField = 8 ' BC30035 Syntax Error
AnObject.AField = 8 ' This is fine
End Sub
End Module
How does the syntax of VB.NET work that there's a difference between these two cases? It seems that if we're calling a method, or reading a field, the parentheses are allowed, but if we're writing a field, they're not.
I've tried looking at the Visual Basic Language Reference but I didn't see anything like a formal grammar. I've also tried googling this, although it's a bit hard to come up with a good set of search keywords.
UPDATE
So I've looked over the language grammar that Jimi linked and I'm even more confused -- in particular we have
RegularAssignmentStatement ::= Expression Equals Expression StatementTerminator
Expression ::= SimpleExpression | MemberAccessExpression | ...
MemberAccessExpression ::=
[ MemberAccessBase ] Period IdentifierOrKeyword
[ OpenParenthesis Of TypeArgumentList CloseParenthesis ]
MemberAccessBase ::= Expression | ...
SimpleExpression ::= LiteralExpression |
ParenthesizedExpression |
SimpleNameExpression |
...
SimpleNameExpression ::= Identifier [ OpenParenthesis Of TypeArgumentList CloseParenthesis ]
ParenthesizedExpression ::= OpenParenthesis Expression CloseParenthesis
According to this grammar, this isn't a syntax error! To be specific,
AnObject is an Identifier, hence a SimpleNameExpression, hence a Simple Expression, hence an Expression. (I didn't include the definition of identifiers here, but according to the documentation strings of alphabetic characters definitely qualify.)
Consequently, (AnObject) is a ParenthesizedExpression, hence a SimpleExpression, hence an Expression, hence a MemberAccessBase.
AField is an Identifier.
Putting these two together, (AnObject).AField is a MemberAccessExpression, hence an Expression
8 is a LiteralExpression, hence an Expression
The newline at the end of the line is a StatementTerminator
As a result, (AnObject).AField = 8 is a RegularAssignmentStatement, according to this grammar.
So, according to the document, this statement ought to parse!
I’m purely guessing here but I’d say that this is an artefact of VB’s feature to force value over reference passing by using parentheses:
Sub ChangeMe(ByRef x As Integer)
x += 1
End Sub
Dim x = 1
ChangeMe(x) ' x = 2
ChangeMe((x)) ' still x = 2
In your code, the compiler probably treats (AnObject) as a value rather than a reference to the original object, determines that an assignment to a field would therefore be discarded, and disallows the assignment.
Of course even when passing AnObject to a method by value, modifying AnObject.Field would still modify the original object. So, by analogy, the code should work. I’m guessing that the VB compiler is applying a faulty heuristic here.

Rails 4 querying against postgresql column with array data type error

I am trying to query a table with a column with the postgresql array data type in Rails 4.
Here is the table schema:
create_table "db_of_exercises", force: true do |t|
t.text "preparation"
t.text "execution"
t.string "category"
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.string "body_part", default: [], array: true
t.hstore "muscle_groups"
t.string "equipment_type", default: [], array: true
end
The following query works:
SELECT * FROM db_of_exercises WHERE ('Arms') = ANY (body_part);
However, this query does not:
SELECT * FROM db_of_exercises WHERE ('Arms', 'Chest') = ANY (body_part);
It throws this error:
ERROR: operator does not exist: record = character varying
This does not work for me either:
SELECT * FROM "db_of_exercises" WHERE "body_part" IN ('Arms', 'Chest');
That throws this error:
ERROR: array value must start with "{" or dimension information
So, how do I query a column with an array data type in ActiveRecord??
What I have right now is:
#exercises = DbOfExercise.where(body_part: params[:body_parts])
I want to be able to query records that have more than one body_part associated with them, which was the whole point of using an array data type, so if someone could enlighten me on how to do this that would be awesome. I don't see it anywhere in the docs.
Final solution for posterity:
Using the overlap operator (&&):
SELECT * FROM db_of_exercises WHERE ARRAY['Arms', 'Chest'] && body_part;
I was getting this error:
ERROR: operator does not exist: text[] && character varying[]
so I typecasted ARRAY['Arms', 'Chest'] to varchar:
SELECT * FROM db_of_exercises WHERE ARRAY['Arms', 'Chest']::varchar[] && body_part;
and that worked.
I don't think that it has related to rails.
What if you do the follow?
SELECT * FROM db_of_exercises WHERE 'Arms' = ANY (body_part) OR 'Chest' = ANY (body_part)
I know that rails 4 supports Postgresql ARRAY datatype, but I'm not sure if ActiveRecord creates new methods for query the datatype. Maybe you can use Array Overlap I mean the && operator and then doind something like:
WHERE ARRAY['Arms', 'Chest'] && body_part
or maybe give a look to this gem: https://github.com/dockyard/postgres_ext/blob/master/docs/querying.md
And then do a query like:
DBOfExercise.where.overlap(:body_part => params[:body_parts])
#Aguardientico is absolutely right that what you want is the array overlaps operator &&. I'm following up with some more explanation, but would prefer you to accept that answer, not this one.
Anonymous rows (records)
The construct ('item1', 'item2', ...) is a row-constructor unless it appears in an IN (...) list. It creates an anonymous row, which PostgreSQL calls a "record". The error:
ERROR: operator does not exist: record = character varying
is because ('Arms', 'Chest') is being interpreted as if it were ROW('Arms', 'Chest'), which produces a single record value:
craig=> SELECT ('Arms', 'Chest'), ROW('Arms', 'Chest'), pg_typeof(('Arms', 'Chest'));
row | row | pg_typeof
--------------+--------------+-----------
(Arms,Chest) | (Arms,Chest) | record
(1 row)
and PostgreSQL has no idea how it's supposed to compare that to a string.
I don't really like this behaviour; I'd prefer it if PostgreSQL required you to explicitly use a ROW() constructor when you want an anonymous row. I expect that the behaviour shown here exists to support SET (col1,col2,col3) = (val1,val2,val3) and other similar operations where a ROW(...) constructor wouldn't make as much sense.
But the same thing with a single item works?
The reason the single ('Arms') case works is because unless there's a comma it's just a single parenthesised value where the parentheses are redundant and may be ignored:
craig=> SELECT ('Arms'), ROW('Arms'), pg_typeof(('Arms')), pg_typeof(ROW('Arms'));
?column? | row | pg_typeof | pg_typeof
----------+--------+-----------+-----------
Arms | (Arms) | unknown | record
(1 row)
Don't be alarmed by the type unknown. It just means that it's a string literal that hasn't yet had a type applied:
craig=> SELECT pg_typeof('blah');
pg_typeof
-----------
unknown
(1 row)
Compare array to scalar
This:
SELECT * FROM "db_of_exercises" WHERE "body_part" IN ('Arms', 'Chest');
fails with:
ERROR: array value must start with "{" or dimension information
because of implicit casting. The type of the body_part column is text[] (or varchar[]; same thing in PostgreSQL). You're comparing it for equality with the values in the IN clause, which are unknown-typed literals. The only valid equality operator for an array is = another array of the same type, so PostgreSQL figures that the values in the IN clause must also be arrays of text[] and tries to parse them as arrays.
Since they aren't written as array literals, like {"FirstValue","SecondValue"}, this parsing fails. Observe:
craig=> SELECT 'Arms'::text[];
ERROR: array value must start with "{" or dimension information
LINE 1: SELECT 'Arms'::text[];
^
See?
It's easier to understand this once you see that IN is actually just a shorthand for = ANY. It's an equality comparison to each element in the IN list. That isn't what you want if you really want to find out if two arrays overlap.
So that's why you want to use the array overlaps operator &&.

Nested lambda expression translated from SQL statement

Using lambda expressions, how do you translate this query?
select * from employee where emp_id=1 and dep_id in (1,2,3,4).
I am trying this expression but this results in exceptions:
public IEnumrable<employees> getemployee(int emp,list<int> dep )
{
_employeeService.GetAll(e=>(e.emp_id=emp||emp==null) && (e.dep_id.where(dep.contains(e.dep_id))|| dep.count==0 )
}
Any suggestion for translating these queries to these lambda expressions?
wahts wrong in these function?
I don't mean to sound patronizing, but I'd suggest you pick up a beginner's C# book before going further. You've made errors in basic syntax such as operator precedence and equality comparison.
Also, remember that primitive data types cannot be checked for null, unless they're explicitly specified as nullable. In your case emp would be of type int?,not int.
Meanwhile, try
_employeeService.Where(e=>(e.emp_id==emp) && (dep == null || dep.contains(e.dep_id)) );