summaryrefslogtreecommitdiff
path: root/frontend/lexer.ll
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-02-15 04:10:38 +0100
committerEugen Wissner <belka@caraus.de>2026-02-15 04:10:38 +0100
commit5959fbb5524bbeb05a96eb15aba59e961a3efcb7 (patch)
tree811be9bb8fba9bec6ae549c50f9cf92000b259c9 /frontend/lexer.ll
downloadelna-5959fbb5524bbeb05a96eb15aba59e961a3efcb7.tar.gz
Initial commit
Diffstat (limited to 'frontend/lexer.ll')
-rw-r--r--frontend/lexer.ll320
1 files changed, 320 insertions, 0 deletions
diff --git a/frontend/lexer.ll b/frontend/lexer.ll
new file mode 100644
index 0000000..f14497b
--- /dev/null
+++ b/frontend/lexer.ll
@@ -0,0 +1,320 @@
+/* Lexical analyzer.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+%{
+#define YY_NO_UNISTD_H
+#define YY_USER_ACTION this->location.columns(yyleng);
+
+#include <sstream>
+#include "parser.hh"
+
+#undef YY_DECL
+#define YY_DECL yy::parser::symbol_type elna::frontend::lexer::lex(driver& driver)
+#define yyterminate() return yy::parser::make_YYEOF(this->location)
+%}
+
+%option c++ noyywrap never-interactive
+%option yyclass="lexer"
+
+%x IN_COMMENT
+
+ID1 [A-Za-z_]
+ID2 [A-Za-z0-9_]
+HIGIT [0-9a-fA-F]
+BIGIT [01]
+
+%%
+%{
+ this->location.step();
+%}
+
+<IN_COMMENT>{
+ \*\) BEGIN(INITIAL);
+ [^*\n]+ ; /* Eat comment in chunks. */
+ \* ; /* Eat the lone star. */
+ \n+ {
+ this->location.lines(yyleng);
+ this->location.step();
+ }
+}
+\(\* BEGIN(IN_COMMENT);
+[ \t\r] {
+ this->location.step();
+}
+\n+ {
+ this->location.lines(yyleng);
+}
+if {
+ return yy::parser::make_IF(this->location);
+}
+then {
+ return yy::parser::make_THEN(this->location);
+}
+else {
+ return yy::parser::make_ELSE(this->location);
+}
+elsif {
+ return yy::parser::make_ELSIF(this->location);
+}
+while {
+ return yy::parser::make_WHILE(this->location);
+}
+do {
+ return yy::parser::make_DO(this->location);
+}
+proc {
+ return yy::parser::make_PROCEDURE(this->location);
+}
+begin {
+ return yy::parser::make_BEGIN_BLOCK(this->location);
+ }
+end {
+ return yy::parser::make_END_BLOCK(this->location);
+}
+extern {
+ return yy::parser::make_EXTERN(this->location);
+}
+const {
+ return yy::parser::make_CONST(this->location);
+}
+var {
+ return yy::parser::make_VAR(this->location);
+}
+type {
+ return yy::parser::make_TYPE(this->location);
+}
+record {
+ return yy::parser::make_RECORD(this->location);
+}
+union {
+ return yy::parser::make_UNION(this->location);
+}
+true {
+ return yy::parser::make_BOOLEAN(true, this->location);
+}
+false {
+ return yy::parser::make_BOOLEAN(false, this->location);
+}
+nil {
+ return yy::parser::make_NIL(this->location);
+}
+\& {
+ return yy::parser::make_AND(this->location);
+}
+xor {
+ return yy::parser::make_XOR(this->location);
+}
+or {
+ return yy::parser::make_OR(this->location);
+}
+\| {
+ return yy::parser::make_PIPE(this->location);
+}
+\~ {
+ return yy::parser::make_NOT(this->location);
+}
+return {
+ return yy::parser::make_RETURN(this->location);
+}
+module {
+ return yy::parser::make_MODULE(this->location);
+}
+program {
+ return yy::parser::make_PROGRAM(this->location);
+}
+import {
+ return yy::parser::make_IMPORT(this->location);
+}
+cast {
+ return yy::parser::make_CAST(this->location);
+}
+defer {
+ return yy::parser::make_DEFER(this->location);
+}
+case {
+ return yy::parser::make_CASE(this->location);
+}
+of {
+ return yy::parser::make_OF(this->location);
+}
+{ID1}{ID2}* {
+ return yy::parser::make_IDENTIFIER(yytext, this->location);
+}
+#{ID1}{ID2}* {
+ return yy::parser::make_TRAIT(yytext + 1, this->location);
+}
+[[:digit:]]+u {
+ unsigned long result = strtoul(yytext, NULL, 10);
+
+ if (errno == ERANGE)
+ {
+ REJECT;
+ }
+ else
+ {
+ return yy::parser::make_WORD(result, this->location);
+ }
+}
+[[:digit:]]+ {
+ long result = strtol(yytext, NULL, 10);
+
+ if (errno == ERANGE)
+ {
+ REJECT;
+ }
+ else
+ {
+ return yy::parser::make_INTEGER(result, this->location);
+ }
+}
+0x{HIGIT}+ {
+ unsigned long result = strtoul(yytext, NULL, 16);
+
+ if (errno == ERANGE)
+ {
+ REJECT;
+ }
+ else
+ {
+ return yy::parser::make_WORD(result, this->location);
+ }
+}
+0b{BIGIT}+ {
+ unsigned long result = strtoul(yytext, NULL, 2);
+
+ if (errno == ERANGE)
+ {
+ REJECT;
+ }
+ else
+ {
+ return yy::parser::make_WORD(result, this->location);
+ }
+}
+[[:digit:]]+\.[[:digit:]]+ {
+ float result = strtof(yytext, NULL);
+
+ if (errno == ERANGE)
+ {
+ REJECT;
+ }
+ else
+ {
+ return yy::parser::make_FLOAT(result, this->location);
+ }
+}
+'[[:print:]]+' {
+ std::optional<std::string> result = escape_string(yytext);
+ if (!result.has_value() || result.value().size() != 1)
+ {
+ REJECT;
+ }
+ return yy::parser::make_CHARACTER(result.value(), this->location);
+}
+\"[[:print:]]*\" {
+ std::optional<std::string> result = escape_string(yytext);
+ if (!result.has_value())
+ {
+ REJECT;
+ }
+ return yy::parser::make_STRING(result.value(), this->location);
+}
+\( {
+ return yy::parser::make_LEFT_PAREN(this->location);
+}
+\) {
+ return yy::parser::make_RIGHT_PAREN(this->location);
+}
+\[ {
+ return yy::parser::make_LEFT_SQUARE(this->location);
+}
+\] {
+ return yy::parser::make_RIGHT_SQUARE(this->location);
+}
+\<\< {
+ return yy::parser::make_SHIFT_LEFT(this->location);
+}
+\>\> {
+ return yy::parser::make_SHIFT_RIGHT(this->location);
+}
+\>= {
+ return yy::parser::make_GREATER_EQUAL(this->location);
+}
+\<= {
+ return yy::parser::make_LESS_EQUAL(this->location);
+}
+\> {
+ return yy::parser::make_GREATER_THAN(this->location);
+}
+\< {
+ return yy::parser::make_LESS_THAN(this->location);
+}
+\<\> {
+ return yy::parser::make_NOT_EQUAL(this->location);
+}
+= {
+ return yy::parser::make_EQUALS(this->location);
+}
+; {
+ return yy::parser::make_SEMICOLON(this->location);
+}
+\. {
+ return yy::parser::make_DOT(this->location);
+}
+, {
+ return yy::parser::make_COMMA(this->location);
+}
+\+ {
+ return yy::parser::make_PLUS(this->location);
+}
+\-> {
+ return yy::parser::make_ARROW(this->location);
+}
+\- {
+ return yy::parser::make_MINUS(this->location);
+}
+\* {
+ return yy::parser::make_MULTIPLICATION(this->location);
+}
+\/ {
+ return yy::parser::make_DIVISION(this->location);
+}
+% {
+ return yy::parser::make_REMAINDER(this->location);
+}
+:= {
+ return yy::parser::make_ASSIGNMENT(this->location);
+}
+: {
+ return yy::parser::make_COLON(this->location);
+}
+\^ {
+ return yy::parser::make_HAT(this->location);
+}
+@ {
+ return yy::parser::make_AT(this->location);
+}
+! {
+ return yy::parser::make_EXCLAMATION(this->location);
+}
+. {
+ std::stringstream ss;
+
+ ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
+ driver.add_error<syntax_error>(ss.str(), driver.input_file, this->location);
+}
+%%