LDPL 19 Standard
Revision 2

Index

About this Document

Revision 2 (2019-01-30): Added EXIT and STORE LENGTH OF. Fixed some typos.

Revision 1 (2019-01-28): modified the EXECUTE statement description as it didn't match its backus-naur self. Now SUB-PROCEDURES should be closed with an END SUB-PROCEDURE statement instead of a RETURN. Added CONTINUE, BREAK, EXECUTE AND STORE OUPUT and EXECUTE AND STORE EXIT CODE statements. Fixed some typos.

LDPL 19 base (2019-01-24): initial release.

About this Document

The LDPL Commitee have compiled this document with the desire to teach and standarize the LDPL programming language. It should be considered a limiting boundary for any LDPL implementation, that should not include any extra commands or definitions nor lack any of the former. If it did, it should be marked accordingly with the names LDPL-ALT, Alternative LDPL or something similar that implies that it's not a standard implementation.

This document is definitive and backwards compatible, and any future revisions that build upon it will only add features to the language, not remove nor change any functionality and, as such, any code written for a previous LDPL specification should continue to run as it did with the specification it was written for.

Feedback, corrections and suggestions are welcome, both on the main LDPL repository or by e-mail to mdelrio (at) dc.uba.ar. New commitee members are also welcome.

The Language

