Project GBX

Muu yhteisön välinen keskustelu.
Post Reply
User avatar
Sami The Great
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 4:15 pm
Contact:

Project GBX

Post by Sami The Great » Mon May 27, 2019 8:29 am

Hei vaan kaikille pitkästä aikaa! En tiedä lukeeko kukaan täällä enää mitään postauksia, mutta päätin nyt kuitenkin kirjoittaa.

Olen tässä CoolBasicistä insipoituneena kehitellyt vapaa-ajallani omaa virtuaalikonetta, joka nyt pääpiirteittäin toimii. Ideana olisi kasata sen päälle jokin CoolBasic:iä muistuttava Basic syntaksilla toimiva koodikieli ja siihen C++:lla taustalla toimiva pelimoottori.

Virtuaalikone on toteutettu C++:lla ja toimii tulkkiperiaatteella (compiler tekee keksimästäni "assemblystä" tavukoodia, jota virtuaalikone osaa suorittaa). Olen myös toteuttanut oman työkalun, joka osaa reflektoida natiiviluokat virtuaalikoneen käyttöön. Työkalun (build tool) avulla voin nopeasti lisätä uuden C++-funktion/luokan, joka tulee automaattisesti virtuaalikoneen käytettäväksi. Pääideanani oli saada tavukoodi toimimaan saumattomasti natiivikoodin kanssa, jolloin funktioita voidaan kutsua aina mistä vaan olkoon se sitten C++-funktio tai tavukoodissa toteutettu funktio.

Tällä hetkellä toimii funktiot (mukana myös virtual-funktiot), luokat (myös periytyminen), muuttujat, uusien objektien alustus luokasta, objektien propertyjen lukeminen ja kirjoittaminen, dynaaminen taulukko (myös objektitaulukot), dynaaminen map (key value pari), natiivi funktioiden kutsuminen sekä tavukoodiin luodun "event-funktion" kutsuminen C++-koodista.

Code: Select all

#pragma once

#include "GBXCoreLib.h"
#include "GBXPlatform.h"

#if GBX_PLATFORM == GBX_PLATFORM_WINDOWS
#include <Windows.h>
#endif

#include "GBXConsole.gen.h"
GBX_GENERATE_FILE()

namespace GBX
{
	GBX_CLASS(Static)
	class Console
	{
	public:
		GBX_GENERATED_BODY_Console()

	public:

		Console();
		~Console();

		// Prints line of text to the console
		GBX_FUNCTION()
		static void Print(gbx::string Text);

	private:
	};
	GBX_END_CLASS()
}
Esimerkiksi Console-luokassa olen määritellyt "Print"-funktion, joka tulostaa tekstin konsoliin. GBX_FUNCTION()-macro kertoo build toolille, että funktio kuuluu reflektoida, jonka jälkeen työkalu generoi tarvittavat asiat funktion näkymiselle ja käyttämiselle virtuaalikoneessa.

Reflektointi makroille voidaan myös antaa parametreja, jotka muokkaavat generointia. Esim. GBX_CLASS(Static) tekee luokasta staattisen, jolloin kyseisestä luokasta ei voida alustaa objekteja. GBX_FUNCTION(ImplementableEvent)-parametrilla reflektoitu funktio generoi uuden C++-funktion, jota kutsumalla virtuaalikone suorittaa tavukoodiin määrietllyn toteutuksen kyseiselle funktiolle.

Esimerkki eventeistä:

Code: Select all

// Header
GBX_FUNCTION(ImplementableEvent)
void OnUpdate(gbx::float32 DeltaTime, gbx::int32 FrameCount, gbx::boolean SkipFrame);

//Cpp
void TestObjectClass::OnUpdate(gbx::float32 DeltaTime, gbx::int32 FrameCount, gbx::boolean SkipFrame)
{
	ExecuteEventImplementation_OnUpdate(this, DeltaTime, FrameCount, SkipFrame);
}
Kutsumalla OnUpdate-funktiota C++-koodissa ajaa funktion toteutuksen tavukoodissa.

Oma "assembly"-koodini toimii välikielenä, jota olisi tarkoitus muodostaa Basic-syntaksi tyylisestä kielestä. Tällä hetkellä kieli näyttää kutakuinkin tältä:

Code: Select all

