形式语言与自动机定义
-
文法 (Grammar) - G = (V, T, P, S)
- V: 变量的非空有限集。∀A∈V,A 是语法变量(简称变量),也称为非终结符。V 定义了一个语法类别。
- T: 终结符的非空有限集。∀a∈T,a 称为终结符,是语言句子中的实际符号。注意 V 描述的是语法类别,所以 V ∩ T = ∅。
- P: 产生式的非空有限集。P = {α → β | ∃αᵢ ∈ V, α = α₁α₂...αₙ, α ∈ (V ∪ T)⁺, β ∈ (V ∪ T)*}。产生式 α → β 读作'α 定义为 β',也称为定义或语法规则。
- S: S ∈ V,是文法 G 的开始符号。
注:α → β₁,...,α → βₙ 可简化为 α → β₁|...|βₙ,β₁,...,βₙ 称为候选项。
-
推导 (Derivation) 若 α → β ∈ P, γ, δ ∈ (V ∪ T)*,则 γαδ ⇒G γβδ
实现
#include <cmath>
#include <format>
#include <iostream>
#include <memory>
#include <numbers>
#include <regex>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
struct Token {
enum Type {
PLUS = 1,
MINUS = 1 << 1,
NUMBER = 1 << 2,
VAR = 1 << 3,
MUL = 1 << ,
DIV = << ,
POW = << ,
LPR = << ,
RPR = << ,
PI = << ,
EXP = << ,
Func = << ,
ANY = PLUS | MINUS | NUMBER | VAR | MUL | DIV | POW | LPR | RPR | PI | EXP | Func
};
Type type;
std::string text;
type}, text{text} {}
type}, text{text} {}
type}, text{text} {}
std::ostream& <<(std::ostream& os, Token & tk) {
os << << (tk.type) << << tk.text << ;
os;
}
;
{
std::string result;
(bitmask & PLUS) result += ;
(bitmask & MINUS) result += ;
(bitmask & NUMBER) result += ;
(bitmask & VAR) result += ;
(bitmask & MUL) result += ;
(bitmask & DIV) result += ;
(bitmask & POW) result += ;
(bitmask & LPR) result += ;
(bitmask & RPR) result += ;
(bitmask & PI) result += ;
(bitmask & EXP) result += ;
(bitmask & Func) result += ;
(!result.()) result.();
result + ;
}
:
{
(c) {
: (Token::PLUS, );
: (Token::MINUS, );
: (Token::MUL, );
: (Token::DIV, );
: (Token::POW, );
: (Token::LPR, );
: (Token::RPR, );
: (Token::EXP, );
: (Token::VAR, );
: (Token::VAR, );
: (Token::VAR, );
: std::;
}
}
};
{
std::vector<Token> result;
re = std::();
begin = input.();
(begin != input.()) {
t = (*begin);
(t) {
result.(std::(t.()));
begin++;
;
}
PI = ;
(std::(PI, PI + , begin)) {
result.(Token::PI, PI);
begin += ;
;
}
(std::(*begin)) {
std::smatch m;
(std::(begin, input.(), m, re)) {
number = m[].();
result.(Token::NUMBER, number);
begin += number.();
;
}
} (std::(*begin)) {
f = std::(begin, input.(), []( c) { !std::(c); });
result.(Token::Func, std::(begin, f));
begin = f;
;
}
std::format_error();
}
result;
}
;
{
std::vector<> variable_feed;
(std::vector<> init_list) : (std::(init_list)) {}
;
};
{
Node = std::unique_ptr<ast_element>;
std::string text;
Node l, r;
value;
(std::string text, Node l, Node r) : (std::(text)), (std::(l)), (std::(r)) {}
= ;
;
~() = ;
};
: ast_element {
(std::string text, value) : (std::(text), , ) { ->value = value; }
{ ->value; }
};
: ast_element {
feed = ;
(std::string text, feed = ) : (std::(text), , ), feed{feed} {}
{ ->value = visitor.variable_feed[feed]; }
};
: ast_element {
BOp = std::function<(, )>;
BOp f;
(std::string text, Node l, Node r, BOp f) : (std::(text), std::(l), std::(r)), (std::(f)) {}
{ ->value = (l->value, r->value); }
};
: ast_element {
UOp = std::function<()>;
UOp f;
(std::string text, Node l, UOp f) : (std::(text), std::(l), ), (std::(f)) {}
{ ->value = (l->value); }
};
{
Node = ast_element::Node;
std::string text;
() {}
(std::string text) : (std::(text)) {}
{ ->text = std::(text); *; }
{ ; }
{ ; }
{ ; }
~() = ;
};
: ast_factory {
BOp = BinaryOp::BOp;
UOp = UnaryOp::UOp;
Op = std::variant<BOp, UOp>;
Op f;
(Op f) : (), (std::(f)) {}
(std::string text, Op f) : (std::(text)), (std::(f)) {}
{ ->f = std::(op); *; }
{ std::<BinaryOp>(text, std::(l), std::(r), std::<BOp>(f)); }
{ std::<UnaryOp>(text, std::(l), std::<UOp>(f)); }
};
: ast_factory {
value;
() {}
(std::string text, value) : (std::(text)), value{value} {}
{ ->value = val; *; }
{ std::<Constant>(text, value); }
};
: ast_factory {
() {}
(std::string text) : (std::(text)) {}
{ std::<Variable>(text); }
};
: std::exception {
itr = std::vector<Token>::const_iterator;
std::string err;
( std::string& expecting, std::string& having) : (std::format(, expecting, having)) {}
( std::string& having) : (std::format(, having)) {}
{ err.(); }
};
{
Node = ast_element::Node;
itr = std::vector<Token>::const_iterator;
std::unordered_map<std::string, op_factory::UOp> function_table;
itr begin, end;
(itr begin, itr end) : begin{begin}, end{end} {}
{
function_table[text] = std::(func);
*;
}
{ (); }
{ begin == end; }
:
{
(begin == end) ();
}
{
();
(begin->type != type) (Token::(type), begin->text);
begin++;
}
{
c = ();
(begin == end || (begin->type != Token::PLUS && begin->type != Token::MINUS)) c;
factory = (begin->text, begin->type == Token::PLUS ? op_factory::(std::plus<>{}) : op_factory::(std::minus<>{}));
begin++;
d = ();
factory.(std::(c), std::(d));
}
{
();
(begin->type == Token::PLUS || begin->type == Token::MINUS) {
begin++;
factory = (begin->text, begin->type == Token::PLUS ? op_factory::([]( v) { v; }) : op_factory::([]( v) { -v; }));
t = ();
factory.(std::(t));
}
t = ();
t;
}
{
t = ();
(begin == end || (begin->type != Token::PLUS && begin->type != Token::MINUS)) t;
factory = (begin->text, begin->type == Token::PLUS ? op_factory::(std::plus<>{}) : op_factory::(std::minus<>{}));
begin++;
d = ();
factory.(std::(t), std::(d));
}
{
f = ();
(begin == end || (begin->type != Token::MUL && begin->type != Token::DIV)) f;
fun = begin->type == Token::MUL ? op_factory::([]( a, b) { a * b; }) : op_factory::([]( a, b) { a / b; });
factory = (begin->text, fun);
begin++;
t = ();
factory.(std::(f), std::(t));
}
{
p = ();
(begin == end || begin->type != Token::POW) p;
factory = (begin->text, []( a, b) { std::(a, b); });
begin++;
factory.(std::(p), ());
}
{
();
(begin->type == Token::LPR) {
(Token::LPR);
e = ();
(Token::RPR);
e;
}
(begin->type == Token::Func) ();
(begin->type == Token::VAR) ();
factory = ();
(begin->type) {
Token::NUMBER: factory.(std::(begin->text)); ;
Token::PI: factory.(std::numbers::pi); ;
Token::EXP: factory.(std::numbers::e); ;
: (, begin->text);
}
factory.(begin->text);
begin++;
factory.();
}
{
factory = (begin->text, function_table.(begin->text));
begin++;
(Token::LPR);
e = ();
(Token::RPR);
factory.(std::(e));
}
{
factory = (begin->text);
begin++;
factory.();
}
};
{
elem.(*);
elem.(*);
}
{
(l) l->(visitor);
(r) r->(visitor);
->(visitor);
std::cout << << text << ;
}
{
std::string input;
std::cin >> input;
lex = Token::(input);
parser = (lex.(), lex.());
parser.(, []( v) { std::(v); })
.(, []( v) { std::(v); })
.(, []( v) { std::(v); })
.(, []( v) { std::(v); })
.(, []( v) { std::(v); })
.(, []( v) { std::(v); })
.(, []( v) { std::(v); });
ast = parser.();
std::cout << << std::boolalpha << parser.() << ;
visitor = ({});
result = (*ast);
std::cout << << result;
}

