Serenity Operating System
at master 137 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2020, Hüseyin Aslıtürk <asliturk@hotmail.com> 3 * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include "INILexer.h" 9#include <AK/CharacterTypes.h> 10#include <AK/Vector.h> 11 12namespace GUI { 13 14IniLexer::IniLexer(StringView input) 15 : m_input(input) 16 , m_iterator(m_input.begin()) 17{ 18} 19 20u32 IniLexer::peek(size_t offset) const 21{ 22 return m_iterator.peek(offset).value_or(0); 23} 24 25u32 IniLexer::consume() 26{ 27 VERIFY(m_iterator != m_input.end()); 28 u32 ch = *m_iterator; 29 ++m_iterator; 30 if (ch == '\n') { 31 m_position.line++; 32 m_position.column = 0; 33 } else { 34 m_position.column++; 35 } 36 return ch; 37} 38 39Vector<IniToken> IniLexer::lex() 40{ 41 Vector<IniToken> tokens; 42 IniPosition token_start_position; 43 44 auto emit_token = [&](auto type) { 45 IniToken token; 46 token.m_type = type; 47 token.m_start = m_position; 48 consume(); 49 token.m_end = m_position; 50 tokens.append(token); 51 }; 52 53 auto begin_token = [&] { 54 token_start_position = m_position; 55 }; 56 57 auto commit_token = [&](auto type) { 58 IniToken token; 59 token.m_type = type; 60 token.m_start = token_start_position; 61 token.m_end = m_position; 62 tokens.append(token); 63 }; 64 65 while (m_iterator != m_input.end()) { 66 auto ch = peek(); 67 68 if (is_ascii_space(ch)) { 69 begin_token(); 70 while (is_ascii_space(peek())) 71 consume(); 72 commit_token(IniToken::Type::Whitespace); 73 continue; 74 } 75 76 // ;Comment or #Comment 77 if (ch == ';' || ch == '#') { 78 begin_token(); 79 while (peek() && peek() != '\n') 80 consume(); 81 commit_token(IniToken::Type::Comment); 82 continue; 83 } 84 85 // [Section] 86 if (ch == '[') { 87 // [ Token 88 begin_token(); 89 consume(); 90 commit_token(IniToken::Type::LeftBracket); 91 92 // Section 93 begin_token(); 94 while (peek() && !(peek() == ']' || peek() == '\n')) 95 consume(); 96 commit_token(IniToken::Type::Section); 97 98 // ] Token 99 if (peek() && peek() == ']') { 100 begin_token(); 101 consume(); 102 commit_token(IniToken::Type::RightBracket); 103 } 104 105 continue; 106 } 107 108 // Empty Line 109 if (ch == '\n') { 110 consume(); 111 emit_token(IniToken::Type::Unknown); 112 continue; 113 } 114 115 // Name=Value 116 begin_token(); 117 while (peek() && !(peek() == '=' || peek() == '\n')) 118 consume(); 119 commit_token(IniToken::Type::Name); 120 121 if (peek() && peek() == '=') { 122 begin_token(); 123 consume(); 124 commit_token(IniToken::Type::Equal); 125 } 126 127 if (peek()) { 128 begin_token(); 129 while (peek() && peek() != '\n') 130 consume(); 131 commit_token(IniToken::Type::Value); 132 } 133 } 134 return tokens; 135} 136 137}