$decl_class 1 NameClass ObjectBase
$property string Name
$decl_class 1 NameClassDerived ObjectBase
$parent NameClass
$decl_func 1 string GetName NameClass 1 0 0 0
$RET this	NameClass:Name	<<p
$decl_func 2 void SetName NameClass 0 0 0 1 name string
$EXEC name	<<	this	NameClass:Name	=p
$RET
$decl_func 1 string GetName NameClassDerived 1 0 0 0
$RET this	NameClass:Name	<<p	" added string	.+.
$decl_func 9 int32 Main global 0 0 0 0
$BS
$REG ref obj
$EXEC NameClassDerived	new	obj	=
$EXEC obj	<<	.	"Nimi	NameClass:SetName	(m)
$REG string name
$EXEC obj	<<	.	NameClass:GetName	(v)	name	=
$EXEC name	<<	Console:Print	()
$ES
$RET 0
Koodissa on kaksi luokkaa (NameClass ja NameClassDerived), joista NameClassDerived peritään NameClass:stä. NameClass sisältää yhden string-tyyppisen propertyn, joka voidaan asettaa SetName-funktiolla. GetName-funktio on määritelty virtuaaliseksi ja on ylikirjoitettu NameClassDerived-luokassa. Main-funktiossa luodaan uusi NameClassDerived-tyyppinen objekti, jolle kutsutaan GetName-funktiota (NameClass-versiota), jolloin virtuaali funktion takia kutsutaakin oikeasti NameClassDerived-luokassa määriteltyä funktiota. $EXEC name << Console:Print ()- rivi tulostaa name-nimisen muutujan konsoliin käyttäen ylempänä olevaa C++-luokan Print funktiota.

Seuraavan olisi tarkoitus lähteä miettimään, basic-syntaksia ja kääntäjää sille, joka tuottaa ylläolevaa koodia.
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.

User avatar
Zero
Lead Developer
Lead Developer
Posts: 725
Joined: Sun Aug 26, 2007 2:30 pm
Location: Helsinki, Finland
Contact:

Re: Project GBX

Post by Zero » Mon May 27, 2019 11:23 pm

Mielenkiintoista.

Minusta aina luontevin järjestys oli lähteä liikkeelle kääntäjästä ja toteuttaa tulkki vasta sen jälkeen. Esimerkistäsi ei käy ilmi millä tavalla expressionit on esitetty "assembly-muodossa", mutta jos se eroaa paljon siitä mitä pinokone tavallisesti syö, niin tuo "assembly-muoto" vaikuttaa vähän ylimääräiseltä välivaiheelta ;)

Kerro toki lisää suunnitelmistasi.
CoolBasic henkilökuntaa
Johtava Suunnittelija
CoolBasic V3, CoolBasic Classic

http://www.coolbasic.com/blog

User avatar
Sami The Great
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 4:15 pm
Contact:

Re: Project GBX

Post by Sami The Great » Tue May 28, 2019 8:04 am

Zero wrote:
Mon May 27, 2019 11:23 pm
Mielenkiintoista.

Minusta aina luontevin järjestys oli lähteä liikkeelle kääntäjästä ja toteuttaa tulkki vasta sen jälkeen. Esimerkistäsi ei käy ilmi millä tavalla expressionit on esitetty "assembly-muodossa", mutta jos se eroaa paljon siitä mitä pinokone tavallisesti syö, niin tuo "assembly-muoto" vaikuttaa vähän ylimääräiseltä välivaiheelta ;)

Kerro toki lisää suunnitelmistasi.
Lähdin alunperin liikkeelle kääntäjästä, mutta asiaa vaikeutti se, että en vielä tarkalleen tiennyt miten aion toteuttaa virtuaalikoneen. Toteutin tulkin ensin ja kirjoitin yksikkötestejä testaamaan sen toimintaa, jolloin en tarvinnut mitään testiversiota kääntäjästä.

"Assembly" toimii välikielenä, koska se voidaan kääntää tavukoodiksi "sellaisenaan", jolloin sen muuntaminen tavukoodiksi on äärimmäisen nopeaa. Tämä siksi, että BASIC-syntaksilla varustetut tiedostot voidaan kääntää omiin "Assembly"-tiedostoihinsa ja ainoastaan muutoksen tapahtuessa se pitää kääntää uudestaan "Assemblyksi". BASIC-koodin parserointi on huomattavasti raskaampaa, koska pitää tarkistaa errorit jne. Kääntämällä vain tarvittavat muutokset nopeuttaa käännösprosessia huomattavasti. Lopuksi kaikki asm-tiedostot luetaan ja tungetaan samaan pötköön ja kännetään se tavukoodiksi.

