Jump to content

EasyCodeIt - cross-platform AutoIt implementation


Recommended Posts

5 hours ago, TheDcoder said:

Sorry guys but it looks like I need a couple more days before I can start work on the parser.

Don't worry bud, I have faith in you, and have already come to terms with the imminent release of EasyCodeIt, just after my demise, some time in the future (far hopefully), in the full knowledge you will dedicate it to my memory. :muttley:

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

No way! I promise to finish it before your time runs out... so that you can finally enjoy the fruits of Linux without any restrictions :lol:

Disclaimer: The above mentioned text should not be, in any way, be constructed into a contract, promise, guarantee or any other type of bond with liability :muttley:

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

2 hours ago, TheDcoder said:

so that you can finally enjoy the fruits of Linux without any restrictions

Inherent restrictions of Linux aside. :P

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

8 hours ago, TheSaint said:

Inherent restrictions of Linux aside. :P

Now you are just being delusional, there is no such thing :P

Anything and everything is possible in Linux, unlike Windows where you are restricted to the capabilities it provides. Linux is more open and innovative, anyone can extended it to make it work however they like.

You just need to know how things work in Linux, which is different from Windows obviously.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Yeah yeah, believe what you want nerdy. :P 

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

  • 2 weeks later...

Thanks @Skysnake, any help is appreciated, I am working on the new parser right now and I will certainly need some testers in the coming weeks. Why not join the forum (link in signature) to keep up to date? I am planning to coordinate all testing and development there.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

18 hours ago, Skysnake said:

I cannot really develop, but I am willing to test.

Now that’s impressive! 

Developers can be like electric guitar shredders, producing a dazzling but often ego-driven performance.

And everyone wants to be one.

Good QA people are like bassists, committed to the groove, listening to the other players.

And so hard to find a good one!

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

  • 3 weeks later...
Quote

Damn, another month already? I got way too caught up with work and never found the time to actually start writing code... until today :)

I started small, rewrote the OG version of the parser in flex:


%{
#include <stdlib.h>
#include <string.h>

char *token_str = NULL;
size_t token_len = 0;

#define YY_USER_ACTION free(token_str); token_str = strndup(yytext, token_len = yyleng);

enum { // Token Types
	UNKNOWN = 420,
	WS,
	COMMENT, DIRECTIVE,
	NUMBER, STRING, BOOL,
	WORD,
	MACRO, VARIABLE,
	OPERATOR, BRACKET, DOT, COMMA,
};

%}

WS	[ \t\r\n]+
NL	\r?\n?

COD [;#][^\r\n]*

%%

{WS} ;

[;#][^\r\n]* return *yytext == ';' ? COMMENT : DIRECTIVE;

.	return UNKNOWN;

%%

#include <stddef.h>
#include <stdio.h>

static void print_token(char *str, size_t len, int type) {
	puts("---### TOKEN ###---");
	char *token_type;
	switch (type) {
		case UNKNOWN:
			token_type = "Unknown";
			break;
		case WS:
			token_type = "Whitespace";
			break;
		case COMMENT:
			token_type = "Comment";
			break;
		case DIRECTIVE:
			token_type = "Directive";
			break;
		case NUMBER:
			token_type = "Number";
			break;
		case STRING:
			token_type = "String";
			break;
		case WORD:
			token_type = "Word";
			break;
		case MACRO:
			token_type = "Macro";
			break;
		case VARIABLE:
			token_type = "Variable";
			break;
		case OPERATOR:
			token_type = "Operator";
			break;
		case BRACKET:
			token_type = "Bracket";
			break;
		case DOT:
			token_type = "Dot";
			break;
		case COMMA:
			token_type = "Comma";
			break;
		default:
			token_type = "Unnamed";
			break;
	}
	fputs("Type: ", stdout);
	puts(token_type);
	fputs("Data: ", stdout);
	puts(str);
}

int main(void) {
	int type;
	for (;;) {
		type = yylex();
		if (!type) break;
		print_token(token_str, token_len, type);
	}
	return 0;
}

At the moment it only supports comments and directives (which are basically the same), I believe that this is exactly what I started with when I wrote the first parser. Will post updates as I expand on the parser, a grammar definition will come soon once I am satisfied with the amount of tokens I can scan, shouldn't be much effort since it is all just regex.

Here is how it works:


TheDcoder@arch /m/d/P/C/E/parser (master)> flex lexer.l && cc lex.yy.c -lfl
TheDcoder@arch /m/d/P/C/E/parser (master)> cat /tmp/comments.au3 | ./a.out
---### TOKEN ###---
Type: Directive
Data: #include <test>
---### TOKEN ###---
Type: Comment
Data: ; comment
---### TOKEN ###---
Type: Comment
Data: ; comment 2

First we call flex to generate the actual C program and then we call cc() C compiler) to compile the program, by default it reads from standard input so we pass the contents of our comments.au3 with a pipe.

Cheers everyone!

Source: https://forum.dtw.tools/d/26-easycodeit-update-our-hand-written-parser-is-going-away/8

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Hi everyone,

I already posted an update yesterday where I mentioned that I have started work on the new parser which uses Flex and Bison to generate C code for parsing.

So far the experience has been very nice, I am able to test and develop things very fast compared to doing it all on my own.

I have completed the initial version of the tokenizer/scanner/lexer, it should be able to scan all tokens which could possibly occur in a valid script :)

