Written by
Ardit Xhaferi

Share this post!

Tweet

← ../

Worlds First Albanian Programming Language

April 18, 202217 min read


Table Of Content



Starting Point

I woke up one morning and thought to myself how dumb and funny would a programming language be if it was written in Albanian so for example instead of writting "if" for a if condition we would write "nese" and so here we are.

The goal of this project is to make our own Albanian Programming Language with its own compiler

Project Memz



The Lexer

We are implementing our own version of basic.

BASIC stands for "Beginner's All-purpose Symbolic Instruction Code."

First issue we need user input, so we are going to create shell.py which will read the raw input from the terminal window.

And then we need something that reads our 5HQ1P code that's were the lexer comes in play. The lexer will go through the input character by character and break up the text into a list of tokens.

Lexer Visualised
Lexer Visualised

A program that performs lexical analysis may be termed a lexer, tokenizer, or scanner, although scanner is also a term for the first stage of a lexer. A lexer is generally combined with a parser, which together analyze the syntax of programming languages, web pages, and so forth.

I created a new file named basic.py which will hold the most logic for our language. We will start by making a token class it will have a type and value and a lexer class that will read our SHQIP code character by character and creates the appropriate token classes.

This is our output after finishing the lexer and the token classes:

shqip > 1 + 2    
[INT:1, PLUS, INT:1]



Illegal Character

But what if we come across a character that we didn't define in our tokens, for that we need a error handler that handles this Illegal Character. Here is how it looks after implementation:

shqip > 1 + $   
Gabim Karakteri: '$'
Dosja <stdin>, rreshti 1

1 + $
    ^



The parser

We have the tokens from the lexer but the issue now is we need some order for these operations too, that's where the parser will help us.

I continued by implementing a Parser for the tokens, we need an AST for expressions like: “2 * 7 +3” to know what operations have to be performed and in what order.

An Abstract Syntax Tree, or AST for short, is a deeply nested object that represents code. Usually, AST will come in a form of a Tree representation of the abstract syntactic structure of a source code. The “abstract” acronym is used in the sense that it does not represent every detail appearing in the real syntax, but rather just the structure and a syntactic construct like an if-condition-then expression may be denoted by means of a single node with three branches

Abstract Syntax Tree
The Abstract Syntax Tree

After I finished working on the parser now we have the order structured in parentheses, this is how it looks now:

shqip > (1 + 2) * 3
((INT:1, PLUS, INT:1), MUL, INT:3)

I noticed that the “basic.py” file was getting too big so deconstructed it into more folders and files.

This is how it looks right now but ill probably update it later:

File Structure
File Structure

This is how it looks right now not really familiar with file structures in python but it will change progresively.




Syntax Error

Now again the same as on the lexer, what if we abruptly stop writting a operation in a way that the parser can't create the AST meaning breaking the syntax of our ocde, in that case we need a handler for this Syntax Error.

Gabim Sintakse: Pritet int, float, '+', '-' ose '('
Dosja <stdin>, rreshti 1

1 + 
    ^

And in the error will output what our language expected at that mentioned line.




The Interpreter

Now we have the order created from the parser but we still need excute all these operations in that order that's where Interpreter comes in.

An interpreter is a computer program that is used to directly execute program instructions written using one of the many high-level programming languages.

The interpreter will look at the AST we created earlier with the parser and it will determine what code should be executed.

For example, here we have the binary operation node, and if we come across it with a multiplication sign (*) it should multiply its left and right node together.

AST example for the interpreter.
AST example for the interpreter.

After creating the interpreter class and passing the AST I created methods to visit every node, so if we run an operation now:

shqip > 1 * 3 + 5    
Found bin op node!
Found bin op node!
Found number node!
Found number node!
Found number node!

So we found every node in this expression, so the interpreter is getting in place now.

We implement a number class that we will use to store numbers and do operations.

And we will implemnt an error handler for these operations for example division by zero basically a runtime error.

