⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.m

📁 一个matlab的将军模型
💻 M
字号:
function top = parse(top)

% Parse the cell array of terminal symbols into a tree using ACTL grammar
% in `positive normal form`.
%
% Syntax:
%   "top = parse(top)"
%
% Description:
%   Parse the ACTL expression specified by the string (cell array) of
%   terminal symbols in "top" and return the parse tree in "top" if the
%   parsing is successful. The productions in the positive normal form ACTL
%   grammar are listed, in order of precedence, below.
%
%   * `ap` --> `name` "==" `name`
%
%   * `ap` --> `name`
%
%   * `sf` --> "~"`ap`
%
%   * `sf` --> `ap`
%
%   * `sf` --> "AX" `sf`
%
%   * `sf` --> "AF" `sf`
%
%   * `sf` --> "AG" `sf`
%
%   * `sf` --> "A" `sf` "U" `sf`
%
%   * `sf` --> "A" `sf` "R" `sf`
%
%   * `sf` --> `sf` "&" `sf`
%
%   * `sf` --> `sf` "|" `sf`
%
%   * `sf` --> "(" `sf` ")"
%
%   where `ap` and `sf` are the variables for an `atomic proposition` and
%   a `state formula`, respectively. Note that in the positive normal
%   form ACTL, only universal path quatifier A is allowed and negations
%   must be applied directly to atomic propositions.
%
% Implementation:
%   The parsing is done iteratively in a `bottom-up` manner. In each
%   iteration, the function "parse()" searches for the highest precedence
%   production rule that could be applied to a sequence of the top level
%   nodes in the parse tree. If a valid production is found, that
%   sequence of top level nodes is replaced by a single node with the
%   nodes in the production sequence as its children. The parsing
%   continues until a single node remains at the top level. If a valid
%   production cannot be found, the `key symbols`, one of which is
%   assigned to each production, are used to issue the error message
%   suggesting a specific production rule that is violated.
%
% See Also:
%   identerm,compile_ap,build_ap,evaluate,model_check

global PRODUCTION

PRODUCTION = {};
% Define productions for the positive normal form grammar of ACTL 
% in order of precedence. In positive normal form ACTL, only universal 
% path quatifier A is allowed and negations must be applied directly 
% to atomic propositions.

% ap --> name == name
create_production('fsmap', 'ap', {}, {'name' '==' 'name'})
% ap --> name
create_production('polyap', 'ap', {}, {'name'})
% sf --> ~ap
create_production('not_ap', 'sf', {'~'}, {'~' 'ap'});
% sf --> ap
create_production('ap', 'sf', {}, {'ap'});
% sf --> AX sf
create_production('AX', 'sf', {'X'}, {'A' 'X' 'sf'});
% sf --> AF sf
create_production('AF', 'sf', {'F'}, {'A' 'F' 'sf'});
% sf --> AG sf
create_production('AG', 'sf', {'G'}, {'A' 'G' 'sf'});
% sf --> A sf U sf
create_production('AU', 'sf', {'U'}, {'A' 'sf' 'U' 'sf'});
% sf --> A sf R sf
create_production('AR', 'sf', {'R'}, {'A' 'sf' 'R' 'sf'});
% sf --> sf & sf
create_production('and', 'sf', {'&'}, {'sf' '&' 'sf'});
% sf --> sf | sf
create_production('or', 'sf', {'|'}, {'sf' '|' 'sf'});
% sf --> ( sf )
create_production('parentheses', 'sf', {'(',')'}, {'(' 'sf' ')'});

% Parse the cell array of terminals in top from bottom up. Successful
% parsing of ACTL expression should yield a single symbol node in the cell
% array top. A symbol node represents a terminal or a variable symbol. For
% our implementation of ACTL, we have the following terminals
%
%     ( ) ~ & | X F G U R A == name
%
% where name is a name string described in the m-file identerm.m. The
% variables are ap (atomic proposition) and sf (state formula).
%
% A symbol for a path formula is not needed since we combine path formulae
% into production for AX, AF, AG, AU, and AR.  Each symbol node in the parse
% tree has the following format.
%
%     node.symbol     : type name of terminal or variable symbols (string)
%     node.production : name of production that is used to obtain the
%                       symbol's value (next field). valid only for state
%                       formula symbol
%     node.value      : cell array of symbol nodes comprising the current
%                       symbol value

