Skip to content

Advantages

Ronald Franco edited this page Dec 27, 2018 · 2 revisions

Flexibility

The AFP Library is implemented as a collection of C++11 header files that enable users to quickly create AFParser objects that accepts some LL(k) language. Additionally, the collection of header files also defines classes that enable the user to implement custom scanning methods, specify semantics with non-primitive data types, and visualize AFG productions or parse trees for some input. The library supports the given features without needing installation or code generation making it a viable alternative to popular parser-generators such as Bison/YACC.

Custom Scanning

Lexical analysis turns out to be the most expensive aspect of syntax directed translation. As a result, many individuals looking to develop a fast translator opt to create a specialized lexical analyzer for the task. The accompanying parser is designed to allow users to easily integrate custom lexical analyzers, by making using of the Tokenizer class, to prepare some token-based input. As a result, users can use the AFP Library to develop AFParser objects in C++11 that accepts some LL(k) language without being limited to a general lexical analyzer that could bottleneck the translation process.

Debugging

The AFP Library inherently provides users with tools to assist with debugging an AFG. First, the user may make use of multiple starting nonterminals in an AFG by altering the nonterminal the parse() member function is invoked on. Consider the binary number AFG example with two starting nonterminals, REC_NUM and IT_NUM:

Parser<> REC_NUM, IT_NUM, GETBIT, BIT;

// Tail Recursive Version
REC_NUM(x)>>z = GETBIT(x)>>y & REC_NUM(y)>>z
| GETBIT(x)>>z;

GETBIT(x)>>y = BIT>>b & [&]{ y = 2 * x + b; };

// Iterative Version
IT_NUM>>z = [&]{ z = 0; } & +( BIT>>b & [&]{ z = 2 * z + b; } );

BIT>>b = Token(‘0’) & [&]{ b = 0; } 
| Token(‘1’) & [&]{ b = 1; };

The parse() member function may be invoked on either starting nonterminal, REC_NUM and IT_NUM. Note, both starting nonterminals make use of a set of common AFG productions which is convenient and promotes modularity in an AFG.

Further, the use of the PrettyParser class provides the user with methods to visualize AFG productions and parse trees for some input. The following are visualizations for binary number example on input string "101011":

Recursive Binary Number Parse Tree Iterative Binary Number Parse Tree
Recursive Binary Number Parse Tree Iterative Binary Number Parse Tree

Finally, the use of semantic actions within AFG productions allow the user to generate logging messages, that may be printed to stdout, a file, or even some data structure. Consider the following altered binary number AFG:

Parser<> REC_NUM, IT_NUM, GETBIT, BIT;

// tail recursive starting nonterminal
  REC_NUM(x)>>z = [&]{ std::cout << "Recursive call" << std::endl; } & GETBIT(x)>>y & REC_NUM(y)>>z 
    | [&]{ std::cout << "Recursive call" << std::endl; } & GETBIT(x)>>z;

  GETBIT(x)>>y = BIT>>b & [&]{ y = 2 * x + b; std::cout << "Decimal value is now: " << y << std::endl; };

  // iterative starting nonterminal
  IT_NUM>>z = [&]{ std::cout << "Iterative" << std::endl; z = 0; } 
              & +( BIT>>b & [&]{ z = 2 * z + b; std::cout << "Decimal value is now: " << z << std::endl; } );

  BIT>>b = Token('0') & [&]{ b = 0; }
	  | Token('1') & [&]{ b = 1; };

The altered AFG above will yield the following output with input string "101011" when REC_NUM is the starting nonterminal:

Recursive call
Decimal value is now: 1
Recursive call
Decimal value is now: 2
Recursive call
Decimal value is now: 5
Recursive call
Decimal value is now: 10
Recursive call
Decimal value is now: 21
Recursive call
Decimal value is now: 43
Recursive call
Recursive call
Recursive call
Decimal value is now: 43
Success! 101011 is 43

Looking carefully at the last 5 lines of output, we can see that we tried to match the first two productions of REC_NUM but failed to match another bit, backtracking a total of 3 times.

The altered AFG above will yield the following output with input string "101011" when IT_NUM is the starting nonterminal:

Iterative
Decimal value is now: 1
Decimal value is now: 2
Decimal value is now: 5
Decimal value is now: 10
Decimal value is now: 21
Decimal value is now: 43
Success! 101011 is 43
Clone this wiki locally