And now if we do an operation like

shqip > 3 + 3 * 3
12

We will get 12 because it will be executed in the right order, and we can change the order of the operations with parenthesis:

shqip > (3 + 3) * 3
18

Besides that now we can use negative numbers in expressions

shqip > -4 + 5
1

And we can use double negatives, triple and so on

shqip > --4
4



Runtime Error

But now if we try diving something by zero:

shqip > 6 / 0

We will get a nasty python error, because the syntax is fine and we have no illegal characters but during execution time we can’t divide by zero so basically we need to add our own handler for runtime errors.

A program with a runtime error is one that passed the interpreter's syntax checks and started to execute. However, during the execution of one of the statements in the program, an error occurred that caused the interpreter to stop executing the program and display an error message.

So now if we do the division by zero again we should get the runtime error:

shqip > 6 / 0
Gabim Ekzekutimi: Pjestimi me zero?
Dosja <stdin>, rreshti 1

6 / 0
    ^



Traceback

Here we have some python code where we have a divide by zero function, so now when we call the DBZ function **winks at anime fans** python will show the division by zero error but it will also show the trace going back to the functions that were called.

def DBZ():
	return 6 / ( 6-6 )

DBZ()

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    DBZ()
  File "test.py", line 2, in DBZ
    return 6 / ( 6-6 )
ZeroDivisionError: integer division or modulo by zero

So it shows that the error happened in the DBZ function and displays kinda a history from where it was called, even though or language doesn’t have any capabilities for functions right now we need to update our runtime error to display the traceback/context of the error for the future.

A traceback is a report containing the function calls made in your code at a specific point i.e when you get an error it is recommended that you should trace it backward(traceback).

So now after implementing the traceback and running our SHQIP code again

shqip > 3 / 0 
Historiku (kërkesa e re në fund):
Dosja <stdin>, rreshti 1, në <program>
Gabim Ekzekutimi: Pjestimi me zero?

3 / 0
    ^

It’s pointing out where the error is, it’s showing the error type, the line number, and the context that it is in.

Basically, it will show the whole traceback or should I call it our “Historiku” from now on our code will transition more and more into Albanian so I added a table of translations below for clarity.

OriginalTranslation
TracebackHistoriku
FileDosja
LineRreshti
Runtime ErrorGabim Ekzekutimi
CallThirrje
ExpectedPritet
OrOse
IntegerNumër
IntNum
FloatDec / Numër Decimal
IdentifierIdentifikuesi
AssignorPërcaktuesi



Setup

Before continuing with variables, you can already test the language out if you are not interested in the documentation.

Now I'm going to explain how you can run your 5HQ1P code with our custom written complier. The first prerequisite is having python installed.

Installing Python

The installer for python can be found here. As a good documentation should be we will continue only using one OS and the obvious choice is Windows, besides who even uses something else :)

Please don't forget to check the checkbox for adding Python to your PATH.

Python Setup
Installing Python

To determine whether you have Python installed:

  • Open the Command Prompt window or any terminal.
  • When the console window opens, type in:
$ python

If this command is not unrecognized, you need to reinstall Python or troubleshoot.

Link to github

Here is the link to the repository: https://github.com/ArditXhaferi/5HQ1P

In the repository you can find the compiler and the examples codes for 5HQ1P, you can even go inside the compiler and check the code out.

Run

Our complier uses Python to run, you can run it like so:

python3 5HQ1P-Compiler/shell.py

In the root of your project you can add the 5HQ1P-Compiler and the compiler will automatically try to excetue the "index.sq" file in the parent directory, if not found the language will be accessible through the terminal.




Variables finally!

Up until now we were working on operations and you guys probably got criticial thinking that this looks like any other programming language but this is were the fun begins.

And I want to thank CodePulse I've been following his tutorials he's been a great help and don't want to forget Ruslan's Blog check these two out if you want something familiar done.

So let's look at how variables are going to work in 5HQ1P:

