Joos1W Compiler Framework
All Classes Functions Typedefs Pages
joos1w_lexer_internal.h
1 #pragma once
2 
3 #include <algorithm>
4 #include <cstring>
5 #include <string>
7  #warning "This file should not be included directly"
8  #include <FlexLexer.h>
9 #endif
10 
11 #include "diagnostics/Diagnostics.h"
12 #include "diagnostics/Location.h"
13 #include "diagnostics/SourceManager.h"
14 #include "joos1w.parser.tab.h"
15 #include "parsetree/ParseTree.h"
16 #include "utils/BumpAllocator.h"
17 
18 class Joos1WParser;
19 
20 class Joos1WLexer : public yyFlexLexer {
21  using Node = parsetree::Node;
22  using Operator = parsetree::Operator;
23  using Literal = parsetree::Literal;
24  using Identifier = parsetree::Identifier;
25  using Modifier = parsetree::Modifier;
26  using BasicType = parsetree::BasicType;
27  friend class Joos1WParser;
28 
29 private:
30  Joos1WLexer(BumpAllocator& alloc, diagnostics::DiagnosticEngine* diag,
31  SourceFile file = {})
32  : file{file}, yycolumn{1}, diag{diag}, alloc{alloc}, messages{alloc} {}
33 
34 public:
35  /// @brief This is the generate Flex lexer function
36  int yylex();
37  // This is a bison-specific lexer function, implemented in the .l file
38  int bison_lex(YYSTYPE* lvalp, YYLTYPE* llocp);
39 
40  /// @brief Wrapper around the node constructor
41  /// @param ...args The arguments to the node constructor
42  /// @return The newly created node
43  template <typename... Args>
44  Node* make_node(YYLTYPE& loc, Node::Type type, Args&&... args) {
45  void* bytes = alloc.allocate_bytes(sizeof(Node));
46  return new(bytes)
47  Node(make_range(loc), alloc, type, std::forward<Args>(args)...);
48  }
49  /// @brief Wrapper around constructing a dataless leaf node
50  /// @param type The type of the leaf node
51  /// @return The newly created leaf node
52  Node* make_leaf(YYLTYPE& loc, Node::Type type) {
53  void* bytes = alloc.allocate_bytes(sizeof(Node));
54  return new(bytes) Node(make_range(loc), type);
55  }
56  /// @brief See make_node
57  Node* make_poison(YYLTYPE& loc);
58  /// @brief See make_node
59  Node* make_operator(YYLTYPE& loc, Operator::Type type);
60  /// @brief See make_node
61  Node* make_literal(YYLTYPE& loc, Literal::Type type, char const* value);
62  /// @brief See make_node
63  Node* make_identifier(YYLTYPE& loc, char const* name);
64  /// @brief See make_node
65  Node* make_modifier(YYLTYPE& loc, Modifier::Type type);
66  /// @brief See make_node
67  Node* make_basic_type(YYLTYPE& loc, BasicType::Type type);
68 
69  /// @brief Report a parser or lexer error to the diagnostic engine
70  /// @param loc The location of the error
71  /// @param msg The message to report
72  /// @param ranges List of additional ranges to report
73  inline void report_parser_error(YYLTYPE& loc, char const* msg,
74  std::initializer_list<YYLTYPE> ranges = {}) {
75  if(!diag) return;
76  auto os = diag->ReportError(make_range(loc));
77  // Copy msg to the heap
78  size_t length = std::min(1024UL, strlen(msg) + 1);
79  char* ptr = reinterpret_cast<char*>(alloc.allocate(length));
80  strncpy(ptr, msg, length);
81  messages.push_back(ptr);
82  os << std::string_view{ptr};
83  for(auto const& range : ranges) os << make_range(range);
84  }
85 
86 private:
87  /// @brief This is a private function that is called by the lexer to handle
88  /// comments. It is implemented in the .l file
89  void comment();
90 
91  /// @brief Converts the lexer location to a source range
92  SourceRange make_range(YYLTYPE const& loc) {
93  return SourceRange{SourceLocation{file, loc.first_line, loc.first_column},
94  SourceLocation{file, loc.last_line, loc.last_column}};
95  }
96 
97 private:
98  SourceFile file;
99  YYLTYPE yylloc; // This is the LEXER location
100  YYSTYPE yylval;
101  int yycolumn;
102  diagnostics::DiagnosticEngine* diag;
103  BumpAllocator& alloc;
104  std::pmr::vector<const char*> messages;
105 };