LDPL (Lartu's Definitive Programming Language) was designed from the beginning to be an excessively expressive programming language, one that can be read from top to bottom without pausing to ponder what symbols mean or what a sentence does. As such, it is mostly written in a series of statements that mimics plain English, with the desire that it can be understood by anybody.

LDPL also aims to suppress unreadable code and redundancy by only having one way of doing anything. What a command does should never overlap with the purpose of another and, as such, every LDPL command does one and only one thing. Every line is a step further towards the completition of an algorithm, no more, no less.

Structure of a LDPL Source Code

LDPL was designed to be a rigidly structured programming language and, as such, variable declarations and the rest of the code procedure are separated in two diferent, mutually exclusive sections within a source file. Variable declarations should be placed within the DATA section, while the rest of the code should be placed inside the PROCEDURE section. Further subprocedures should be placed also within the PROCEDURE section, inside their own SUB-PROCEDURE subsection.

Bearing this in mind, the basic skeleton of a LDPL source code will look like this:

DATA:

PROCEDURE:

The DATA section can be obviated if no variables are declared.

Every statement in LDPL has to be on its own line. Thus, statements are separated by line breaks and it's not possible to have two statements on the same line.

Comments in LDPL are denoted with a hash symbol ('#') and can be placed both on their own line or at the end of a line that already contains a statement. Everything after the hash is considered to be part of the comment and, therefore, not executed nor compiled.

DATA: #This is the DATA section

PROCEDURE:
  #This is a comment within the PROCEDURE section!

The preferred file extension for LDPL source codes is '.lsc' (LDPL Source Code). '.ldpl' should also be accepted if the later interfered with existing file extensions.

Data Types

LDPL natively supports the NUMBER and TEXT data types. It also supports VECTORS of values of such types.

The NUMBER data type, as its name suggests, depicts numeric values. It's recommended that it be represented internally as a binary64 double-precision floating-point format number as defined by the IEEE 754.

Both variables and numeric constants can be members of the NUMBER type.

The TEXT data type, as its name suggests, represents alphanumeric strings. In the interest of supporting as many locales as possible, LDPL should be utf-8 encoded to be compatible with Unicode. A TEXT maximum length is explicitly not defined and it should be limited only by the amount of available memory on the system.

Both variables and string constants can be members of the TEXT type.

The VECTOR data type is not a type itself but a collection of NUMBER or TEXT variables. This implies that only variables can be members of the VECTOR type, as collections of constants (and thus, constant VECTORs) are not present in the language.

VECTORs superficially resemble arrays in other programming languages but with fundamental differences. In LDPL, there's no need to specify the size of a VECTOR before you start to use it. Additionally, any number or string in LDPL may be used as an array index, not just consecutive integers.

VECTORs, as collections of NUMBER or TEXT variables, can only have one defined type at any given time: TEXT or NUMBER. A single VECTOR is not capable of storing both numeric and alphanumeric values.

DATA Section

As stated here, LDPL programs are divided in two sections, one of them being the DATA section. The DATA section is where variables are declared. In no other part of a LDPL source can variables be declared. If no variables are declared, the DATA section can be obviated.

All variables in LDPL are global (LDPL has no concept of scope) and have a defined data type.

The DATA section is defined and preceded by the DATA: keyword, as shown in this example. On every line within the DATA section (that is, on every line after the DATA: keyword and before the PROCEDURE: keyword) one and only one variable can be declared. The syntax for declaring a variable in LDPL is

variable name IS data type

Variable names can contain any character except for spaces and colons (':').

Available data types are NUMBER, TEXT, NUMBER VECTOR and TEXT VECTOR.

A DATA section cannot contain anything but variable declarations, comments and empty lines. Following the skeleton shown here, the example could be completed further like this:

DATA: #This is the DATA section
  myNumber IS NUMBER
  #Next I'm going to declare a text vector
  niceTextVector IS TEXT VECTOR

PROCEDURE:
  #This is a comment within the PROCEDURE section!

PROCEDURE Section

As stated here, LDPL programs are divided in two sections, one of them being the DATA section, the other being the PROCEDURE section. The PROCEDURE section is where all the code of a LDPL program that is not a variable declaration is written. A LDPL program must contain a PROCEDURE section, even if it's empty. Compilation will fail otherwise.

Within the PROCEDURE section, as said here, every line can contain either a comment, a statement, a statement and a comment or be empty. No two statements can be written on the same line.

PROCEDURE:
  #A comment
  STORE 5 IN myVariable
  STORE 6 IN myOtherVariable #A statement and a comment

Available statements will be explained further in the following sections of this document.

Code within the PROCEDURE section is executed from top to bottom, skipping SUB-PROCEDURE sections, unless explicitly called.

About Statements

LDPL is not a case sensitive language. Variables called myVar and MYVAR are considered to be the same variable, the same with subprocedure names and statements of any kind.

Usage of Variables

In the following sections you will see excerpts of code like this one:

STORE NUMBER-VAR or NUMBER IN NUMBER-VAR

Notice the parts in magenta. Parts of procedures colored like that mean that they should be replaced by whatever they say in that color. In the example above, the first replazable part can be substituted with the name of a variable of NUMBER type or by a NUMBER constant.

Available replacement values are:

Usage of Vectors

Vectors in LDPL aren't more than a collection of variables. When you declare a vector, you declare a structure that lets you store something of its type on any subindex of the variable. For example, say you declare the vector myVector:

DATA:
 myVector IS NUMBER VECTOR

Then you can use myVector as a multivariable with various indexes where you can store NUMBERs.

DATA:
 myVector IS NUMBER VECTOR
PROCEDURE:
 STORE 5 IN myVector:1 #Stores 5 in the subindex 1 of myVector
 STORE -10.2 IN myVector:5 #Stores -10.2 in the subindex 5 of myVector

Vector subindexes can't just be constant NUMBERs, though. They can also be NUMBER variables, TEXT and TEXT variables, or even subindexes of other arrays. For example:

DATA:
 myVector IS NUMBER VECTOR
 myOtherVector IS NUMBER VECTOR
 myVar IS NUMBER

PROCEDURE:
 STORE 17 IN myVar
 STORE 1 IN myVector:"hello" #Stores 1 in the subindex "hello" of myVector
 STORE 7 IN myVector:myVar #Stores 7 in the position of index value of myVar
 STORE 3 IN myVector:myOtherVector:4
 #Stores 7 in the position of index value of myVar of myOtherVector

Plase note that as a VECTOR is a collection of variables, a single index of a VECTOR is a variable in itself. This means that a VECTOR with a subindex can be used in any position where you could use a variable of the same type of the vector.

Statements: Control Flow

STORE

IF

WHILE

BREAK

CONTINUE

SUB-PROCEDURE

CALL SUB-PROCEDURE

RETURN

EXIT

Statements: Arithmetic Operations

ADD

SUBTRACT

MULTIPLY

DIVIDE

MODULO

ABS

Statements: Text Operations

JOIN

GET CHARACTER AT

STORE LENGTH OF

Statements: Input / Output

DISPLAY

ACCEPT

EXECUTE

EXECUTE AND STORE OUTPUT

EXECUTE AND STORE EXIT CODE

Language Grammar

The grammar is listed below in Backus-Naur form. In the listing, an asterisk ("*") denotes zero or more of the object to its left; parentheses group objects; and an epsilon ("ε") signifies the empty set. As is common in computer language grammar notation, the vertical bar ("|") distinguishes alternatives, as does their being listed on separate lines. The symbol "CRLF" denotes a carriage return (usually generated by a keyboard's "Enter" key).

# DATA TYPES
digit ::= 1 | 2 | ... | 9 | 0
letter ::= A | B | C | ... | a | b | c | ... | á | ñ | あ | ... | 仮 | ... | ر | ...
procedure-name ::= letter letter*
string ::= " letter* "
number ::= (ε | - ) digit digit* (ε | (. digit digit*))

# VARIABLE DEFINITIONS
num-var-name ::= letter letter*
str-var-name ::= letter letter*
var ::= num-var | str-var
num-var-definition ::= num-var-name IS NUMBER (VECTOR | ε)
str-var-definition ::= str-var-name IS TEXT (VECTOR | ε)
num-var ::= num-var-name (: (number | num-var | string | str-var))*
str-var ::= str-var-name (: (number | num-var | string | str-var))*
var-definition ::= num-var-definition | str-var-definition

# STATEMENTS
block ::= (statement \n)*
statement ::= display | accept | join | store | while | if | addition | subtraction | multiplication | division | modulo | abs | subroutine-call | get-char | sys-exec | return | break | continue | get-length | exit
display ::= DISPLAY (var | string | number | CRLF) (var | string | number | CRLF)*
accept ::= ACCEPT var
join ::= JOIN (var | string | number) AND (var | string | number) INTO str-var
str-store ::= STORE (str-var | string) IN str-var
num-store ::= STORE (num-var | number) IN num-var
store ::= str-store | num-store
num-while ::= WHILE (num-var | number) (relop1 | relop2) (num-var | number) DO block REPEAT
str-while ::= WHILE (str-var | string) relop1 (str-var | string) DO block REPEAT
while ::= num-while | str-while
num-if ::= IF (num-var | number) (relop1 | relop2) (num-var | number) THEN block ((ELSE block) | ε) END-IF
str-if ::= IF (str-var | string) relop1 (str-var | string) THEN block ((ELSE block) | ε) END-IF
if ::= num-if | str-if
addition ::= ADD (num-var | number) AND (num-var | number) IN (num-var)
subtraction ::= SUBTRACT (num-var | number) FROM (num-var | number) IN (num-var)
multiplication ::= MULTIPLY (num-var | number) BY (num-var | number) IN (num-var)
division ::= DIVIDE (num-var | number) BY (num-var | number) IN (num-var)
modulo ::= MODULO (num-var | number) BY (num-var | number) IN (num-var)
abs ::= ABS num-var
subroutine-call ::= CALL SUB-PROCEDURE procedure-name
get-char ::= GET CHARACTER AT (num-var | number) FROM (string | str-var) IN str-var
get-length ::= STORE LENGTH OF (string | str-var) IN num-var
exit ::= EXIT
sys-exec ::= EXECUTE (string | str-var) ((AND STORE EXIT CODE IN num-var) | (AND STORE OUTPUT IN str-var) | ε)
return ::= RETURN
break ::= BREAK
continue ::= CONTINUE

# RELATIONAL OPERATORS
relop1 ::= (IS EQUAL TO) | (IS NOT EQUAL TO)
relop2 ::= (IS GREATER THAN) | (IS LESS THAN) | (IS GREATER THAN OR EQUAL TO) | (IS LESS THAN OR EQUAL TO)

# CODE SECTIONS
data-section ::= DATA: \n (var-definition \n)*
procedure-section ::= PROCEDURE: block
sub-procedure-section ::= SUB-PROCEDURE procedure-name: block RETURN (block | ε)

# VALID CODE
valid-code ::= (data-section | ε) procedure-section sub-procedure-section*

Known Implementations

That's it

Go Home

Wiby.me Best Viewed With Any Browser Compiled with HTMLKoala