To create a variable we are going to use VAR phrase and it should be followed by the variable name and value like this:

VAR ardit = 10

To access the variable we are going to refer to its name like this:

ardit
> 10

And then we can use that variable in our expressions:

ardit * 2
> 20

The first thing we need to update is our lexer, there we have to add 3 new tokens the Keyword, Identifier and Assignor.

After creating the logic on the lexer to detect these three tokens and create their apropiate classes we will move on to the parser.

Variable Structure
Variable Structure

In the parser we first will check if our current token class is equal to any our of keywords for example now we only have the "Var" keyword that stand for "Variabël" in Albanian with wich we will create our variables with.

Then we will check if it is followed by Identifier (the variable name) and a Assignor (=), and in the case if any of these elements are missing we will bomb our poor developer with Syntax Errors.

Syntax Meme

But if the syntax is in order we are going to call a new node that takes in the Identifier and the value of the variable and handles the assigment for the variable.

Symbol Table

And to complete the variables for our language we just need to update the interpreter. For this we are going to implement a symbol table class to keep track of all variable names and their values.

Symbol table is an important data structure created and maintained by compilers in order to store information about the occurrence of various entities such as variable names, function names, objects, classes, interfaces, etc.

Symbol Table
Its a really simple concept

Right now we only have two columns the "Identifier" so the variable name and it's value, but in the future we will add more columns for example type, scope etc.

After implementing the symbol table now we can define INTS & FLOATS in 5HQ1P.

Now lets define some variables and lets print out the symbol table to see how they are getting inserted.

shqip > var a = 3
Symbol Table => {'a': 3}
shqip > var b = 4
Symbol Table => {'a': 3, 'b': 4}
shqip > var c = 3.4
Symbol Table => {'a': 3, 'b': 4, 'c': 3.4}

Now that we know that everything is getting stored in the symbol table correctly we can even do some operations with the numbers like so:

shqip > a + b + c
10.4

If we have the same value for multiple variables we can declare them like so:

shqip > var a = var b = var c = 3.4
Symbol Table => {'a': 3.4, 'b': 3.4, 'c': 3.4}

Declaring a varible it will return that variable value like so:

shqip > var a = 3
3

So that means we can declare variables inside operations:

shqip > 5 * (var a = 3)
Symbol Table => {'a': 3}
15

Basically you can do operations and declare variables at the same time, as you can see the a variable is added to the symbol list.




Comparison Operators

What are they?

Now that we have variables we would like to compare some, if one is bigger smaller or maybe equal and so etc, that's where the comparison operators come in play.

Comparison operators can compare numbers or strings and perform evaluations. Expressions that use comparison operators do not return a number value as do arithmetic expressions. Comparison expressions return booleans either 1 , which represents true, or 0 , which represents false.

Symbol Table
Every operation here should return true



How do we need them?

What do we want here exactly? If the comparative operation is correct it should return the number 1 (True):

shqip > 3 == 3
1

And if the statment is incorrect:

shqip > 3 == 6
0



How to integrate it?

The first step is always on the lexer, there we detect when we use these four as our starting characters for a expression ("!", "=", ">", "<") and we check if they are continued by a "=" or their appropiate character.

If they fullfill the criteria we will then create the apropiate token, if not then we will output a new Expected Chararcter Error.




Fixing the priority

And then in our parser I continued to fix the priority for the comparison operation, because if we want to do a expression like so:

3 + 3 == 9 + 9

We would want our parenthesis(priority) to look like this:

(3 + 3) == (9 + 9)

Rather ran looking like this, it wouldnt make much sense:

3 + (3 == 9) + 9

So basically the comparison operation will take less priority. But that's not the case for variable assigment that's where the comparison operation will take more priority.

var a = (5 == 5) ✓
var (a = 5) == 5



Making it work with our AST

And finally in the interpreter based on the tokens that we generated on the lexer we will excute their methods.

