Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
unicode_ident.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//bertini2/io/parsing/unicode_ident.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//bertini2/io/parsing/unicode_ident.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with bertini2/io/parsing/unicode_ident.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
22
45
46#pragma once
47
48#include <string>
49
50#include <boost/spirit/include/qi.hpp>
51#include <boost/regex/pending/unicode_iterator.hpp>
52
53#include "bertini2/naming.hpp" // IsIdentStart / IsIdentCont -- the shared name policy
54
55namespace bertini {
56namespace parsing {
57namespace classic {
58
59// IsIdentStart / IsIdentCont live in namespace bertini (bertini2/naming.hpp) so the
60// grammar and the object model share one definition of a legal name; they resolve
61// here by enclosing-namespace lookup.
62
64
65// Match a whole UTF-8 identifier (IsIdentStart, then zero or more IsIdentCont)
66// and expose the matched raw bytes as a std::string. Self-contained: decodes
67// contiguous code points itself, so it never sub-skips inside an identifier even
68// when used in a rule that carries a space skipper.
69struct utf8_identifier_parser
70 : boost::spirit::qi::primitive_parser<utf8_identifier_parser>
71{
72 template <typename Context, typename Iterator>
73 struct attribute { typedef std::string type; };
74
75 template <typename Iterator, typename Context, typename Skipper, typename Attribute>
76 bool parse(Iterator& first, Iterator const& last,
77 Context&, Skipper const& skipper, Attribute& attr) const
78 {
79 boost::spirit::qi::skip_over(first, last, skipper);
80 Iterator const begin = first;
81 Iterator it = first;
82 try
83 {
84 if (it == last)
85 return false;
86 {
87 boost::u8_to_u32_iterator<Iterator> u(it, it, last);
88 if (!IsIdentStart(*u))
89 return false;
90 ++u;
91 it = u.base();
92 }
93 while (it != last)
94 {
95 boost::u8_to_u32_iterator<Iterator> u(it, it, last);
96 if (!IsIdentCont(*u))
97 break;
98 ++u;
99 it = u.base();
100 }
101 }
102 catch (...)
103 {
104 return false; // malformed UTF-8 -> clean parse failure
105 }
106 std::string matched(begin, it);
107 boost::spirit::traits::assign_to(matched, attr);
108 first = it;
109 return true;
110 }
111
112 template <typename Context>
113 boost::spirit::info what(Context&) const
114 {
115 return boost::spirit::info("utf8_identifier");
116 }
117};
118
119// Zero-width negative lookahead: succeeds (consuming nothing beyond the skipper)
120// iff the next code point is NOT an identifier-continuation code point (or the
121// input has ended). Replaces the ASCII `!qi::alnum` guard so a following
122// Unicode letter (e.g. `α` after a known `Ω`) also blocks a greedy symbol match.
123struct utf8_ident_boundary_parser
124 : boost::spirit::qi::primitive_parser<utf8_ident_boundary_parser>
125{
126 template <typename Context, typename Iterator>
127 struct attribute { typedef boost::spirit::unused_type type; };
128
129 template <typename Iterator, typename Context, typename Skipper, typename Attribute>
130 bool parse(Iterator& first, Iterator const& last,
131 Context&, Skipper const& skipper, Attribute&) const
132 {
133 boost::spirit::qi::skip_over(first, last, skipper);
134 if (first == last)
135 return true; // nothing follows -> boundary holds
136 try
137 {
138 boost::u8_to_u32_iterator<Iterator> u(first, first, last);
139 return !IsIdentCont(*u); // followed by an ident char -> boundary fails
140 }
141 catch (...)
142 {
143 return true; // malformed following bytes -> treat as a boundary
144 }
145 }
146
147 template <typename Context>
148 boost::spirit::info what(Context&) const
149 {
150 return boost::spirit::info("utf8_ident_boundary");
151 }
152};
153
155
156} // namespace classic
157} // namespace parsing
158} // namespace bertini
Definition classic_utilities.hpp:41
bool parse(Iterator first, Iterator last, std::shared_ptr< bertini::node::Node > &func)
Parse a function expression from the iterator range into a node tree.
Definition function_parsers.hpp:46
Definition classic_utilities.hpp:40
Definition algorithm_builder.hpp:36
bool IsIdentStart(char32_t cp)
True if code point cp may START an identifier: any Unicode letter (ASCII A-Z a-z, plus Ω,...
Definition naming.hpp:86
bool IsIdentCont(char32_t cp)
True if code point cp may CONTINUE an identifier: any Unicode alphanumeric, one of the legacy continu...
Definition naming.hpp:95
The single policy for what makes a legal identifier (variable/symbol name).