Mercurial > projects > dil
view trunk/src/dil/doc/Macro.d @ 723:5dd17d4568ce
Wrote code for expandMacros().
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Fri, 01 Feb 2008 20:51:44 +0100 |
parents | ceaac6a24258 |
children | 0b8a6e876b6d |
line wrap: on
line source
/++ Author: Aziz Köksal License: GPL3 +/ module dil.doc.Macro; import dil.lexer.Funcs; import dil.Unicode; import common; class Macro { string name; /// The name of the macro. string text; /// Substitution text. this (string name, string text) { this.name = name; this.text = text; } } class MacroTable { MacroTable parent; Macro[string] table; this(MacroTable parent = null) { this.parent = parent; } void insert(Macro macro_) { table[macro_.name] = macro_; } Macro search(string name) { auto pmacro = name in table; if (pmacro) return *pmacro; if (parent) return parent.search(name); return null; } bool isRoot() { return parent is null; } } struct MacroParser { char* p; char* textEnd; Macro[] parse(string text) { if (!text.length) return null; if (text[$-1] != '\0') text ~= '\0'; p = text.ptr; textEnd = p + text.length; Macro[] macros; char* idBegin, idEnd, bodyBegin; char* nextIdBegin, nextIdEnd, nextBodyBegin; // Init. findNextMacroId(idBegin, idEnd, bodyBegin); // Continue. while (findNextMacroId(nextIdBegin, nextIdEnd, nextBodyBegin)) { macros ~= new Macro(makeString(idBegin, idEnd), makeString(bodyBegin, nextIdBegin)); idBegin = nextIdBegin; idEnd = nextIdEnd; bodyBegin = nextBodyBegin; } // Add last macro. macros ~= new Macro(makeString(idBegin, idEnd), makeString(bodyBegin, textEnd)); return macros; } bool findNextMacroId(ref char* ref_idBegin, ref char* ref_idEnd, ref char* ref_bodyBegin) { while (p < textEnd) { skipWhitespace(); auto idBegin = p; if (isidbeg(*p) || isUnicodeAlpha(p, textEnd)) // IdStart { do // IdChar* p++; while (isident(*p) || isUnicodeAlpha(p, textEnd)) auto idEnd = p; skipWhitespace(); if (*p == '=') { p++; skipWhitespace(); ref_idBegin = idBegin; ref_idEnd = idEnd; ref_bodyBegin = p; return true; } } skipLine(); } return false; } void skipWhitespace() { while (p < textEnd && (isspace(*p) || *p == '\n')) p++; } void skipLine() { while (p < textEnd && *p != '\n') p++; p++; } } char[] makeString(char* begin, char* end) { return begin[0 .. end - begin]; } char[] expandMacros(MacroTable table, char[] text) { char[] result; char* p = text.ptr; char* textEnd = p + text.length; char* macroEnd = p; while (p+3 < textEnd) // minimum 4 chars: $(x) { if (*p == '$' && p[1] == '(') { // Copy string between macros. result ~= makeString(macroEnd, p); p += 2; auto idBegin = p; if (isidbeg(*p) || isUnicodeAlpha(p, textEnd)) // IdStart { do // IdChar* p++; while (p < textEnd && (isident(*p) || isUnicodeAlpha(p, textEnd))) auto macroName = makeString(idBegin, p); if (*p == ')') { p++; macroEnd = p; } auto macro_ = table.search(macroName); if (macro_) { result ~= macro_.text; } } } p++; } return result; }