hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 68d7b73519898600f13be2692fe6917ecb0779c0
parent b72c4e29dc1db52d098155ebb2f86dc41de77bad
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 10 Apr 2021 09:48:30 -0400

format::xml: implement XML comments

Diffstat:
Mformat/xml/parser.ha | 156++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
1 file changed, 98 insertions(+), 58 deletions(-)

diff --git a/format/xml/parser.ha b/format/xml/parser.ha @@ -63,29 +63,30 @@ export fn scan(par: *parser) (token | void | error) = { } else return void, rn: rune => rn, }; - // TODO: - // - Comments - // - Entities/references - // - CDATA - // - Processing Instructions return switch (par.state) { - state::ROOT => switch (rn) { + state::ROOT, state::ELEMENT => switch (rn) { '<' => { + const next = match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => { + bufio::unreadrune(par.in, rn); + rn; + }, + }; bufio::unreadrune(par.in, rn); + switch (next) { + '!' => return scan_comment(par), + '?' => return scan_pi(par), + * => void, + }; let el = scan_element(par)?; par.state = state::ATTRS; el; }, - * => return syntaxerr, - }, - state::ELEMENT => switch (rn) { - '<' => { - bufio::unreadrune(par.in, rn); - let el = scan_element(par); - par.state = state::ATTRS; - el; - }, * => { + if (par.state == state::ROOT) { + return syntaxerr; + }; bufio::unreadrune(par.in, rn); scan_content(par)?; }, @@ -107,25 +108,6 @@ export fn scan(par: *parser) (token | void | error) = { }; }; -fn scan_element(par: *parser) (token | error) = { - want(par, '<')?; - let close = false; - match (bufio::scanrune(par.in)?) { - io::EOF => return syntaxerr, - rn: rune => switch (rn) { - '/' => close = true, - * => bufio::unreadrune(par.in, rn), - }, - }; - let name = scan_name(par)?; - if (close) { - free(name); - return elementend; - } else { - return name: elementstart; - }; -}; - fn scan_attr(par: *parser) (token | error) = { let name = scan_name(par)?; want(par, OPTWS, '=', OPTWS); @@ -135,8 +117,8 @@ fn scan_attr(par: *parser) (token | error) = { io::EOF => return syntaxerr, rn: rune => { switch (rn) { - '<' => abort(), // TODO - '&' => abort(), // TODO + '<' => return syntaxerr, + '&' => abort(), // TODO: Entities * => void, }; if (rn == quot) break; @@ -146,29 +128,39 @@ fn scan_attr(par: *parser) (token | error) = { return (name, strio::finish(val)): attribute; }; -fn scan_name(par: *parser) (str | error) = { - let buf = strio::dynamic(); - - const rn = match (bufio::scanrune(par.in)?) { - io::EOF => return syntaxerr, - rn: rune => rn, - }; - if (!isnamestart(rn)) { - return syntaxerr; - }; - strio::appendrune(buf, rn); - - for (true) match (bufio::scanrune(par.in)?) { +fn scan_comment(par: *parser) (token | void | error) = { + want(par, "<!")?; + match (bufio::scanrune(par.in)?) { io::EOF => return syntaxerr, - rn: rune => if (isname(rn)) { - strio::appendrune(buf, rn); - } else { - bufio::unreadrune(par.in, rn); - break; + rn: rune => switch (rn) { + '-' => { // Comments + want(par, '-')?; + }, + '[' => { // CDATA + want(par, "CDATA[")?; + abort(); // TODO + }, + * => return syntaxerr, }, }; - - return strio::finish(buf); + for (true) { + let rn = match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => rn, + }; + if (rn != '-') continue; + let rn = match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => rn, + }; + if (rn != '-') continue; + let rn = match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => rn, + }; + if (rn == '>') break; + }; + return scan(par); }; fn scan_content(par: *parser) (text | error) = { @@ -183,11 +175,11 @@ fn scan_content(par: *parser) (text | error) = { }, '&' => { bufio::unreadrune(par.in, rn); - abort(); // TODO + abort(); // TODO: Entities }, '%' => { bufio::unreadrune(par.in, rn); - abort(); // TODO + abort(); // TODO: Parameter entities }, }; strio::appendrune(content, rn); @@ -196,6 +188,54 @@ fn scan_content(par: *parser) (text | error) = { return strio::finish(content); }; +fn scan_element(par: *parser) (token | error) = { + want(par, '<')?; + let close = false; + match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => switch (rn) { + '/' => close = true, + * => bufio::unreadrune(par.in, rn), + }, + }; + let name = scan_name(par)?; + if (close) { + free(name); + return elementend; + } else { + return name: elementstart; + }; +}; + +fn scan_name(par: *parser) (str | error) = { + let buf = strio::dynamic(); + + const rn = match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => rn, + }; + if (!isnamestart(rn)) { + return syntaxerr; + }; + strio::appendrune(buf, rn); + + for (true) match (bufio::scanrune(par.in)?) { + io::EOF => return syntaxerr, + rn: rune => if (isname(rn)) { + strio::appendrune(buf, rn); + } else { + bufio::unreadrune(par.in, rn); + break; + }, + }; + + return strio::finish(buf); +}; + +fn scan_pi(par: *parser) (void | error) = { + abort(); // TODO: Processor instructions +}; + fn prolog(par: *parser) (void | error) = { want(par, "<?xml", WS)?;