For the equals token we would check if both child nodes are equal like so:

Comparison Operators
AST example with Comparison Operators



Testing

And now after everything is working we can test all of comparisons:

shqip > 5 > 3
1
shqip > 3 < 5
1
shqip > 3 == 3
1
shqip > 3 != 9
1
shqip > 3 >= 1
1
shqip > 1 <= 3
1



Logical Operators

What are they?

Now what if we want to use multiple comparisons and create some form of logic with it?

That's where our logical operators come into play, we have "edhe" which should return true if both comparisons are true.

We have "ose" which should return true if atleast one of the comparisons is true.

And finally we have "jo" which takes truth to falsity and vice versa.

A logical operator is a symbol or word used to connect two or more expressions such that the value of the compound expression produced depends only on that of the original expressions and on the meaning of the operator. Common logical operators include AND, OR, and NOT.

Logical Operators
Every operation here should return true



Integration

Most of the logic will be implemented the same as we did it for the comparison operators.

So after working on the lexer and parser our AST would something like this:

Logical Operators
AST example with logical operators



Results

And finally we can use "edhe", "ose" and "jo"

shqip > 1 == 1 edhe 1 == 2
0

shqip > 1 == 1 ose 1 == 2
1

shqip > jo 1 == 1
0



Booleans

We are going to add some hardcoded variables to our symbol table that we call Booleans.

A boolean is a logical data type that can have only the values true or false.

For True we are going to use Bon:

shqip > bon         
1

And for false we are going to use Sbon:

shqip > sbon
0



IF Statement

Now we are going to integrate the IF Statement into 5HQ1P, like in most languages we will have our IF key but we will name it NESE. This key will be followed by a condition.

These two keys will be followed by the THEN key but we are renaming it to TANI and then finally we will define our expression.

This is what we call a inline if (a if that you can write in one line) in the future we will implement multi-line support.

IF Statment Logic
IF Statement Logic
nese 3 >= 1 tani var a = 3

We are going to start by checking on the parser if we are using the NESE token and if its followed by the TANI key.

And we will create the logic so we can accept 0 or more TJETER (ELIF) keys and a optional PERNDRYSHE (else) key at the end of our statement.

IF Statment Logic
IF Statement Logic



IF, ELSE IF and ELSE example in 5HQ1P

nese 
    (3 == 1)
tani 
    var a = 3
tjeter 
    (3 == 2)
tani 
    var a = 2
perndryshe 
    var a = 1

//Result
a = 1



Loops

Now we are going to implement loops, a loop is a sequence of instruction s that is continually repeated until a certain condition is reached.

Typically, a certain process is done, such as getting an item of data and changing it, and then some condition is checked such as whether a counter has reached a prescribed number.

Loops are important
Loops are important...



For Loop

A for loop is used for iterating over a sequence (that is either a array, a object or a string).

This is used to repeat a specific block of code a known number of times. For example, if we want to check the grade of every student in the class, we loop from 1 to that number. When the number of times is not known before hand, we use a "While" loop.

Now in 5HQ1P we are going to use PER instead of FOR it will work like this.

For Loops in 5HQ1P
For Loops in 5HQ1P

Testing

#Define our variable
shqip > var result = 3
3

#Run our for loop, it will iterate 6 times
shqip > per i = 0 deri 6 tani var result = result * 3

#The result is correct
shqip > result
2187



Using steps

We can define the step(increment value) in our For Loop with the our HAP keyword like this:

#Define our variable
shqip > var result = 0

#Run our for loop, it will iterate 3 times because of our step
shqip > per i = 0 deri 10 hap 3 tani var result = result + i

#The result is correct
shqip > result
18



While Loop

A "While" Loop is used to repeat a specific block of code an unknown number of times, until a condition is met.

For example, if we want to ask a user for a number between 1 and 10, we don't know how many times the user may enter a larger number, so we keep asking "while the number is not between 1 and 10".