Expressionit käännetään niin, että tulkki osaa lukea operandit ja operaattorit samassa järjestyksessä, kuin "assembly"-koodiin on ne kirjoitettu. Tulkissani myös luokat ja funktiot ovat operandeja ja vasta funktiokutsu tarkoittaa, että otetaan pinosta funktio-operandi ja kutsutaan sitä. Samoin luokilla, jolloin voin antaa myös tietyn luokan tai siitä perittyjä luokkia funktioiden argumenteiksi.

Esim. tämä toimii seuraavasti:

Code: Select all

$EXEC obj	<<	.	"Nimi	NameClass:SetName	(m)
$EXEC-ohje kertoo, että suoritetaan expression joka on "obj << . "Nimi NameClass:SetName (m)". Tokenit erotellaan tabulaattorilla. Jolloin saamme listan eri tokeneita.
  • obj : pusketaan pinoon obj nimisen muuttujan indeksi (indeksi, joka on lisätty rekisteriin aikaisemmin $REG ohjeella)
    << : (Register read operaattori), luetaan obj muuttujan sisältämä arvo, popataan pinosta ja lisätään pinoon muuttujan sisältämä arvo
    . : (Member operaattori), popataan pinosta pointteri (joka osoittaa objektiin) ja asetetaan kyseinen pointteri member contextiksi*
    "Nimi : Pusketaan pinoon literal string
    NameClass:SetName : Pusketaan pinoon funktio operandina
    (m) : (Member funktion kutsuminen), popataan pinosta funktio operandi ja haetaan sen avulla funktion "descriptor" funktio taulusta. Käsketään virtuaalikonetta kutsumaan kyseistä funktiota tämän hetkiselle member contextille.
*Member context on yksi pointteri funktion suorittajaobjektissa, jonka avulla tiedämme mille objektille funktioita kutsutaan

Funktioiden kutsumisessa käytetään kolmea operaattoria:
  • (), staattinen funktiokutsu
    (m), member funktiokutsu, jolloin funktio kutsutaan tietylle objektille
    (v), virtuaalinen member funktiokutsu, jolloin kutsutaan aina viimeiseksi määriteltyä versiota funktiosta (yläluokan funktiota voidaan kutsua virtuaalifunktiosta käyttämällä (m)-operaattoria)
"Assembly"-ohjeet on määritelty seuraavasti koodissani:

Code: Select all

// ASSEMBLY TYPES
#define GBX_ASM_TYPE_VOID		"void"
#define GBX_ASM_TYPE_BOOL		"bool"
#define GBX_ASM_TYPE_UINT8		"uint8"
#define GBX_ASM_TYPE_INT32		"int32"
#define GBX_ASM_TYPE_FLOAT32	"float32"
#define GBX_ASM_TYPE_STRING	"string"
#define GBX_ASM_TYPE_REF		"ref" // Automatically managed object pointer
#define GBX_ASM_TYPE_CLASS		"class"
#define GBX_ASM_TYPE_FUNCTION	"func"
#define GBX_ASM_TYPE_VARIABLE	"var" // Variable as pointer

/** Defines class
* $decl_class [desc len] [name] [native parent name]
*	$parent [name]
	$property [type] [name]

*	Notes:
*	Native parent must be derived from GBXObject
*	Only one parent can have properties and it should be the first parent after decl_class
*	Additional parents are treated as interfaces and can contain only virtual functions
*/
#define GBX_ASM_CLASS_DECL "$decl_class"
#define GBX_ASM_CLASS_PARENT "$parent"
#define GBX_ASM_CLASS_PROPERTY "$property"


/** Defines function
* $decl_func [instruction length] [return type] [name] [class name (global if no class)] [is virtual] [is static] [is event] [param count] [params (name) (type)]
* [Instructions...]
*/
#define GBX_ASM_FUNC_DECL "$decl_func"




// ------ INSTRUCTIONS -----//


/** 
* Returns from function. Follows with expression if value should be returned, instead will be compiled as RETURN_VOID
* $RET [Optional expression]
*/
#define GBX_ASM_INST_RETURN	"$RET"

/**
* Jumps to location inside function. Relative to the first instruction of the function
* $JUMP [gbx::uint32 index]
*/
#define GBX_ASM_INST_GOTO "$JUMP"

