aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-12 01:35:30 +0200
committerEugen Wissner <belka@caraus.de>2026-09-12 01:35:30 +0200
commite72e20e025ab14320c79c2dca75721a0a5e002bd (patch)
tree3b2d0d90f38c80442ee518e000b4026e753c66c9
parent2d3ba9b352478e5a3d3add482f56f1c801965428 (diff)
downloadelna-e72e20e025ab14320c79c2dca75721a0a5e002bd.tar.gz
Allow random text after ending the module
-rw-r--r--boot/lexer.ll15
-rw-r--r--boot/parser.yy6
-rw-r--r--include/elna/boot/driver.h3
-rw-r--r--testsuite/compilable/trailing_text.elna4
4 files changed, 27 insertions, 1 deletions
diff --git a/boot/lexer.ll b/boot/lexer.ll
index e8dde7c..89eb4ed 100644
--- a/boot/lexer.ll
+++ b/boot/lexer.ll
@@ -55,6 +55,10 @@ EXPONENT [eE][+-]?[[:digit:]]+
%%
%{
+ if (driver.finished)
+ {
+ return yy::parser::make_YYEOF(this->location);
+ }
this->location.step();
%}
@@ -65,8 +69,17 @@ EXPONENT [eE][+-]?[[:digit:]]+
\n+ {
this->location.step();
}
+ <<EOF>> {
+ driver.add_error<syntax_error>("Unterminated comment", this->comment_start);
+ BEGIN(INITIAL);
+
+ return yy::parser::make_YYEOF(this->location);
+ }
+}
+\(\* {
+ this->comment_start = this->location;
+ BEGIN(IN_COMMENT);
}
-\(\* BEGIN(IN_COMMENT);
[ \t\r] {
this->location.step();
}
diff --git a/boot/parser.yy b/boot/parser.yy
index cc0a46c..f97d545 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see
{
public:
yy::location location;
+ /// Where the comment being scanned was opened.
+ yy::location comment_start;
lexer(std::istream& arg_yyin)
: yyFlexLexer(&arg_yyin)
@@ -167,12 +169,16 @@ along with GCC; see the file COPYING3. If not see
program:
import_part type_part variable_part procedure_part "end" "."
{
+ driver.finished = true;
+
boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4);
driver.tree.reset(tree);
}
| import_part type_part variable_part procedure_part
"program" "(" optional_identifiers ")" procedure_body "end" "."
{
+ driver.finished = true;
+
boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4,
std::move($7), boot::make_position(@5), std::move(*$9));
driver.tree.reset(tree);
diff --git a/include/elna/boot/driver.h b/include/elna/boot/driver.h
index 45e2e40..e918954 100644
--- a/include/elna/boot/driver.h
+++ b/include/elna/boot/driver.h
@@ -39,6 +39,9 @@ namespace elna::boot
{
public:
std::unique_ptr<unit> tree;
+ /// Set once the module terminator has been parsed. The lexer stops
+ /// scanning then, so whatever follows is not program text.
+ bool finished{ false };
driver() = default;
};
diff --git a/testsuite/compilable/trailing_text.elna b/testsuite/compilable/trailing_text.elna
new file mode 100644
index 0000000..1eb3595
--- /dev/null
+++ b/testsuite/compilable/trailing_text.elna
@@ -0,0 +1,4 @@
+end.
+
+Everything after the module terminator is ignored and is never scanned, so it
+does not have to be Elna: proc 1 2 3 "unterminated