This post will be edited by xuzuning on 16:40:33.
I have tried grammar analysis recently, and there are many problems.
Please provide suggestions. The code cannot be stored. There are two pages. Http://download.csdn.net/detail/xuzuning/4529066
Include 'ttrie. php '; class Rule extends TTrie {public $ rule = array (); public $ savematch = 0; function _ construct ($ s = '') {$ this-> set (array (''=> 'paramted'," \ r \ n "=> 'set _ rule ', "\ n" => 'set _ rule', "\ t" => 'secparated ','-> '=> 'secparated ', '→' => 'paramted', '|' => 'set _ parallel_rule',); $ this-> match ($ s ); if ($ this-> rule [0] [0] = $ this-> rule [0] [1]) {if (count ($ this-> rule [0]) = 2) $ this-> rule [0] [0]. = "'"; Else array_unshift ($ this-> rule, array ($ this-> rule [0] [0]. "'", $ this-> rule [0] [0]);} else {$ c = $ this-> rule [0] [0]; $ n = 0; foreach ($ this-> rule as $ r) if ($ r [0] = $ c) $ n ++; if ($ n> 1) array_unshift ($ this-> rule, array ($ this-> rule [0] [0]. "'", $ this-> rule [0] [0]);} function Separated () {} function set_rule () {$ this-> rule [] = $ this-> buffer; $ this-> buffer = array ();} function set_parallel_rule () {$ t = $ This-> buffer [0]; $ this-> set_rule (); $ this-> buffer [] = $ t ;}} class Grammar {var $ closure = array (); var $ first = array (); var $ follow = array (); var $ rule = array (); var $ identifier = array (); var $ leay = array (); var $ forecast = array (); var $ stack = array (); var $ ll ='ll (0) '; var $ lr = 'LR (0)'; function _ construct ($ s = '') {$ p = new Rule ($ s); $ this-> rule = $ p-> rule; $ this-> set_grammar ();} function Set_grammar () {foreach ($ this-> rule as $ rule) {if (! In_array ($ rule [0], $ this-> identifier) $ this-> identifier [] = $ rule [0];} foreach ($ this-> rule as $ rule) {foreach ($ rule as $ v) if (! In_array ($ v, $ this-> identifier )&&! In_array ($ v, $ this-> leay) $ this-> leay [] = $ v;} $ this-> set_first (); $ this-> set_follow (); $ this-> set_closure (); $ this-> set_select (); $ this-> set_forecast ();} function set_first () {foreach ($ this-> rule as $ rule) $ this-> first [$ rule [0] = array (); // directly charged for a shape such as U->... Generate the formula (where a is the Terminator) to generate a into the First (U) foreach ($ this-> rule as $ v) {if (in_array ($ v [1], $ this-> leay) $ this-> first [$ v [0] [] = $ v [1];} // repeatedly transmitted to the U-> P1P2P3... In the production formula of Pn (where P is not a Terminator), the full content in First (P1) should be First transmitted to First (U). If P1 contains ε, the First (P2) the content in is transmitted to First (U), and so on until there is no ε do {$ t = serialize ($ this-> first) in Pi ); foreach ($ this-> rule as $ rule) {for ($ I = 1; $ I
Identifier) {$ this-> first [$ rule [0] = array_unique (array_merge ($ this-> first [$ rule [0], $ this-> first [$ v]); if (! In_array ('#', $ this-> first [$ v]) break;} else break ;}} while ($ t! = Serialize ($ this-> first);} function set_follow () {foreach ($ this-> rule as $ rule) $ this-> follow [$ rule [0] = array (); // directly collects data such... Ua... To directly generate a into the Follow (U) foreach ($ this-> rule as $ rule) {for ($ I = 1; $ I
Identifier) & in_array ($ rule [$ I + 1], $ this-> leay )) $ this-> follow [$ rule [$ I] [] = $ rule [$ I + 1];} if (in_array ($ rule [$ I], $ this-> identifier) $ this-> follow [$ rule [$ I] [] = '#';} foreach ($ this-> follow as & $ v) if (! $ V) $ v [] = '#'; // directly collects data such... UP... (P is not a Terminator). It transfers non-ε income of First (P) to foreach ($ this-> rule as $ rule) {for ($ I = 1; $ I
Identifier) & in_array ($ rule [$ I + 1], $ this-> identifier )) {$ this-> follow [$ rule [$ I] = array_unique (array_merge ($ this-> follow [$ rule [$ I], array_diff ($ this-> first [$ rule [$ I + 1], array ('#'))));}}} // The Follow (U) should be set) to do {$ t = serialize ($ this-> Follow); foreach ($ this-> rule as $ rule) {$ s = $ rule [0]; $ d = end ($ rule); if (in_array ($ d, $ this-> leay) continue; $ P = prev ($ rule); if (in_array ($ p, $ this-> leay )) $ this-> follow [$ d] = array_unique (array_merge ($ this-> follow [$ d], $ this-> follow [$ s]); elseif (in_array ('#', $ this-> follow [$ d]) $ this-> follow [$ p] = array_unique (array_merge ($ this-> follow [$ p], $ this-> follow [$ s]);} while ($ t! = Serialize ($ this-> follow);} function set_closure () {$ shift = array (); $ this-> closure [0] [] = array ('offs' => 1, 'rule' => 0); for ($ I = 0; $ I <count ($ this-> closure); $ I ++) {$ cnt = count ($ this-> closure ); // Construct the closure $ ex = array (); $ j = 0; $ tmp = array (); do {$ size = count ($ this-> closure [$ I]); for ($ j = 0; $ j
Closure [$ I]); $ j ++) {$ dfa = $ this-> closure [$ I] [$ j]; $ rule = $ this-> rule [$ dfa ['rule']; if (isset ($ rule [$ dfa ['offs']) {$ ch = $ ex [] = $ rule [$ dfa ['offs'];} foreach ($ this-> rule as $ r => $ rule) {if (in_array ($ rule [0], $ ex) {$ t = array ('offs' => 1, 'rule' => $ r); if (! Isset ($ tmp [$ r] [1]) $ this-> closure [$ I] [] = $ t; $ tmp [$ r] [1] = 1 ;}}} while (count ($ this-> closure [$ I])! = $ Size); // wait until it no longer increases. // The judgment status changes to go $ out = array (); foreach ($ this-> closure [$ I] as $ k => $ dfa) {$ rule = $ this-> rule [$ dfa ['rule']; if (isset ($ rule [$ dfa ['offs']) {$ t = "$ dfa [rule], $ dfa [offs]"; $ ch = $ rule [$ dfa ['offs']; $ this-> closure [$ I] [$ k] ['char '] = $ ch; if (isset ($ out [$ ch]) $ shift [$ t] = $ out [$ ch]; if (isset ($ shift [$ t]) {$ this-> closure [$ I] [$ k] ['target'] = $ shift [$ t]; $ dfa ['offs'] ++; if (! $ This-> in_closure ($ dfa, $ this-> closure [$ shift [$ t]) $ this-> closure [$ shift [$ t] [] = $ dfa;} else {$ cnt = count ($ this-> closure ); $ this-> closure [$ I] [$ k] ['target'] = $ cnt; $ shift [$ t] = $ cnt; $ dfa ['offs'] ++; $ this-> closure [count ($ this-> closure)] [] = $ dfa; $ out [$ ch] = $ cnt ;}}// structure the State conversion table foreach ($ this-> closure [$ I] as $ k =>$ dfa) {if (isset ($ dfa ['target']) {$ v = $ dfa ['char ']; if (in_array ($ v, $ this-> identifier )) $ thi S-> goto [$ I] [$ v] = $ dfa ['target']; else {$ this-> action [$ I] [$ v] [] = "S $ dfa [target]"; $ this-> request [$ I] [$ v] = $ dfa ['rule'];} else {$ ch = $ this-> rule [$ dfa ['rule'] [0]; foreach ($ this-> follow [$ ch] as $ v) {$ this-> action [$ I] [$ v] [] = "r$ dfa [rule]"; $ this-> request [$ I] [$ v] = $ dfa ['rule'] ;}} foreach ($ this-> action [$ I] as $ c => $ v) {$ v = array_unique ($ v); if (count ($ v)> 1) $ this-> lr = 'slr (1) '; $ this-> action [$ I] [$ c] = $ V ;}} function in_closure ($ t, $ s) {foreach ($ s as $ r) if ($ t ['offs'] = $ r ['offs'] & $ t ['rule'] = $ r ['rule']) return true; return false; return in_array (serialize ($ t), array_map ('serialize', $ s);} function set_select () {foreach ($ this-> rule as $ I => $ rule) {$ y = array ($ rule [1]); if (in_array ($ y [0], $ this-> leay) {if ($ y [0]! = '#') {$ This-> select [$ I] = $ y; continue;} else $ y = $ this-> first [$ rule [1]; $ x = $ this-> follow [$ rule [0]; // SELECT (X-> Y) = (FIRST (Y)-{ε }) and FOLLOW (X) $ this-> select [$ I] = array_unique (array_merge (array_diff ($ y, array ('#'), $ x ));}} /*** construct a prediction analysis table **/function set_forecast () {foreach ($ this-> select as $ I => $ r) {$ c = $ this-> rule [$ I] [0]; $ v = array_reverse (array_slice ($ this-> rule [$ I], 1 )); foreach ($ r as $ k) {$ this-> forecast [$ c] [$ k] [] = $ v ;}} // Check for conflicting foreach ($ this-> forecast as $ c =>r r) {foreach ($ r as $ k) {if (count ($ k)> 1) {$ this-> ll ='ll (1 )';}}}}
Reply to discussion (solution)
Continued
Function ll_start ($ s) {$ t = array (); foreach ($ this-> rule as $ rule) if ($ rule [0] = $ rule [1]) $ t [] = $ rule; if ($ t) {foreach ($ t as $ rule) printf ('% S has left recursion', Preg_replace (' // ',' → ', join ('', $ rule), 1); return;} $ stack = array ('#', key ($ this-> forecast); $ I = 0; $ step = 1; $ timeout = 10 * strlen ($ s ); while ($ stack & $ I <strlen ($ s) & $ timeout --) {$ r = end ($ stack ); if ($ r === s {$ I}) {$ msg = $ r == '#'? 'Successfully': "$ r matched";} elseif (isset ($ this-> forecast [$ r] [$ s {$ I}]) $ msg = $ r. '→ '. join ('', array_reverse ($ this-> forecast [$ r] [$ s {$ I}] [0]); else $ msg = 'error '; printf ("% D% S% S% S", $ Step ++, substr (join ('', $ stack),-50), substr ($ s, $ I), $ msg ); if ($ r === s {$ I}) {array_pop ($ stack); $ I ++ ;} elseif (isset ($ this-> forecast [$ r] [$ s {$ I}]) {array_pop ($ stack ); if (current ($ this-> forecast [$ r] [$ s {$ I}] [0])! = '#') $ Stack = array_merge ($ stack, $ this-> forecast [$ r] [$ s {$ I}] [0]);} else break ;}} function lr_start ($ s) {$ State = array (0); // State stack $ Symbol = array ('#'); // symbol stack $ I = 0; $ step = 1; $ timeout = 10 * strlen ($ s); while ($ I <strlen ($ s) & $ timeout --) {$ ch = $ s {$ I}; $ sp = end ($ State); $ msg = substr ($ s, $ I ); if (isset ($ this-> action [$ sp] [$ ch]) & $ this-> action [$ sp] [$ ch] [0] = 'r0 ') $ msg = 'ACC '; if (isset ($ this-> request [$ sp] [$ ch]) $ request = preg_replace ('//', '→', join ('', $ this-> rule [$ this-> request [$ sp] [$ ch]), 1); else $ request = 'error'; printf ("% D% S% S% S% S", $ Step ++, substr (join ('', $ State),-50), join ('', $ Symbol), $ msg, $ request ); if (isset ($ this-> action [$ sp] [$ ch]) | isset ($ this-> goto [$ sp] [$ ch]) {$ t = isset ($ this-> action [$ sp] [$ ch])? $ This-> action [$ sp] [$ ch] [0]: $ this-> goto [$ sp] [$ ch]; $ n = substr ($ t, 1) + 0; if ($ t {0 }== 'r') {for ($ j = 0; $ j
Rule [$ n])-1; $ j ++) {array_pop ($ State); array_pop ($ Symbol);} if ($ n = 0) break; $ c = $ Symbol [] = $ this-> rule [$ n] [0]; $ State [] = $ this-> goto [end ($ State)] [$ c];} elseif ($ t {0 }== 's') {$ State [] = $ n; $ Symbol [] = $ ch; $ I ++;} else break;} function report ($ in = '') {if ($ in) $ in = trim ($ in, '#'). '#'; echo'
'; Echo'
Grammar |
'; Foreach ($ this-> rule as $ rule) {echo'
'; Echo preg_replace (' // ',' → ', join ('', $ rule), 1); echo' |
';} Echo'
'; $ Identifier = $ this-> identifier; echo'
Identifier | '; Echo'
'. Join ('', $ identifier ).' |
'; Echo'
'; $ Leay = array_diff ($ this-> leay, array (' # '); $ leay [] =' # '; echo'
Terminator | '; Echo'
'. Join ('', $ leay ).' |
'; Echo'
'; Echo'
Identifier |
Release Blank |
FIRST Set |
FOLLOW set |
'; Foreach ($ identifier as $ ch) {echo'
'. $ Ch .' | '; Echo'
'. (In_array (' # ', $ this-> first [$ ch])? 'True': 'false ').' | '; Echo'
'. Join ('', $ this-> first [$ ch]).' | '; Echo'
'. Join ('', $ this-> follow [$ ch]).' | '; Echo'
';} Echo'
'; Echo'
|
'. $ This-> ll.' grammar analysis |
'; Echo'
Generate |
Select set |
'; Foreach ($ this-> rule as $ I => $ rule) {echo'
'; Echo'
'. Preg_replace (' // ',' → ', join ('', $ rule), 1 ).' | '; Echo'
'. Join ('', $ this-> select [$ I]).' | '; Echo'
';} Echo'
'; $ Forecast = $ this-> forecast; echo'
Prediction Analysis Table |
'; Echo'
'; Echo'
|
'. Join (' |
', $ Leay ).' |
'; Foreach ($ identifier as $ ch) {echo'
'. $ Ch .' | '; Foreach ($ leay as $ v) {$ s = ''; if (isset ($ forecast [$ ch] [$ v]) {foreach ($ forecast [$ ch] [$ v] as $ t) {if ($ s) $ s. =''; $ S. = $ ch. '→ '. join ('', array_reverse ($ t);} if (count ($ forecast [$ ch] [$ v])> 1) $ s =" $ s ";} else $ s. = ''; echo'
'. $ S .' | ';} Echo'
';} Echo'
|
'; Echo'
'; If ($ in) {echo'
Test string | '; Echo'
'. Trim ($ in ,'#').' |
'; Echo'
'; Echo'
Procedure |
Analysis stack |
Remaining characters |
Generate or match |
'; $ This-> ll_start ($ in); echo'
';} Echo'
|
'; Echo'
'. $ This-> lr.' grammar analysis |
|
'; Echo'
'; Echo'
'; Echo'
Status |
Action |
Goto |
DFA |
'; Echo'
'. Join (' |
', $ Leay ).' |
'. Join (' |
', $ Identifier ).' |
'; Foreach ($ this-> action as $ I => $ item) {echo"
$ I | "; Foreach ($ leay as $ v) {$ s = isset ($ item [$ v])? Join (',', $ item [$ v]): ''; if (strpos ($ s, ',') $ s =" $ s "; echo"
$ S | ";} Foreach ($ identifier as $ v) {$ s = isset ($ this-> goto [$ I] [$ v])? $ This-> goto [$ I] [$ v]: ''; echo"
$ S | ";} Echo'
'. $ This-> showDFA ($ I ).' | '; Echo'
';} Echo'
'; If ($ in) {echo'
Test string | '; Echo'
'. Trim ($ in ,'#').' |
'; Echo'
'; Echo'
Procedure |
Status stack |
Symbol stack |
Remaining characters |
Generate |
'; $ This-> lr_start ($ in); echo'
';}} Function showDFA ($ I) {$ res = array (); foreach ($ this-> closure [$ I] as $ dfa) {$ rule = $ this-> rule [$ dfa ['rule']; array_splice ($ rule, $ dfa ['offs'], 0 ,'·'); array_splice ($ rule, 1, 0, '→'); if (isset ($ dfa ['target']) $ rule [] = "[$ dfa [target]"; $ res [] = join ('', $ rule);} return join (';', $ res) ;}}for ($ I = 1; $ I <= count (glob ('*. txt '); $ I ++) echo "$ I"; $ n = current ($ _ GET) or $ n = 1; $ S = ''; include "cmdn.txt"; $ p = new grammar ($ G); $ p-> report ($ S );
Ttrie. php
$ V) $ this-> set ($ k, $ v); return ;}$ p = count ($ this-> dict); $ cur = 0; // current node number foreach (str_split ($ word) as $ c) {if (isset ($ this-> dict [$ cur] [$ c]) {// if it already exists, move down $ cur = $ this-> dict [$ cur] [$ c]; continue ;} $ this-> dict [$ p] = array (); // Create a node $ this-> dict [$ cur] [$ c] = $ p; // record the subnode number on the parent node $ cur = $ p; // set the current node as the newly inserted $ p ++ ;} $ this-> dict [$ cur] ['ACC '] = $ action; // end of a word and mark the leaf node} function match ($ s) {$ ret = array (); $ cur = 0; // the current node, initially the root node. Point $ I = & $ this-> input; // Current string offset $ p = & $ this-> backtracking; // string backtracking position $ s. = "\ 0"; // Append $ len = strlen ($ s); $ buf = ''; while ($ I <$ len) {$ c = $ s {$ I}; if (isset ($ this-> dict [$ cur] [$ c]) {// if $ cur = $ this-> dict [$ cur] [$ c] exists; // go to the corresponding position if (isset ($ this-> dict [$ cur] [$ s [$ I + 1]) {// check whether the next character can be matched. the length takes precedence over $ I ++; continue;} if (isset ($ this-> dict [$ cur] ['ACC ']). {// It is a leaf node, and the word matches! If ($ buf) {$ this-> buffer [] = $ buf; $ buf = '';} if ($ this-> savematch) $ this-> buffer [] = substr ($ s, $ p, $ I-$ p + 1 ); // Retrieve the matching position and the matching word $ ar = explode (',', $ this-> dict [$ cur] ['ACC ']); call_user_func_array (array ($ this, array_shift ($ ar), $ ar); $ p = $ I + 1; // set the next backtracking position $ cur = 0; // reset the current node to the root node} else {// does not match $ buf. = $ s {$ p}; // substr ($ s, $ p, $ I-$ p + 1 ); // Save the unmatched position and content $ cur = 0; // reset the current node to the root node $ I = $ p; // set the current offset to the backtracking position $ p = $ I + 1; // set the next backtracking position} $ I ++; // next character} if (trim ($ buf, "\ 0") $ this-> buffer [] = trim ($ buf, "\ 0 ");} function _ call ($ method, $ param) {if ($ this-> debug) printf ("offset: % d backtracking: % d \ n ", $ this-> input, $ this-> backtracking );}}
Related data files
1. txt
a HH -> a M dH -> dM -> A bM -> #A -> a MA ->eTXT;$S = 'aaaebbd#';
2. txt
EE -> E + TE -> TT -> T * FT -> FF -> ( E )F -> iTXT;$S = 'i*(i+i)#';
3. txt
4. txt
5. txt
6. txt
7. txt
8. txt
I'm interested. Unfortunately, the compilation principle is completely forgotten.
Weak or weak: the efficiency of advanced language compilers will be too low ..
It is better to write some text and draw a dot chart. Reading code is too difficult
It is better to write some text and draw a dot chart. Reading code is too difficult
Copy the code and run it.
I packed and uploaded it, but I couldn't see it for a moment.
I don't even know how compilation works.
Have time to study
Nagging is a scientist
We are first-line production workers.
On-site observation of scientists
I don't even know how compilation works.
Have time to study
Good stuff. check it out later in the afternoon.
I have never learned how to compile!
Go back to the compilation principle, published by Tsinghua University Press.
Lexical analysis, syntax analysis, semantic analysis... just graduated, I still have a certain impression.
Yacc. lex is powerful.
It is better to have comments
It is better to have comments
You are too academic.
It seems that you have made it complicated.
You can draw a picture based on the lua code. His code is concise. It's just a bit of a good hierarchy!
This language is too advanced, but there is no need to worry about performance.
Er, ask for comments.
You cannot understand
First, describe your grammar. how can someone understand it?
Follow up!
Thank you!
Learned
No? Oh!
I will pay more attention to it soon
There are so many great experts on the site. I hope you will take care of me when I arrive at Guibao.
Do not understand compilation, so pay attention
Compilation principles are powerful !!
Sorry, post back to earn points.
The course design compiled at that time was like this. if you put it up two years ago, I don't have to do it myself ~
You can calculate the total score by 20 minutes ~
You cannot understand
Right.
First, describe your grammar. how can someone understand it?
This statement is supported. The reference on the first floor is incorrect.
Do you want to describe the grammar first? a layman says that he can directly guess from the code that the pears are very big ..
Friends are not Chinese, right?
Formal language is learning. I just got started with grammar. how does compilation work?
I read more than half of them? Small ?? I understand, do ?????? Note ....
Not understand
Downloads: 33
Reply times: 45
No one raised an objection to the output.
No suggestions for program improvement
No one challenges algorithm problems
The data used is obtained online (of course, it is also copied from textbooks)
The program does not handle any conflicts (only list)
It can be seen that these grammar examples have been carefully designed and won't be wrong.
Read only LL (1)
1. select non #
Why does left recursion not be eliminated for 2, 3, and 8?
5. 7 extract factors.
LR at night.
Compilation principles are hard to understand
Read only LL (1)
1. select non #
Why does left recursion not be eliminated for 2, 3, and 8?
5. 7 extract factors.
LR at night. Thank you.
In fact, I am a beginner. I have read it before and have never figured it out.
This is a clear point. we are studying the implementation of algorithms for eliminating left recursion and factor extraction. So you didn't
PHP oh ,,,,,
Think about the full score of the university course. I forget it now.
Go to review
I looked at it. I wrote 1 + 1 = 2 in that year. That's not the case!
Complicated algorithms. I did not expect that some of the business systems could not be understood after three years.
You have to study the algorithm.
I can't understand it. ..
I am also working on a very simple two-step compiler myself recently. I have to communicate with you more.
The program runs the Grammar. php file directly. I cannot understand it, and the pressure is high.
I can see $
Powerful lexical analysis tool: flex
Powerful syntax analysis tools: bison and BYACC.
PHP is an interpreted programming language. The syntax is to simulate the C language. it is too slow to perform syntax analysis.
Directly use C language + flex + BISON
I used the LR analysis method to write a syntax Analyzer. how does your program support a large syntax? how is the speed?
I have a part of the grammar for my own SQL language. do you want to give it a try?
Algorithms are very important!
Good stuff. check it out later in the afternoon.
Now I am getting started with php and try to climb up
Well-known things seem to have been returned to the teacher for a long time --
Not understood
Write it in php.
It looks very advanced. php is a little bit small and it will make simple things. mark One, learn more.
Ah, this thing is returned to the teacher after one semester in college.
@@
@@
It's too complicated to read.
Hahaha, the landlord has finished a connection and compiled it online.
I have never learned and cannot use it for the moment. Let's talk about it later, with limited energy.
Running results look very familiar, but can not understand...
Looking up ......
Write more comments. it looks very tired.
I don't understand.
What algorithm are you implemented based on?
Hi, elder brother!