/**
* Makes conditional jump. Works as $JUMP but with two possible outcomes
* $COND [gbx::uint32 false jump index] [gbx::uint32 true jump index] [Expression]
*/
#define GBX_ASM_INST_IF "$COND"

/**
* Executes expression
* $EXEC [Expression]
*/
#define GBX_ASM_INST_EXPR "$EXEC"

/**
* Adds variable to function local register
* $REG [variable type] [variable name]
*/
#define GBX_ASM_INST_REGISTER "$REG"

/**
* Begins a new scope. All registered variables after this will belong to this scope
* Note: Compile time only
*/
#define GBX_ASM_INST_BSCOPE	"$BS"

/** 
* Ends current scope. Unregisters all variables in the scope
* Note: Compile time only
*/
#define GBX_ASM_INST_ESCOPE	"$ES"


// ------ Expression instructions -----//

#define GBX_ASM_OP_CALL		"()" // Static function call
#define GBX_ASM_OP_CALL_V		"(v)" // Virtual function call (member)
#define GBX_ASM_OP_CALL_M		"(m)" // Member function call

#define GBX_ASM_OP_MINUS		"(-)" // Unary minus
#define GBX_ASM_OP_ADD		"+"
#define GBX_ASM_OP_SUB			"-"
#define GBX_ASM_OP_MUL		"*"
#define GBX_ASM_OP_DIV			"/"
#define GBX_ASM_OP_MOD		"%"

#define GBX_ASM_OP_AND		"&&"
#define GBX_ASM_OP_OR			"||"
#define GBX_ASM_OP_NOT		"!"
#define GBX_ASM_OP_NOT_EQUAL	"!="
#define GBX_ASM_OP_EQUAL		"=="
#define GBX_ASM_OP_LESS		"<" 
#define GBX_ASM_OP_LESS_EQUAL	"<="
#define GBX_ASM_OP_GREATER		">"
#define GBX_ASM_OP_GREATER_EQUAL ">="
#define GBX_ASM_OP_CONCAT_STR	".+."

#define GBX_ASM_OP_ASSIGN		"="
#define GBX_ASM_OP_ASSIGN_P	"=p" // Assignment of property
#define GBX_ASM_OP_ASSIGN_PN	"=pn" // Assigment of property that is native

#define GBX_ASM_OP_CAST_OBJ	"(->)" // Dynamic cast. Reads pointer from the stack and will replace it with nullptr if the cast fails
#define GBX_ASM_OP_MEMBER		"."
#define GBX_ASM_OP_NEW_OBJ	"new"
#define GBX_ASM_OP_THIS		"this" // Sets member context to this

#define GBX_ASM_OP_READ_VAR	"<<" // Reads registered variable value 
#define GBX_ASM_OP_READ_P		"<<p" // Reads property of the current member context
#define GBX_ASM_OP_READ_PN		"<<pn" // Reads native property of the current member context
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.

User avatar
Zero
Lead Developer
Lead Developer
Posts: 725
Joined: Sun Aug 26, 2007 2:30 pm
Location: Helsinki, Finland
Contact:

Re: Project GBX

Post by Zero » Tue May 28, 2019 8:49 am

Aivan. Nyt tuo kryptisen näköinen syntaksi käy järkeen.

Kääntäjä lienee se kaikkein työläin vaihe projektia. Ja sitä ennen pitäisi olla suunniteltuna [Basic] kielen syntaksi. Oletettavasti olet lähdössä oliopohjaiseen suuntaan siinä?

Huomasin myös että yhtäsuuruusoperaattori on "==" (ja vastaavasti erisuuruus "!="). Entä array access... tavallisilla sulkeilla vai hakasulkeilla? Kannattaa nimittäin olla tarkkana että syntaksi on edelleen samaistuttavissa Basiciin.
CoolBasic henkilökuntaa
Johtava Suunnittelija
CoolBasic V3, CoolBasic Classic

http://www.coolbasic.com/blog

User avatar
valscion
Moderator
Moderator
Posts: 1587
Joined: Thu Dec 06, 2007 8:46 pm
Location: Espoo
Contact:

Re: Project GBX

Post by valscion » Tue May 28, 2019 11:01 am

