To precisely describe what can be interpreted as meaningful by the OpenEuphoria engine, some conventions are needed. They were described at the very beginning of part A, but it may be useful to state them again here.
The vertical bar ( | ) will denote a choice to be made among a finite number of options, like in for | if | while.
This section enumerates the various syntactic entities that form an OpenEuphoria program, and the allowed arrangements of them.
program::=
statement
statement::=
var-decl | routine
forwarding | routine | struct | general-code
includer::=
include filename | (filename) [as identifier] | import filename [from identifier] | promote [but] "{identifier}" | identifier [from identifier] | promote _ from identifier |
demote [but] "{identifier}" | identifier [from identifier] | demote _ from identifier
Note that the from clause is mandatory when demote but is used.
filename::=
Consecutive characters in a row, possibly between double quotes | an expression between parentheses, whose value will be taken as an immediate file name to be passed to the OS.
identifier::=
One or more printable alphanumreic characters, starting with a letter. Identifiers are case sensitive, so that foo, Foo, FOO, etc... are all different identifiers.
general_identifier::=
identifier[index_levels] [[[expr]]]
index_levels::= index_level[index_levels]
index_level::= [{basic_index} | ..]
The [..] and [] special symbols refer to the whole sequence.
basic_index::= expr | expr..expr
The second form of basic_index is called a slice.
In basic_indexes, the symbols end and $ both stand for "the last element of",
and are translated to -1.
letter::=
Any character with ASCII code in the range 65-90,97-122,128-255, or any Unicode double-byte character greater than 256. Additional interpreter specific restrictions may be enforced.
printable alphanumeric character::=
letter | digit | _
digit::=
Any in the ASCII range 35,48-57,65-70,97-102. Note that the # sign can appear only before digits, and that the letters a-f and a-f are digits only if the number they are in starts with #.
optname::=
trace | profile | warning | seq_compat | RDS | type_check | def_include | rounding
scope block::=
scope [identifier]
statement
end scope
routine forwarding::= forward routine definition
routine definition::=
[rattr ]identifier({[update ][type ]identifier})
Note that the type of routine arguments needs not be repeated for each argument. if a type item is absent, the type of the argument before is assumed. The first argument must have an explicit type.
rttype::=
routine | reftype | type | procedure | function | handler
rattr::= forward | global
type::=
boolean | object | char | integer | atom | nonatomic type | user-defined
type
user-defined type::=identifier
nonatomic type::=
array(number) [of type] | sequence [of type]
of object is assumed if the of claue is omitted.
number::=
#[-]hexdigit | [- | +]decdigit
hexdigit::=
Any character in ASCII range 48-57,65-70,97-102, or, in other words, '0'-'9', 'A'-'F','a'-'f'. The underscore ("_") is also allowed as visual separator for groups of digits, but underscores must not start or end a number.
decdigit::=
any character in ASCII range 48-57, or '0'-'9'. The underscore ("_") is also allowed as visual separator for groups of digits, but underscores must not start or end a number.
routine::=
routine definition
[var-decl]
[general-code]
end rttype
Note that the last rttype must match the one in routine definition.
var-decl::=
type {identifier[=expr]} | constant {[type] identifier=expr}
Note that the above lists should not be empty. If the type is not specified, the object type is assumed.
struct::=
record identifier({type | _ identifier | _}) end record
general-code::=
procedure call | assignment | action | loop | if
block | select block |
flow | comment | other | dynamic |
with optname |
without optname
dynamic::=
execute(expr) | call_func(expr,list) |
call_proc(expr,list) | call_routine(expr,list) |
resume_execute(expr) | return_execute(expr)
list::={{expr}} | expr
attr::=byval | byref
procedure call::=identifier({[attr ]expr})
assignment::=
identifier[: | operator]=expr |
#({identifier})[operator]=expr |
#({identifier})#[operator]=expr
See specific usage notes about the third form in sections 5.5.2 and 8.5.2 in part A.
operator::= any listed in 1.3.1 in part A.
action::=
label identifier | name general_identifier as identifier | rename general_identifier as identifier | unname general_identifier | ?expr
flow::=
exit [number | identifier] | exif [number | identifier] |
next [number | identifier] | retry [number | identifier] |
break [number | identifier] | return [expr]
Note that break is only allowed inside a select block; exit, next and retry are allowed only inside a loop; exif is allowed only inside an if block; return is allowed only inside routines.
loop::=
lptype lpparm do general-code end lptype
The starting and ending lptype tokens must match. lpparm depends on lptype; see individual entries for more details.
lptype::= for | while | wfor
if block::=
if cond then
general-code
[elsif cond then
general-code]
[else general-code]
end if
cond::=
[not] clause [logical cond]
logical::=and | or
clause::=
routine call | expr rel_op expr | (expr rel_op expr) rel_op::= < | <= | = | != | > | >= expr::= identifier[@meta] | number | expr op expr | (expr op expr) | routine call meta::= name | assigned | value | size | type | id | deftype | scope | format | types | decl_mode
select block::=
select expr
[case shortcond: general-code]
[otherwise general-code]
end select
shortcond::=<
expr | expr thru expr | rel_op expr
You can use the anonymous variable "_" inside a sortcond to refer to the value of the selector of the surrounding select block.
comment::=--characterline_end
whitespace::=tab | space | line_end
line_end::=newline | carriage return
A source file is a file of any extension (if the concept is supported by the host OS) made of (possibly unicode) characters arranged in logical lines. Logical lines start at the top of the file or after a line_end, and they end with a line_end or the end of the file, which does not need any special control character.
Lines are made of whitespace and non-whitespace characters. Consecutive whitespace are coalesced to one. In some cases, an absent whitespace character is assumed, or an existing whitespace is ignored.
def_include | disables priority rules for unprefixed global symbols | |
rounding | turns rounding of floatiing point numbers before compare on | |
RDS | combines seq_compat, def_include and turns rounding off | |
profile | turns profiling facility on | |
seq_compat | turns extension of relational operators to nonatoms on | |
trace | turns trace facility on | |
type_check | turns systematic type checking on assignment on | |
warning[=list] | specifies the warnings to be turned on. No optional list means all kinds of warnings are enabled. |
The warnings issued by OpenEuphoria are as follow:
- UnusedPrivateVar --a private variable is not referenced in the routine
- UnusedFormalParm --a routine does not use some of its formal parameter
- ShadowingDefaultGlobal --a global symbol in default: is being shadowed by another global.
- ShortCircuitSideEffect --an expression with side effects is bypassed because of short circuit evaluation
- StatementAfterReturn --rncountered a statement following a return instruction which cannot be executed.
- VariableIsWriteProtected -- attempt to write to a locked variable.
- OverridingBuiltin -- a symbol from builtin: is being shadowed