%option noyywrap nodefault

%{
#include <stdlib.h>
#include <string.h>

char *token_str = NULL;
size_t token_len = 0;

size_t comment_level = 0;

//#define YY_USER_ACTION free(token_str); token_str = strndup(yytext, token_len = yyleng);
#define YY_USER_ACTION token_str = yytext; token_len = yyleng;

enum { // Token Types
	UNKNOWN = 420,
	WS,
	COMMENT, DIRECTIVE,
	NUMBER, STRING, BOOL,
	WORD,
	MACRO, VARIABLE,
	OPERATOR, BRACKET, DOT, COMMA,
};

%}

%x ML_COMMENT

WS	[ \t\r\n]+
NL	\r?\n?

DIGIT	[0-9]
XDIGIT	[0-9A-Fa-f]

QUOTE	[\'\"]

%%

 /* Whitespace */
{WS}	;

 /* Comment */
<INITIAL,ML_COMMENT>"#cs"|"#comment-start"{WS}	{BEGIN ML_COMMENT; ++comment_level;};
<ML_COMMENT>"#ce"|"#comment-end"	if (--comment_level == 0) BEGIN INITIAL;
<ML_COMMENT>(?s:.)	;
[;#][^\r\n]*	return *yytext == ';' ? COMMENT : DIRECTIVE;

 /* Number */
{DIGIT}+(\.{DIGIT}+(e{DIGIT}+)?)?	return NUMBER;
0[xX]{XDIGIT}+	return NUMBER;

 /* String */
\"[^\n\"]*\"	return STRING;
\'[^\n\']*\'	return STRING;

 /* Bool */
(?i:"True"|"False")	return BOOL;

 /* Word */
[A-Za-z][A-Za-z0-9]*	return WORD;

 /* Macro or Variable */
[@$][A-Za-z][A-Za-z0-9]*	return *yytext == '@' ? MACRO : VARIABLE;

 /* Operator */
[+\-*/^&=<>?:]	return OPERATOR;

 /* Misc */
[[\]()]	return BRACKET;
\.		return DOT;
\,		return COMMA;

 /* Catch-all for everything else */
.	return UNKNOWN;

%%

#include <stddef.h>
#include <stdio.h>

static void print_token(char *str, size_t len, int type) {
	puts("---### TOKEN ###---");
	char *token_type;
	switch (type) {
		case UNKNOWN:
			token_type = "Unknown";
			break;
		case WS:
			token_type = "Whitespace";
			break;
		case COMMENT:
			token_type = "Comment";
			break;
		case DIRECTIVE:
			token_type = "Directive";
			break;
		case NUMBER:
			token_type = "Number";
			break;
		case STRING:
			token_type = "String";
			break;
		case BOOL:
			token_type = "Boolean";
			break;
		case WORD:
			token_type = "Word";
			break;
		case MACRO:
			token_type = "Macro";
			break;
		case VARIABLE:
			token_type = "Variable";
			break;
		case OPERATOR:
			token_type = "Operator";
			break;
		case BRACKET:
			token_type = "Bracket";
			break;
		case DOT:
			token_type = "Dot";
			break;
		case COMMA:
			token_type = "Comma";
			break;
		default:
			token_type = "Unnamed";
			break;
	}
	fputs("Type: ", stdout);
	puts(token_type);
	fputs("Data: ", stdout);
	puts(str);
}

int main(void) {
	int type;
	for (;;) {
		type = yylex();
		if (!type) break;
		print_token(token_str, token_len, type);
	}
	return 0;
}

I passed this "script" as the input:

#cs
    #cs
        nested comment
    #ce
#ce

; Calm Mints

42
0xDEADBEEF
3.14
6.02214076e23

"Hell'o World"
'"To C or not to C"'

True
true
fAlSe
False
tRUe

@TheTruth
$TheFact

-((1 + 2) / 3) * 4

And here is the output:

---### TOKEN ###---
Type: Comment
Data: ; Calm Mints
---### TOKEN ###---
Type: Number
Data: 42
---### TOKEN ###---
Type: Number
Data: 0xDEADBEEF
---### TOKEN ###---
Type: Number
Data: 3.14
---### TOKEN ###---
Type: Number
Data: 6.02214076e23
---### TOKEN ###---
Type: String
Data: "Hell'o World"
---### TOKEN ###---
Type: String
Data: '"To C or not to C"'
---### TOKEN ###---
Type: Boolean
Data: True
---### TOKEN ###---
Type: Boolean
Data: true
---### TOKEN ###---
Type: Boolean
Data: fAlSe
---### TOKEN ###---
Type: Boolean
Data: False
---### TOKEN ###---
Type: Boolean
Data: tRUe
---### TOKEN ###---
Type: Macro
Data: @TheTruth
---### TOKEN ###---
Type: Variable
Data: $TheFact
---### TOKEN ###---
Type: Operator
Data: -
---### TOKEN ###---
Type: Bracket
Data: (
---### TOKEN ###---
Type: Bracket
Data: (
---### TOKEN ###---
Type: Number
Data: 1
---### TOKEN ###---
Type: Operator
Data: +
---### TOKEN ###---
Type: Number
Data: 2
---### TOKEN ###---
Type: Bracket
Data: )
---### TOKEN ###---
Type: Operator
Data: /
---### TOKEN ###---
Type: Number
Data: 3
---### TOKEN ###---
Type: Bracket
Data: )
---### TOKEN ###---
Type: Operator
Data: *
---### TOKEN ###---
Type: Number
Data: 4

Which is very similar if not exactly the same as what our old parser would have produced :)

The next step is to add support for including files (#include <...>) and then I will start work on the syntactic analysis, which is the actual "parsing" to convert list of words into actions. Hopefully I won't get held up by last time due to all the fatigue, using these tools should speed up the process significantly.

Stay tuned for more updates this week!

Source: https://forum.dtw.tools/d/28-easycodeit-update-flex-bison-parser

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

  • 3 weeks later...

I got busy with work again, but luckily I didn't take another month long break :P

I implemented support for #include and #include-once in the lexer, which means the lexer part is more or less done. Here is the new code:

// lexer.l
%option batch noyywrap nounput nodefault yylineno

%{
/* 
 * This file is part of EasyCodeIt.
 * 
 * Copyright (C) 2021 TheDcoder <TheDcoder@protonmail.com>
 * 
 * EasyCodeIt is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct BufferStack {
	struct BufferStack *prev;
	char *code;
	YY_BUFFER_STATE state;
	size_t line;
	char *file;
} *lex_buffer = NULL;

static char *token_str = NULL;
static size_t token_len = 0;
static size_t comment_level = 0;

#define YY_USER_ACTION token_str = yytext; token_len = yyleng;

enum { // Token Types
	UNKNOWN = 420,
	WS,
	COMMENT, DIRECTIVE,
	NUMBER, STRING, BOOL,
	WORD,
	MACRO, VARIABLE,
	OPERATOR, BRACKET, DOT, COMMA,
};

#include "parser.h"

static source_reader read_file;

static bool push_file(char *file);
static bool pop_file(void);

%}

%x INCLUDE
%x DIRECTIVE_LINE
%x ML_COMMENT

WS	[ \t\r\n]+
NL	\r?\n?

DIGIT	[0-9]
XDIGIT	[0-9A-Fa-f]

QUOTE	[\'\"]

%%

 /* Include File */
 /* TODO: #include-once */
^"#include"{WS}[\"<]	BEGIN INCLUDE;
<INCLUDE>[^\n\">]+	{
	int c;
	while((c = input()) && c != '\n') /* Eat up any leftover junk in the include line */;
	++yylineno;
	push_file(yytext);
	BEGIN INITIAL;
}
<INCLUDE>.|\n	/* Ignore bad include line */;
"#include-once"	{
	/* Add current file to "include once" list*/
	read_file(lex_buffer->file, NULL, true);
}

 /* Whitespace */
{WS}	;

 /* Directive */
"#"	{BEGIN DIRECTIVE_LINE; yymore();};
<DIRECTIVE_LINE>.+	{BEGIN INITIAL; return DIRECTIVE;};

 /* Comment */
<INITIAL,ML_COMMENT>"#cs"|"#comment-start"{WS}	{BEGIN ML_COMMENT; ++comment_level;};
<ML_COMMENT>"#ce"|"#comment-end"	if (--comment_level == 0) BEGIN INITIAL;
<ML_COMMENT>(?s:.)	;
;[^\r\n]*	return COMMENT;

 /* Number */
{DIGIT}+(\.{DIGIT}+(e{DIGIT}+)?)?	return NUMBER;
0[xX]{XDIGIT}+	return NUMBER;

 /* String */
\"[^\n\"]*\"	return STRING;
\'[^\n\']*\'	return STRING;

 /* Bool */
(?i:"True"|"False")	return BOOL;

 /* Word */
[A-Za-z][A-Za-z0-9]*	return WORD;

 /* Macro or Variable */
[@$][A-Za-z][A-Za-z0-9]*	return *yytext == '$' ? VARIABLE : MACRO;

 /* Operator */
 /* IDEA: Make a parser mode where the character will be returned literally */
[+\-*/^&=<>?:]	return OPERATOR;

 /* Misc */
[[\]()]	return BRACKET;
\.		return DOT;
\,		return COMMA;

 /* Pop file and terminate if top-level */
<<EOF>>	if(!pop_file()) yyterminate();

 /* Catch-all for everything else */
.	return UNKNOWN;

%%

#include <stddef.h>
#include <stdio.h>

static void print_token(char *str, int type) {
	puts("---### TOKEN ###---");
	char *token_type;
	switch (type) {
		case UNKNOWN:
			token_type = "Unknown";
			break;
		case WS:
			token_type = "Whitespace";
			break;
		case COMMENT:
			token_type = "Comment";
			break;
		case DIRECTIVE:
			token_type = "Directive";
			break;
		case NUMBER:
			token_type = "Number";
			break;
		case STRING:
			token_type = "String";
			break;
		case BOOL:
			token_type = "Boolean";
			break;
		case WORD:
			token_type = "Word";
			break;
		case MACRO:
			token_type = "Macro";
			break;
		case VARIABLE:
			token_type = "Variable";
			break;
		case OPERATOR:
			token_type = "Operator";
			break;
		case BRACKET:
			token_type = "Bracket";
			break;
		case DOT:
			token_type = "Dot";
			break;
		case COMMA:
			token_type = "Comma";
			break;
		default:
			token_type = "Unnamed";
			break;
	}
	fputs("Type: ", stdout);
	puts(token_type);
	fputs("Data: ", stdout);
	puts(str);
}

static void scan() {
	int type;
	for (;;) {
		type = yylex();
		if (!type) break;
		print_token(token_str, type);
	}
}

bool parse(char *file, source_reader read_func) {
	read_file = read_func;
	push_file(file);
	scan();
	return true;
}

static bool push_file(char *file) {
	size_t code_len;
	file = strdup(file);
	if (!file) return false;
	char *code = read_file(file, &code_len, false);
	if (!code) {
		free(file);
		return false;
	}
	struct BufferStack *new_buffer = malloc(sizeof *new_buffer);
	if (!new_buffer) return false;
	if (lex_buffer) lex_buffer->line = yylineno;
	*new_buffer = (struct BufferStack){
		.prev = lex_buffer,
		.code = code,
		.state = yy_scan_buffer(code, code_len + 2),
		.file = file,
		.line = yylineno = 1,
	};
	lex_buffer = new_buffer;
	yy_switch_to_buffer(lex_buffer->state);
	return true;
}

static bool pop_file() {
	struct BufferStack *prev_buffer = lex_buffer->prev;
	yy_delete_buffer(lex_buffer->state);
	free(lex_buffer->code);
	free(lex_buffer->file);
	free(lex_buffer);
	lex_buffer = prev_buffer;
	if (!lex_buffer) return false;
	yylineno = lex_buffer->line;
	yy_switch_to_buffer(lex_buffer->state);
	return true;
}

 
// eci.c
/* 
 * This file is part of EasyCodeIt.
 * 
 * Copyright (C) 2020 TheDcoder <TheDcoder@protonmail.com>
 * 
 * EasyCodeIt is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
static char *provide_code(char *file, size_t *size, bool once) {
	static char **once_list = NULL;
	static size_t once_list_len = 0;
	if (once) {
		// Add the file to "include once" list
		if (!once_list) {
			once_list = malloc(sizeof(char *));
			if (!once_list) return NULL;
			++once_list_len;
		} else {
			char **expanded_list = realloc(once_list, sizeof(char *) * ++once_list_len);
			if (!expanded_list) {
				--once_list_len;
				return NULL;
			}
			once_list = expanded_list;
		}
		once_list[once_list_len - 1] = strdup(file);
		
		return NULL;
	} else {
		// Skip if the file is in the "include once" list
		for (size_t i = 0; i < once_list_len; ++i) {
			if (strcmp(once_list[i], file) == 0) return NULL;
		}
	}
	
	// Open the source file
	char *code;
	FILE *source_file = fopen(file, "r");
	if (source_file) {
		// Read the source file
		code = readfile(source_file);
		fclose(source_file);
		if (!code) die("Failed to read from source file!");
	} else {
		code = malloc(1);
		code[0] = '\0';
	}
	
	// The following is required because the parser needs a string with two null terminators
	*size = strlen(code);
	char *code_padded = realloc(code, *size + 2);
	if (!code_padded) {
		free(code);
		die("Failed to expand code buffer");
	}
	code_padded[*size + 1] = '\0';
	
	return code_padded;
}

int main(int argc, char *argv[]) {
	if (argc < 2) die("No arguments!");
	
	// Parse the code
	parse(argv[1], provide_code);
	
	return EXIT_SUCCESS;
}

It was surprisingly easy to write a fully featured scanner/tokenizer in flex, guess I should have used it from the beginning. Now I can start work on the parser, hopefully it will be easy too, surely easier than writing it all manually 🥵

Source: https://forum.dtw.tools/d/28-easycodeit-update-flex-bison-parser/2

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

That comma after COMMA looks suspicious :)

enum { // Token Types
    UNKNOWN = 420,
    WS,
    COMMENT, DIRECTIVE,
    NUMBER, STRING, BOOL,
    WORD,
    MACRO, VARIABLE,
    OPERATOR, BRACKET, DOT, COMMA,
};

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

@jpm Oops, thanks, fixed :)

 /* Macro or Variable */
[@$][A-Za-z0-9_]+	return *yytext == '$' ? VARIABLE : MACRO;

I also removed the limitation of not being able start a variable (or macro) with a digit, seems arbitrary as we already have a special symbol to denote a variable.

1 minute ago, JockoDundee said:

That comma after COMMA looks suspicious :)

LOL, indeed, normally it shouldn't be there but it is allowed since C99... patches are cleaner if you change those values because you don't have to add that extra comma at that time.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

9 hours ago, TheDcoder said:

patches are cleaner if you change those values because you don't have to add that extra comma at that time.

Wow, did not know.   For me it’s often the other way around, in a loop I keep adding a comma to a concatenated string and then have to remember to lop off the last one. This is so brilliant it’s inspired me to song:

Comma, Comma, Comma, Comma, Comma, Chameleon,

You come and go, you come and go,

Adapted from the Original

Code hard, but don’t hard code...

Link to comment
Share on other sites

Boy, has George got a lot to answer for. ;)

But then maybe he's just a comma medium ... comedian for short ... who have poetic lie sense I guess. :lol:

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 7/17/2021 at 1:05 PM, JockoDundee said:

Comma, Comma, Comma, Comma, Comma, Chameleon,

You come and go, you come and go,

Adapted from the Original

Interestingly, I didn't realize until a few years ago that it wasn't Chame (like the first part of Chameleon).

On 7/17/2021 at 7:51 PM, TheSaint said:

comma medium ... comedian for short ... who have poetic lie sense

This hurt to read

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

I think this is a new record, another update just before a week passes! 🥳

I am here to present the first prototype of the new bison parser:

// parser.y
/* 
 * This file is part of EasyCodeIt.
 * 
 * Copyright (C) 2021 TheDcoder <TheDcoder@protonmail.com>
 * 
 * EasyCodeIt is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

%code top {
	#define _GNU_SOURCE /* Required to enable (v)asprintf */
	#include <stdio.h>
	#include <string.h>
}

%union {
	char *str;
}

%token UNKNOWN
%token WS
%token COMMENT DIRECTIVE
%token <str> NUMBER STRING BOOL
%token WORD
%token MACRO VARIABLE
%token OPERATOR BRACKET DOT COMMA

 /* Operators */
%precedence '?'
%precedence ':'
%left AND "And" OR "Or"
%left LT '<' GT '>' LTE "<=" GTE ">=" EQU '=' NEQ "<>" SEQU "=="
%left '&'
%left '+' '-'
%left '*' '/'
%left '^'
%left NOT "Not"
%precedence INVERSION
%precedence GROUPING

%type <str> expression

%{
int yylex();
void yyerror(const char *s);
%}

%%

exp-list: /* nothing */
	| expression {puts($1);}

expression: NUMBER {$$ = strdup($1);}
	| expression '?' expression ':' expression {asprintf(&$$, " (%s ? %s : %s) ", $1, $3, $5);}
	| expression "And" expression {asprintf(&$$, " (%s And %s) ", $1, $3);}
	| expression "Or" expression {asprintf(&$$, " (%s Or %s) ", $1, $3);}
	| expression '<' expression {asprintf(&$$, " (%s < %s) ", $1, $3);}
	| expression '>' expression {asprintf(&$$, " (%s > %s) ", $1, $3);}
	| expression '=' expression {asprintf(&$$, " (%s = %s) ", $1, $3);}
	| expression "<=" expression {asprintf(&$$, " (%s <= %s) ", $1, $3);}
	| expression ">=" expression {asprintf(&$$, " (%s >= %s) ", $1, $3);}
	| expression "<>" expression {asprintf(&$$, " (%s <> %s) ", $1, $3);}
	| expression "==" expression {asprintf(&$$, " (%s == %s) ", $1, $3);}
	| expression '&' expression {asprintf(&$$, " (%s & %s) ", $1, $3);}
	| expression '+' expression {asprintf(&$$, " (%s + %s) ", $1, $3);}
	| expression '-' expression {asprintf(&$$, " (%s - %s) ", $1, $3);}
	| expression '*' expression {asprintf(&$$, " (%s * %s) ", $1, $3);}
	| expression '/' expression {asprintf(&$$, " (%s / %s) ", $1, $3);}
	| expression '^' expression {asprintf(&$$, " (%s ^ %s) ", $1, $3);}
	| "Not" expression {asprintf(&$$, " (Not %s) ", $2);}
	| '-' expression %prec INVERSION {asprintf(&$$, " (-%s) ", $2);}
	| '(' expression ')' %prec GROUPING {asprintf(&$$, " (%s) ", $2);}

%%

void start_parser() {
	yyparse();
}

void yyerror(char const *s) {
	fputs(s, stderr);
	fputs("\n", stderr);
}

This version can only handle numeric expressions, and the output is just a string with an excessive amount of brackets to show the correct order of evaluation. It ain't pretty but it does the job :P

Here are a few sample inputs I tried:

> echo '1 + 2' | ./eci /dev/fd/0
 (1 + 2) 
> echo '-((1 + 2) / 3) * 4' | ./eci /dev/fd/0
 ( (- ( ( ( (1 + 2) )  / 3) ) )  * 4) 
> echo '42 ? 123 ? 86 : -((1 + 2) / 3) * 4 : 007' | ./eci /dev/fd/0
 (42 ?  (123 ? 86 :  ( (- ( ( ( (1 + 2) )  / 3) ) )  * 4) )  : 007)

(the output is the line of text below the > shell prompt)

Even though this is very primitive, it has served as proof that I can use bison to write a proper parser, now I can move onto the more intricate details of parsing such as evaluating values and constructing a syntax tree to represent the code.

I will keep you guys updated on the progress, hope the next update comes as soon as this one 🤞

Source: https://forum.dtw.tools/d/28-easycodeit-update-flex-bison-parser/5

--

Also, If anyone has not noticed the new thread I created, please check it out:

I am gathering community consensus on which features are more popular so that they can be prioritized accordingly.

Edited by TheDcoder

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

So just for the hell of it I installed gcc under wsl and compiled an exe that was nothing more than a for loop to 1000000000.

It ran 15 times faster than the same functionality via an autoit executable.

Not dissing autoit, but whats your take on the speed differential on something super primitive like a for loop?

I'm sure that gcc optimizes it well, but how much is there to do?

Do you think, in this case, that its because of variant math that eats up the time?

Code hard, but don’t hard code...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...