Kiinnostavaa! Postaile ihmeessä lisää, itse ainakin täällä edelleen käyn vähintään viikottain kattelemassa menoa ja poistelemassa spämmibotteja jos spämmiä meinaa tänne eksyä
cbEnchanted, uudelleenkirjoitettu runtime. Uusin versio: 0.4.1 — Nyt myös sorsat GitHubissa!
NetMatch - se kunnon nettimättö-deathmatch! Avoimella lähdekoodilla varustettu
vesalaakso.com

User avatar
Sami The Great
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 4:15 pm
Contact:

Re: Project GBX

Post by Sami The Great » Wed May 29, 2019 8:30 am

Zero wrote:
Tue May 28, 2019 8:49 am
Aivan. Nyt tuo kryptisen näköinen syntaksi käy järkeen.

Kääntäjä lienee se kaikkein työläin vaihe projektia. Ja sitä ennen pitäisi olla suunniteltuna [Basic] kielen syntaksi. Oletettavasti olet lähdössä oliopohjaiseen suuntaan siinä?

Huomasin myös että yhtäsuuruusoperaattori on "==" (ja vastaavasti erisuuruus "!="). Entä array access... tavallisilla sulkeilla vai hakasulkeilla? Kannattaa nimittäin olla tarkkana että syntaksi on edelleen samaistuttavissa Basiciin.
Tosiaan syntaxsin miettiminen on seuraavana edessä. Ajatus oli, että IF-lauseessa = operaattori kääntyisi equal-operaattoriksi (==), kun se käännetään välikielelle. Array access olisi tarkoitus toteuttaa käyttämällä kaarisulkeita. Virtuaalikoneeni käsittelee kaikki arrayt objekteina, jolloin sille voidaan myös kutsua funktoita. Esim. array.GetSize()
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.

User avatar
Sami The Great
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 4:15 pm
Contact:

Re: Project GBX

Post by Sami The Great » Wed Jun 12, 2019 7:47 am

Sain juuri jonkinlaisen suunitelman valmiiksi kääntäjän arkkitehtuurista. Kääntäjän toteutan C#-kielellä, koska .NET-framework sisältää paljon valmiiksi ominaisuuksia, joiden avulla koodaaminen nopeutuu verrattaen C++:aan. Esim. tiedostojen käsittely yms. Lisäksi pystyn helpommin käyttämään C#-kirjastojani editorista, jonka aion toteuttaa WPF-XAML-applikaationa.

Tällä hetkellä valmiina on myös jonkin asteinen source-tiedostojen käsyttely projektissa sekä esikäsittelijä. Lähdekooditiedostojen muutoksista pidetään kirjaa, jotta vain muuttuneet tiedostot pitää kääntää uudelleen. Käännös tapahtuu taustalla omissa säikeissä per tiedosto, jolloin saadaan kaikki hyöty irti prosessorista. Esim. jos prosessorissa on 8 ydintä, voidaan kääntää 7 tiedostoa samaan aikaan jättäen vapaaksi yksi ydin editorille ja käännös-säikeiden hallinnalle.

Esikäsittelijä säästää tarkat tiedot parseroiduista koodista (rivinumero, column-indeksi sekä tiedosto, josta kyseinen rivi on peräisin), jolloin kääntäjä pystyy myöhemmin kertomaan tarkalleen, missä kohtaa mahdollinen virhe tapahtui. Esikäsittelijä poistaa kommentit, turhat välilyönnit sekä korvaa tabullaattorit neljällä välilyönnillä. Tabulaattorit poistetaan siksi, että ASM-koodissani tabulaattorilla erotellaan expression tokenit. Kommentit toimii C-tyyliin, jossa //-merkin jälkeen kaikki teksti on kommenttia ja /* - */ merkeillä voidaan tehdä monirivisiä kommentteja tai tehdä kommentti koodin väliin.

Seuraavaksi työnalla on symbolien parserointi esikäsitellystä koodista.
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.

User avatar
valscion
Moderator
Moderator
Posts: 1587
Joined: Thu Dec 06, 2007 8:46 pm
Location: Espoo
Contact:

Re: Project GBX

Post by valscion » Wed Jun 12, 2019 9:28 am

Jännää!
cbEnchanted, uudelleenkirjoitettu runtime. Uusin versio: 0.4.1 — Nyt myös sorsat GitHubissa!
NetMatch - se kunnon nettimättö-deathmatch! Avoimella lähdekoodilla varustettu
vesalaakso.com

User avatar
Zero
Lead Developer
Lead Developer
Posts: 725
Joined: Sun Aug 26, 2007 2:30 pm
Location: Helsinki, Finland
Contact:

Re: Project GBX

Post by Zero » Wed Jun 12, 2019 10:24 am

Luin suunnitelmasi pieni virne naamalla. Olisin itse tehnyt sen nimittäin aika pitkälti samalla tavalla (C#, WPF-editori, säikeistetty tokenointi, tiedostojen muutostenhallinta jne).

En ole ihan varma onko sinulla erillinen esikäsittelijä ennen leksikaalista analyysiä (tokenointi) vai onko tuo esikäsittelijä käytännössä se. Joka tapauksessa ei liene tarpeellista muuttaa tabeja välilyönneiksi koska molemmat käsitetään tokenoinnissa white-spaceina (jotka siis vaan heitetään pois).
CoolBasic henkilökuntaa
Johtava Suunnittelija
CoolBasic V3, CoolBasic Classic

http://www.coolbasic.com/blog

User avatar
Latexi95
Guru
Posts: 1164
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Project GBX

Post by Latexi95 » Wed Jun 12, 2019 3:13 pm

Jaahah... Pitäisiköhän sitä taas kaivaa omat kääntäjäprojektit jäistä... Vielä ehtisi saamaan jotain valmiiksi CBMiittiin mennessä.

Itse olen tulkkien sijaan käyttänyt LLVM kirjastoa ja kääntänyt koodit konekieleksi.

User avatar
Sami The Great
Advanced Member
Posts: 485
Joined: Tue Aug 28, 2007 4:15 pm
Contact:

Re: Project GBX

Post by Sami The Great » Wed Jun 12, 2019 8:02 pm

Zero wrote:
Wed Jun 12, 2019 10:24 am
Luin suunnitelmasi pieni virne naamalla. Olisin itse tehnyt sen nimittäin aika pitkälti samalla tavalla (C#, WPF-editori, säikeistetty tokenointi, tiedostojen muutostenhallinta jne).

En ole ihan varma onko sinulla erillinen esikäsittelijä ennen leksikaalista analyysiä (tokenointi) vai onko tuo esikäsittelijä käytännössä se. Joka tapauksessa ei liene tarpeellista muuttaa tabeja välilyönneiksi koska molemmat käsitetään tokenoinnissa white-spaceina (jotka siis vaan heitetään pois).
Esikäsittelijä suorittaa osan tokenoinnista, jonka jälkeen esikäsiteltyyn koodiin tulee vielä suorittaa tarkempi analyysi. Välilyönnit ja tabulaattorit tosiaan poistuu esikäsittelyn jälkeen. Poikkeuksena ovat literal-stringit, joissa tabulaattoreita voi esiintyä vielä käsitelyn jälkeen. Käytännössä esikäsitellystä koodista ollaan suodatettu pois kommentit, tyhjät rivit, vain välilyöntejä tai tabeja sisältävät rivit sekä eroteltu kaikki muu koodi merkkijonoista. Tämän jälkeen käsitelty koodi voidaan tokenoida.

Tokenoitu koodi annetaan symbol-parserille, joka selvittää kaikki mahdolliset luokkien-, muuttujien- ja funktioiden nimet. Symbolien parseroinnin jälkeen tokenoitu koodi voidaan antaa kääntäjälle, joka pystyy tiedettyjen symbolien avulla kääntämään koodin. Symbolit tallennetaan erilliseen Symbol cacheen, josta niitä pystyy etsimään.
http://www.rockodilegames.com
CoolBasickin käyttäjä vuodesta 2004.

User avatar
Zero
Lead Developer
Lead Developer
Posts: 725
Joined: Sun Aug 26, 2007 2:30 pm
Location: Helsinki, Finland
Contact:

Re: Project GBX

Post by Zero » Thu Jun 13, 2019 8:05 am

Kuulostaa siltä että esikäsittelijän tehtävänä on siivota koodi semmoiseen muotoon että se on helpompi tokenoida regexpeillä.

Toinen vaihtoehto on käydä koodi käsin läpi merkki merkiltä ja erotella sekä poimia talteen kaikki tokenit yhdellä kertaa (samalla saat rivin ja sarakkeen jokaiselle tokenille). Tämä yhdistäisi kaksi eri vaihetta yhdeksi ja on todennäköisesti nopeampi.
CoolBasic henkilökuntaa
Johtava Suunnittelija
CoolBasic V3, CoolBasic Classic

http://www.coolbasic.com/blog

Post Reply