You need to be careful using While Loops
You need to be careful using While Loops u may never return home

Now in 5HQ1P we are going to use DERISA instead of WHILE it will work like this.

While Loops in 5HQ1P
While Loops in 5HQ1P



Testing

#Define our variable
shqip > var i = 3
3

#Run our while loop, it will loop until the statement is false
shqip > derisa i < 9 tani var i = i + 1

#Check the result
shqip > i
9



Functions

A function is simply a “chunk” of code that you can use over and over again, rather than writing it out multiple times.

Functions enable programmers to break down or decompose a problem into smaller chunks, each of which performs a particular task.

Now in our language the way that we will define a function will be with the FUNKSION keyword, like this:

Function in 5HQ1P
Function in 5HQ1P

Testing

#Define our function
shqip > funksion sum(a, b) -> a + b
<funksioni sum>

#Run our function
shqip > sum(5, 5)
10

Validating arguments

This is how we handle function calls when you pass too few arguments:

#Call our function
shqip > sum()
Historiku (thirrja më e re në fund):
Dosja <stdin>, rreshti 1, në <program>

#Too few arguments passed
Gabim Ekzekutimi: ku i ki 2 parametra n'sum'

sum()
^^^

And this is how we handle when you pass to many arguments:

#Call our function
shqip > sum(5, 7, 4)
Historiku (thirrja më e re në fund):
Dosja <stdin>, rreshti 1, në <program>

#Too many arguments passed
Gabim Ekzekutimi: shum parametra bre n'sum'

sum(5, 7, 4)

hope these error logs seem funny to anyone

Assigning functions to variables

#Assign our variable to a function
shqip > var shuma = funksion (a) -> a + 5
<funksioni <panjohur>>

#Call the variable
shqip > shuma(5)   
10

Testing traceback

#Define our function
shqip > funksion division(a) -> a / 0
<funksioni division>

#Call the function and check the traceback
shqip > division(123) 
Historiku (thirrja më e re në fund):
Dosja <stdin>, rreshti 1, në <program>

#It shows from which function it was called
Dosja <stdin>, rreshti 1, në division
Gabim Ekzekutimi: Pjestimi me zero?

funksion division(a) -> a / 0
                            ^



Strings

Most programming languages have a data type called a string, which is used for data values that are made up of ordered sequences of characters, such as "hello world".

A string can contain any sequence of characters, visible or invisible, and characters may be repeated.

Now in 5HQ1P we can create string like this:

#Define normal string
shqip > var a = "ardit"
"ardit"

#Define string with qoutes
shqip > "String with \"quotes\""
"String with "quotes""

#Define string with new lines
shqip > "String with \nnewlines"
"String with 
newlines"

Concatenate strings

#Concatenate strings
shqip > var a = "ardit-" + "tidra"
"ardit-tidra

Multiplying strings

#Multiplying strings
shqip > "hello " * 3
"hello hello hello "

Arrays

An array is a data structure, which can store a fixed-size collection of elements of the same data type.

An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

Arrays in 5HQ1P
Arrays in 5HQ1P start at 0 •`_´•

In 5HQ1P like in most programming languages we can define our array with a opening and closing bracket.

#Defining a array
var a = [1, 2, 3]

Pushing items

If we want to push a item into our array we can do it with the plus operator.

#Define our array
shqip > var a = [1, 2, 3]
[1, 2, 3]

#Append one item
shqip > a + 4
[1, 2, 3, 4]

Indexing

We can get a specific item from the list with the <= operator.

#Define our array
shqip > var a = [1, 2, 3]
[1, 2, 3]

#Get the element with index 0
shqip > a <= 0
1

Removing items

We can remove a specific item from the list with the - operator.

#Define our array
shqip > var a = [1, 2, 3]
[1, 2, 3]

#Delete the element with index 0
shqip > a - 0
[2, 3]

Mergin Arrays

We can merge arrays with the EDHE operator

#Define our first array
shqip > var a = [1, 2, 3]
[1, 2, 3]

#Define our second array
shqip > var b = [4, 5, 6]
[4, 5, 6]

#Merge our arrays
shqip > var c = a edhe b
[1, 2, 3, 4, 5, 6]



Built-In Functions

A built-in function is a function that is already available in a programming language, application, or another tool that can be accessed by end users.

For example, most spreadsheet applications support a built-in SUM function that adds up all cells in a row or column.

Now on our case we just need to use the function class we already created and extened it into a new built-in class were we will have all of the logic for the built-in functions.




Print-printo() function

We will start of simple, this method will print text on the console:

#Printing out string
shqip > printo("ardit")
ardit

#Printing out lists
shqip > printo(["ardit", "xhaferi"])
[ardit, xhaferi]



Input-shtyp() function

The Shtyp() function allows user input.

The input functions don't expect any arguments.

#The input method will simple return the user input.
shqip > shtyp()
> wow
"wow"

#We can save the user input into a variable.
shqip > var emri = shtyp()
> ardit

#And if we check the variable we should have our input.
shqip > emri
"ardit"



Input-shtyp_num() function

The shtyp_num() function allows user input but only if its a number.

#Saving the number input into our variable
shqip > var mosha = shtyp_num()
> 10

#Checking the var
shqip > mosha
10

#And if we input string for example we will get this validation error.
shqip > var mosha = shtyp_num()
> ardit
'ardit' duhet te jete nje numer.



is_number-eshte_num() function

The eshte_num() function checks if the passed argument is a number.

Accepts only one argument.

#Check if the argument is a number
shqip > eshte_num(13)   
1

#Strings of course fail this test
shqip > eshte_num("ardit")
0

#If we try passing more arguments
shqip > eshte_num(1, 2)
Historiku (thirrja më e re në fund):
Dosja <stdin>, rreshti 1, në <program>
Gabim Ekzekutimi: 2 shum parametra bre n'<funksioni i integruar eshte_num>

eshte_num(1, 2)
^^^^^^^^^^^^^^



is_string-eshte_tekst() function

The eshte_tekst() function checks if the passed argument is a string.

#Check if the argument is a string
shqip > eshte_tekst("ardit")   
1

#Integers of course fail this test
shqip > eshte_tekst(13)
0



is_list-eshte_list() function

The eshte_list() function checks if the passed argument is a list.

#Check if the argument is a list
shqip > eshte_list(["ardit", 1])   
1

#Strings of course fail this test
shqip > eshte_list("ardit")
0



is_fun-eshte_fun() function

The eshte_fun() function checks if the passed argument is a function.

#Define our function
shqip > funksion ardit() -> printo("ardit")
<funksioni ardit>


#Check if the argument is a function
shqip > eshte_fun(ardit)   
1

#Strings of course fail this test
shqip > eshte_fun("ardit")
0



append-shto() function

The shto() function adds a item to your desired list.

The first argument has to be the list and the second argument will be the item you want to add.

#Define our array
shqip > var a = []

#Add a item with the shto function
shqip > shto(a, "ardit")

#Check our variable
shqip > printo(a)
[ardit]

#We can even have nested lists
shqip > shto(a, ["ardit", "xhaferi"])

shqip > printo(a)
[ardit, [ardit, xhaferi]]



Pop-fshij() function

The fshij() function removes a item from your list at a specific index.

The first argument has to be the list and the second argument will be the index.

#Define our array
shqip > var a = ["ardit", "xhaferi"]

#Add a item with the shto function
shqip > fshij(a, 1)

#Check our variable
shqip > printo(a)
[ardit]



Extend-zgjat() function

The zgjat() function copies the items of the second list to the first so it basically extends it.

The first and second argument will have to be lists.

#Define our first array
shqip > var a = ["ardit", "xhaferi"]

#Define our second array
shqip > var b = ["nashta", "programer"]

#Extend our first list with the items of the second list
shqip > zgjat(a, b)

#Check our variable
shqip > printo(a)
["ardit", "xhaferi", "nashta", "programer"]



Len-sa() function

The sa() (as in "sa copa") function returns the number of items in an object. When the object is a string, the len() function returns the number of characters in the string.

The first will have to be a list.

#Define our array
shqip > var a = ["ardit", "xhaferi", "coding"]

#Print out list length
shqip > print(sa(a))
Expected Result: 3



Multi-line statements

We are going to change the logic of our language quite a bit, now instead of executing a single expression we will execute a list of expressions seperated by new lines or by semicolons.

And shortly after we will start reading our code directly from .sq files

#Statements seperated by newlines
printo("Pershdentje Bote")
printo("Pershdentje Bote")

#Statements seperated by semicolons
printo("Pershdentje Bote"); printo("Pershdentje Bote")



Multi-line IFs, FORs and FUNs

We are going to update the if expression, so if we put the expression on the same line it will only exceute that expression

Now we can write down multiple expressions on newlines but we have to end it with the fund expression.

The same logic applies to For loops, While loops and Functions

Multi-line IF in 5HQ1P
Multi-line IF in 5HQ1P



Return-Kthe

We will add the return-kthe keyword to our language more specifically inside our functions in 5HQ1P.

Return statement is a special statement that you can use inside a function or method to send the function's result back to the caller. A return statement consists of the return keyword followed by an optional return value.

It will look something like this:

fun plus(a, b)
    kthe a + b
fund

And we can return without a value if we want to leave the function early.

fun plus(a, b)
    nese ... tani
        kthe
    fund
fund

Testing

#We will create the function that should return the number 5
shqip > 
    funksion test(); 
        var a = 5; 
        kthe a; 
    fund

#And if we call this function
shqip > test()

#It will return 5
shqip > 5



Breaks-Kpute

Break-kpute is a loop control statement. It is used to control the sequence of the loop.

Suppose you want to terminate a loop and skip to the next code after the loop; break will help you do that.

This is how it looks in the for loop:

per i = 0 deri 10
    nese kushti tani
        kpute
    fund
fund

This is how it looks in the while loop:

#We are going to loop through
#But we are going to 'break' on number 5
shqip > 
    per i = 0 deri 10 tani; 
        nese i == 5 tani; 
            kpute; 
        fund; 
        var a = a + i; 
    fund

#And if we check our variable we will see that we stopped counting at 5
shqip > a
[0, 1, 2, 3, 4]



Continue-Vazhdo

The continue-vazhdo keyword is used to end the current iteration in a for loop (or a while loop), and continues to the next iteration.

Testing

#We are going to loop through every number expect on 4;
#On 4 we are going to 'continue'

shqip > 
    per i = 0 deri 10 tani; 
        nese i == 5 tani; 
            vazhdo; 
        fund; 
        var a = a + i;
    fund

#And if we check our variable we will see that we have all numbers expect 4
shqip > a
[0, 1, 2, 3, 5, 6, 7, 8, 9]

While with continue and break

#Define our array
shqip > var a = []

#Define our index
shqip > var i = 0

#Create our while loop with 'kpute' and 'vazhdo'
shqip > 
    derisa i < 9 tani; 
        var i = i + 1; 
        nese i == 4 tani vazhdo; 
        nese i == 8 tani kpute; 
        var a = a + i; 
    fund

#Check if everything is fine
shqip > a
[1, 2, 3, 5, 6, 7]



Comments

Comments in 5HQ1P begin with a hash mark ( ~ ) and whitespace character and continue to the end of the line.

~ This is a comment



Run-Zbato

Now with the Zbato statement we can excecute our code from external files.

index.sq > ~ printo("Pershendetje bote")

# Execute our file
shqip > zbato("index.sq")
Pershendetje bot

Published April 18, 2022, by Ardit Xhaferi.

You don't have to share this post, but if you feel like it:

Tweet