DEBUG = 0;
if DEBUG
  print_nodes(top)
end
production_found = 1;
while (length(top) > 1) | production_found
  % Search for the highest precedence production that can be applied.
  production_found = 0;
  k = 1;
  while (k <= length(PRODUCTION)) & ~production_found
    [production_found,idx] = match_production(top,PRODUCTION{k}.rule);
    if ~production_found
      k = k + 1;
    end
  end
  
  if production_found
    % If a matching production is found, apply the production rule to 
    % replace the sequence of nodes by a node representing a
    % state formula.
    top = apply_production(top,idx,PRODUCTION{k});
  else
    if length(top) > 1
      % If no matching production is found, find the production with the
      % highest precedence such that one of its key symbols is present
      % in the sequence of top nodes.
      k = 1;
      while (k <= length(PRODUCTION)) & ...
            ~find_key_symbol(top,PRODUCTION{k}.key_symbol)
        k = k + 1;
      end
      % If a production with a key symbol present in top is found
      % display its production rule in the syntax error message.
      % Otherwise, signify an unknown syntax error.
      if (k <= length(PRODUCTION))
        errmsg = sprintf('The following rule is violated:\n');
        errmsg = [errmsg PRODUCTION{k}.rule{1}];
        for l = 2:length(PRODUCTION{k}.rule)
          errmsg = [errmsg ' ' PRODUCTION{k}.rule{l}];
        end
        error(errmsg)
      else
        error('Unknown syntax error.')
      end
    end
  end
  if DEBUG
    print_nodes(top)
  end
end
top = top{1};
return

% -----------------------------------------------------------------------------

function create_production(name,var,key_symbol,rule)

global PRODUCTION

% Each production LHS --> RHS has the following structure:
%   PRODUCTION{i}.name       : production identifier
%   PRODUCTION{i}.var        : LHS variable
%   PRODUCTION{i}.key_symbol : Key symbols to look for if error occurs
%   PRODUCTION{i}.rule       : RHS string of variables and terminals
new = length(PRODUCTION)+1;
PRODUCTION{new}.name = name;
PRODUCTION{new}.var = var;
PRODUCTION{new}.key_symbol = key_symbol;
PRODUCTION{new}.rule = rule;
return

% -----------------------------------------------------------------------------

function [match,idx] = match_production(top,rule)

idx = 1;
match = 0;
while (idx+length(rule)-1 <= length(top)) & ~(match)
  match = 1;
  for k = 1:length(rule)
    if ~strcmp(top{idx+k-1}.symbol,rule{k})
      match = 0;
      break;
    end
  end
  if ~match
    idx = idx + 1;
  end
end

% -----------------------------------------------------------------------------

function top_new = apply_production(top,idx,production)

% Apply production to sequence of symbol nodes (which are variables or
% terminals) starting with top{idx}. Replace the whole sequence of nodes by
% a single state formula node that contains this sequence of nodes in its
% value.

top_new = {};
for l = 1:idx-1
  top_new{l} = top{l};
end
top_new{idx}.symbol = production.var;
top_new{idx}.production = production.name;
top_new{idx}.value = {};
for l = idx:idx+length(production.rule)-1
  top_new{idx}.value{l-idx+1} = top{l};
end
for l = idx+length(production.rule):length(top)
  top_new{l-length(production.rule)+1} = top{l};
end
return

% -----------------------------------------------------------------------------

function found = find_key_symbol(top,key_symbol)

found = 0;
for idx = 1:length(top)
  if ismember(top{idx}.symbol,key_symbol)
    found = 1;
    break
  end
end
return

% -----------------------------------------------------------------------------

function print_nodes(nodes)

for k = 1:length(nodes)
  fprintf(1,'%s ',nodes{k}.symbol)
end
fprintf(1,'\n')
return

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -